9d1b3f
diff -up ./doc/sudoers.man.in.CVE-2019-19232 ./doc/sudoers.man.in
9d1b3f
--- ./doc/sudoers.man.in.CVE-2019-19232	2019-10-28 13:28:52.000000000 +0100
9d1b3f
+++ ./doc/sudoers.man.in	2020-01-14 15:34:46.908027286 +0100
9d1b3f
@@ -2942,6 +2942,23 @@ This flag is
9d1b3f
 \fIoff\fR
9d1b3f
 by default.
9d1b3f
 .TP 18n
9d1b3f
+runas_allow_unknown_id
9d1b3f
+If enabled, allow matching of runas user and group IDs that are
9d1b3f
+not present in the password or group databases.
9d1b3f
+In addition to explicitly matching unknown user or group IDs in a
9d1b3f
+\fRRunas_List\fR,
9d1b3f
+this option also allows the
9d1b3f
+\fBALL\fR
9d1b3f
+alias to match unknown IDs.
9d1b3f
+This flag is
9d1b3f
+\fIoff\fR
9d1b3f
+by default.
9d1b3f
+.sp
9d1b3f
+This setting is only supported by version 1.8.29 or higher.
9d1b3f
+Older versions of
9d1b3f
+\fBsudo\fR
9d1b3f
+always allowed matching of unknown user and group IDs.
9d1b3f
+.TP 18n
9d1b3f
 runaspw
9d1b3f
 If set,
9d1b3f
 \fBsudo\fR
9d1b3f
diff -up ./doc/sudoers.mdoc.in.CVE-2019-19232 ./doc/sudoers.mdoc.in
9d1b3f
--- ./doc/sudoers.mdoc.in.CVE-2019-19232	2019-10-28 13:28:52.000000000 +0100
9d1b3f
+++ ./doc/sudoers.mdoc.in	2020-01-14 15:34:46.908027286 +0100
9d1b3f
@@ -2768,6 +2768,22 @@ when running a command or editing a file
9d1b3f
 This flag is
9d1b3f
 .Em off
9d1b3f
 by default.
9d1b3f
+.It runas_allow_unknown_id
9d1b3f
+If enabled, allow matching of runas user and group IDs that are
9d1b3f
+not present in the password or group databases.
9d1b3f
+In addition to explicitly matching unknown user or group IDs in a
9d1b3f
+.Li Runas_List ,
9d1b3f
+this option also allows the
9d1b3f
+.Sy ALL
9d1b3f
+alias to match unknown IDs.
9d1b3f
+This flag is
9d1b3f
+.Em off
9d1b3f
+by default.
9d1b3f
+.Pp
9d1b3f
+This setting is only supported by version 1.8.29 or higher.
9d1b3f
+Older versions of
9d1b3f
+.Nm sudo
9d1b3f
+always allowed matching of unknown user and group IDs.
9d1b3f
 .It runaspw
9d1b3f
 If set,
9d1b3f
 .Nm sudo
9d1b3f
diff -up ./plugins/sudoers/defaults.c.CVE-2019-19232 ./plugins/sudoers/defaults.c
9d1b3f
--- ./plugins/sudoers/defaults.c.CVE-2019-19232	2020-01-14 15:34:46.902027246 +0100
9d1b3f
+++ ./plugins/sudoers/defaults.c	2020-01-14 15:34:46.909027293 +0100
9d1b3f
@@ -581,6 +581,7 @@ init_defaults(void)
9d1b3f
     def_fdexec = digest_only;
9d1b3f
     def_log_allowed = true;
9d1b3f
     def_log_denied = true;
9d1b3f
+    def_runas_allow_unknown_id = false;
9d1b3f
 
9d1b3f
     /* Syslog options need special care since they both strings and ints */
9d1b3f
 #if (LOGGING & SLOG_SYSLOG)
9d1b3f
diff -up ./plugins/sudoers/def_data.c.CVE-2019-19232 ./plugins/sudoers/def_data.c
9d1b3f
--- ./plugins/sudoers/def_data.c.CVE-2019-19232	2020-01-14 15:34:46.908027286 +0100
9d1b3f
+++ ./plugins/sudoers/def_data.c	2020-01-14 15:40:19.441555509 +0100
9d1b3f
@@ -514,6 +514,10 @@ struct sudo_defs_types sudo_defs_table[]
9d1b3f
 	N_("Don't fork and wait for the command to finish, just exec it"),
9d1b3f
 	NULL,
9d1b3f
     }, {
9d1b3f
+	"runas_allow_unknown_id", T_FLAG,
9d1b3f
+	N_("Allow the use of unknown runas user and/or group ID"),
9d1b3f
+	NULL,
9d1b3f
+    }, {
9d1b3f
 	NULL, 0, NULL
9d1b3f
     }
9d1b3f
 };
9d1b3f
diff -up ./plugins/sudoers/def_data.h.CVE-2019-19232 ./plugins/sudoers/def_data.h
9d1b3f
--- ./plugins/sudoers/def_data.h.CVE-2019-19232	2020-01-14 15:34:46.909027293 +0100
9d1b3f
+++ ./plugins/sudoers/def_data.h	2020-01-14 15:41:33.658012401 +0100
9d1b3f
@@ -236,6 +236,8 @@
9d1b3f
 #define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag)
9d1b3f
 #define I_CMND_NO_WAIT          118
9d1b3f
 #define def_cmnd_no_wait        (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag)
9d1b3f
+#define I_RUNAS_ALLOW_UNKNOWN_ID 119
9d1b3f
+#define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag)
9d1b3f
 
9d1b3f
 enum def_tuple {
9d1b3f
 	never,
9d1b3f
diff -up ./plugins/sudoers/def_data.in.CVE-2019-19232 ./plugins/sudoers/def_data.in
9d1b3f
--- ./plugins/sudoers/def_data.in.CVE-2019-19232	2020-01-14 15:34:46.909027293 +0100
9d1b3f
+++ ./plugins/sudoers/def_data.in	2020-01-14 15:42:42.176481484 +0100
9d1b3f
@@ -372,3 +372,6 @@ legacy_group_processing
9d1b3f
 cmnd_no_wait
9d1b3f
 	T_FLAG
9d1b3f
 	"Don't fork and wait for the command to finish, just exec it"
9d1b3f
+runas_allow_unknown_id
9d1b3f
+	T_FLAG
9d1b3f
+	"Allow the use of unknown runas user and/or group ID"
9d1b3f
diff -up ./plugins/sudoers/sudoers.c.CVE-2019-19232 ./plugins/sudoers/sudoers.c
9d1b3f
--- ./plugins/sudoers/sudoers.c.CVE-2019-19232	2020-01-14 15:34:46.905027266 +0100
9d1b3f
+++ ./plugins/sudoers/sudoers.c	2020-01-14 15:34:46.910027299 +0100
9d1b3f
@@ -105,6 +105,8 @@ static char *prev_user;
9d1b3f
 static char *runas_user;
9d1b3f
 static char *runas_group;
9d1b3f
 static struct sudo_nss_list *snl;
9d1b3f
+static bool unknown_runas_uid;
9d1b3f
+static bool unknown_runas_gid;
9d1b3f
 
9d1b3f
 #ifdef __linux__
9d1b3f
 static struct rlimit nproclimit;
9d1b3f
@@ -354,6 +356,22 @@ sudoers_policy_main(int argc, char * con
9d1b3f
 	}
9d1b3f
     }
9d1b3f
 
9d1b3f
+    /* Defer uid/gid checks until after defaults have been updated. */
9d1b3f
+    if (unknown_runas_uid && !def_runas_allow_unknown_id) {
9d1b3f
+	audit_failure(NewArgc, NewArgv, N_("unknown user: %s"),
9d1b3f
+	    runas_pw->pw_name);
9d1b3f
+	sudo_warnx(U_("unknown user: %s"), runas_pw->pw_name);
9d1b3f
+	goto done;
9d1b3f
+    }
9d1b3f
+    if (runas_gr != NULL) {
9d1b3f
+	if (unknown_runas_gid && !def_runas_allow_unknown_id) {
9d1b3f
+	    audit_failure(NewArgc, NewArgv, N_("unknown group: %s"),
9d1b3f
+		runas_gr->gr_name);
9d1b3f
+	    sudo_warnx(U_("unknown group: %s"), runas_gr->gr_name);
9d1b3f
+	    goto done;
9d1b3f
+	}
9d1b3f
+    }
9d1b3f
+
9d1b3f
     /*
9d1b3f
      * Look up the timestamp dir owner if one is specified.
9d1b3f
      */
9d1b3f
@@ -1167,12 +1185,15 @@ set_runaspw(const char *user, bool quiet
9d1b3f
     struct passwd *pw = NULL;
9d1b3f
     debug_decl(set_runaspw, SUDOERS_DEBUG_PLUGIN)
9d1b3f
 
9d1b3f
+    unknown_runas_uid = false;
9d1b3f
     if (*user == '#') {
9d1b3f
 	const char *errstr;
9d1b3f
 	uid_t uid = sudo_strtoid(user + 1, &errstr);
9d1b3f
 	if (errstr == NULL) {
9d1b3f
-	    if ((pw = sudo_getpwuid(uid)) == NULL)
9d1b3f
+	    if ((pw = sudo_getpwuid(uid)) == NULL) {
9d1b3f
+		unknown_runas_uid = true;
9d1b3f
 		pw = sudo_fakepwnam(user, user_gid);
9d1b3f
+	    }
9d1b3f
 	}
9d1b3f
     }
9d1b3f
     if (pw == NULL) {
9d1b3f
@@ -1198,12 +1219,15 @@ set_runasgr(const char *group, bool quie
9d1b3f
     struct group *gr = NULL;
9d1b3f
     debug_decl(set_runasgr, SUDOERS_DEBUG_PLUGIN)
9d1b3f
 
9d1b3f
+    unknown_runas_gid = false;
9d1b3f
     if (*group == '#') {
9d1b3f
 	const char *errstr;
9d1b3f
 	gid_t gid = sudo_strtoid(group + 1, &errstr);
9d1b3f
 	if (errstr == NULL) {
9d1b3f
-	    if ((gr = sudo_getgrgid(gid)) == NULL)
9d1b3f
+	    if ((gr = sudo_getgrgid(gid)) == NULL) {
9d1b3f
+		unknown_runas_gid = true;
9d1b3f
 		gr = sudo_fakegrnam(group);
9d1b3f
+	    }
9d1b3f
 	}
9d1b3f
     }
9d1b3f
     if (gr == NULL) {