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