From: Todd C. Miller Date: Sat, 15 Dec 2001 00:24:27 +0000 (+0000) Subject: Add new sudoers option "preserve_groups". Previously sudo would not X-Git-Tag: SUDO_1_6_4~85 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=761b119e2eaf89090086ea680fc1d65208b5bdcb;p=sudo Add new sudoers option "preserve_groups". Previously sudo would not 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. --- diff --git a/def_data.c b/def_data.c index 6c1a4a43f..ec02d8871 100644 --- a/def_data.c +++ b/def_data.c @@ -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" diff --git a/def_data.h b/def_data.h index 89c1a30e2..dcf2cc8ef 100644 --- a/def_data.h +++ b/def_data.h @@ -32,26 +32,27 @@ #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 diff --git a/def_data.in b/def_data.in index d1f3313a8..3fac37342 100644 --- a/def_data.in +++ b/def_data.in @@ -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" diff --git a/set_perms.c b/set_perms.c index 873a925dd..0c161348c 100644 --- a/set_perms.c +++ b/set_perms.c @@ -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 7bb229529..b99b780ee 100644 --- 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 6d5367f1f..942326be9 100644 --- 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() diff --git a/sudo.pod b/sudo.pod index 348f66f79..819437fa9 100644 --- a/sudo.pod +++ b/sudo.pod @@ -42,8 +42,8 @@ sudo - execute a command as another user =head1 SYNOPSIS B 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 ] [ B<-c> I|I<-> ] -[ B<-a> I ] +[ B<-H> ] [B<-P> ] [B<-S> ] [ B<-b> ] | [ B<-p> I ] +[ B<-c> I|I<-> ] [ B<-a> I ] [ B<-u> I|I<#uid> ] I =head1 DESCRIPTION @@ -183,6 +183,14 @@ The B<-H> (I) option sets the C environment variable to the homedir of the target user (root by default) as specified in passwd(5). By default, B does not modify C. +=item -P + +The B<-P> (I) option causes B to preserve +the user's group vector unaltered. By default, B 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) option causes B to read the password from diff --git a/sudoers.pod b/sudoers.pod index 623e987dd..ac3825024 100644 --- a/sudoers.pod +++ b/sudoers.pod @@ -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, B 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 by default. +=item preserve_groups + +By default B will initialize the group vector to the list of +groups the target user is in. When I 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 by default. + =item fqdn Set this flag if you want to put fully qualified hostnames in the