diff --git a/Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch b/Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch new file mode 100644 index 0000000000000000000000000000000000000000..15d4538c6cc7ebc787f5f28006f72f0ccf78e6f3 --- /dev/null +++ b/Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch @@ -0,0 +1,199 @@ +From 807e17ceedf2500aeca67b37f62463ee112d63c4 Mon Sep 17 00:00:00 2001 +From: Todd C. Miller +Date: Mon, 09 Dec 2019 17:14:06 -0700 +Subject: [PATCH] Fix CVE-2019-19234 + +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 | 17 +++++++++++++++++ + doc/sudoers.mdoc.in | 16 ++++++++++++++++ + 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, 69 insertions(+), 2 deletions(-) + +diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in +index e2470b5..45a600f 100644 +--- a/doc/sudoers.man.in ++++ b/doc/sudoers.man.in +@@ -2869,6 +2869,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 2053b5d..6a511d9 100644 +--- a/doc/sudoers.mdoc.in ++++ b/doc/sudoers.mdoc.in +@@ -2698,6 +2698,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 07e3433..97eaf79 100644 +--- a/plugins/sudoers/def_data.c ++++ b/plugins/sudoers/def_data.c +@@ -494,6 +494,10 @@ struct sudo_defs_types sudo_defs_table[] = { + N_("Ignore case when matching group names"), + 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 65f10c3..55878c9 100644 +--- a/plugins/sudoers/def_data.h ++++ b/plugins/sudoers/def_data.h +@@ -226,6 +226,8 @@ + #define def_case_insensitive_user (sudo_defs_table[I_CASE_INSENSITIVE_USER].sd_un.flag) + #define I_CASE_INSENSITIVE_GROUP 113 + #define def_case_insensitive_group (sudo_defs_table[I_CASE_INSENSITIVE_GROUP].sd_un.flag) ++#define I_RUNAS_ALLOW_UNKNOWN_ID 114 ++#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 99d4360..cf0eead 100644 +--- a/plugins/sudoers/def_data.in ++++ b/plugins/sudoers/def_data.in +@@ -357,3 +357,6 @@ case_insensitive_user + case_insensitive_group + T_FLAG + "Ignore case when matching group names" ++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 4c8c262..d5b1d9c 100644 +--- a/plugins/sudoers/defaults.c ++++ b/plugins/sudoers/defaults.c +@@ -574,6 +574,7 @@ init_defaults(void) + def_sudoedit_checkdir = true; + def_iolog_mode = S_IRUSR|S_IWUSR; + def_fdexec = digest_only; ++ 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 1267949..b393d70 100644 +--- a/plugins/sudoers/sudoers.c ++++ b/plugins/sudoers/sudoers.c +@@ -101,6 +101,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; +@@ -332,6 +334,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. + */ +@@ -1124,12 +1142,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, NULL, NULL, &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) { +@@ -1155,12 +1176,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, NULL, NULL, &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) { +-- +1.8.3.1 + diff --git a/Fix-CVE-2019-19234-add-runas_check_shell-flag.patch b/Fix-CVE-2019-19234-add-runas_check_shell-flag.patch new file mode 100644 index 0000000000000000000000000000000000000000..d17604d31a524b14e13697034528019923e067ed --- /dev/null +++ b/Fix-CVE-2019-19234-add-runas_check_shell-flag.patch @@ -0,0 +1,485 @@ +From 1078336fb8769eb9e022d088f5b2db443bb775d6 Mon Sep 17 00:00:00 2001 +From: Todd C. Miller +Date: Mon, 09 Dec 2019 19:29:45 -0700 +Subject: [PATCH] Fix CVE-2019-19234 + +Add runas_check_shell flag to require a runas user to have a valid shell. +Not enabled by default. +--- + MANIFEST | 1 + + config.h.in | 3 + + configure | 26 +++++++++ + configure.ac | 6 +- + doc/sudoers.man.in | 22 +++++++ + doc/sudoers.mdoc.in | 20 +++++++ + include/sudo_compat.h | 11 ++++ + lib/util/Makefile.in | 12 ++++ + lib/util/getusershell.c | 138 ++++++++++++++++++++++++++++++++++++++++++++ + mkdep.pl | 2 +- + plugins/sudoers/check.c | 25 ++++++++ + plugins/sudoers/def_data.c | 4 ++ + plugins/sudoers/def_data.h | 2 + + plugins/sudoers/def_data.in | 3 + + plugins/sudoers/sudoers.c | 7 +++ + plugins/sudoers/sudoers.h | 1 + + 16 files changed, 281 insertions(+), 2 deletions(-) + create mode 100644 lib/util/getusershell.c + +diff --git a/MANIFEST b/MANIFEST +index 08d7f25..d883174 100644 +--- a/MANIFEST ++++ b/MANIFEST +@@ -111,6 +111,7 @@ lib/util/gethostname.c + lib/util/getline.c + lib/util/getopt_long.c + lib/util/gettime.c ++lib/util/getusershell.c + lib/util/gidlist.c + lib/util/glob.c + lib/util/inet_ntop.c +diff --git a/config.h.in b/config.h.in +index 9b83b12..c65a6f7 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -337,6 +337,9 @@ + /* Define to 1 if you have the `getuserattr' function. */ + #undef HAVE_GETUSERATTR + ++/* Define to 1 if you have the `getusershell' function. */ ++#undef HAVE_GETUSERSHELL ++ + /* Define to 1 if you have the `getutid' function. */ + #undef HAVE_GETUTID + +diff --git a/configure b/configure +index e1b5dbb..658768e 100755 +--- a/configure ++++ b/configure +@@ -19418,6 +19418,32 @@ done + fi + done + ++for ac_func in getusershell ++do : ++ ac_fn_c_check_func "$LINENO" "getusershell" "ac_cv_func_getusershell" ++if test "x$ac_cv_func_getusershell" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_GETUSERSHELL 1 ++_ACEOF ++ ++else ++ ++ case " $LIBOBJS " in ++ *" getusershell.$ac_objext "* ) ;; ++ *) LIBOBJS="$LIBOBJS getusershell.$ac_objext" ++ ;; ++esac ++ ++ ++ for _sym in sudo_getusershell; do ++ COMPAT_EXP="${COMPAT_EXP}${_sym} ++" ++ done ++ ++ ++fi ++done ++ + for ac_func in reallocarray + do : + ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray" +diff --git a/configure.ac b/configure.ac +index 962a032..c6d6c55 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,7 +1,7 @@ + dnl + dnl Use the top-level autogen.sh script to generate configure and config.h.in + dnl +-dnl Copyright (c) 1994-1996,1998-2018 Todd C. Miller ++dnl Copyright (c) 1994-1996,1998-2019 Todd C. Miller + dnl + AC_PREREQ([2.59]) + AC_INIT([sudo], [1.8.27], [https://bugzilla.sudo.ws/], [sudo]) +@@ -2839,6 +2839,10 @@ AC_CHECK_FUNCS([vsyslog], [], [ + SUDO_APPEND_COMPAT_EXP(sudo_vsyslog) + COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }vsyslog_test" + ]) ++AC_CHECK_FUNCS([getusershell], [], [ ++ AC_LIBOBJ(getusershell) ++ SUDO_APPEND_COMPAT_EXP(sudo_getusershell) ++]) + dnl + dnl 4.4BSD-based systems can force the password or group file to be held open + dnl +diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in +index 45a600f..8a97a55 100644 +--- a/doc/sudoers.man.in ++++ b/doc/sudoers.man.in +@@ -2886,6 +2886,28 @@ Older versions of + \fBsudo\fR + always allowed matching of unknown user and group IDs. + .TP 18n ++runas_check_shell ++.br ++If enabled, ++\fBsudo\fR ++will only run commands as a user whose shell appears in the ++\fI/etc/shells\fR ++file, even if the invoking user's ++\fRRunas_List\fR ++would otherwise permit it. ++If no ++\fI/etc/shells\fR ++file is present, a system-dependent list of built-in default shells is used. ++On many operating systems, system users such as ++\(lqbin\(rq, ++do not have a valid shell and this flag can be used to prevent ++commands from being run as those users. ++This flag is ++\fIoff\fR ++by default. ++.sp ++This setting is only supported by version 1.8.30 or higher. ++.TP 18n + runaspw + If set, + \fBsudo\fR +diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in +index 6a511d9..ec7ed4f 100644 +--- a/doc/sudoers.mdoc.in ++++ b/doc/sudoers.mdoc.in +@@ -2714,6 +2714,26 @@ 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 runas_check_shell ++If enabled, ++.Nm sudo ++will only run commands as a user whose shell appears in the ++.Pa /etc/shells ++file, even if the invoking user's ++.Li Runas_List ++would otherwise permit it. ++If no ++.Pa /etc/shells ++file is present, a system-dependent list of built-in default shells is used. ++On many operating systems, system users such as ++.Dq bin , ++do not have a valid shell and this flag can be used to prevent ++commands from being run as those users. ++This flag is ++.Em off ++by default. ++.Pp ++This setting is only supported by version 1.8.30 or higher. + .It runaspw + If set, + .Nm sudo +diff --git a/include/sudo_compat.h b/include/sudo_compat.h +index 5c32840..3faa167 100644 +--- a/include/sudo_compat.h ++++ b/include/sudo_compat.h +@@ -409,6 +409,17 @@ __dso_public ssize_t sudo_getline(char **bufp, size_t *bufsizep, FILE *fp); + # undef getline + # define getline(_a, _b, _c) sudo_getline((_a), (_b), (_c)) + #endif /* HAVE_GETLINE */ ++#ifndef HAVE_GETUSERSHELL ++__dso_public char *sudo_getusershell(void); ++# undef getusershell ++# define getusershell() sudo_getusershell() ++__dso_public void sudo_setusershell(void); ++# undef setusershell ++# define setusershell() sudo_setusershell() ++__dso_public void sudo_endusershell(void); ++# undef endusershell ++# define endusershell() sudo_endusershell() ++#endif /* HAVE_GETUSERSHELL */ + #ifndef HAVE_UTIMENSAT + __dso_public int sudo_utimensat(int fd, const char *file, const struct timespec *times, int flag); + # undef utimensat +diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in +index cadfcf2..aa21ac9 100644 +--- a/lib/util/Makefile.in ++++ b/lib/util/Makefile.in +@@ -630,6 +630,18 @@ gettime.i: $(srcdir)/gettime.c $(incdir)/compat/stdbool.h \ + $(CC) -E -o $@ $(CPPFLAGS) $< + gettime.plog: gettime.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gettime.c --i-file $< --output-file $@ ++getusershell.lo: $(srcdir)/getusershell.c $(incdir)/compat/stdbool.h \ ++ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ ++ $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \ ++ $(incdir)/sudo_util.h $(top_builddir)/config.h ++ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/getusershell.c ++getusershell.i: $(srcdir)/getusershell.c $(incdir)/compat/stdbool.h \ ++ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ ++ $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \ ++ $(incdir)/sudo_util.h $(top_builddir)/config.h ++ $(CC) -E -o $@ $(CPPFLAGS) $< ++getusershell.plog: getusershell.i ++ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getusershell.c --i-file $< --output-file $@ + gidlist.lo: $(srcdir)/gidlist.c $(incdir)/compat/stdbool.h \ + $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ +diff --git a/lib/util/getusershell.c b/lib/util/getusershell.c +new file mode 100644 +index 0000000..6aeae3b +--- /dev/null ++++ b/lib/util/getusershell.c +@@ -0,0 +1,138 @@ ++/* ++ * SPDX-License-Identifier: ISC ++ * ++ * Copyright (c) 2019 Todd C. Miller ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * This is an open source non-commercial project. Dear PVS-Studio, please check it. ++ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define DEFAULT_TEXT_DOMAIN "sudo" ++#include "sudo_gettext.h" /* must be included before sudo_compat.h */ ++ ++#include "sudo_compat.h" ++#include "sudo_debug.h" ++#include "sudo_util.h" ++ ++static char **allowed_shells, **current_shell; ++static char *default_shells[] = { ++ "/bin/sh", ++ "/bin/ksh", ++ "/bin/ksh93", ++ "/bin/bash", ++ "/bin/dash", ++ "/bin/zsh", ++ "/bin/csh", ++ "/bin/tcsh", ++ NULL ++}; ++ ++static char ** ++read_shells(void) ++{ ++ size_t maxshells = 16, nshells = 0; ++ size_t linesize = 0; ++ char *line = NULL; ++ FILE *fp; ++ debug_decl(read_shells, SUDO_DEBUG_UTIL) ++ ++ if ((fp = fopen("/etc/shells", "r")) == NULL) ++ goto bad; ++ ++ free(allowed_shells); ++ allowed_shells = reallocarray(NULL, maxshells, sizeof(char *)); ++ if (allowed_shells == NULL) ++ goto bad; ++ ++ while (sudo_parseln(&line, &linesize, NULL, fp, PARSELN_CONT_IGN) != -1) { ++ if (nshells + 1 >= maxshells) { ++ char **new_shells; ++ ++ new_shells = reallocarray(NULL, maxshells + 16, sizeof(char *)); ++ if (new_shells == NULL) ++ goto bad; ++ allowed_shells = new_shells; ++ maxshells += 16; ++ } ++ if ((allowed_shells[nshells] = strdup(line)) == NULL) ++ goto bad; ++ nshells++; ++ } ++ allowed_shells[nshells] = NULL; ++ ++ free(line); ++ fclose(fp); ++ debug_return_ptr(allowed_shells); ++bad: ++ free(line); ++ if (fp != NULL) ++ fclose(fp); ++ while (nshells != 0) ++ free(allowed_shells[--nshells]); ++ free(allowed_shells); ++ allowed_shells = NULL; ++ debug_return_ptr(default_shells); ++} ++ ++void ++sudo_setusershell(void) ++{ ++ debug_decl(setusershell, SUDO_DEBUG_UTIL) ++ ++ current_shell = read_shells(); ++ ++ debug_return; ++} ++ ++void ++sudo_endusershell(void) ++{ ++ debug_decl(endusershell, SUDO_DEBUG_UTIL) ++ ++ if (allowed_shells != NULL) { ++ char **shell; ++ ++ for (shell = allowed_shells; *shell != NULL; shell++) ++ free(*shell); ++ free(allowed_shells); ++ allowed_shells = NULL; ++ } ++ current_shell = NULL; ++ ++ debug_return; ++} ++ ++char * ++sudo_getusershell(void) ++{ ++ debug_decl(getusershell, SUDO_DEBUG_UTIL) ++ ++ if (current_shell == NULL) ++ current_shell = read_shells(); ++ ++ debug_return_str(*current_shell++); ++} +diff --git a/mkdep.pl b/mkdep.pl +index 2040320..02b5f41 100755 +--- a/mkdep.pl ++++ b/mkdep.pl +@@ -112,7 +112,7 @@ sub mkdep { + # XXX - fill in AUTH_OBJS from contents of the auth dir instead + $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; + $makefile =~ s:\@DIGEST\@:digest.lo digest_openssl.lo digest_gcrypt.lo:; +- $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_uniform.lo closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getline.lo getopt_long.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo strtonum.lo utimens.lo vsyslog.lo pipe2.lo:; ++ $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_uniform.lo closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getline.lo getopt_long.lo getusershell.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo strtonum.lo utimens.lo vsyslog.lo pipe2.lo:; + + # Parse OBJS lines + my %objs; +diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c +index 92f859c..31d2615 100644 +--- a/plugins/sudoers/check.c ++++ b/plugins/sudoers/check.c +@@ -331,3 +331,28 @@ get_authpw(int mode) + + debug_return_ptr(pw); + } ++ ++/* ++ * Returns true if the specified shell is allowed by /etc/shells, else false. ++ */ ++bool ++check_user_shell(const struct passwd *pw) ++{ ++ const char *shell; ++ debug_decl(check_user_shell, SUDOERS_DEBUG_AUTH) ++ ++ if (!def_runas_check_shell) ++ debug_return_bool(true); ++ ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "%s: checking /etc/shells for %s", __func__, pw->pw_shell); ++ ++ setusershell(); ++ while ((shell = getusershell()) != NULL) { ++ if (strcmp(shell, pw->pw_shell) == 0) ++ debug_return_bool(true); ++ } ++ endusershell(); ++ ++ debug_return_bool(false); ++} +diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c +index 97eaf79..7b111f8 100644 +--- a/plugins/sudoers/def_data.c ++++ b/plugins/sudoers/def_data.c +@@ -498,6 +498,10 @@ struct sudo_defs_types sudo_defs_table[] = { + N_("Allow the use of unknown runas user and/or group ID"), + NULL, + }, { ++ "runas_check_shell", T_FLAG, ++ N_("Only permit running commands as a user with a valid shell"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h +index 55878c9..50725e6 100644 +--- a/plugins/sudoers/def_data.h ++++ b/plugins/sudoers/def_data.h +@@ -228,6 +228,8 @@ + #define def_case_insensitive_group (sudo_defs_table[I_CASE_INSENSITIVE_GROUP].sd_un.flag) + #define I_RUNAS_ALLOW_UNKNOWN_ID 114 + #define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag) ++#define I_RUNAS_CHECK_SHELL 115 ++#define def_runas_check_shell (sudo_defs_table[I_RUNAS_CHECK_SHELL].sd_un.flag) + + enum def_tuple { + never, +diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in +index cf0eead..bb81d8b 100644 +--- a/plugins/sudoers/def_data.in ++++ b/plugins/sudoers/def_data.in +@@ -360,3 +360,6 @@ case_insensitive_group + runas_allow_unknown_id + T_FLAG + "Allow the use of unknown runas user and/or group ID" ++runas_check_shell ++ T_FLAG ++ "Only permit running commands as a user with a valid shell" +diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c +index b393d70..a791942 100644 +--- a/plugins/sudoers/sudoers.c ++++ b/plugins/sudoers/sudoers.c +@@ -390,6 +390,13 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], + goto bad; + } + ++ /* Check runas user's shell. */ ++ if (!check_user_shell(runas_pw)) { ++ log_warningx(SLOG_RAW_MSG, N_("invalid shell for user %s: %s"), ++ runas_pw->pw_name, runas_pw->pw_shell); ++ goto bad; ++ } ++ + /* + * We don't reset the environment for sudoedit or if the user + * specified the -E command line flag and they have setenv privs. +diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h +index 28dbbb3..d33c4ef 100644 +--- a/plugins/sudoers/sudoers.h ++++ b/plugins/sudoers/sudoers.h +@@ -250,6 +250,7 @@ int find_path(const char *infile, char **outfile, struct stat *sbp, + + /* check.c */ + int check_user(int validate, int mode); ++bool check_user_shell(const struct passwd *pw); + bool user_is_exempt(void); + + /* prompt.c */ +-- +1.8.3.1 + diff --git a/sudo.spec b/sudo.spec index f33d64b80e1774305576f3b62159306e79e43ab8..969380e3b4787f83dc05af01b27f18ccc9950b1d 100644 --- a/sudo.spec +++ b/sudo.spec @@ -1,6 +1,6 @@ Name: sudo Version: 1.8.27 -Release: 3 +Release: 4 Summary: Allows restricted root access for specified users License: ISC URL: http://www.courtesan.com/sudo/ @@ -12,6 +12,8 @@ Source3: sudo-i Patch6000: sudo_minus_1_uid.patch Patch6001: strtoid_minus_1_test_fix.patch +Patch6002: Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch +Patch6003: Fix-CVE-2019-19234-add-runas_check_shell-flag.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: pam @@ -147,6 +149,9 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i %exclude %{_pkgdocdir}/ChangeLog %changelog +* Mon Jan 20 2020 openEuler Buildteam - 1.8.27-4 +- fix CVE-2019-19232 and CVE-2019-19234 + * Sat Jan 11 2020 openEuler Buildteam - 1.8.27-3 - clean code