]> granicus.if.org Git - sudo/commitdiff
Add new sudoers option "preserve_groups". Previously sudo would not
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 15 Dec 2001 00:24:27 +0000 (00:24 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 15 Dec 2001 00:24:27 +0000 (00:24 +0000)
call initgroups() if the target user was root.  Now it always calls
initgroups() unless the -P command line option or the "preserve_groups"
sudoers option is set.  Idea from TJ Saunders.

def_data.c
def_data.h
def_data.in
set_perms.c
sudo.c
sudo.h
sudo.pod
sudoers.pod

index 6c1a4a43f8c38bf4cfcc1295206d42b3833f84df..ec02d8871db3a12b1ba185a243d98afd7d7ee5f5 100644 (file)
@@ -101,6 +101,9 @@ struct sudo_defs_types sudo_defs_table[] = {
     }, {
        "env_reset", T_FLAG,
        "Reset the environment to a default set of variables"
+    }, {
+       "preserve_groups", T_FLAG,
+       "Don't initialize the group vector to that of the target user"
     }, {
        "loglinelen", T_UINT|T_BOOL,
        "Length at which to wrap log file lines (0 for no wrap): %d"
index 89c1a30e2e5cf6138da4a8078694fd0ba815f9d9..dcf2cc8ef8c73b1f86fef963a02cd88daa36e3d9 100644 (file)
 #define I_SET_LOGNAME           31
 #define I_STAY_SETUID           32
 #define I_ENV_RESET             33
-#define I_LOGLINELEN            34
-#define I_TIMESTAMP_TIMEOUT     35
-#define I_PASSWD_TIMEOUT        36
-#define I_PASSWD_TRIES          37
-#define I_UMASK                 38
-#define I_LOGFILE               39
-#define I_MAILERPATH            40
-#define I_MAILERFLAGS           41
-#define I_MAILTO                42
-#define I_MAILSUB               43
-#define I_BADPASS_MESSAGE       44
-#define I_TIMESTAMPDIR          45
-#define I_EXEMPT_GROUP          46
-#define I_PASSPROMPT            47
-#define I_RUNAS_DEFAULT         48
-#define I_EDITOR                49
-#define I_ENV_CHECK             50
-#define I_ENV_DELETE            51
-#define I_ENV_KEEP              52
-#define I_LISTPW_I              53
-#define I_VERIFYPW_I            54
-#define I_LISTPW                55
-#define I_VERIFYPW              56
+#define I_PRESERVE_GROUPS       34
+#define I_LOGLINELEN            35
+#define I_TIMESTAMP_TIMEOUT     36
+#define I_PASSWD_TIMEOUT        37
+#define I_PASSWD_TRIES          38
+#define I_UMASK                 39
+#define I_LOGFILE               40
+#define I_MAILERPATH            41
+#define I_MAILERFLAGS           42
+#define I_MAILTO                43
+#define I_MAILSUB               44
+#define I_BADPASS_MESSAGE       45
+#define I_TIMESTAMPDIR          46
+#define I_EXEMPT_GROUP          47
+#define I_PASSPROMPT            48
+#define I_RUNAS_DEFAULT         49
+#define I_EDITOR                50
+#define I_ENV_CHECK             51
+#define I_ENV_DELETE            52
+#define I_ENV_KEEP              53
+#define I_LISTPW_I              54
+#define I_VERIFYPW_I            55
+#define I_LISTPW                56
+#define I_VERIFYPW              57
index d1f3313a84504d4439a29eb1e620aa308f355c57..3fac37342f77f6074093dc3ba12106a9a29cbf67 100644 (file)
@@ -108,6 +108,9 @@ stay_setuid
 env_reset
        T_FLAG
        "Reset the environment to a default set of variables"
+preserve_groups
+       T_FLAG
+       "Don't initialize the group vector to that of the target user"
 loglinelen
        T_UINT|T_BOOL
        "Length at which to wrap log file lines (0 for no wrap): %d"
index 873a925dd2159e52064418781af32d935b511802..0c161348cce6e4ef79c1129137038a478c1c5dbe 100644 (file)
@@ -276,7 +276,7 @@ static void
 runas_setup()
 {
 #ifdef HAVE_LOGIN_CAP_H
-    int error;
+    int error, flags;
     extern login_cap_t *lc;
 #endif
 
@@ -284,13 +284,18 @@ runas_setup()
 #ifdef HAVE_LOGIN_CAP_H
        if (def_flag(I_USE_LOGINCLASS)) {
            /*
-            * We don't have setusercontext()
-            * set the user since we may only
-            * want to set the effective uid.
+             * We don't have setusercontext() set the user since we
+             * may only want to set the effective uid.  Depending on
+             * sudoers and/or command line arguments we may not want
+             * setusercontext() to call initgroups().
             */
+           flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
+           if (!def_flag(I_PRESERVE_GROUPS))
+               flags |= LOGIN_SETGROUP;
+           else if (setgid(runas_pw->pw_gid))
+               perror("cannot set gid to runas gid");
            error = setusercontext(lc, runas_pw,
-               runas_pw->pw_uid,
-               LOGIN_SETGROUP|LOGIN_SETRESOURCES|LOGIN_SETPRIORITY);
+               runas_pw->pw_uid, flags);
            if (error)
                perror("unable to set user context");
        } else
@@ -300,10 +305,9 @@ runas_setup()
                perror("cannot set gid to runas gid");
 #ifdef HAVE_INITGROUPS
            /*
-            * Initialize group vector only if are
-            * going to run as a non-root user.
+            * Initialize group vector unless asked not to.
             */
-           if (strcmp(*user_runas, "root") != 0 &&
+           if (!def_flag(I_PRESERVE_GROUPS) &&
                initgroups(*user_runas, runas_pw->pw_gid) < 0)
                perror("cannot set group vector");
 #endif /* HAVE_INITGROUPS */
diff --git a/sudo.c b/sudo.c
index 7bb2295295931eb5bea86a8898399e3f83e72abc..b99b780ee95444cc4cc84528c8a4685b13aa4043 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -291,6 +291,10 @@ main(argc, argv, envp)
        exit(1);
     }
 
+    /* If given the -P option, set the "preserve_groups" flag. */
+    if (sudo_mode & MODE_PRESERVE_GROUPS)
+       def_flag(I_PRESERVE_GROUPS) = TRUE;
+
     /* If no command line args and "set_home" is not set, error out. */
     if ((sudo_mode & MODE_IMPLIED_SHELL) && !def_flag(I_SHELL_NOARGS))
        usage(1);
@@ -699,6 +703,9 @@ parse_args()
            case 'H':
                rval |= MODE_RESET_HOME;
                break;
+           case 'P':
+               rval |= MODE_PRESERVE_GROUPS;
+               break;
            case 'S':
                tgetpass_flags |= TGP_STDIN;
                break;
@@ -990,7 +997,7 @@ usage(exit_val)
 {
 
     (void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s",
-       "[-H] [-S] [-b] [-p prompt]\n            [-u username/#uid] ");
+       "[-H] [-P] [-S] [-b] [-p prompt]\n            [-u username/#uid] ");
 #ifdef HAVE_LOGIN_CAP_H
     (void) fprintf(stderr, "[-c class] ");
 #endif
diff --git a/sudo.h b/sudo.h
index 6d5367f1ff7e50fe8ccd8e622eef10145e3cd53b..942326be9fc216313846f6ce74c91223228869ea 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -93,18 +93,19 @@ struct sudo_user {
 /*
  * Various modes sudo can be in (based on arguments) in octal
  */
-#define MODE_RUN                 00001
-#define MODE_VALIDATE            00002
-#define MODE_INVALIDATE          00004
-#define MODE_KILL                00010
-#define MODE_VERSION             00020
-#define MODE_HELP                00040
-#define MODE_LIST                00100
-#define MODE_LISTDEFS            00200
-#define MODE_BACKGROUND          00400
-#define MODE_SHELL               01000
-#define MODE_IMPLIED_SHELL       02000
-#define MODE_RESET_HOME          04000
+#define MODE_RUN                 000001
+#define MODE_VALIDATE            000002
+#define MODE_INVALIDATE          000004
+#define MODE_KILL                000010
+#define MODE_VERSION             000020
+#define MODE_HELP                000040
+#define MODE_LIST                000100
+#define MODE_LISTDEFS            000200
+#define MODE_BACKGROUND          000400
+#define MODE_SHELL               001000
+#define MODE_IMPLIED_SHELL       002000
+#define MODE_RESET_HOME          004000
+#define MODE_PRESERVE_GROUPS     010000
 
 /*
  * Used with set_perms()
index 348f66f7945b860b60821f8f5b1afd6cfe72454f..819437fa96600dbe6a07e09d54df455625db9a58 100644 (file)
--- a/sudo.pod
+++ b/sudo.pod
@@ -42,8 +42,8 @@ sudo - execute a command as another user
 =head1 SYNOPSIS
 
 B<sudo> B<-V> | B<-h> | B<-l> | B<-L> | B<-v> | B<-k> | B<-K> | B<-s> |
-[ B<-H> ] [B<-S> ] [ B<-b> ] | [ B<-p> I<prompt> ] [ B<-c> I<class>|I<-> ]
-[ B<-a> I<auth_type> ]
+[ B<-H> ] [B<-P> ] [B<-S> ] [ B<-b> ] | [ B<-p> I<prompt> ]
+[ B<-c> I<class>|I<-> ] [ B<-a> I<auth_type> ]
 [ B<-u> I<username>|I<#uid> ] I<command>
 
 =head1 DESCRIPTION
@@ -183,6 +183,14 @@ The B<-H> (I<HOME>) option sets the C<HOME> environment variable
 to the homedir of the target user (root by default) as specified
 in passwd(5).  By default, B<sudo> does not modify C<HOME>.
 
+=item -P
+
+The B<-P> (I<preserve group vector>) option causes B<sudo> to preserve
+the user's group vector unaltered.  By default, B<sudo> will initialize
+the group vector to the list of groups the target user is in.
+The real and effective group IDs, however, are still set to match
+the target user.
+
 =item -S
 
 The B<-S> (I<stdin>) option causes B<sudo> to read the password from
index 623e987dd1f70af69511268151c25183a5a43d10..ac38250244b81904077a1facc659f6b3c7b8d7a0 100644 (file)
@@ -342,9 +342,17 @@ to disable this as it could be used to gather information on the
 location of executables that the normal user does not have access
 to.  The disadvantage is that if the executable is simply not in
 the user's C<PATH>, B<sudo> will tell the user that they are not
-allowed to run it, which can be confusing.  This flag is off by
+allowed to run it, which can be confusing.  This flag is I<off> by
 default.
 
+=item preserve_groups
+
+By default B<sudo> will initialize the group vector to the list of
+groups the target user is in.  When I<preserve_groups> is set, the
+user's existing group vector is left unaltered.  The real and
+effective group IDs, however, are still set to match the target
+user.  This flag is I<off> by default.
+
 =item fqdn
 
 Set this flag if you want to put fully qualified hostnames in the