diff --git a/Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch b/Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch deleted file mode 100644 index 15d4538c6cc7ebc787f5f28006f72f0ccf78e6f3..0000000000000000000000000000000000000000 --- a/Fix-CVE-2019-19232-control-matching-of-unknown-IDs.patch +++ /dev/null @@ -1,199 +0,0 @@ -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 deleted file mode 100644 index d17604d31a524b14e13697034528019923e067ed..0000000000000000000000000000000000000000 --- a/Fix-CVE-2019-19234-add-runas_check_shell-flag.patch +++ /dev/null @@ -1,485 +0,0 @@ -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/strtoid_minus_1_test_fix.patch b/strtoid_minus_1_test_fix.patch deleted file mode 100644 index cba289e072de5ea790397feeda5845b5a748f1ae..0000000000000000000000000000000000000000 --- a/strtoid_minus_1_test_fix.patch +++ /dev/null @@ -1,96 +0,0 @@ -diff -r fcd7a6d8330e lib/util/regress/atofoo/atofoo_test.c ---- a/lib/util/regress/atofoo/atofoo_test.c Fri Jan 11 13:31:15 2019 -0700 -+++ b/lib/util/regress/atofoo/atofoo_test.c Thu Oct 10 14:02:30 2019 -0600 -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2014 Todd C. Miller -+ * Copyright (c) 2014-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 -@@ -24,6 +24,7 @@ - #else - # include "compat/stdbool.h" - #endif -+#include - - #include "sudo_compat.h" - #include "sudo_util.h" -@@ -78,15 +79,20 @@ static struct strtoid_data { - id_t id; - const char *sep; - const char *ep; -+ int errnum; - } strtoid_data[] = { -- { "0,1", 0, ",", "," }, -- { "10", 10, NULL, NULL }, -- { "-2", -2, NULL, NULL }, -+ { "0,1", 0, ",", ",", 0 }, -+ { "10", 10, NULL, NULL, 0 }, -+ { "-1", 0, NULL, NULL, EINVAL }, -+ { "4294967295", 0, NULL, NULL, EINVAL }, -+ { "4294967296", 0, NULL, NULL, ERANGE }, -+ { "-2147483649", 0, NULL, NULL, ERANGE }, -+ { "-2", -2, NULL, NULL, 0 }, - #if SIZEOF_ID_T != SIZEOF_LONG_LONG -- { "-2", (id_t)4294967294U, NULL, NULL }, -+ { "-2", (id_t)4294967294U, NULL, NULL, 0 }, - #endif -- { "4294967294", (id_t)4294967294U, NULL, NULL }, -- { NULL, 0, NULL, NULL } -+ { "4294967294", (id_t)4294967294U, NULL, NULL, 0 }, -+ { NULL, 0, NULL, NULL, 0 } - }; - - static int -@@ -102,11 +108,23 @@ test_strtoid(int *ntests) - (*ntests)++; - errstr = "some error"; - value = sudo_strtoid(d->idstr, d->sep, &ep, &errstr); -- if (errstr != NULL) { -- if (d->id != (id_t)-1) { -- sudo_warnx_nodebug("FAIL: %s: %s", d->idstr, errstr); -+ if (d->errnum != 0) { -+ if (errstr == NULL) { -+ sudo_warnx_nodebug("FAIL: %s: missing errstr for errno %d", -+ d->idstr, d->errnum); -+ errors++; -+ } else if (value != 0) { -+ sudo_warnx_nodebug("FAIL: %s should return 0 on error", -+ d->idstr); -+ errors++; -+ } else if (errno != d->errnum) { -+ sudo_warnx_nodebug("FAIL: %s: errno mismatch, %d != %d", -+ d->idstr, errno, d->errnum); - errors++; - } -+ } else if (errstr != NULL) { -+ sudo_warnx_nodebug("FAIL: %s: %s", d->idstr, errstr); -+ errors++; - } else if (value != d->id) { - sudo_warnx_nodebug("FAIL: %s != %u", d->idstr, (unsigned int)d->id); - errors++; -diff -r fcd7a6d8330e plugins/sudoers/regress/testsudoers/test5.out.ok ---- a/plugins/sudoers/regress/testsudoers/test5.out.ok Fri Jan 11 13:31:15 2019 -0700 -+++ b/plugins/sudoers/regress/testsudoers/test5.out.ok Thu Oct 10 14:02:30 2019 -0600 -@@ -4,7 +4,7 @@ Parse error in sudoers near line 1. - Entries for user root: - - Command unmatched --testsudoers: test5.inc should be owned by gid 4294967295 -+testsudoers: test5.inc should be owned by gid 4294967294 - Parse error in sudoers near line 1. - - Entries for user root: -diff -r fcd7a6d8330e plugins/sudoers/regress/testsudoers/test5.sh ---- a/plugins/sudoers/regress/testsudoers/test5.sh Fri Jan 11 13:31:15 2019 -0700 -+++ b/plugins/sudoers/regress/testsudoers/test5.sh Thu Oct 10 14:02:30 2019 -0600 -@@ -24,7 +24,7 @@ EOF - - # Test group writable - chmod 664 $TESTFILE --./testsudoers -U $MYUID -G -1 root id < - 1.9.2-1 +- update to 1.9.2 + * Fri Apr 17 2020 Anakin Zhang - 1.8.27-5 - Read drop-in files from /etc/sudoers.d diff --git a/sudo_minus_1_uid.patch b/sudo_minus_1_uid.patch deleted file mode 100644 index dbf9db77acf5bf57e39499f56ed367bedc52675b..0000000000000000000000000000000000000000 --- a/sudo_minus_1_uid.patch +++ /dev/null @@ -1,172 +0,0 @@ -Treat an ID of -1 as invalid since that means "no change". -Fixes CVE-2019-14287. -Found by Joe Vennix from Apple Information Security. - -diff -r fcd7a6d8330e lib/util/strtoid.c ---- a/lib/util/strtoid.c Fri Jan 11 13:31:15 2019 -0700 -+++ b/lib/util/strtoid.c Thu Oct 10 09:52:12 2019 -0600 -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2013-2016 Todd C. Miller -+ * Copyright (c) 2013-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 -@@ -47,6 +47,27 @@ - #include "sudo_util.h" - - /* -+ * Make sure that the ID ends with a valid separator char. -+ */ -+static bool -+valid_separator(const char *p, const char *ep, const char *sep) -+{ -+ bool valid = false; -+ debug_decl(valid_separator, SUDO_DEBUG_UTIL) -+ -+ if (ep != p) { -+ /* check for valid separator (including '\0') */ -+ if (sep == NULL) -+ sep = ""; -+ do { -+ if (*ep == *sep) -+ valid = true; -+ } while (*sep++ != '\0'); -+ } -+ debug_return_bool(valid); -+} -+ -+/* - * Parse a uid/gid in string form. - * If sep is non-NULL, it contains valid separator characters (e.g. comma, space) - * If endp is non-NULL it is set to the next char after the ID. -@@ -60,38 +81,35 @@ sudo_strtoid_v1(const char *p, const cha - char *ep; - id_t ret = 0; - long long llval; -- bool valid = false; - debug_decl(sudo_strtoid, SUDO_DEBUG_UTIL) - - /* skip leading space so we can pick up the sign, if any */ - while (isspace((unsigned char)*p)) - p++; -- if (sep == NULL) -- sep = ""; -+ -+ /* While id_t may be 64-bit signed, uid_t and gid_t are 32-bit unsigned. */ - errno = 0; - llval = strtoll(p, &ep, 10); -- if (ep != p) { -- /* check for valid separator (including '\0') */ -- do { -- if (*ep == *sep) -- valid = true; -- } while (*sep++ != '\0'); -+ if ((errno == ERANGE && llval == LLONG_MAX) || llval > (id_t)UINT_MAX) { -+ errno = ERANGE; -+ if (errstr != NULL) -+ *errstr = N_("value too large"); -+ goto done; - } -- if (!valid) { -+ if ((errno == ERANGE && llval == LLONG_MIN) || llval < INT_MIN) { -+ errno = ERANGE; -+ if (errstr != NULL) -+ *errstr = N_("value too small"); -+ goto done; -+ } -+ -+ /* Disallow id -1, which means "no change". */ -+ if (!valid_separator(p, ep, sep) || llval == -1 || llval == (id_t)UINT_MAX) { - if (errstr != NULL) - *errstr = N_("invalid value"); - errno = EINVAL; - goto done; - } -- if (errno == ERANGE) { -- if (errstr != NULL) { -- if (llval == LLONG_MAX) -- *errstr = N_("value too large"); -- else -- *errstr = N_("value too small"); -- } -- goto done; -- } - ret = (id_t)llval; - if (errstr != NULL) - *errstr = NULL; -@@ -106,30 +124,15 @@ sudo_strtoid_v1(const char *p, const cha - { - char *ep; - id_t ret = 0; -- bool valid = false; - debug_decl(sudo_strtoid, SUDO_DEBUG_UTIL) - - /* skip leading space so we can pick up the sign, if any */ - while (isspace((unsigned char)*p)) - p++; -- if (sep == NULL) -- sep = ""; -+ - errno = 0; - if (*p == '-') { - long lval = strtol(p, &ep, 10); -- if (ep != p) { -- /* check for valid separator (including '\0') */ -- do { -- if (*ep == *sep) -- valid = true; -- } while (*sep++ != '\0'); -- } -- if (!valid) { -- if (errstr != NULL) -- *errstr = N_("invalid value"); -- errno = EINVAL; -- goto done; -- } - if ((errno == ERANGE && lval == LONG_MAX) || lval > INT_MAX) { - errno = ERANGE; - if (errstr != NULL) -@@ -142,28 +145,31 @@ sudo_strtoid_v1(const char *p, const cha - *errstr = N_("value too small"); - goto done; - } -- ret = (id_t)lval; -- } else { -- unsigned long ulval = strtoul(p, &ep, 10); -- if (ep != p) { -- /* check for valid separator (including '\0') */ -- do { -- if (*ep == *sep) -- valid = true; -- } while (*sep++ != '\0'); -- } -- if (!valid) { -+ -+ /* Disallow id -1, which means "no change". */ -+ if (!valid_separator(p, ep, sep) || lval == -1) { - if (errstr != NULL) - *errstr = N_("invalid value"); - errno = EINVAL; - goto done; - } -+ ret = (id_t)lval; -+ } else { -+ unsigned long ulval = strtoul(p, &ep, 10); - if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) { - errno = ERANGE; - if (errstr != NULL) - *errstr = N_("value too large"); - goto done; - } -+ -+ /* Disallow id -1, which means "no change". */ -+ if (!valid_separator(p, ep, sep) || ulval == UINT_MAX) { -+ if (errstr != NULL) -+ *errstr = N_("invalid value"); -+ errno = EINVAL; -+ goto done; -+ } - ret = (id_t)ulval; - } - if (errstr != NULL) diff --git a/sudoers b/sudoers index 8926b0e234f4a9985c56c5983c642d87e12d130a..e68d56cc3c3d5d49c9697fbc6591fa2924d3d5aa 100644 --- a/sudoers +++ b/sudoers @@ -7,6 +7,45 @@ ## ## This file must be edited with the 'visudo' command. +## Host Aliases +## Groups of machines. You may prefer to use hostnames (perhaps using +## wildcards for entire domains) or IP addresses instead. +# Host_Alias FILESERVERS = fs1, fs2 +# Host_Alias MAILSERVERS = smtp, smtp2 + +## User Aliases +## These aren't often necessary, as you can use regular groups +## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname +## rather than USERALIAS +# User_Alias ADMINS = jsmith, mikem + + +## Command Aliases +## These are groups of related commands... + +## Networking +# Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool + +## Installation and management of software +# Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum + +## Services +# Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start, /usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart, /usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/bin/systemctl disable + +## Updating the locate database +# Cmnd_Alias LOCATE = /usr/bin/updatedb + +## Storage +# Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount + +## Delegating permissions +# Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp + +## Processes +# Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall + +## Drivers +# Cmnd_Alias DRIVERS = /sbin/modprobe # Defaults specification @@ -15,6 +54,24 @@ # Defaults !visiblepw +# +# Preserving HOME has security implications since many programs +# use it when searching for configuration files. Note that HOME +# is already set when the the env_reset option is enabled, so +# this option is only effective for configurations where either +# env_reset is disabled or HOME is present in the env_keep list. +# +Defaults always_set_home +Defaults match_group_by_gid + +# Prior to version 1.8.15, groups listed in sudoers that were not +# found in the system group database were passed to the group +# plugin, if any. Starting with 1.8.15, only groups of the form +# %:group are resolved via the group plugin by default. +# We enable always_query_group_plugin to restore old behavior. +# Disable this option for new behavior. +Defaults always_query_group_plugin + Defaults env_reset Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" @@ -22,6 +79,12 @@ Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" +# +# Adding HOME to env_keep may enable a user to run unrestricted +# commands via sudo. +# +# Defaults env_keep += "HOME" + Defaults secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ## Next comes the main part: which users can run what software on @@ -36,8 +99,22 @@ Defaults secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbi ## Allow root to run any commands anywhere root ALL=(ALL) ALL +## Allows members of the 'sys' group to run networking, software, +## service management apps and more. +# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS + ## Allows people in group wheel to run all commands %wheel ALL=(ALL) ALL +## Same thing without a password +# %wheel ALL=(ALL) NOPASSWD: ALL + +## Allows members of the users group to mount and unmount the +## cdrom as root +# %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom + +## Allows members of the users group to shutdown this system +# %users localhost=/sbin/shutdown -h now + ## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment) #includedir /etc/sudoers.d