}, {
"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"
#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
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"
runas_setup()
{
#ifdef HAVE_LOGIN_CAP_H
- int error;
+ int error, flags;
extern login_cap_t *lc;
#endif
#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
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 */
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);
case 'H':
rval |= MODE_RESET_HOME;
break;
+ case 'P':
+ rval |= MODE_PRESERVE_GROUPS;
+ break;
case 'S':
tgetpass_flags |= TGP_STDIN;
break;
{
(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
/*
* 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()
=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
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
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