2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-02 15:25:58 +00:00

Add support for controlling whether utmp is updated and which user is

listed in the entry.
This commit is contained in:
Todd C. Miller
2011-03-15 15:53:49 -04:00
parent cf7ec7a3cc
commit 3506f01077
12 changed files with 72 additions and 16 deletions

View File

@@ -591,6 +591,20 @@ Allocate a pseudo-tty to run the command in, regardless of whether
or not I/O logging is in use. By default, B<sudo> will only run
the command in a pty when an I/O log plugin is loaded.
=item set_utmp=bool
Create a utmp (or utmpx) entry when a pseudo-tty is allocated. By
default, the new entry will be a copy of the user's existing utmp
entry (if any), with the tty, time, type and pid fields updated.
=item utmp_user=string
User name to use when constructing a new utmp (or utmpx) entry when
I<set_utmp> is enabled. This option can be used to set the user
field in the utmp entry to the user the command runs as rather than
the invoking user. If not set, B<sudo> will base the new entry on
the invoking user's existing entry.
=back
Unsupported values will be ignored.

View File

@@ -338,6 +338,14 @@ struct sudo_defs_types sudo_defs_table[] = {
"iolog_file", T_STR,
"File in which to store the input/output log",
NULL,
}, {
"set_utmp", T_FLAG,
"Add an entry to the utmp/utmpx file when allocating a pty",
NULL,
}, {
"utmp_runas", T_FLAG,
"Set the user in utmp to the runas user, not the invoking user",
NULL,
}, {
NULL, 0, NULL
}

View File

@@ -156,6 +156,10 @@
#define I_IOLOG_DIR 77
#define def_iolog_file (sudo_defs_table[78].sd_un.str)
#define I_IOLOG_FILE 78
#define def_set_utmp (sudo_defs_table[79].sd_un.flag)
#define I_SET_UTMP 79
#define def_utmp_runas (sudo_defs_table[80].sd_un.flag)
#define I_UTMP_RUNAS 80
enum def_tuple {
never,

View File

@@ -250,3 +250,9 @@ iolog_dir
iolog_file
T_STR
"File in which to store the input/output log"
set_utmp
T_FLAG
"Add an entry to the utmp/utmpx file when allocating a pty"
utmp_runas
T_FLAG
"Set the user in utmp to the runas user, not the invoking user"

View File

@@ -498,6 +498,7 @@ init_defaults(void)
def_secure_path = estrdup(SECURE_PATH);
#endif
def_editor = estrdup(EDITOR);
def_set_utmp = TRUE;
/* Finally do the lists (currently just environment tables). */
init_envtables();

View File

@@ -646,6 +646,10 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
command_info[info_len++] = estrdup("noexec=true");
if (def_noexec_file)
command_info[info_len++] = fmt_string("noexec_file", def_noexec_file);
if (def_set_utmp)
command_info[info_len++] = estrdup("set_utmp=true");
if (def_utmp_runas)
command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name);
#ifdef HAVE_LOGIN_CAP_H
if (lc != NULL)
command_info[info_len++] = fmt_string("login_class", lc->lc_class);

View File

@@ -203,6 +203,7 @@ int
sudo_execve(struct command_details *details, struct command_status *cstat)
{
int maxfd, n, nready, sv[2], log_io = FALSE;
const char *utmp_user = NULL;
fd_set *fdsr, *fdsw;
sigaction_t sa;
pid_t child;
@@ -231,8 +232,10 @@ sudo_execve(struct command_details *details, struct command_status *cstat)
if (!tq_empty(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) {
log_io = TRUE;
if (!ISSET(details->flags, CD_BACKGROUND)) {
if (ISSET(details->flags, CD_SET_UTMP))
utmp_user = details->utmp_user ? details->utmp_user : user_details.username;
sudo_debug(8, "allocate pty for I/O logging");
pty_setup(details->euid, user_details.tty);
pty_setup(details->euid, user_details.tty, utmp_user);
}
}

View File

@@ -118,7 +118,7 @@ cleanup(int gotsignal)
#ifdef HAVE_SELINUX
selinux_restore_tty();
#endif
utmp_logout(slavename);
utmp_logout(slavename); /* XXX - only if CD_SET_UTMP */
}
/*
@@ -127,17 +127,16 @@ cleanup(int gotsignal)
* and slavename globals.
*/
void
pty_setup(uid_t uid, const char *tty)
pty_setup(uid_t uid, const char *tty, const char *utmp_user)
{
io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
if (io_fds[SFD_USERTTY] != -1) {
if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE],
slavename, sizeof(slavename), uid))
error(1, "Can't get pty");
/*
* Add entry to utmp/utmpx.
*/
utmp_login(tty, slavename, io_fds[SFD_SLAVE]);
/* Add entry to utmp/utmpx? */
if (utmp_user != NULL)
utmp_login(tty, slavename, io_fds[SFD_SLAVE], utmp_user);
}
}
@@ -656,7 +655,7 @@ pty_close(struct command_status *cstat)
}
}
}
utmp_logout(slavename);
utmp_logout(slavename); /* XXX - only if CD_SET_UTMP */
}
/*

View File

@@ -605,6 +605,11 @@ command_info_to_details(char * const info[], struct command_details *details)
case 's':
SET_STRING("selinux_role=", selinux_role)
SET_STRING("selinux_type=", selinux_type)
if (strncmp("set_utmp=", info[i], sizeof("set_utmp=") - 1) == 0) {
if (atobool(info[i] + sizeof("set_utmp=") - 1) == TRUE)
SET(details->flags, CD_SET_UTMP);
break;
}
if (strncmp("sudoedit=", info[i], sizeof("sudoedit=") - 1) == 0) {
if (atobool(info[i] + sizeof("sudoedit=") - 1) == TRUE)
SET(details->flags, CD_SUDOEDIT);
@@ -647,6 +652,7 @@ command_info_to_details(char * const info[], struct command_details *details)
SET(details->flags, CD_USE_PTY);
break;
}
SET_STRING("utmp_user=", utmp_user)
break;
}
}

View File

@@ -120,6 +120,7 @@ struct user_details {
#define CD_BACKGROUND 0x0400
#define CD_RBAC_ENABLED 0x0800
#define CD_USE_PTY 0x1000
#define CD_SET_UTMP 0x2000
struct command_details {
uid_t uid;
@@ -139,6 +140,7 @@ struct command_details {
const char *chroot;
const char *selinux_role;
const char *selinux_type;
const char *utmp_user;
char **argv;
char **envp;
};

View File

@@ -38,12 +38,13 @@ int suspend_parent(int signo);
void fd_set_iobs(fd_set *fdsr, fd_set *fdsw);
void handler(int s);
void pty_close(struct command_status *cstat);
void pty_setup(uid_t uid, const char *tty);
void pty_setup(uid_t uid, const char *tty, const char *utmp_user);
void terminate_child(pid_t pid, int use_pgrp);
extern int signal_pipe[2];
/* utmp.c */
int utmp_login(const char *from_line, const char *to_line, int ttyfd);
int utmp_login(const char *from_line, const char *to_line, int ttyfd,
const char *user);
int utmp_logout(const char *line);
#endif /* _SUDO_EXEC_H */

View File

@@ -125,14 +125,20 @@ utmp_settime(sudo_utmp_t *ut)
* Fill in a utmp entry, using an old entry as a template if there is one.
*/
static void
utmp_fill(const char *line, sudo_utmp_t *ut_old, sudo_utmp_t *ut_new)
utmp_fill(const char *line, const char *user, sudo_utmp_t *ut_old,
sudo_utmp_t *ut_new)
{
if (ut_old == NULL) {
memset(ut_new, 0, sizeof(*ut_new));
strncpy(ut_new->ut_user, user_details.username, sizeof(ut_new->ut_user));
if (user == NULL) {
strncpy(ut_new->ut_user, user_details.username,
sizeof(ut_new->ut_user));
}
} else if (ut_old != ut_new) {
memcpy(ut_new, ut_old, sizeof(*ut_new));
}
if (user != NULL)
strncpy(ut_new->ut_user, user, sizeof(ut_new->ut_user));
strncpy(ut_new->ut_line, line, sizeof(ut_new->ut_line));
#if defined(HAVE_STRUCT_UTMPX_UT_ID) || defined(HAVE_STRUCT_UTMP_UT_ID)
utmp_setid(ut_old, ut_new);
@@ -156,7 +162,8 @@ utmp_fill(const char *line, sudo_utmp_t *ut_old, sudo_utmp_t *ut_new)
*/
#if defined(HAVE_GETUTXID) || defined(HAVE_GETUTID)
int
utmp_login(const char *from_line, const char *to_line, int ttyfd)
utmp_login(const char *from_line, const char *to_line, int ttyfd,
const char *user)
{
sudo_utmp_t utbuf, *ut_old = NULL;
int rval = FALSE;
@@ -174,7 +181,7 @@ utmp_login(const char *from_line, const char *to_line, int ttyfd)
strncpy(utbuf.ut_line, from_line, sizeof(utbuf.ut_line));
ut_old = getutxline(&utbuf);
}
utmp_fill(to_line, ut_old, &utbuf);
utmp_fill(to_line, user, ut_old, &utbuf);
if (pututxline(&utbuf) != NULL)
rval = TRUE;
endutxent();
@@ -253,7 +260,8 @@ utmp_slot(const char *line, int ttyfd)
# endif /* HAVE_GETTTYENT */
int
utmp_login(const char *from_line, const char *to_line, int ttyfd)
utmp_login(const char *from_line, const char *to_line, int ttyfd,
const char *user)
{
sudo_utmp_t utbuf, *ut_old = NULL;
int slot, rval = FALSE;
@@ -288,7 +296,7 @@ utmp_login(const char *from_line, const char *to_line, int ttyfd)
}
}
}
utmp_fill(to_line, ut_old, &utbuf);
utmp_fill(to_line, user, ut_old, &utbuf);
if (fseek(fp, slot * (long)sizeof(utbuf), SEEK_SET) == 0) {
if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1)
rval = TRUE;