Compare commits

...

No commits in common. "c8" and "c9s" have entirely different histories.
c8 ... c9s

40 changed files with 523 additions and 3444 deletions

30
.gitignore vendored
View File

@ -1 +1,29 @@
SOURCES/sudo-1.8.29.tar.gz
/sudo-1.8.16.tar.gz
/sudo-1.8.17p1.tar.gz
/sudo-1.8.18b2.tar.gz
/sudo-1.8.18rc2.tar.gz
/sudo-1.8.18rc4.tar.gz
/sudo-1.8.18.tar.gz
/sudo-90e4538c001fbe1b791a11d6a2c37607472fafe5.tar.gz
/sudo-738c3cbf3e8400bf4a5aeab8966427ff6d630cd2.tar.gz
/sudo-1.8.19p2.tar.gz
/sudo-1.8.20b1.tar.gz
/sudo-1.8.20p1.tar.gz
/sudo-1.8.20p2.tar.gz
/sudo-1.8.21p2.tar.gz
/sudo-1.8.22b1.tar.gz
/sudo-1.8.23b3.tar.gz
/sudo-1.8.23.tar.gz
/sudo-1.8.25.tar.gz
/sudo-1.8.25p1.tar.gz
/sudo-1.8.27.tar.gz
/sudo-1.8.28.tar.gz
/sudo-1.8.28p1.tar.gz
/sudo-1.8.29.tar.gz
/sudo-1.9.0b1.tar.gz
/sudo-1.9.0b4.tar.gz
/sudo-1.9.1.tar.gz
/sudo-1.9.2.tar.gz
/sudo-1.9.3p1.tar.gz
/sudo-1.9.5p1.tar.gz
/sudo-1.9.5p2.tar.gz

View File

@ -1 +1 @@
fdce342856f1803478eb549479190370001dca95 SOURCES/sudo-1.8.29.tar.gz
08bde247a1e08bc881eec43e09733f7ca06408f5 sudo-1.9.5p2.tar.gz

View File

@ -1,11 +0,0 @@
--- sudo-1.6.7p5/install-sh.strip 2005-07-21 14:28:25.000000000 +0200
+++ sudo-1.6.7p5/install-sh 2005-07-21 14:29:18.000000000 +0200
@@ -138,7 +138,7 @@
fi
;;
X-s)
- STRIPIT=true
+ #STRIPIT=true
;;
X--)
shift

View File

@ -1,27 +0,0 @@
From 44a602b49365969e56c63c9f12eda197e951302f Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
Date: Fri, 19 Aug 2016 14:07:35 +0200
Subject: [PATCH 02/10] Added "Enviroment debugging" message
rebased from:
Patch2: sudo-1.7.2p1-envdebug.patch
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 9feddfd..39a2d86 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1390,7 +1390,7 @@ AC_ARG_ENABLE(env_debug,
[AS_HELP_STRING([--enable-env-debug], [Whether to enable environment debugging.])],
[ case "$enableval" in
yes) AC_MSG_RESULT(yes)
- AC_DEFINE(ENV_DEBUG)
+ AC_DEFINE(ENV_DEBUG, [], [Environment debugging.])
;;
no) AC_MSG_RESULT(no)
;;
--
2.7.4

View File

@ -1,89 +0,0 @@
diff -up ./plugins/sudoers/cvtsudoers.c.legacy-processing ./plugins/sudoers/cvtsudoers.c
--- ./plugins/sudoers/cvtsudoers.c.legacy-processing 2019-10-28 13:28:52.000000000 +0100
+++ ./plugins/sudoers/cvtsudoers.c 2019-10-30 13:32:43.309480623 +0100
@@ -347,6 +347,15 @@ main(int argc, char *argv[])
sudo_fatalx("error: unhandled input %d", input_format);
}
+ /*
+ * cvtsudoers group filtering doesn't work if def_match_group_by_gid
+ * is set to true by default (at compile-time). It cannot be set to false
+ * because cvtsudoers doesn't apply the parsed Defaults.
+ *
+ * Related: sudo-1.8.23-legacy-group-processing.patch
+ */
+ def_match_group_by_gid = def_legacy_group_processing = false;
+
/* Apply filters. */
filter_userspecs(&parsed_policy, conf);
filter_defaults(&parsed_policy, conf);
diff -up ./plugins/sudoers/defaults.c.legacy-processing ./plugins/sudoers/defaults.c
--- ./plugins/sudoers/defaults.c.legacy-processing 2019-10-28 13:28:52.000000000 +0100
+++ ./plugins/sudoers/defaults.c 2019-10-30 13:32:43.309480623 +0100
@@ -93,6 +93,7 @@ static struct early_default early_defaul
{ I_FQDN },
#endif
{ I_MATCH_GROUP_BY_GID },
+ { I_LEGACY_GROUP_PROCESSING },
{ I_GROUP_PLUGIN },
{ I_RUNAS_DEFAULT },
{ I_SUDOERS_LOCALE },
@@ -494,6 +495,8 @@ init_defaults(void)
}
/* First initialize the flags. */
+ def_legacy_group_processing = true;
+ def_match_group_by_gid = true;
#ifdef LONG_OTP_PROMPT
def_long_otp_prompt = true;
#endif
diff -up ./plugins/sudoers/def_data.c.legacy-processing ./plugins/sudoers/def_data.c
--- ./plugins/sudoers/def_data.c.legacy-processing 2019-10-30 13:32:43.309480623 +0100
+++ ./plugins/sudoers/def_data.c 2019-10-30 13:37:25.914602825 +0100
@@ -506,6 +506,10 @@ struct sudo_defs_types sudo_defs_table[]
N_("Log when a command is denied by sudoers"),
NULL,
}, {
+ "legacy_group_processing", T_FLAG,
+ N_("Don't pre-resolve all group names"),
+ NULL,
+ }, {
NULL, 0, NULL
}
};
diff -up ./plugins/sudoers/def_data.h.legacy-processing ./plugins/sudoers/def_data.h
--- ./plugins/sudoers/def_data.h.legacy-processing 2019-10-30 13:32:43.310480638 +0100
+++ ./plugins/sudoers/def_data.h 2019-10-30 13:40:59.651713757 +0100
@@ -232,6 +232,8 @@
#define def_log_allowed (sudo_defs_table[I_LOG_ALLOWED].sd_un.flag)
#define I_LOG_DENIED 116
#define def_log_denied (sudo_defs_table[I_LOG_DENIED].sd_un.flag)
+#define I_LEGACY_GROUP_PROCESSING 117
+#define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag)
enum def_tuple {
never,
diff -up ./plugins/sudoers/def_data.in.legacy-processing ./plugins/sudoers/def_data.in
--- ./plugins/sudoers/def_data.in.legacy-processing 2019-10-30 13:32:43.310480638 +0100
+++ ./plugins/sudoers/def_data.in 2019-10-30 13:42:20.915896239 +0100
@@ -366,3 +366,6 @@ log_allowed
log_denied
T_FLAG
"Log when a command is denied by sudoers"
+legacy_group_processing
+ T_FLAG
+ "Don't pre-resolve all group names"
diff -up ./plugins/sudoers/sudoers.c.legacy-processing ./plugins/sudoers/sudoers.c
--- ./plugins/sudoers/sudoers.c.legacy-processing 2019-10-28 13:28:53.000000000 +0100
+++ ./plugins/sudoers/sudoers.c 2019-10-30 13:32:43.310480638 +0100
@@ -221,6 +221,10 @@ sudoers_policy_init(void *info, char * c
if (set_loginclass(runas_pw ? runas_pw : sudo_user.pw))
ret = true;
+ if (!def_match_group_by_gid || !def_legacy_group_processing) {
+ def_match_group_by_gid = false;
+ def_legacy_group_processing = false;
+ }
cleanup:
if (!restore_perms())
ret = -1;

View File

@ -1,60 +0,0 @@
diff -up ./plugins/sudoers/def_data.c.nowait ./plugins/sudoers/def_data.c
--- ./plugins/sudoers/def_data.c.nowait 2019-10-30 13:43:48.376168944 +0100
+++ ./plugins/sudoers/def_data.c 2019-10-30 13:43:48.378168973 +0100
@@ -510,6 +510,10 @@ struct sudo_defs_types sudo_defs_table[]
N_("Don't pre-resolve all group names"),
NULL,
}, {
+ "cmnd_no_wait", T_FLAG,
+ N_("Don't fork and wait for the command to finish, just exec it"),
+ NULL,
+ }, {
NULL, 0, NULL
}
};
diff -up ./plugins/sudoers/def_data.h.nowait ./plugins/sudoers/def_data.h
--- ./plugins/sudoers/def_data.h.nowait 2019-10-30 13:43:48.378168973 +0100
+++ ./plugins/sudoers/def_data.h 2019-10-30 13:45:38.425770365 +0100
@@ -234,6 +234,8 @@
#define def_log_denied (sudo_defs_table[I_LOG_DENIED].sd_un.flag)
#define I_LEGACY_GROUP_PROCESSING 117
#define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag)
+#define I_CMND_NO_WAIT 118
+#define def_cmnd_no_wait (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag)
enum def_tuple {
never,
diff -up ./plugins/sudoers/def_data.in.nowait ./plugins/sudoers/def_data.in
--- ./plugins/sudoers/def_data.in.nowait 2019-10-30 13:43:48.376168944 +0100
+++ ./plugins/sudoers/def_data.in 2019-10-30 13:43:48.379168987 +0100
@@ -369,3 +369,6 @@ log_denied
legacy_group_processing
T_FLAG
"Don't pre-resolve all group names"
+cmnd_no_wait
+ T_FLAG
+ "Don't fork and wait for the command to finish, just exec it"
diff -up ./plugins/sudoers/sudoers.c.nowait ./plugins/sudoers/sudoers.c
--- ./plugins/sudoers/sudoers.c.nowait 2019-10-30 13:43:48.376168944 +0100
+++ ./plugins/sudoers/sudoers.c 2019-10-30 13:43:48.379168987 +0100
@@ -225,6 +225,20 @@ sudoers_policy_init(void *info, char * c
def_match_group_by_gid = false;
def_legacy_group_processing = false;
}
+
+ /*
+ * Emulate cmnd_no_wait option by disabling PAM session, PTY allocation
+ * and I/O logging. This will cause sudo to execute the given command
+ * directly instead of forking a separate process for it.
+ */
+ if (def_cmnd_no_wait) {
+ def_pam_setcred = false;
+ def_pam_session = false;
+ def_use_pty = false;
+ def_log_input = false;
+ def_log_output = false;
+ }
+
cleanup:
if (!restore_perms())
ret = -1;

View File

@ -1,32 +0,0 @@
diff -up sudo-1.8.23/doc/Makefile.in.sudoldapconfman sudo-1.8.23/doc/Makefile.in
--- sudo-1.8.23/doc/Makefile.in.sudoldapconfman 2018-04-29 21:59:31.000000000 +0200
+++ sudo-1.8.23/doc/Makefile.in 2018-05-17 13:56:24.693651178 +0200
@@ -345,10 +345,16 @@ install-doc: install-dirs
rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
echo ln -s sudo.$(mansectsu)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
ln -s sudo.$(mansectsu)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ rm -f $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform)$(MANCOMPRESSEXT); \
+ echo ln -s sudoers.ldap.$(mansectform)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform)$(MANCOMPRESSEXT); \
+ ln -s sudoers.ldap.$(mansectform)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform)$(MANCOMPRESSEXT); \
else \
rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
echo ln -s sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
ln -s sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ rm -f $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform); \
+ echo ln -s sudoers.ldap.$(mansectform) $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform); \
+ ln -s sudoers.ldap.$(mansectform) $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform); \
fi
install-plugin:
@@ -363,8 +369,9 @@ uninstall:
$(DESTDIR)$(mandirsu)/visudo.$(mansectsu) \
$(DESTDIR)$(mandirform)/sudo.conf.$(mansectform) \
$(DESTDIR)$(mandirform)/sudoers.$(mansectform) \
- $(DESTDIR)$(mandirform)/sudoers_timestamp.$(mansectform)
- $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform)
+ $(DESTDIR)$(mandirform)/sudoers_timestamp.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform)
splint:

View File

@ -1,77 +0,0 @@
diff -up ./src/tgetpass.c.CVE-2019-18634 ./src/tgetpass.c
--- ./src/tgetpass.c.CVE-2019-18634 2019-10-28 13:27:39.000000000 +0100
+++ ./src/tgetpass.c 2020-02-05 14:08:27.516101197 +0100
@@ -61,7 +61,7 @@ enum tgetpass_errval {
static volatile sig_atomic_t signo[NSIG];
static void tgetpass_handler(int);
-static char *getln(int, char *, size_t, int, enum tgetpass_errval *);
+static char *getln(int, char *, size_t, bool, enum tgetpass_errval *);
static char *sudo_askpass(const char *, const char *);
static int
@@ -125,6 +125,7 @@ tgetpass(const char *prompt, int timeout
static char buf[SUDO_CONV_REPL_MAX + 1];
int i, input, output, save_errno, ttyfd;
bool need_restart, neednl = false;
+ bool feedback = ISSET(flags, TGP_MASK);
enum tgetpass_errval errval;
debug_decl(tgetpass, SUDO_DEBUG_CONV)
@@ -180,7 +181,7 @@ restart:
*/
if (!ISSET(flags, TGP_ECHO)) {
for (;;) {
- if (ISSET(flags, TGP_MASK))
+ if (feedback)
neednl = sudo_term_cbreak(input);
else
neednl = sudo_term_noecho(input);
@@ -194,6 +195,9 @@ restart:
}
}
}
+ /* Only use feedback mode when we can disable echo. */
+ if (!neednl)
+ feedback = false;
/*
* Catch signals that would otherwise cause the user to end
@@ -224,7 +228,7 @@ restart:
if (timeout > 0)
alarm(timeout);
- pass = getln(input, buf, sizeof(buf), ISSET(flags, TGP_MASK), &errval);
+ pass = getln(input, buf, sizeof(buf), feedback, &errval);
alarm(0);
save_errno = errno;
@@ -360,7 +364,7 @@ sudo_askpass(const char *askpass, const
extern int sudo_term_eof, sudo_term_erase, sudo_term_kill;
static char *
-getln(int fd, char *buf, size_t bufsiz, int feedback,
+getln(int fd, char *buf, size_t bufsiz, bool feedback,
enum tgetpass_errval *errval)
{
size_t left = bufsiz;
@@ -389,15 +393,15 @@ getln(int fd, char *buf, size_t bufsiz,
while (cp > buf) {
if (write(fd, "\b \b", 3) == -1)
break;
- --cp;
+ cp--;
}
+ cp = buf;
left = bufsiz;
continue;
} else if (c == sudo_term_erase) {
if (cp > buf) {
- if (write(fd, "\b \b", 3) == -1)
- break;
- --cp;
+ ignore_result(write(fd, "\b \b", 3));
+ cp--;
left++;
}
continue;

View File

@ -1,169 +0,0 @@
diff -up ./doc/sudoers.man.in.CVE-2019-19232 ./doc/sudoers.man.in
--- ./doc/sudoers.man.in.CVE-2019-19232 2019-10-28 13:28:52.000000000 +0100
+++ ./doc/sudoers.man.in 2020-01-14 15:34:46.908027286 +0100
@@ -2942,6 +2942,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.29 or higher.
+Older versions of
+\fBsudo\fR
+always allowed matching of unknown user and group IDs.
+.TP 18n
runaspw
If set,
\fBsudo\fR
diff -up ./doc/sudoers.mdoc.in.CVE-2019-19232 ./doc/sudoers.mdoc.in
--- ./doc/sudoers.mdoc.in.CVE-2019-19232 2019-10-28 13:28:52.000000000 +0100
+++ ./doc/sudoers.mdoc.in 2020-01-14 15:34:46.908027286 +0100
@@ -2768,6 +2768,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.29 or higher.
+Older versions of
+.Nm sudo
+always allowed matching of unknown user and group IDs.
.It runaspw
If set,
.Nm sudo
diff -up ./plugins/sudoers/defaults.c.CVE-2019-19232 ./plugins/sudoers/defaults.c
--- ./plugins/sudoers/defaults.c.CVE-2019-19232 2020-01-14 15:34:46.902027246 +0100
+++ ./plugins/sudoers/defaults.c 2020-01-14 15:34:46.909027293 +0100
@@ -581,6 +581,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 -up ./plugins/sudoers/def_data.c.CVE-2019-19232 ./plugins/sudoers/def_data.c
--- ./plugins/sudoers/def_data.c.CVE-2019-19232 2020-01-14 15:34:46.908027286 +0100
+++ ./plugins/sudoers/def_data.c 2020-01-14 15:40:19.441555509 +0100
@@ -514,6 +514,10 @@ struct sudo_defs_types sudo_defs_table[]
N_("Don't fork and wait for the command to finish, just exec it"),
NULL,
}, {
+ "runas_allow_unknown_id", T_FLAG,
+ N_("Allow the use of unknown runas user and/or group ID"),
+ NULL,
+ }, {
NULL, 0, NULL
}
};
diff -up ./plugins/sudoers/def_data.h.CVE-2019-19232 ./plugins/sudoers/def_data.h
--- ./plugins/sudoers/def_data.h.CVE-2019-19232 2020-01-14 15:34:46.909027293 +0100
+++ ./plugins/sudoers/def_data.h 2020-01-14 15:41:33.658012401 +0100
@@ -236,6 +236,8 @@
#define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag)
#define I_CMND_NO_WAIT 118
#define def_cmnd_no_wait (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag)
+#define I_RUNAS_ALLOW_UNKNOWN_ID 119
+#define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag)
enum def_tuple {
never,
diff -up ./plugins/sudoers/def_data.in.CVE-2019-19232 ./plugins/sudoers/def_data.in
--- ./plugins/sudoers/def_data.in.CVE-2019-19232 2020-01-14 15:34:46.909027293 +0100
+++ ./plugins/sudoers/def_data.in 2020-01-14 15:42:42.176481484 +0100
@@ -372,3 +372,6 @@ legacy_group_processing
cmnd_no_wait
T_FLAG
"Don't fork and wait for the command to finish, just exec it"
+runas_allow_unknown_id
+ T_FLAG
+ "Allow the use of unknown runas user and/or group ID"
diff -up ./plugins/sudoers/sudoers.c.CVE-2019-19232 ./plugins/sudoers/sudoers.c
--- ./plugins/sudoers/sudoers.c.CVE-2019-19232 2020-01-14 15:34:46.905027266 +0100
+++ ./plugins/sudoers/sudoers.c 2020-01-14 15:34:46.910027299 +0100
@@ -105,6 +105,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;
@@ -354,6 +356,22 @@ sudoers_policy_main(int argc, char * con
}
}
+ /* 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.
*/
@@ -1167,12 +1185,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) {
@@ -1198,12 +1219,15 @@ set_runasgr(const char *group, bool quie
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) {

View File

@ -1,439 +0,0 @@
diff -up ./config.h.in.CVE-2019-19234 ./config.h.in
--- ./config.h.in.CVE-2019-19234 2019-10-28 13:28:52.000000000 +0100
+++ ./config.h.in 2020-01-14 15:53:40.506988064 +0100
@@ -334,6 +334,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 -up ./configure.ac.CVE-2019-19234 ./configure.ac
--- ./configure.ac.CVE-2019-19234 2020-01-14 15:53:40.496987995 +0100
+++ ./configure.ac 2020-01-14 15:53:40.509988084 +0100
@@ -2562,6 +2562,10 @@ AC_CHECK_FUNCS([getdelim], [], [
SUDO_APPEND_COMPAT_EXP(sudo_getdelim)
COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }getdelim_test"
])
+AC_CHECK_FUNCS([getusershell], [], [
+ AC_LIBOBJ(getusershell)
+ SUDO_APPEND_COMPAT_EXP(sudo_getusershell)
+])
AC_CHECK_FUNCS([reallocarray], [], [
AC_LIBOBJ(reallocarray)
SUDO_APPEND_COMPAT_EXP(sudo_reallocarray)
diff -up ./configure.CVE-2019-19234 ./configure
--- ./configure.CVE-2019-19234 2019-10-28 13:29:14.000000000 +0100
+++ ./configure 2020-01-14 15:53:40.509988084 +0100
@@ -19395,6 +19395,32 @@ esac
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 -up ./doc/sudoers.man.in.CVE-2019-19234 ./doc/sudoers.man.in
--- ./doc/sudoers.man.in.CVE-2019-19234 2020-01-14 15:53:40.503988043 +0100
+++ ./doc/sudoers.man.in 2020-01-14 15:53:40.510988091 +0100
@@ -2959,6 +2959,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.29 or higher.
+.TP 18n
runaspw
If set,
\fBsudo\fR
diff -up ./doc/sudoers.mdoc.in.CVE-2019-19234 ./doc/sudoers.mdoc.in
--- ./doc/sudoers.mdoc.in.CVE-2019-19234 2020-01-14 15:53:40.504988050 +0100
+++ ./doc/sudoers.mdoc.in 2020-01-14 15:53:40.510988091 +0100
@@ -2784,6 +2784,26 @@ This setting is only supported by versio
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.29 or higher.
.It runaspw
If set,
.Nm sudo
diff -up ./include/sudo_compat.h.CVE-2019-19234 ./include/sudo_compat.h
--- ./include/sudo_compat.h.CVE-2019-19234 2019-10-28 13:28:52.000000000 +0100
+++ ./include/sudo_compat.h 2020-01-14 15:53:40.511988098 +0100
@@ -407,6 +407,17 @@ __dso_public ssize_t sudo_getdelim(char
# undef getdelim
# define getdelim(_a, _b, _c, _d) sudo_getdelim((_a), (_b), (_c), (_d))
#endif /* HAVE_GETDELIM */
+#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 -up ./lib/util/getusershell.c.CVE-2019-19234 ./lib/util/getusershell.c
--- ./lib/util/getusershell.c.CVE-2019-19234 2020-01-14 15:53:40.511988098 +0100
+++ ./lib/util/getusershell.c 2020-01-14 15:53:40.511988098 +0100
@@ -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 -up ./lib/util/Makefile.in.CVE-2019-19234 ./lib/util/Makefile.in
--- ./lib/util/Makefile.in.CVE-2019-19234 2019-10-28 13:28:53.000000000 +0100
+++ ./lib/util/Makefile.in 2020-01-14 15:53:40.511988098 +0100
@@ -678,6 +678,18 @@ gettime.i: $(srcdir)/gettime.c $(incdir)
$(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 -up ./MANIFEST.CVE-2019-19234 ./MANIFEST
--- ./MANIFEST.CVE-2019-19234 2019-10-28 13:28:52.000000000 +0100
+++ ./MANIFEST 2020-01-14 15:53:40.506988064 +0100
@@ -103,6 +103,7 @@ lib/util/getgrouplist.c
lib/util/gethostname.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 -up ./mkdep.pl.CVE-2019-19234 ./mkdep.pl
--- ./mkdep.pl.CVE-2019-19234 2019-10-28 13:28:52.000000000 +0100
+++ ./mkdep.pl 2020-01-14 15:53:40.511988098 +0100
@@ -116,7 +116,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 getdelim.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 str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.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 getdelim.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 str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo utimens.lo vsyslog.lo pipe2.lo:;
# Parse OBJS lines
my %objs;
diff -up ./plugins/sudoers/check.c.CVE-2019-19234 ./plugins/sudoers/check.c
--- ./plugins/sudoers/check.c.CVE-2019-19234 2019-10-28 13:27:45.000000000 +0100
+++ ./plugins/sudoers/check.c 2020-01-14 15:53:40.511988098 +0100
@@ -333,3 +333,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 -up ./plugins/sudoers/def_data.c.CVE-2019-19234 ./plugins/sudoers/def_data.c
--- ./plugins/sudoers/def_data.c.CVE-2019-19234 2020-01-14 15:53:40.504988050 +0100
+++ ./plugins/sudoers/def_data.c 2020-01-14 15:53:40.511988098 +0100
@@ -518,6 +518,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 -up ./plugins/sudoers/def_data.h.CVE-2019-19234 ./plugins/sudoers/def_data.h
--- ./plugins/sudoers/def_data.h.CVE-2019-19234 2020-01-14 15:53:40.512988105 +0100
+++ ./plugins/sudoers/def_data.h 2020-01-14 15:58:06.927808982 +0100
@@ -238,6 +238,8 @@
#define def_cmnd_no_wait (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag)
#define I_RUNAS_ALLOW_UNKNOWN_ID 119
#define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag)
+#define I_RUNAS_CHECK_SHELL 120
+#define def_runas_check_shell (sudo_defs_table[I_RUNAS_CHECK_SHELL].sd_un.flag)
enum def_tuple {
never,
diff -up ./plugins/sudoers/def_data.in.CVE-2019-19234 ./plugins/sudoers/def_data.in
--- ./plugins/sudoers/def_data.in.CVE-2019-19234 2020-01-14 15:53:40.505988057 +0100
+++ ./plugins/sudoers/def_data.in 2020-01-14 15:53:40.512988105 +0100
@@ -375,3 +375,7 @@ cmnd_no_wait
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 -up ./plugins/sudoers/sudoers.c.CVE-2019-19234 ./plugins/sudoers/sudoers.c
--- ./plugins/sudoers/sudoers.c.CVE-2019-19234 2020-01-14 15:53:40.505988057 +0100
+++ ./plugins/sudoers/sudoers.c 2020-01-14 15:53:40.512988105 +0100
@@ -273,7 +273,7 @@ sudoers_policy_main(int argc, char * con
/* Not an audit event. */
sudo_warnx(U_("sudoers specifies that root is not allowed to sudo"));
goto bad;
- }
+ }
if (!set_perms(PERM_INITIAL))
goto bad;
@@ -412,6 +412,13 @@ sudoers_policy_main(int argc, char * con
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 -up ./plugins/sudoers/sudoers.h.CVE-2019-19234 ./plugins/sudoers/sudoers.h
--- ./plugins/sudoers/sudoers.h.CVE-2019-19234 2020-01-14 15:53:40.502988036 +0100
+++ ./plugins/sudoers/sudoers.h 2020-01-14 15:53:40.512988105 +0100
@@ -264,6 +264,7 @@ int find_path(const char *infile, char *
/* check.c */
int check_user(int validate, int mode);
+bool check_user_shell(const struct passwd *pw);
bool user_is_exempt(void);
/* prompt.c */

View File

@ -1,154 +0,0 @@
From 4b6de608c25a6ffbdb507be958e12f814b43077c Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Wed, 4 Dec 2019 12:38:22 -0700
Subject: [PATCH] Only update the time stamp entry after the approval function
has succeeded. Bug #910
---
plugins/sudoers/check.c | 59 +++++++++++++++++++----------------------
1 file changed, 27 insertions(+), 32 deletions(-)
diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c
index db8e05161..ea1d89085 100644
--- a/plugins/sudoers/check.c
+++ b/plugins/sudoers/check.c
@@ -51,6 +51,7 @@ static bool display_lecture(int);
static struct passwd *get_authpw(int);
struct getpass_closure {
+ int tstat;
void *cookie;
struct passwd *auth_pw;
};
@@ -89,27 +90,20 @@ getpass_resume(int signo, void *vclosure)
* or -1 on fatal error.
*/
static int
-check_user_interactive(int validated, int mode, struct passwd *auth_pw)
+check_user_interactive(int validated, int mode, struct getpass_closure *closure)
{
struct sudo_conv_callback cb, *callback = NULL;
- struct getpass_closure closure;
- int status = TS_ERROR;
int ret = -1;
char *prompt;
bool lectured;
debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH)
- /* Setup closure for getpass_{suspend,resume} */
- closure.auth_pw = auth_pw;
- closure.cookie = NULL;
- sudo_pw_addref(closure.auth_pw);
-
/* Open, lock and read time stamp file if we are using it. */
if (!ISSET(mode, MODE_IGNORE_TICKET)) {
/* Open time stamp file and check its status. */
- closure.cookie = timestamp_open(user_name, user_sid);
- if (timestamp_lock(closure.cookie, closure.auth_pw))
- status = timestamp_status(closure.cookie, closure.auth_pw);
+ closure->cookie = timestamp_open(user_name, user_sid);
+ if (timestamp_lock(closure->cookie, closure->auth_pw))
+ closure->tstat = timestamp_status(closure->cookie, closure->auth_pw);
/* Construct callback for getpass function. */
memset(&cb, 0, sizeof(cb));
@@ -120,7 +114,7 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
callback = &cb;
}
- switch (status) {
+ switch (closure->tstat) {
case TS_FATAL:
/* Fatal error (usually setuid failure), unsafe to proceed. */
goto done;
@@ -144,32 +138,22 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
}
/* XXX - should not lecture if askpass helper is being used. */
- lectured = display_lecture(status);
+ lectured = display_lecture(closure->tstat);
/* Expand any escapes in the prompt. */
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
- closure.auth_pw->pw_name);
+ closure->auth_pw->pw_name);
if (prompt == NULL)
goto done;
- ret = verify_user(closure.auth_pw, prompt, validated, callback);
+ ret = verify_user(closure->auth_pw, prompt, validated, callback);
if (ret == true && lectured)
(void)set_lectured(); /* lecture error not fatal */
free(prompt);
break;
}
- /*
- * Only update time stamp if user was validated.
- * Failure to update the time stamp is not a fatal error.
- */
- if (ret == true && ISSET(validated, VALIDATE_SUCCESS) && status != TS_ERROR)
- (void)timestamp_update(closure.cookie, closure.auth_pw);
done:
- if (closure.cookie != NULL)
- timestamp_close(closure.cookie);
- sudo_pw_delref(closure.auth_pw);
-
debug_return_int(ret);
}
@@ -180,7 +164,7 @@ done:
int
check_user(int validated, int mode)
{
- struct passwd *auth_pw;
+ struct getpass_closure closure = { TS_ERROR };
int ret = -1;
bool exempt = false;
debug_decl(check_user, SUDOERS_DEBUG_AUTH)
@@ -189,9 +173,9 @@ check_user(int validated, int mode)
* Init authentication system regardless of whether we need a password.
* Required for proper PAM session support.
*/
- if ((auth_pw = get_authpw(mode)) == NULL)
+ if ((closure.auth_pw = get_authpw(mode)) == NULL)
goto done;
- if (sudo_auth_init(auth_pw) == -1)
+ if (sudo_auth_init(closure.auth_pw) == -1)
goto done;
/*
@@ -222,15 +206,26 @@ check_user(int validated, int mode)
}
}
- ret = check_user_interactive(validated, mode, auth_pw);
+ ret = check_user_interactive(validated, mode, &closure);
done:
if (ret == true) {
/* The approval function may disallow a user post-authentication. */
- ret = sudo_auth_approval(auth_pw, validated, exempt);
+ ret = sudo_auth_approval(closure.auth_pw, validated, exempt);
+
+ /*
+ * Only update time stamp if user validated and was approved.
+ * Failure to update the time stamp is not a fatal error.
+ */
+ if (ret == true && closure.tstat != TS_ERROR) {
+ if (ISSET(validated, VALIDATE_SUCCESS))
+ (void)timestamp_update(closure.cookie, closure.auth_pw);
+ }
}
- sudo_auth_cleanup(auth_pw);
- sudo_pw_delref(auth_pw);
+ timestamp_close(closure.cookie);
+ sudo_auth_cleanup(closure.auth_pw);
+ if (closure.auth_pw != NULL)
+ sudo_pw_delref(closure.auth_pw);
debug_return_int(ret);
}
--
2.25.1

View File

@ -1,29 +0,0 @@
From 5472b1751645f750e42a0ba6daac667983b1a56c Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Fri, 24 Jan 2020 11:13:55 -0700
Subject: [PATCH] Fix crash in sudo 1.8.30 when suspending sudo at the password
prompt. The closure pointer in sudo_conv_callback was being filled in with a
struct getpass_closure ** instead of a struct getpass_closure *. The bug was
introduced in the fix for Bug #910; previously the closure variable was a
struct getpass_closure, not a pointer. Fix from Michael Norton; Bug #914.
---
plugins/sudoers/check.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c
index 72e87eef6..9b03c7a05 100644
--- a/plugins/sudoers/check.c
+++ b/plugins/sudoers/check.c
@@ -108,7 +108,7 @@ check_user_interactive(int validated, int mode, struct getpass_closure *closure)
/* Construct callback for getpass function. */
memset(&cb, 0, sizeof(cb));
cb.version = SUDO_CONV_CALLBACK_VERSION;
- cb.closure = &closure;
+ cb.closure = closure;
cb.on_suspend = getpass_suspend;
cb.on_resume = getpass_resume;
callback = &cb;
--
2.25.1

View File

@ -1,206 +0,0 @@
diff -up ./plugins/sudoers/policy.c.heap-buffer ./plugins/sudoers/policy.c
--- ./plugins/sudoers/policy.c.heap-buffer 2019-10-28 13:28:52.000000000 +0100
+++ ./plugins/sudoers/policy.c 2021-01-20 11:38:06.481807015 +0100
@@ -100,10 +100,11 @@ parse_bool(const char *line, int varlen,
int
sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
{
+ const int edit_mask = MODE_EDIT|MODE_IGNORE_TICKET|MODE_NONINTERACTIVE;
struct sudoers_policy_open_info *info = v;
- char * const *cur;
const char *p, *errstr, *groups = NULL;
const char *remhost = NULL;
+ char * const *cur;
int flags = 0;
debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN)
@@ -332,6 +333,12 @@ sudoers_policy_deserialize_info(void *v,
#endif
}
+ /* Sudo front-end should restrict mode flags for sudoedit. */
+ if (ISSET(flags, MODE_EDIT) && (flags & edit_mask) != flags) {
+ sudo_warnx(U_("invalid mode flags from sudo front end: 0x%x"), flags);
+ goto bad;
+ }
+
user_gid = (gid_t)-1;
user_sid = (pid_t)-1;
user_uid = (gid_t)-1;
diff -up ./plugins/sudoers/sudoers.c.heap-buffer ./plugins/sudoers/sudoers.c
--- ./plugins/sudoers/sudoers.c.heap-buffer 2021-01-20 11:34:57.523317977 +0100
+++ ./plugins/sudoers/sudoers.c 2021-01-20 12:08:01.331553520 +0100
@@ -451,7 +451,7 @@ sudoers_policy_main(int argc, char * con
/* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
/* XXX - causes confusion when root is not listed in sudoers */
- if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
+ if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT) && prev_user != NULL) {
if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
struct passwd *pw;
@@ -834,8 +834,8 @@ set_cmnd(void)
if (user_cmnd == NULL)
user_cmnd = NewArgv[0];
- if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
- if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
+ if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) {
+ if (!ISSET(sudo_mode, MODE_EDIT)) {
if (def_secure_path && !user_is_exempt())
path = def_secure_path;
if (!set_perms(PERM_RUNAS))
@@ -873,7 +873,8 @@ set_cmnd(void)
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(-1);
}
- if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
+ if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL) &&
+ ISSET(sudo_mode, MODE_RUN)) {
/*
* When running a command via a shell, the sudo front-end
* escapes potential meta chars. We unescape non-spaces
@@ -881,10 +882,22 @@ set_cmnd(void)
*/
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
- if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+ if (from[0] == '\\' && from[1] != '\0' &&
+ !isspace((unsigned char)from[1])) {
from++;
+ }
+ if (size - (to - user_args) < 1) {
+ sudo_warnx(U_("internal error, %s overflow"),
+ __func__);
+ debug_return_int(NOT_FOUND_ERROR);
+ }
*to++ = *from++;
}
+ if (size - (to - user_args) < 1) {
+ sudo_warnx(U_("internal error, %s overflow"),
+ __func__);
+ debug_return_int(NOT_FOUND_ERROR);
+ }
*to++ = ' ';
}
*--to = '\0';
diff -up ./plugins/sudoers/timestamp.c.heap-buffer ./plugins/sudoers/timestamp.c
--- ./plugins/sudoers/timestamp.c.heap-buffer 2021-01-20 12:11:28.218774128 +0100
+++ ./plugins/sudoers/timestamp.c 2021-01-20 12:20:41.772324808 +0100
@@ -652,8 +652,8 @@ timestamp_lock(void *vcookie, struct pas
} else if (entry.type != TS_LOCKEXCL) {
/* Old sudo record, convert it to TS_LOCKEXCL. */
entry.type = TS_LOCKEXCL;
- memset((char *)&entry + offsetof(struct timestamp_entry, type), 0,
- nread - offsetof(struct timestamp_entry, type));
+ memset((char *)&entry + offsetof(struct timestamp_entry, flags), 0,
+ nread - offsetof(struct timestamp_entry, flags));
if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1)
debug_return_bool(false);
}
diff -up ./src/parse_args.c.heap-buffer ./src/parse_args.c
--- ./src/parse_args.c.heap-buffer 2021-01-20 11:35:18.231043445 +0100
+++ ./src/parse_args.c 2021-01-20 12:26:31.290591673 +0100
@@ -124,7 +124,10 @@ struct environment {
/*
* Default flags allowed when running a command.
*/
-#define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_SHELL)
+#define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_PRESERVE_GROUPS|MODE_SHELL)
+#define EDIT_VALID_FLAGS MODE_NONINTERACTIVE
+#define LIST_VALID_FLAGS (MODE_NONINTERACTIVE|MODE_LONG_LIST)
+#define VALIDATE_VALID_FLAGS MODE_NONINTERACTIVE
/* Option number for the --host long option due to ambiguity of the -h flag. */
#define OPT_HOSTNAME 256
@@ -269,6 +272,7 @@ parse_args(int argc, char **argv, int *n
progname = "sudoedit";
mode = MODE_EDIT;
sudo_settings[ARG_SUDOEDIT].value = "true";
+ valid_flags = EDIT_VALID_FLAGS;
}
/* Load local IP addresses and masks. */
@@ -360,7 +364,7 @@ parse_args(int argc, char **argv, int *n
usage_excl(1);
mode = MODE_EDIT;
sudo_settings[ARG_SUDOEDIT].value = "true";
- valid_flags = MODE_NONINTERACTIVE;
+ valid_flags = EDIT_VALID_FLAGS;
break;
case 'g':
assert(optarg != NULL);
@@ -371,6 +375,7 @@ parse_args(int argc, char **argv, int *n
break;
case 'H':
sudo_settings[ARG_SET_HOME].value = "true";
+ SET(flags, MODE_RESET_HOME);
break;
case 'h':
if (optarg == NULL) {
@@ -421,7 +426,7 @@ parse_args(int argc, char **argv, int *n
usage_excl(1);
}
mode = MODE_LIST;
- valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST;
+ valid_flags = LIST_VALID_FLAGS;
break;
case 'n':
SET(flags, MODE_NONINTERACTIVE);
@@ -429,6 +434,7 @@ parse_args(int argc, char **argv, int *n
break;
case 'P':
sudo_settings[ARG_PRESERVE_GROUPS].value = "true";
+ SET(flags, MODE_PRESERVE_GROUPS);
break;
case 'p':
/* An empty prompt is allowed. */
@@ -478,7 +484,7 @@ parse_args(int argc, char **argv, int *n
if (mode && mode != MODE_VALIDATE)
usage_excl(1);
mode = MODE_VALIDATE;
- valid_flags = MODE_NONINTERACTIVE;
+ valid_flags = VALIDATE_VALID_FLAGS;
break;
case 'V':
if (mode && mode != MODE_VERSION)
@@ -505,7 +511,7 @@ parse_args(int argc, char **argv, int *n
if (!mode) {
/* Defer -k mode setting until we know whether it is a flag or not */
if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) {
- if (argc == 0 && !(flags & (MODE_SHELL|MODE_LOGIN_SHELL))) {
+ if (argc == 0 && !ISSET(flags, MODE_SHELL|MODE_LOGIN_SHELL)) {
mode = MODE_INVALIDATE; /* -k by itself */
sudo_settings[ARG_IGNORE_TICKET].value = NULL;
valid_flags = 0;
@@ -568,23 +574,24 @@ parse_args(int argc, char **argv, int *n
/*
* For shell mode we need to rewrite argv
*/
- if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {
+ if (ISSET(flags, MODE_SHELL|MODE_LOGIN_SHELL) && ISSET(mode, MODE_RUN)) {
char **av, *cmnd = NULL;
int ac = 1;
if (argc != 0) {
/* shell -c "command" */
char *src, *dst;
- size_t cmnd_size = (size_t) (argv[argc - 1] - argv[0]) +
- strlen(argv[argc - 1]) + 1;
+ size_t size = 0;
- cmnd = dst = reallocarray(NULL, cmnd_size, 2);
- if (cmnd == NULL)
+ for (av = argv; *av != NULL; av++)
+ size += strlen(*av) + 1;
+
+ if (size == 0 || (cmnd = reallocarray(NULL, size, 2)) == NULL)
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
if (!gc_add(GC_PTR, cmnd))
exit(1);
- for (av = argv; *av != NULL; av++) {
+ for (dst = cmnd, av = argv; *av != NULL; av++) {
for (src = *av; *src != '\0'; src++) {
/* quote potential meta characters */
if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$')

View File

@ -1,90 +0,0 @@
From 06b46ae226fecd4188af372ac0ccd7aa582e21c8 Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
Date: Wed, 17 Aug 2016 10:12:11 +0200
Subject: [PATCH] Sudo logs username root instead of realuser
RHEL7 sudo logs username root instead of realuser in /var/log/secure
Rebased from:
Patch50: sudo-1.8.6p7-logsudouser.patch
Resolves:
rhbz#1312486
---
plugins/sudoers/logging.c | 14 +++++++-------
plugins/sudoers/sudoers.h | 1 +
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c
index 45cae67..74b2220 100644
--- a/plugins/sudoers/logging.c
+++ b/plugins/sudoers/logging.c
@@ -104,7 +104,7 @@ do_syslog(int pri, char *msg)
* Log the full line, breaking into multiple syslog(3) calls if necessary
*/
fmt = _("%8s : %s");
- maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name));
+ maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(sudo_user_name));
for (p = msg; *p != '\0'; ) {
len = strlen(p);
if (len > maxlen) {
@@ -120,7 +120,7 @@ do_syslog(int pri, char *msg)
save = *tmp;
*tmp = '\0';
- mysyslog(pri, fmt, user_name, p);
+ mysyslog(pri, fmt, sudo_user_name, p);
*tmp = save; /* restore saved character */
@@ -128,11 +128,11 @@ do_syslog(int pri, char *msg)
for (p = tmp; *p == ' '; p++)
continue;
} else {
- mysyslog(pri, fmt, user_name, p);
+ mysyslog(pri, fmt, sudo_user_name, p);
p += len;
}
fmt = _("%8s : (command continued) %s");
- maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name));
+ maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(sudo_user_name));
}
sudoers_setlocale(oldlocale, NULL);
@@ -179,10 +179,10 @@ do_logfile(const char *msg)
timestr = "invalid date";
if (def_log_host) {
len = asprintf(&full_line, "%s : %s : HOST=%s : %s",
- timestr, user_name, user_srunhost, msg);
+ timestr, sudo_user_name, user_srunhost, msg);
} else {
len = asprintf(&full_line, "%s : %s : %s",
- timestr, user_name, msg);
+ timestr, sudo_user_name, msg);
}
if (len == -1) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
@@ -746,7 +746,7 @@ send_mail(const char *fmt, ...)
if ((timestr = get_timestr(time(NULL), def_log_year)) == NULL)
timestr = "invalid date";
- (void) fprintf(mail, "\n\n%s : %s : %s : ", user_host, timestr, user_name);
+ (void) fprintf(mail, "\n\n%s : %s : %s : ", user_host, timestr, sudo_user_name);
va_start(ap, fmt);
(void) vfprintf(mail, fmt, ap);
va_end(ap);
diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h
index cfd5abb..c69a043 100644
--- a/plugins/sudoers/sudoers.h
+++ b/plugins/sudoers/sudoers.h
@@ -180,6 +180,7 @@ struct sudo_user {
/*
* Shortcuts for sudo_user contents.
*/
+#define sudo_user_name (sudo_user.pw->pw_name)
#define user_name (sudo_user.name)
#define user_uid (sudo_user.uid)
#define user_gid (sudo_user.gid)
--
2.7.4

View File

@ -1,171 +0,0 @@
diff -up ./plugins/sudoers/editor.c.other ./plugins/sudoers/editor.c
--- ./plugins/sudoers/editor.c.other 2023-01-16 17:37:04.659967300 +0100
+++ ./plugins/sudoers/editor.c 2023-01-16 17:40:35.944400376 +0100
@@ -39,6 +39,82 @@
#include "sudoers.h"
/*
+ * Non-destructive word-split that handles single and double quotes and
+ * escaped white space. Quotes are only recognized at the start of a word.
+ * They are treated as normal characters inside a word.
+ */
+static const char *
+wordsplit(const char *str, const char *endstr, const char **last)
+{
+ const char *cp;
+ debug_decl(wordsplit, SUDO_DEBUG_UTIL);
+
+ /* If no str specified, use last ptr (if any). */
+ if (str == NULL) {
+ str = *last;
+ /* Consume end quote if present. */
+ if (*str == '"' || *str == '\'')
+ str++;
+ }
+
+ /* Skip leading white space characters. */
+ while (str < endstr && (*str == ' ' || *str == '\t'))
+ str++;
+
+ /* Empty string? */
+ if (str >= endstr) {
+ *last = endstr;
+ debug_return_ptr(NULL);
+ }
+
+ /* If word is quoted, skip to end quote and return. */
+ if (*str == '"' || *str == '\'') {
+ const char *endquote = memchr(str + 1, *str, endstr - str);
+ if (endquote != NULL) {
+ *last = endquote;
+ debug_return_const_ptr(str + 1);
+ }
+ }
+
+ /* Scan str until we encounter white space. */
+ for (cp = str; cp < endstr; cp++) {
+ if (*cp == '\\') {
+ /* quoted char, do not interpret */
+ cp++;
+ continue;
+ }
+ if (*cp == ' ' || *cp == '\t') {
+ /* end of word */
+ break;
+ }
+ }
+ *last = cp;
+ debug_return_const_ptr(str);
+}
+
+/* Copy len chars from string, collapsing chars escaped with a backslash. */
+static char *
+copy_arg(const char *src, size_t len)
+{
+ const char *src_end = src + len;
+ char *copy, *dst;
+ debug_decl(copy_arg, SUDOERS_DEBUG_UTIL);
+
+ if ((copy = malloc(len + 1)) != NULL) {
+ for (dst = copy; src < src_end; ) {
+ if (*src == '\\') {
+ src++;
+ continue;
+ }
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ }
+
+ debug_return_ptr(copy);
+}
+
+/*
* Search for the specified editor in the user's PATH, checking
* the result against allowlist if non-NULL. An argument vector
* suitable for execve() is allocated and stored in argv_out.
@@ -52,7 +128,7 @@ static char *
resolve_editor(const char *ed, size_t edlen, int nfiles, char **files,
int *argc_out, char ***argv_out, char * const *allowlist)
{
- char **nargv, *editor, *editor_path = NULL;
+ char **nargv = NULL, *editor = NULL, *editor_path = NULL;
const char *cp, *ep, *tmp;
const char *edend = ed + edlen;
struct stat user_editor_sb;
@@ -64,14 +140,12 @@ resolve_editor(const char *ed, size_t ed
* The EDITOR and VISUAL environment variables may contain command
* line args so look for those and alloc space for them too.
*/
- cp = sudo_strsplit(ed, edend, " \t", &ep);
+ cp = wordsplit(ed, edend, &ep);
if (cp == NULL)
debug_return_str(NULL);
- editor = strndup(cp, (size_t)(ep - cp));
- if (editor == NULL) {
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
- debug_return_str(NULL);
- }
+ editor = copy_arg(cp, ep - cp);
+ if (editor == NULL)
+ goto oom;
/* If we can't find the editor in the user's PATH, give up. */
if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"), 0, allowlist) != FOUND) {
@@ -81,30 +155,22 @@ resolve_editor(const char *ed, size_t ed
}
/* Count rest of arguments and allocate editor argv. */
- for (nargc = 1, tmp = ep; sudo_strsplit(NULL, edend, " \t", &tmp) != NULL; )
+ for (nargc = 1, tmp = ep; wordsplit(NULL, edend, &tmp) != NULL; )
nargc++;
if (nfiles != 0)
nargc += nfiles + 1;
nargv = reallocarray(NULL, nargc + 1, sizeof(char *));
- if (nargv == NULL) {
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
- free(editor);
- free(editor_path);
- debug_return_str(NULL);
- }
+ if (nargv == NULL)
+ goto oom;
/* Fill in editor argv (assumes files[] is NULL-terminated). */
nargv[0] = editor;
- for (nargc = 1; (cp = sudo_strsplit(NULL, edend, " \t", &ep)) != NULL; nargc++) {
- nargv[nargc] = strndup(cp, (size_t)(ep - cp));
- if (nargv[nargc] == NULL) {
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
- free(editor_path);
- while (nargc--)
- free(nargv[nargc]);
- free(nargv);
- debug_return_str(NULL);
- }
+ editor = NULL;
+ for (nargc = 1; (cp = wordsplit(NULL, edend, &ep)) != NULL; nargc++) {
+ /* Copy string, collapsing chars escaped with a backslash. */
+ nargv[nargc] = copy_arg(cp, ep - cp);
+ if (nargv[nargc] == NULL)
+ goto oom;
}
if (nfiles != 0) {
nargv[nargc++] = "--";
@@ -116,6 +182,16 @@ resolve_editor(const char *ed, size_t ed
*argc_out = nargc;
*argv_out = nargv;
debug_return_str(editor_path);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(editor);
+ free(editor_path);
+ if (nargv != NULL) {
+ while (nargc--)
+ free(nargv[nargc]);
+ free(nargv);
+ }
+ debug_return_str(NULL);
}
/*

View File

@ -1,57 +0,0 @@
diff -up ./plugins/sudoers/editor.c.whitelist ./plugins/sudoers/editor.c
--- ./plugins/sudoers/editor.c.whitelist 2023-01-16 17:31:58.108335076 +0100
+++ ./plugins/sudoers/editor.c 2023-01-16 17:33:37.375547672 +0100
@@ -40,7 +40,7 @@
/*
* Search for the specified editor in the user's PATH, checking
- * the result against whitelist if non-NULL. An argument vector
+ * the result against allowlist if non-NULL. An argument vector
* suitable for execve() is allocated and stored in argv_out.
* If nfiles is non-zero, files[] is added to the end of argv_out.
*
@@ -50,7 +50,7 @@
*/
static char *
resolve_editor(const char *ed, size_t edlen, int nfiles, char **files,
- int *argc_out, char ***argv_out, char * const *whitelist)
+ int *argc_out, char ***argv_out, char * const *allowlist)
{
char **nargv, *editor, *editor_path = NULL;
const char *cp, *ep, *tmp;
@@ -74,7 +74,7 @@ resolve_editor(const char *ed, size_t ed
}
/* If we can't find the editor in the user's PATH, give up. */
- if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"), 0, whitelist) != FOUND) {
+ if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"), 0, allowlist) != FOUND) {
free(editor);
errno = ENOENT;
debug_return_str(NULL);
@@ -130,7 +130,7 @@ resolve_editor(const char *ed, size_t ed
*/
char *
find_editor(int nfiles, char **files, int *argc_out, char ***argv_out,
- char * const *whitelist, const char **env_editor, bool env_error)
+ char * const *allowlist, const char **env_editor, bool env_error)
{
char *ev[3], *editor_path = NULL;
unsigned int i;
@@ -149,7 +149,7 @@ find_editor(int nfiles, char **files, in
if (editor != NULL && *editor != '\0') {
*env_editor = editor;
editor_path = resolve_editor(editor, strlen(editor),
- nfiles, files, argc_out, argv_out, whitelist);
+ nfiles, files, argc_out, argv_out, allowlist);
if (editor_path != NULL)
break;
if (errno != ENOENT)
@@ -169,7 +169,7 @@ find_editor(int nfiles, char **files, in
for (cp = sudo_strsplit(def_editor, def_editor_end, ":", &ep);
cp != NULL; cp = sudo_strsplit(NULL, def_editor_end, ":", &ep)) {
editor_path = resolve_editor(cp, (size_t)(ep - cp), nfiles,
- files, argc_out, argv_out, whitelist);
+ files, argc_out, argv_out, allowlist);
if (editor_path != NULL)
break;
if (errno != ENOENT)

View File

@ -1,61 +0,0 @@
From db1f27c0350e9e437c93780ffe88648ae1984467 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Wed, 6 Jan 2021 10:16:00 -0700
Subject: [PATCH] Fix potential directory existing info leak in sudoedit. When
creating a new file, sudoedit checks to make sure the parent directory exists
so it can provide the user with a sensible error message. However, this
could be used to test for the existence of directories not normally
accessible to the user by pointing to them with a symbolic link when the
parent directory is controlled by the user. Problem reported by Matthias
Gerstner of SUSE.
---
src/sudo_edit.c | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/src/sudo_edit.c b/src/sudo_edit.c
index 82e04a71b..5502b7bd9 100644
--- a/src/sudo_edit.c
+++ b/src/sudo_edit.c
@@ -541,14 +541,33 @@ sudo_edit_create_tfiles(struct command_details *command_details,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details);
if (ofd != -1 || errno == ENOENT) {
if (ofd == -1) {
- /* New file, verify parent dir exists unless in cwd. */
+ /*
+ * New file, verify parent dir exists unless in cwd.
+ * This fails early so the user knows ahead of time if the
+ * edit won't succeed. Additional checks are performed
+ * when copying the temporary file back to the origin.
+ */
char *slash = strrchr(files[i], '/');
if (slash != NULL && slash != files[i]) {
- int serrno = errno;
+ const int sflags = command_details->flags;
+ const int serrno = errno;