]> granicus.if.org Git - sudo/commitdiff
Add support for controlling whether utmp is updated and which user is
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 15 Mar 2011 19:53:49 +0000 (15:53 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 15 Mar 2011 19:53:49 +0000 (15:53 -0400)
listed in the entry.

12 files changed:
doc/sudo_plugin.pod
plugins/sudoers/def_data.c
plugins/sudoers/def_data.h
plugins/sudoers/def_data.in
plugins/sudoers/defaults.c
plugins/sudoers/sudoers.c
src/exec.c
src/exec_pty.c
src/sudo.c
src/sudo.h
src/sudo_exec.h
src/utmp.c

index d74ea22f2c446b3623d7f3401152748209337794..014bd0a795b49fdbd2f0ec0517bd462ebda9999f 100644 (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.
index 5be92807bfadfc6383cbf941b2b919002767a3f9..ca02cedd66ccfc25b2eed5a2239cd530b4c62728 100644 (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
     }
index bbc35c654d757fce0f6a084999f96a2651bfe33c..f41f7cdd538e6b7d9aa81cd05ce435ce4cf79479 100644 (file)
 #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,
index 655b3470d38cce7e0a999094163977394f02e58f..340a5e489a7218ce64a7cba74544f351cb40d18a 100644 (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"
index 58728b8af6d2e4778da68bddb264cd91a4ff7b9d..f9e9961e9aaccd26e11a2c88d7f3a982492eb381 100644 (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();
index 39fab7477d3764c439b2f173df20f00f4994bdf0..5c029c26f064647540f51104483ca8af720280e6 100644 (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);
index ae2aa48a776d0d2fc97d9d68913d7363831e82be..2cda3c9e801a94a357333b4ee4c042a0048ca9fe 100644 (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);
        }
     }
 
index 6c7a3d6c698c25799b1090b4ae433e5d230826a3..b243f681da92a7e0f21bdd82cbc2d8d0ba2bd2d6 100644 (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 */
 }
 
 /*
index 3615411c0534942333455818da893b7be3db1b04..e9c9d0f9d86cac69726b845c7964442437bcef68 100644 (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;
        }
     }
index 1ad37e26ece2c2dddbb88c03d28cc668108a983e..46a68f153d076059673c6a0cbe7871d40ef29424 100644 (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;
 };
index 1484ae1b68939fcce9fb63c3ed9cdad7936c7b04..9a893ac5d4f171ff187cbf773901085013cff7ee 100644 (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 */
index e5b334d79a851206455a71091bfc84ca31c5e083..55797a714663ff4036803dee5344e7e0348baecd 100644 (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;