diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index 656039e78..c7e7004b0 100644 --- a/doc/sudoers.man.in +++ b/doc/sudoers.man.in @@ -25,7 +25,7 @@ .nr BA @BAMAN@ .nr LC @LCMAN@ .nr PS @PSMAN@ -.TH "SUDOERS" "@mansectform@" "December 6, 2019" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDOERS" "@mansectform@" "December 8, 2019" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -2952,6 +2952,23 @@ This flag is \fIoff\fR by default. .TP 18n +runas_allow_unknown_id +If enabled, allow matching of runas user and group IDs that are +not present in the password or group databases. +In addition to explicitly matching unknown user or group IDs in a +\fRRunas_List\fR, +this option also allows the +\fBALL\fR +alias to match unknown IDs. +This flag is +\fIoff\fR +by default. +.sp +This setting is only supported by version 1.8.30 or higher. +Older versions of +\fBsudo\fR +always allowed matching of unknown user and group IDs. +.TP 18n runaspw If set, \fBsudo\fR diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index 3d70c8db1..7e2b1f3ff 100644 --- a/doc/sudoers.mdoc.in +++ b/doc/sudoers.mdoc.in @@ -24,7 +24,7 @@ .nr BA @BAMAN@ .nr LC @LCMAN@ .nr PS @PSMAN@ -.Dd December 6, 2019 +.Dd December 8, 2019 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -2778,6 +2778,22 @@ when running a command or editing a file. This flag is .Em off by default. +.It runas_allow_unknown_id +If enabled, allow matching of runas user and group IDs that are +not present in the password or group databases. +In addition to explicitly matching unknown user or group IDs in a +.Li Runas_List , +this option also allows the +.Sy ALL +alias to match unknown IDs. +This flag is +.Em off +by default. +.Pp +This setting is only supported by version 1.8.30 or higher. +Older versions of +.Nm sudo +always allowed matching of unknown user and group IDs. .It runaspw If set, .Nm sudo diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c index ebbbc1689..6548eb832 100644 --- a/plugins/sudoers/def_data.c +++ b/plugins/sudoers/def_data.c @@ -525,6 +525,10 @@ struct sudo_defs_types sudo_defs_table[] = { "log_server_peer_key", T_STR|T_BOOL|T_PATH, N_("Path to the sudoers private key file: %s"), NULL, + }, { + "runas_allow_unknown_id", T_FLAG, + N_("Allow the use of unknown runas user and/or group ID"), + NULL, }, { NULL, 0, NULL } diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h index 396f2b28d..063644d09 100644 --- a/plugins/sudoers/def_data.h +++ b/plugins/sudoers/def_data.h @@ -242,6 +242,8 @@ #define def_log_server_peer_cert (sudo_defs_table[I_LOG_SERVER_PEER_CERT].sd_un.str) #define I_LOG_SERVER_PEER_KEY 121 #define def_log_server_peer_key (sudo_defs_table[I_LOG_SERVER_PEER_KEY].sd_un.str) +#define I_RUNAS_ALLOW_UNKNOWN_ID 122 +#define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag) enum def_tuple { never, diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in index 495a22d7a..dbb68ec9b 100644 --- a/plugins/sudoers/def_data.in +++ b/plugins/sudoers/def_data.in @@ -381,3 +381,6 @@ log_server_peer_cert log_server_peer_key T_STR|T_BOOL|T_PATH "Path to the sudoers private key file: %s" +runas_allow_unknown_id + T_FLAG + "Allow the use of unknown runas user and/or group ID" diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index 1d6f22ed2..1af8cd307 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -537,6 +537,7 @@ init_defaults(void) def_fdexec = digest_only; def_log_allowed = true; def_log_denied = true; + def_runas_allow_unknown_id = false; /* Syslog options need special care since they both strings and ints */ #if (LOGGING & SLOG_SYSLOG) diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 1af65a7b7..3fcac02aa 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -106,6 +106,8 @@ static char *prev_user; static char *runas_user; static char *runas_group; static struct sudo_nss_list *snl; +static bool unknown_runas_uid; +static bool unknown_runas_gid; #ifdef __linux__ static struct rlimit nproclimit; @@ -376,6 +378,22 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], } } + /* Defer uid/gid checks until after defaults have been updated. */ + if (unknown_runas_uid && !def_runas_allow_unknown_id) { + audit_failure(NewArgc, NewArgv, N_("unknown user: %s"), + runas_pw->pw_name); + sudo_warnx(U_("unknown user: %s"), runas_pw->pw_name); + goto done; + } + if (runas_gr != NULL) { + if (unknown_runas_gid && !def_runas_allow_unknown_id) { + audit_failure(NewArgc, NewArgv, N_("unknown group: %s"), + runas_gr->gr_name); + sudo_warnx(U_("unknown group: %s"), runas_gr->gr_name); + goto done; + } + } + /* * Look up the timestamp dir owner if one is specified. */ @@ -1192,12 +1210,15 @@ set_runaspw(const char *user, bool quiet) struct passwd *pw = NULL; debug_decl(set_runaspw, SUDOERS_DEBUG_PLUGIN) + unknown_runas_uid = false; if (*user == '#') { const char *errstr; uid_t uid = sudo_strtoid(user + 1, &errstr); if (errstr == NULL) { - if ((pw = sudo_getpwuid(uid)) == NULL) + if ((pw = sudo_getpwuid(uid)) == NULL) { + unknown_runas_uid = true; pw = sudo_fakepwnam(user, user_gid); + } } } if (pw == NULL) { @@ -1223,12 +1244,15 @@ set_runasgr(const char *group, bool quiet) struct group *gr = NULL; debug_decl(set_runasgr, SUDOERS_DEBUG_PLUGIN) + unknown_runas_gid = false; if (*group == '#') { const char *errstr; gid_t gid = sudo_strtoid(group + 1, &errstr); if (errstr == NULL) { - if ((gr = sudo_getgrgid(gid)) == NULL) + if ((gr = sudo_getgrgid(gid)) == NULL) { + unknown_runas_gid = true; gr = sudo_fakegrnam(group); + } } } if (gr == NULL) {