2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-02 07:15:27 +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 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. 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 =back
Unsupported values will be ignored. Unsupported values will be ignored.

View File

@@ -338,6 +338,14 @@ struct sudo_defs_types sudo_defs_table[] = {
"iolog_file", T_STR, "iolog_file", T_STR,
"File in which to store the input/output log", "File in which to store the input/output log",
NULL, 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 NULL, 0, NULL
} }

View File

@@ -156,6 +156,10 @@
#define I_IOLOG_DIR 77 #define I_IOLOG_DIR 77
#define def_iolog_file (sudo_defs_table[78].sd_un.str) #define def_iolog_file (sudo_defs_table[78].sd_un.str)
#define I_IOLOG_FILE 78 #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 { enum def_tuple {
never, never,

View File

@@ -250,3 +250,9 @@ iolog_dir
iolog_file iolog_file
T_STR T_STR
"File in which to store the input/output log" "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); def_secure_path = estrdup(SECURE_PATH);
#endif #endif
def_editor = estrdup(EDITOR); def_editor = estrdup(EDITOR);
def_set_utmp = TRUE;
/* Finally do the lists (currently just environment tables). */ /* Finally do the lists (currently just environment tables). */
init_envtables(); 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"); command_info[info_len++] = estrdup("noexec=true");
if (def_noexec_file) if (def_noexec_file)
command_info[info_len++] = fmt_string("noexec_file", 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 #ifdef HAVE_LOGIN_CAP_H
if (lc != NULL) if (lc != NULL)
command_info[info_len++] = fmt_string("login_class", lc->lc_class); 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) sudo_execve(struct command_details *details, struct command_status *cstat)
{ {
int maxfd, n, nready, sv[2], log_io = FALSE; int maxfd, n, nready, sv[2], log_io = FALSE;
const char *utmp_user = NULL;
fd_set *fdsr, *fdsw; fd_set *fdsr, *fdsw;
sigaction_t sa; sigaction_t sa;
pid_t child; 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)) { if (!tq_empty(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) {
log_io = TRUE; log_io = TRUE;
if (!ISSET(details->flags, CD_BACKGROUND)) { 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"); 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 #ifdef HAVE_SELINUX
selinux_restore_tty(); selinux_restore_tty();
#endif #endif
utmp_logout(slavename); utmp_logout(slavename); /* XXX - only if CD_SET_UTMP */
} }
/* /*
@@ -127,17 +127,16 @@ cleanup(int gotsignal)
* and slavename globals. * and slavename globals.
*/ */
void 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); io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
if (io_fds[SFD_USERTTY] != -1) { if (io_fds[SFD_USERTTY] != -1) {
if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE], if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE],
slavename, sizeof(slavename), uid)) slavename, sizeof(slavename), uid))
error(1, "Can't get pty"); error(1, "Can't get pty");
/* /* Add entry to utmp/utmpx? */
* Add entry to utmp/utmpx. if (utmp_user != NULL)
*/ utmp_login(tty, slavename, io_fds[SFD_SLAVE], utmp_user);
utmp_login(tty, slavename, io_fds[SFD_SLAVE]);
} }
} }
@@ -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': case 's':
SET_STRING("selinux_role=", selinux_role) SET_STRING("selinux_role=", selinux_role)
SET_STRING("selinux_type=", selinux_type) 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 (strncmp("sudoedit=", info[i], sizeof("sudoedit=") - 1) == 0) {
if (atobool(info[i] + sizeof("sudoedit=") - 1) == TRUE) if (atobool(info[i] + sizeof("sudoedit=") - 1) == TRUE)
SET(details->flags, CD_SUDOEDIT); 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); SET(details->flags, CD_USE_PTY);
break; break;
} }
SET_STRING("utmp_user=", utmp_user)
break; break;
} }
} }

View File

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

View File

@@ -38,12 +38,13 @@ int suspend_parent(int signo);
void fd_set_iobs(fd_set *fdsr, fd_set *fdsw); void fd_set_iobs(fd_set *fdsr, fd_set *fdsw);
void handler(int s); void handler(int s);
void pty_close(struct command_status *cstat); 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); void terminate_child(pid_t pid, int use_pgrp);
extern int signal_pipe[2]; extern int signal_pipe[2];
/* utmp.c */ /* 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); int utmp_logout(const char *line);
#endif /* _SUDO_EXEC_H */ #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. * Fill in a utmp entry, using an old entry as a template if there is one.
*/ */
static void 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) { if (ut_old == NULL) {
memset(ut_new, 0, sizeof(*ut_new)); 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) { } else if (ut_old != ut_new) {
memcpy(ut_new, ut_old, sizeof(*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)); strncpy(ut_new->ut_line, line, sizeof(ut_new->ut_line));
#if defined(HAVE_STRUCT_UTMPX_UT_ID) || defined(HAVE_STRUCT_UTMP_UT_ID) #if defined(HAVE_STRUCT_UTMPX_UT_ID) || defined(HAVE_STRUCT_UTMP_UT_ID)
utmp_setid(ut_old, ut_new); 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) #if defined(HAVE_GETUTXID) || defined(HAVE_GETUTID)
int 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; sudo_utmp_t utbuf, *ut_old = NULL;
int rval = FALSE; 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)); strncpy(utbuf.ut_line, from_line, sizeof(utbuf.ut_line));
ut_old = getutxline(&utbuf); ut_old = getutxline(&utbuf);
} }
utmp_fill(to_line, ut_old, &utbuf); utmp_fill(to_line, user, ut_old, &utbuf);
if (pututxline(&utbuf) != NULL) if (pututxline(&utbuf) != NULL)
rval = TRUE; rval = TRUE;
endutxent(); endutxent();
@@ -253,7 +260,8 @@ utmp_slot(const char *line, int ttyfd)
# endif /* HAVE_GETTTYENT */ # endif /* HAVE_GETTTYENT */
int 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; sudo_utmp_t utbuf, *ut_old = NULL;
int slot, rval = FALSE; 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 (fseek(fp, slot * (long)sizeof(utbuf), SEEK_SET) == 0) {
if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1) if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1)
rval = TRUE; rval = TRUE;