From df8f06609c2c7841a30f40fbb706c071240177a8 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 9 Dec 2019 17:14:06 -0700 Subject: [PATCH] Add a new flag "allow_unknown_runas_id" to control matching of unknown IDs. Previous, sudo would always allow unknown user or group IDs if the sudoers entry permitted it. This included the "ALL" alias. With this change, the admin must explicitly enable support for unknown IDs. --- doc/sudoers.man.in | 19 ++++++++++++++++++- doc/sudoers.mdoc.in | 18 +++++++++++++++++- plugins/sudoers/def_data.c | 4 ++++ plugins/sudoers/def_data.h | 2 ++ plugins/sudoers/def_data.in | 3 +++ plugins/sudoers/defaults.c | 1 + plugins/sudoers/sudoers.c | 28 ++++++++++++++++++++++++++-- 7 files changed, 71 insertions(+), 4 deletions(-) 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) {