utmp_update.c revision 4bc0a2ef2b7ba50a7a717e7ddbf31472ad28e358
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*
* As of on28, the utmp interface is obsolete,
* so we only handle updating the utmpx file now.
* The utmpx routines in libc "simulate" calls
* to manipulate utmp entries.
*
* This program runs set uid root on behalf of
* non-privileged user programs. Normal programs cannot
* will invoke this program to write the utmpx entry.
*/
/*
* Header files
*/
#include <stdio.h>
#include <utmpx.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <ctype.h>
#include <stropts.h>
#include <syslog.h>
/*
* Invocation argument definitions
*/
#define UTMPX_NARGS 14
/*
* Return codes
*/
#define NORMAL_EXIT 0
#define BAD_ARGS 1
#define PUTUTXLINE_FAILURE 2
#define FORK_FAILURE 3
#define SETSID_FAILURE 4
#define ALREADY_DEAD 5
#define ENTRY_NOTFOUND 6
#define ILLEGAL_ARGUMENT 7
/*
* Sizes
*/
#define BUF_SIZE 256
/*
* Other defines
*/
#define ROOT_UID 0
/*
* Debugging support
*/
#ifdef DEBUG
static void display_args();
#else /* DEBUG */
#define dprintf(x, y)
#define dprintf3(w, x, y, z)
#endif
/*
* Local functions
*/
static void load_utmpx_struct(struct utmpx *, char **);
static void usage(void);
static void check_utmpx(struct utmpx *);
static int bad_hostname(char *, int);
static int hex2bin(unsigned char);
static int bad_line(char *);
static void check_id(char *, char *);
int
{
#ifdef DEBUG
int debugger = 1;
/* Uncomment the following for attaching with dbx(1) */
/* while (debugger) ; */
#endif /* DEBUG */
/*
* We will always be called by pututxline, so simply
* verify the correct number of args
*/
if (argc != UTMPX_NARGS) {
usage();
return (BAD_ARGS);
}
/*
* we should never be called by root the code in libc already
* updates the file for root so no need to do it here. This
* assumption simpilfies the rest of code since we nolonger
* have to do special processing for the case when we are called
* by root
*
*/
usage();
return (ILLEGAL_ARGUMENT);
}
/*
* Search for matching entry by line name before put operation
* (scan over the whole file using getutxent(3C) to ensure
* that the line name is the same. We can not use getutline(3C)
* because that will return LOGIN_PROCESS and USER_PROCESS
* records. Also check that the entry is for either a dead
* process or a current process that is valid (see
* invalid_utmpx() for details of validation criteria).
*/
break;
}
usage();
return (ILLEGAL_ARGUMENT);
} else {
break;
}
}
}
}
return (PUTUTXLINE_FAILURE);
}
return (NORMAL_EXIT);
}
static int
hex2bin(unsigned char c)
{
if ('0' <= c && c <= '9')
return (c - '0');
else if ('A' <= c && c <= 'F')
return (10 + c - 'A');
else if ('a' <= c && c <= 'f')
return (10 + c - 'a');
dprintf("Bad hex character: 0x%x\n", c);
/* NOTREACHED */
}
/*
* load_utmpx_struct - Load up the utmpx structure with information supplied
* as arguments in argv.
*/
static void
{
int temp, i;
unsigned char *cp;
/*
* Here's where we stamp the exit field of a USER_PROCESS
* record so that we know it was written by a normal user.
*/
}
/*
* usage - There's no need to say more. This program isn't supposed to
* be executed by normal users directly.
*/
static void
usage()
{
}
/*
* check_utmpx - Verify the utmpx structure
*/
static void
{
int uid;
int hostlen;
char *user;
/*
* We nolonger permit the UID of the caller to be different
* the UID to be written to the utmp file. This was thought
* necessary to allow the utmp file to be updated when
* logging out from an xterm(1) window after running
* exec login. Instead we now rely upon utmpd(1) to update
* the utmp file for us.
*
*/
dprintf3("Bad uid: user %s = %d uid = %d \n",
}
}
/*
* Only USER_PROCESS and DEAD_PROCESS entries may be updated
*/
}
/*
* Verify that the pid of the entry field is the same pid as our
* parent, who should be the guy writing the entry. This is commented
* out for now because this restriction is overkill.
*/
#ifdef VERIFY_PID
}
#endif /* VERIFY_PID */
}
dprintf3("Bad syslen of \"%s\" = %d - correcting to %d\n",
}
}
}
/*
* bad_hostname - Previously returned an error if a non alpha numeric
* was in the host field, but now just clears those so
* cmdtool entries will work.
*/
static int
{
int i;
return (1);
/*
* Scan for non-alpha numerics
* Per utmpx.h, len includes the nul character.
*/
for (i = 0; i < len; i++)
name[i] = ' ';
return (0);
}
/*
* Workaround until the window system gets fixed. Look for id's with
* a '/' in them. That means they are probably from libxview.
* Then create a new id that is unique using the last 4 chars in the line.
*/
static void
{
int i, len;
if (len > 0)
len--;
for (i = 0; i < 4; i++)
}
}
/*
* The function invalid_utmpx() enforces the requirement that the record
* being updating in the utmpx file can not have been created by login(1)
* or friends. Also that the id and username of the record to be written match
* those found in the utmpx file. We need this both for security and to ensure
* that pututxline(3C) will NOT reposition the file pointer in the utmpx file,
* so that the record is updated in place.
*
*/
static int
{
}
static int
{
int fd;
/*
* The line field must be a device file that we can write to,
* it should live under /dev which is enforced by requiring
* its name not to contain "../" and opening it as the user for
* writing.
*/
return (1);
}
/*
*/
return (1);
/*
* Check that the line refers to a character
* special device.
*/
return (1);
}
/*
* We need to open the line without blocking so that it does not hang
*/
return (1);
}
/*
* Check that fd is a tty, if this fails all is not lost see below
*/
/*
* It really is a tty, so return success
*/
return (1);
return (0);
}
/*
* Check that the line refers to a character
* special device.
*/
return (1);
}
/*
* Check that the line refers to a streams device
*/
return (1);
}
/*
* if isatty(3C) failed above we assume that the ptem module has
* been popped already and that caused the failure, so we push it
* and try again
*/
return (1);
}
return (1);
}
return (1);
}
return (1);
return (0);
}
#ifdef DEBUG
/*
* display_args - This code prints out invocation arguments
* This is helpful since the program is called with
* up to 15 argumments.
*/
static void
int argc;
char **argv;
{
int i = 0;
while (argc--) {
i++;
}
}
{
printf("ut_exit.e_termination = \"%d\" \n",
}
#endif /* DEBUG */