!2 sudo: fix CVE-2019-19232 and CVE-2019-19234

Merge pull request !2 from guoxiaoqi/next
This commit is contained in:
openeuler-ci-bot 2020-01-20 18:51:56 +08:00 committed by Gitee
commit 73a28d4932
3 changed files with 690 additions and 1 deletions

View File

@ -0,0 +1,199 @@
From 807e17ceedf2500aeca67b37f62463ee112d63c4 Mon Sep 17 00:00:00 2001
From: Todd C. Miller <Todd.Miller@sudo.ws>
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

View File

@ -0,0 +1,485 @@
From 1078336fb8769eb9e022d088f5b2db443bb775d6 Mon Sep 17 00:00:00 2001
From: Todd C. Miller <Todd.Miller@sudo.ws>
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 <Todd.Miller@sudo.ws>
+dnl Copyright (c) 1994-1996,1998-2019 Todd C. Miller <Todd.Miller@sudo.ws>
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 <Todd.Miller@courtesan.com>
+ *
+ * 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 <config.h>
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#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

View File

@ -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 <buildteam@openeuler.org> - 1.8.27-4
- fix CVE-2019-19232 and CVE-2019-19234
* Sat Jan 11 2020 openEuler Buildteam <buildteam@openeuler.org> - 1.8.27-3
- clean code