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:
@@ -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.
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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"
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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 */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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 */
|
||||
|
20
src/utmp.c
20
src/utmp.c
@@ -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;
|
||||
|
Reference in New Issue
Block a user