import UBI sudo-1.9.5p2-1.el8_9
This commit is contained in:
parent
aa5f31f663
commit
f9a521fc01
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/sudo-1.8.29.tar.gz
|
SOURCES/sudo-1.9.5p2.tar.gz
|
||||||
|
@ -1 +1 @@
|
|||||||
fdce342856f1803478eb549479190370001dca95 SOURCES/sudo-1.8.29.tar.gz
|
08bde247a1e08bc881eec43e09733f7ca06408f5 SOURCES/sudo-1.9.5p2.tar.gz
|
||||||
|
35
SOURCES/covscan.patch
Normal file
35
SOURCES/covscan.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
diff -up ./lib/eventlog/eventlog.c.covscan ./lib/eventlog/eventlog.c
|
||||||
|
--- ./lib/eventlog/eventlog.c.covscan 2021-08-26 11:06:35.068915415 +0200
|
||||||
|
+++ ./lib/eventlog/eventlog.c 2021-08-26 11:13:32.432472325 +0200
|
||||||
|
@@ -1075,10 +1075,13 @@ do_logfile_sudo(const char *logline, con
|
||||||
|
if (ferror(fp)) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||||
|
"unable to write log file %s", logfile);
|
||||||
|
- goto done;
|
||||||
|
+ goto ddone;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
+ddone:
|
||||||
|
+ (void)free(full_line);
|
||||||
|
+
|
||||||
|
done:
|
||||||
|
(void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
|
||||||
|
evl_conf.close_log(EVLOG_FILE, fp);
|
||||||
|
diff -up ./logsrvd/logsrvd.c.covscan ./logsrvd/logsrvd.c
|
||||||
|
diff -up ./plugins/audit_json/audit_json.c.covscan ./plugins/audit_json/audit_json.c
|
||||||
|
diff -up ./plugins/sudoers/ldap.c.covscan ./plugins/sudoers/ldap.c
|
||||||
|
--- ./plugins/sudoers/ldap.c.covscan 2021-08-26 15:46:11.614179451 +0200
|
||||||
|
+++ ./plugins/sudoers/ldap.c 2021-08-26 15:51:40.871812534 +0200
|
||||||
|
@@ -443,6 +443,8 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMe
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ free(cp);
|
||||||
|
+
|
||||||
|
/* Walk through options, appending to defs. */
|
||||||
|
for (p = bv; *p != NULL; p++) {
|
||||||
|
char *var, *val;
|
||||||
|
diff -up ./plugins/sudoers/logging.c.covscan ./plugins/sudoers/logging.c
|
||||||
|
diff -up ./plugins/sudoers/rcstr.c.covscan ./plugins/sudoers/rcstr.c
|
||||||
|
diff -up ./src/utmp.c.covscan ./src/utmp.c
|
79
SOURCES/linker.patch
Normal file
79
SOURCES/linker.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
From ecaa9cd08d25870ec89fec82cf17c6cdaa4c7912 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Sat, 6 Feb 2021 08:36:01 -0700
|
||||||
|
Subject: [PATCH] Add libsudo_eventlog.la as a dependency of libsudo_iolog.la
|
||||||
|
No longer need to link against libsudo_eventlog.la in sudoers.
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/iolog/Makefile.in | 7 ++++---
|
||||||
|
plugins/sudoers/Makefile.in | 8 ++++----
|
||||||
|
2 files changed, 8 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/iolog/Makefile.in b/lib/iolog/Makefile.in
|
||||||
|
index 2ae9c1b42..8fbc76c98 100644
|
||||||
|
--- a/lib/iolog/Makefile.in
|
||||||
|
+++ b/lib/iolog/Makefile.in
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
#
|
||||||
|
-# Copyright (c) 2011-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
+# Copyright (c) 2011-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@@ -36,7 +36,8 @@ CC = @CC@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
-LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
|
||||||
|
+LT_LIBS = $(top_builddir)/lib/eventlog/libsudo_eventlog.la \
|
||||||
|
+ $(top_builddir)/lib/util/libsudo_util.la
|
||||||
|
LIBS = @LIBS@ @ZLIB@ $(LT_LIBS)
|
||||||
|
|
||||||
|
# C preprocessor flags
|
||||||
|
@@ -76,7 +77,7 @@ PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
|
||||||
|
|
||||||
|
# Regression tests
|
||||||
|
TEST_PROGS = check_iolog_json check_iolog_mkpath check_iolog_path check_iolog_util host_port_test
|
||||||
|
-TEST_LIBS = @LIBS@ $(top_builddir)/lib/eventlog/libsudo_eventlog.la
|
||||||
|
+TEST_LIBS = @LIBS@
|
||||||
|
TEST_LDFLAGS = @LDFLAGS@
|
||||||
|
|
||||||
|
# Set to non-empty for development mode
|
||||||
|
diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in
|
||||||
|
index 77d54553b..8eadf479d 100644
|
||||||
|
--- a/plugins/sudoers/Makefile.in
|
||||||
|
+++ b/plugins/sudoers/Makefile.in
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
#
|
||||||
|
-# Copyright (c) 1996, 1998-2005, 2007-2020
|
||||||
|
+# Copyright (c) 1996, 1998-2005, 2007-2021
|
||||||
|
# Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and distribute this software for any
|
||||||
|
@@ -61,8 +61,8 @@ LIBLOGSRV = @LIBLOGSRV@
|
||||||
|
LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
|
||||||
|
LIBS = $(LIBUTIL)
|
||||||
|
NET_LIBS = @NET_LIBS@
|
||||||
|
-SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ @LIBTLS@ $(NET_LIBS) $(LIBIOLOG) $(LIBEVENTLOG) $(LIBLOGSRV)
|
||||||
|
-REPLAY_LIBS = @REPLAY_LIBS@ $(LIBEVENTLOG) $(LIBIOLOG)
|
||||||
|
+SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ @LIBTLS@ $(NET_LIBS) $(LIBIOLOG) $(LIBLOGSRV)
|
||||||
|
+REPLAY_LIBS = @REPLAY_LIBS@ $(LIBIOLOG)
|
||||||
|
VISUDO_LIBS = $(NET_LIBS)
|
||||||
|
CVTSUDOERS_LIBS = $(NET_LIBS)
|
||||||
|
TESTSUDOERS_LIBS = $(NET_LIBS)
|
||||||
|
@@ -323,7 +323,7 @@ check_hexchar: $(CHECK_HEXCHAR_OBJS) $(LIBUTIL)
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_HEXCHAR_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
check_iolog_plugin: $(CHECK_IOLOG_PLUGIN_OBJS) $(LIBUTIL) $(LIBIOLOG) $(LIBLOGSRV)
|
||||||
|
- $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBIOLOG) $(LIBEVENTLOG) $(LIBLOGSRV) @LIBTLS@
|
||||||
|
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBIOLOG) $(LIBLOGSRV) @LIBTLS@
|
||||||
|
|
||||||
|
check_starttime: $(CHECK_STARTTIME_OBJS) $(LIBUTIL)
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_STARTTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -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
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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:
|
|
||||||
|
|
@ -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;
|
|
@ -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) {
|
|
@ -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 */
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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 != '$')
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
@ -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)
|
|
@ -1,19 +1,19 @@
|
|||||||
diff -up ./plugins/sudoers/editor.c.cve ./plugins/sudoers/editor.c
|
diff -up ./plugins/sudoers/editor.c.cve ./plugins/sudoers/editor.c
|
||||||
--- ./plugins/sudoers/editor.c.cve 2023-01-16 17:52:37.074066664 +0100
|
--- ./plugins/sudoers/editor.c.cve 2021-01-09 21:12:16.000000000 +0100
|
||||||
+++ ./plugins/sudoers/editor.c 2023-01-16 17:58:06.603774304 +0100
|
+++ ./plugins/sudoers/editor.c 2023-01-17 13:57:05.598949058 +0100
|
||||||
@@ -132,7 +132,7 @@ resolve_editor(const char *ed, size_t ed
|
@@ -126,7 +126,7 @@ resolve_editor(const char *ed, size_t ed
|
||||||
const char *cp, *ep, *tmp;
|
const char *tmp, *cp, *ep = NULL;
|
||||||
const char *edend = ed + edlen;
|
const char *edend = ed + edlen;
|
||||||
struct stat user_editor_sb;
|
struct stat user_editor_sb;
|
||||||
- int nargc;
|
- int nargc;
|
||||||
+ int nargc = 0;
|
+ int nargc = 0;
|
||||||
debug_decl(resolve_editor, SUDOERS_DEBUG_UTIL)
|
debug_decl(resolve_editor, SUDOERS_DEBUG_UTIL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -149,9 +149,7 @@ resolve_editor(const char *ed, size_t ed
|
@@ -144,9 +144,7 @@ resolve_editor(const char *ed, size_t ed
|
||||||
|
|
||||||
/* If we can't find the editor in the user's PATH, give up. */
|
/* 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) {
|
if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"), NULL,
|
||||||
|
0, allowlist) != FOUND) {
|
||||||
- free(editor);
|
- free(editor);
|
||||||
- errno = ENOENT;
|
- errno = ENOENT;
|
||||||
- debug_return_str(NULL);
|
- debug_return_str(NULL);
|
||||||
@ -21,7 +21,7 @@ diff -up ./plugins/sudoers/editor.c.cve ./plugins/sudoers/editor.c
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Count rest of arguments and allocate editor argv. */
|
/* Count rest of arguments and allocate editor argv. */
|
||||||
@@ -171,7 +169,19 @@ resolve_editor(const char *ed, size_t ed
|
@@ -166,6 +164,18 @@ resolve_editor(const char *ed, size_t ed
|
||||||
nargv[nargc] = copy_arg(cp, ep - cp);
|
nargv[nargc] = copy_arg(cp, ep - cp);
|
||||||
if (nargv[nargc] == NULL)
|
if (nargv[nargc] == NULL)
|
||||||
goto oom;
|
goto oom;
|
||||||
@ -36,12 +36,11 @@ diff -up ./plugins/sudoers/editor.c.cve ./plugins/sudoers/editor.c
|
|||||||
+ errno = EINVAL;
|
+ errno = EINVAL;
|
||||||
+ goto bad;
|
+ goto bad;
|
||||||
+ }
|
+ }
|
||||||
}
|
|
||||||
+
|
+
|
||||||
|
}
|
||||||
if (nfiles != 0) {
|
if (nfiles != 0) {
|
||||||
nargv[nargc++] = "--";
|
nargv[nargc++] = "--";
|
||||||
while (nfiles--)
|
@@ -179,6 +189,7 @@ resolve_editor(const char *ed, size_t ed
|
||||||
@@ -184,6 +194,7 @@ resolve_editor(const char *ed, size_t ed
|
|
||||||
debug_return_str(editor_path);
|
debug_return_str(editor_path);
|
||||||
oom:
|
oom:
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
@ -50,16 +49,17 @@ diff -up ./plugins/sudoers/editor.c.cve ./plugins/sudoers/editor.c
|
|||||||
free(editor_path);
|
free(editor_path);
|
||||||
if (nargv != NULL) {
|
if (nargv != NULL) {
|
||||||
diff -up ./plugins/sudoers/sudoers.c.cve ./plugins/sudoers/sudoers.c
|
diff -up ./plugins/sudoers/sudoers.c.cve ./plugins/sudoers/sudoers.c
|
||||||
--- ./plugins/sudoers/sudoers.c.cve 2023-01-16 17:52:37.074066664 +0100
|
--- ./plugins/sudoers/sudoers.c.cve 2023-01-17 13:50:33.718255775 +0100
|
||||||
+++ ./plugins/sudoers/sudoers.c 2023-01-16 18:02:43.928307505 +0100
|
+++ ./plugins/sudoers/sudoers.c 2023-01-17 14:00:53.049710094 +0100
|
||||||
@@ -634,21 +634,32 @@ sudoers_policy_main(int argc, char * con
|
@@ -724,21 +724,34 @@ sudoers_policy_main(int argc, char * con
|
||||||
|
|
||||||
/* Note: must call audit before uid change. */
|
/* Note: must call audit before uid change. */
|
||||||
if (ISSET(sudo_mode, MODE_EDIT)) {
|
if (ISSET(sudo_mode, MODE_EDIT)) {
|
||||||
- int edit_argc;
|
+ const char *env_editor = NULL;
|
||||||
|
char **edit_argv;
|
||||||
|
int edit_argc;
|
||||||
- const char *env_editor;
|
- const char *env_editor;
|
||||||
+ const char *env_editor = NULL;
|
+
|
||||||
+ int edit_argc;
|
|
||||||
|
|
||||||
free(safe_cmnd);
|
free(safe_cmnd);
|
||||||
safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argc,
|
safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argc,
|
||||||
@ -67,47 +67,46 @@ diff -up ./plugins/sudoers/sudoers.c.cve ./plugins/sudoers/sudoers.c
|
|||||||
if (safe_cmnd == NULL) {
|
if (safe_cmnd == NULL) {
|
||||||
- if (errno != ENOENT)
|
- if (errno != ENOENT)
|
||||||
- goto done;
|
- goto done;
|
||||||
- audit_failure(NewArgc, NewArgv, N_("%s: command not found"),
|
- audit_failure(NewArgv, N_("%s: command not found"),
|
||||||
- env_editor ? env_editor : def_editor);
|
- env_editor ? env_editor : def_editor);
|
||||||
- sudo_warnx(U_("%s: command not found"),
|
- sudo_warnx(U_("%s: command not found"),
|
||||||
- env_editor ? env_editor : def_editor);
|
- env_editor ? env_editor : def_editor);
|
||||||
- goto bad;
|
- goto bad;
|
||||||
- }
|
|
||||||
+ switch (errno) {
|
|
||||||
+ case ENOENT:
|
|
||||||
+ audit_failure(NewArgc, NewArgv, N_("%s: command not found"),
|
|
||||||
+ env_editor ? env_editor : def_editor);
|
|
||||||
+ sudo_warnx(U_("%s: command not found"),
|
|
||||||
+ env_editor ? env_editor : def_editor);
|
|
||||||
+ goto bad;
|
|
||||||
+ case EINVAL:
|
|
||||||
+ if (def_env_editor && env_editor != NULL) {
|
|
||||||
+ /* User tried to do something funny with the editor. */
|
|
||||||
+ log_warningx(SLOG_NO_STDERR|SLOG_SEND_MAIL,
|
|
||||||
+ "invalid user-specified editor: %s", env_editor);
|
|
||||||
+ goto bad;
|
|
||||||
+ }
|
|
||||||
+ default:
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
+
|
||||||
if (audit_success(edit_argc, edit_argv) != 0 && !def_ignore_audit_errors)
|
+ switch (errno) {
|
||||||
goto done;
|
+ case ENOENT:
|
||||||
|
+ audit_failure(NewArgv, N_("%s: command not found"),
|
||||||
|
+ env_editor ? env_editor : def_editor);
|
||||||
|
+ sudo_warnx(U_("%s: command not found"),
|
||||||
|
+ env_editor ? env_editor : def_editor);
|
||||||
|
+ goto bad;
|
||||||
|
+ case EINVAL:
|
||||||
|
+ if (def_env_editor && env_editor != NULL) {
|
||||||
|
+ /* User tried to do something funny with the editor. */
|
||||||
|
+ log_warningx(SLOG_NO_STDERR|SLOG_AUDIT|SLOG_SEND_MAIL,
|
||||||
|
+ "invalid user-specified editor: %s", env_editor);
|
||||||
|
+ goto bad;
|
||||||
|
+ }
|
||||||
|
+ FALLTHROUGH;
|
||||||
|
+ default:
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
sudoers_gc_add(GC_VECTOR, edit_argv);
|
||||||
|
NewArgv = edit_argv;
|
||||||
diff -up ./plugins/sudoers/visudo.c.cve ./plugins/sudoers/visudo.c
|
diff -up ./plugins/sudoers/visudo.c.cve ./plugins/sudoers/visudo.c
|
||||||
--- ./plugins/sudoers/visudo.c.cve 2019-10-28 13:28:54.000000000 +0100
|
--- ./plugins/sudoers/visudo.c.cve 2021-01-09 21:12:16.000000000 +0100
|
||||||
+++ ./plugins/sudoers/visudo.c 2023-01-16 18:03:48.713975354 +0100
|
+++ ./plugins/sudoers/visudo.c 2023-01-17 14:02:01.393135129 +0100
|
||||||
@@ -308,7 +308,7 @@ static char *
|
@@ -303,7 +303,7 @@ static char *
|
||||||
get_editor(int *editor_argc, char ***editor_argv)
|
get_editor(int *editor_argc, char ***editor_argv)
|
||||||
{
|
{
|
||||||
char *editor_path = NULL, **whitelist = NULL;
|
char *editor_path = NULL, **allowlist = NULL;
|
||||||
- const char *env_editor;
|
- const char *env_editor;
|
||||||
+ const char *env_editor = NULL;
|
+ const char *env_editor = NULL;
|
||||||
static char *files[] = { "+1", "sudoers" };
|
static char *files[] = { "+1", "sudoers" };
|
||||||
unsigned int whitelist_len = 0;
|
unsigned int allowlist_len = 0;
|
||||||
debug_decl(get_editor, SUDOERS_DEBUG_UTIL)
|
debug_decl(get_editor, SUDOERS_DEBUG_UTIL);
|
||||||
@@ -342,7 +342,11 @@ get_editor(int *editor_argc, char ***edi
|
@@ -337,7 +337,11 @@ get_editor(int *editor_argc, char ***edi
|
||||||
if (editor_path == NULL) {
|
if (editor_path == NULL) {
|
||||||
if (def_env_editor && env_editor != NULL) {
|
if (def_env_editor && env_editor != NULL) {
|
||||||
/* We are honoring $EDITOR so this is a fatal error. */
|
/* We are honoring $EDITOR so this is a fatal error. */
|
||||||
|
31
SOURCES/sudo-1.9.13-CVE-2023-28486-7-1.patch
Normal file
31
SOURCES/sudo-1.9.13-CVE-2023-28486-7-1.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
From e5c1778e7dd32ff3ed8cf969540404c9c0e6d5a1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Thu, 18 Feb 2021 08:32:13 -0700
|
||||||
|
Subject: [PATCH] When logging JSON to syslog, wrap the contents in a "sudo"
|
||||||
|
object. This makes it easier for log parsers to identify what is a sudo log
|
||||||
|
entry.
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/eventlog/eventlog.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index 1f0183b1b..e6f744da5 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -950,10 +950,10 @@ do_syslog_json(int pri, int event_type, const char *reason,
|
||||||
|
if (json_str == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
- /* Syslog it with a @cee: prefix */
|
||||||
|
+ /* Syslog it in a sudo object with a @cee: prefix. */
|
||||||
|
/* TODO: use evl_conf.syslog_maxlen to break up long messages. */
|
||||||
|
evl_conf.open_log(EVLOG_SYSLOG, NULL);
|
||||||
|
- syslog(pri, "@cee:{%s}", json_str);
|
||||||
|
+ syslog(pri, "@cee:{\"sudo\":{%s}}", json_str);
|
||||||
|
evl_conf.close_log(EVLOG_SYSLOG, NULL);
|
||||||
|
free(json_str);
|
||||||
|
debug_return_bool(true);
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
187
SOURCES/sudo-1.9.13-CVE-2023-28486-7-2.patch
Normal file
187
SOURCES/sudo-1.9.13-CVE-2023-28486-7-2.patch
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
From f399c449ad6fc7412588998aa92b52323ef63ee5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Wed, 24 Feb 2021 13:59:17 -0700
|
||||||
|
Subject: [PATCH] Move eventlog_free() into its own file.
|
||||||
|
|
||||||
|
---
|
||||||
|
MANIFEST | 1 +
|
||||||
|
lib/eventlog/Makefile.in | 14 ++++++-
|
||||||
|
lib/eventlog/eventlog.c | 37 ------------------
|
||||||
|
lib/eventlog/eventlog_free.c | 73 ++++++++++++++++++++++++++++++++++++
|
||||||
|
4 files changed, 87 insertions(+), 38 deletions(-)
|
||||||
|
create mode 100644 lib/eventlog/eventlog_free.c
|
||||||
|
|
||||||
|
diff --git a/MANIFEST b/MANIFEST
|
||||||
|
index 8c5a57ae8..a2bed131d 100644
|
||||||
|
--- a/MANIFEST
|
||||||
|
+++ b/MANIFEST
|
||||||
|
@@ -104,6 +104,7 @@ include/sudo_util.h
|
||||||
|
install-sh
|
||||||
|
lib/eventlog/Makefile.in
|
||||||
|
lib/eventlog/eventlog.c
|
||||||
|
+lib/eventlog/eventlog_free.c
|
||||||
|
lib/eventlog/logwrap.c
|
||||||
|
lib/eventlog/regress/logwrap/check_wrap.c
|
||||||
|
lib/eventlog/regress/logwrap/check_wrap.in
|
||||||
|
diff --git a/lib/eventlog/Makefile.in b/lib/eventlog/Makefile.in
|
||||||
|
index 8790ac1ae..24c2dbce9 100644
|
||||||
|
--- a/lib/eventlog/Makefile.in
|
||||||
|
+++ b/lib/eventlog/Makefile.in
|
||||||
|
@@ -82,7 +82,7 @@ SHELL = @SHELL@
|
||||||
|
|
||||||
|
TEST_PROGS = check_wrap
|
||||||
|
|
||||||
|
-LIBEVENTLOG_OBJS = eventlog.lo logwrap.lo
|
||||||
|
+LIBEVENTLOG_OBJS = eventlog.lo eventlog_free.lo logwrap.lo
|
||||||
|
|
||||||
|
IOBJS = $(LIBEVENTLOG_OBJS:.lo=.i)
|
||||||
|
|
||||||
|
@@ -213,6 +213,18 @@ eventlog.i: $(srcdir)/eventlog.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
eventlog.plog: eventlog.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog.c --i-file $< --output-file $@
|
||||||
|
+eventlog_free.lo: $(srcdir)/eventlog_free.c $(incdir)/compat/stdbool.h \
|
||||||
|
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
+ $(incdir)/sudo_eventlog.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)/eventlog_free.c
|
||||||
|
+eventlog_free.i: $(srcdir)/eventlog_free.c $(incdir)/compat/stdbool.h \
|
||||||
|
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
|
||||||
|
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||||
|
+ $(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
+eventlog_free.plog: eventlog_free.i
|
||||||
|
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog_free.c --i-file $< --output-file $@
|
||||||
|
logwrap.lo: $(srcdir)/logwrap.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index e6f744da5..c8c9b7ba5 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -1256,43 +1256,6 @@ eventlog_alert(const struct eventlog *evlog, int flags,
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * Free the strings in a struct eventlog.
|
||||||
|
- */
|
||||||
|
-void
|
||||||
|
-eventlog_free(struct eventlog *evlog)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
- debug_decl(eventlog_free, SUDO_DEBUG_UTIL);
|
||||||
|
-
|
||||||
|
- if (evlog != NULL) {
|
||||||
|
- free(evlog->iolog_path);
|
||||||
|
- free(evlog->command);
|
||||||
|
- free(evlog->cwd);
|
||||||
|
- free(evlog->runchroot);
|
||||||
|
- free(evlog->runcwd);
|
||||||
|
- free(evlog->rungroup);
|
||||||
|
- free(evlog->runuser);
|
||||||
|
- free(evlog->submithost);
|
||||||
|
- free(evlog->submituser);
|
||||||
|
- free(evlog->submitgroup);
|
||||||
|
- free(evlog->ttyname);
|
||||||
|
- if (evlog->argv != NULL) {
|
||||||
|
- for (i = 0; evlog->argv[i] != NULL; i++)
|
||||||
|
- free(evlog->argv[i]);
|
||||||
|
- free(evlog->argv);
|
||||||
|
- }
|
||||||
|
- if (evlog->envp != NULL) {
|
||||||
|
- for (i = 0; evlog->envp[i] != NULL; i++)
|
||||||
|
- free(evlog->envp[i]);
|
||||||
|
- free(evlog->envp);
|
||||||
|
- }
|
||||||
|
- free(evlog);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- debug_return;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static FILE *
|
||||||
|
eventlog_stub_open_log(int type, const char *logfile)
|
||||||
|
{
|
||||||
|
diff --git a/lib/eventlog/eventlog_free.c b/lib/eventlog/eventlog_free.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..49583b61c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/lib/eventlog/eventlog_free.c
|
||||||
|
@@ -0,0 +1,73 @@
|
||||||
|
+/*
|
||||||
|
+ * SPDX-License-Identifier: ISC
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ *
|
||||||
|
+ * Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * 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 <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+#include "sudo_compat.h"
|
||||||
|
+#include "sudo_debug.h"
|
||||||
|
+#include "sudo_eventlog.h"
|
||||||
|
+#include "sudo_util.h"
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Free the strings in a struct eventlog.
|
||||||
|
+ */
|
||||||
|
+void
|
||||||
|
+eventlog_free(struct eventlog *evlog)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+ debug_decl(eventlog_free, SUDO_DEBUG_UTIL);
|
||||||
|
+
|
||||||
|
+ if (evlog != NULL) {
|
||||||
|
+ free(evlog->iolog_path);
|
||||||
|
+ free(evlog->command);
|
||||||
|
+ free(evlog->cwd);
|
||||||
|
+ free(evlog->runchroot);
|
||||||
|
+ free(evlog->runcwd);
|
||||||
|
+ free(evlog->rungroup);
|
||||||
|
+ free(evlog->runuser);
|
||||||
|
+ free(evlog->submithost);
|
||||||
|
+ free(evlog->submituser);
|
||||||
|
+ free(evlog->submitgroup);
|
||||||
|
+ free(evlog->ttyname);
|
||||||
|
+ if (evlog->argv != NULL) {
|
||||||
|
+ for (i = 0; evlog->argv[i] != NULL; i++)
|
||||||
|
+ free(evlog->argv[i]);
|
||||||
|
+ free(evlog->argv);
|
||||||
|
+ }
|
||||||
|
+ if (evlog->envp != NULL) {
|
||||||
|
+ for (i = 0; evlog->envp[i] != NULL; i++)
|
||||||
|
+ free(evlog->envp[i]);
|
||||||
|
+ free(evlog->envp);
|
||||||
|
+ }
|
||||||
|
+ free(evlog);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ debug_return;
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
884
SOURCES/sudo-1.9.13-CVE-2023-28486-7-3.patch
Normal file
884
SOURCES/sudo-1.9.13-CVE-2023-28486-7-3.patch
Normal file
@ -0,0 +1,884 @@
|
|||||||
|
From 412858272365f0e6d6f8873e794f64374da8fa06 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Wed, 24 Feb 2021 14:25:39 -0700
|
||||||
|
Subject: [PATCH] Move eventlog config code into eventlog_conf.c
|
||||||
|
|
||||||
|
---
|
||||||
|
MANIFEST | 1 +
|
||||||
|
include/sudo_eventlog.h | 3 +-
|
||||||
|
lib/eventlog/Makefile.in | 20 ++-
|
||||||
|
lib/eventlog/eventlog.c | 292 +++++++----------------------------
|
||||||
|
lib/eventlog/eventlog_conf.c | 226 +++++++++++++++++++++++++++
|
||||||
|
5 files changed, 303 insertions(+), 239 deletions(-)
|
||||||
|
create mode 100644 lib/eventlog/eventlog_conf.c
|
||||||
|
|
||||||
|
diff --git a/MANIFEST b/MANIFEST
|
||||||
|
index a2bed131d..c960e3e8b 100644
|
||||||
|
--- a/MANIFEST
|
||||||
|
+++ b/MANIFEST
|
||||||
|
@@ -104,6 +104,7 @@ include/sudo_util.h
|
||||||
|
install-sh
|
||||||
|
lib/eventlog/Makefile.in
|
||||||
|
lib/eventlog/eventlog.c
|
||||||
|
+lib/eventlog/eventlog_conf.c
|
||||||
|
lib/eventlog/eventlog_free.c
|
||||||
|
lib/eventlog/logwrap.c
|
||||||
|
lib/eventlog/regress/logwrap/check_wrap.c
|
||||||
|
diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h
|
||||||
|
index 127ee5dd8..e40622a51 100644
|
||||||
|
--- a/include/sudo_eventlog.h
|
||||||
|
+++ b/include/sudo_eventlog.h
|
||||||
|
@@ -66,7 +66,7 @@ enum eventlog_format {
|
||||||
|
#define EVENTLOG_INDENT " "
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Event log config, used with eventlog_setconf()
|
||||||
|
+ * Event log config, used with eventlog_getconf()
|
||||||
|
*/
|
||||||
|
struct eventlog_config {
|
||||||
|
int type;
|
||||||
|
@@ -144,5 +144,6 @@ void eventlog_set_mailto(const char *to_addr);
|
||||||
|
void eventlog_set_mailsub(const char *subject);
|
||||||
|
void eventlog_set_open_log(FILE *(*fn)(int type, const char *));
|
||||||
|
void eventlog_set_close_log(void (*fn)(int type, FILE *));
|
||||||
|
+const struct eventlog_config *eventlog_getconf(void);
|
||||||
|
|
||||||
|
#endif /* SUDO_EVENTLOG_H */
|
||||||
|
diff --git a/lib/eventlog/Makefile.in b/lib/eventlog/Makefile.in
|
||||||
|
index 24c2dbce9..02236f70b 100644
|
||||||
|
--- a/lib/eventlog/Makefile.in
|
||||||
|
+++ b/lib/eventlog/Makefile.in
|
||||||
|
@@ -82,7 +82,7 @@ SHELL = @SHELL@
|
||||||
|
|
||||||
|
TEST_PROGS = check_wrap
|
||||||
|
|
||||||
|
-LIBEVENTLOG_OBJS = eventlog.lo eventlog_free.lo logwrap.lo
|
||||||
|
+LIBEVENTLOG_OBJS = eventlog.lo eventlog_conf.lo eventlog_free.lo logwrap.lo
|
||||||
|
|
||||||
|
IOBJS = $(LIBEVENTLOG_OBJS:.lo=.i)
|
||||||
|
|
||||||
|
@@ -213,6 +213,24 @@ eventlog.i: $(srcdir)/eventlog.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
eventlog.plog: eventlog.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog.c --i-file $< --output-file $@
|
||||||
|
+eventlog_conf.lo: $(srcdir)/eventlog_conf.c $(incdir)/compat/stdbool.h \
|
||||||
|
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
||||||
|
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
|
||||||
|
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
|
||||||
|
+ $(top_builddir)/pathnames.h
|
||||||
|
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/eventlog_conf.c
|
||||||
|
+eventlog_conf.i: $(srcdir)/eventlog_conf.c $(incdir)/compat/stdbool.h \
|
||||||
|
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
||||||
|
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
|
||||||
|
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||||
|
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
|
||||||
|
+ $(top_builddir)/pathnames.h
|
||||||
|
+ $(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
+eventlog_conf.plog: eventlog_conf.i
|
||||||
|
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog_conf.c --i-file $< --output-file $@
|
||||||
|
eventlog_free.lo: $(srcdir)/eventlog_free.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index c8c9b7ba5..e7505d9d9 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -75,35 +75,6 @@
|
||||||
|
isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \
|
||||||
|
(s)[8] == '\0')
|
||||||
|
|
||||||
|
-static FILE *eventlog_stub_open_log(int type, const char *logfile);
|
||||||
|
-static void eventlog_stub_close_log(int type, FILE *fp);
|
||||||
|
-
|
||||||
|
-/* Eventlog config settings (default values). */
|
||||||
|
-static struct eventlog_config evl_conf = {
|
||||||
|
- EVLOG_NONE, /* type */
|
||||||
|
- EVLOG_SUDO, /* format */
|
||||||
|
- LOG_NOTICE, /* syslog_acceptpri */
|
||||||
|
- LOG_ALERT, /* syslog_rejectpri */
|
||||||
|
- LOG_ALERT, /* syslog_alertpri */
|
||||||
|
- MAXSYSLOGLEN, /* syslog_maxlen */
|
||||||
|
- 0, /* file_maxlen */
|
||||||
|
- ROOT_UID, /* mailuid */
|
||||||
|
- false, /* omit_hostname */
|
||||||
|
- _PATH_SUDO_LOGFILE, /* logpath */
|
||||||
|
- "%h %e %T", /* time_fmt */
|
||||||
|
-#ifdef _PATH_SUDO_SENDMAIL
|
||||||
|
- _PATH_SUDO_SENDMAIL, /* mailerpath */
|
||||||
|
-#else
|
||||||
|
- NULL, /* mailerpath (disabled) */
|
||||||
|
-#endif
|
||||||
|
- "-t", /* mailerflags */
|
||||||
|
- NULL, /* mailfrom */
|
||||||
|
- MAILTO, /* mailto */
|
||||||
|
- N_(MAILSUBJECT), /* mailsub */
|
||||||
|
- eventlog_stub_open_log, /* open_log */
|
||||||
|
- eventlog_stub_close_log /* close_log */
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Allocate and fill in a new logline.
|
||||||
|
*/
|
||||||
|
@@ -111,6 +82,7 @@ static char *
|
||||||
|
new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *line = NULL, *evstr = NULL;
|
||||||
|
const char *iolog_file = evlog->iolog_file;
|
||||||
|
const char *tty, *tsid = NULL;
|
||||||
|
@@ -159,7 +131,7 @@ new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
len += strlen(message) + 3;
|
||||||
|
if (errstr != NULL)
|
||||||
|
len += strlen(errstr) + 3;
|
||||||
|
- if (evlog->submithost != NULL && !evl_conf.omit_hostname)
|
||||||
|
+ if (evlog->submithost != NULL && !evl_conf->omit_hostname)
|
||||||
|
len += sizeof(LL_HOST_STR) + 2 + strlen(evlog->submithost);
|
||||||
|
if (tty != NULL)
|
||||||
|
len += sizeof(LL_TTY_STR) + 2 + strlen(tty);
|
||||||
|
@@ -218,7 +190,7 @@ new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
strlcat(line, " ; ", len) >= len)
|
||||||
|
goto toobig;
|
||||||
|
}
|
||||||
|
- if (evlog->submithost != NULL && !evl_conf.omit_hostname) {
|
||||||
|
+ if (evlog->submithost != NULL && !evl_conf->omit_hostname) {
|
||||||
|
if (strlcat(line, LL_HOST_STR, len) >= len ||
|
||||||
|
strlcat(line, evlog->submithost, len) >= len ||
|
||||||
|
strlcat(line, " ; ", len) >= len)
|
||||||
|
@@ -331,8 +303,9 @@ closefrom_nodebug(int lowfd)
|
||||||
|
static void __attribute__((__noreturn__))
|
||||||
|
exec_mailer(int pipein)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *last, *mflags, *p, *argv[MAX_MAILFLAGS + 1];
|
||||||
|
- const char *mpath = evl_conf.mailerpath;
|
||||||
|
+ const char *mpath = evl_conf->mailerpath;
|
||||||
|
int i;
|
||||||
|
char * const root_envp[] = {
|
||||||
|
"HOME=/",
|
||||||
|
@@ -356,7 +329,7 @@ exec_mailer(int pipein)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build up an argv based on the mailer path and flags */
|
||||||
|
- if ((mflags = strdup(evl_conf.mailerflags)) == NULL) {
|
||||||
|
+ if ((mflags = strdup(evl_conf->mailerflags)) == NULL) {
|
||||||
|
syslog(LOG_ERR, _("unable to allocate memory")); // -V618
|
||||||
|
sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
|
||||||
|
_exit(127);
|
||||||
|
@@ -379,14 +352,14 @@ exec_mailer(int pipein)
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change uid to %u",
|
||||||
|
ROOT_UID);
|
||||||
|
}
|
||||||
|
- if (evl_conf.mailuid != ROOT_UID) {
|
||||||
|
- if (setuid(evl_conf.mailuid) != 0) {
|
||||||
|
+ if (evl_conf->mailuid != ROOT_UID) {
|
||||||
|
+ if (setuid(evl_conf->mailuid) != 0) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change uid to %u",
|
||||||
|
- (unsigned int)evl_conf.mailuid);
|
||||||
|
+ (unsigned int)evl_conf->mailuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
|
||||||
|
- if (evl_conf.mailuid == ROOT_UID)
|
||||||
|
+ if (evl_conf->mailuid == ROOT_UID)
|
||||||
|
execve(mpath, argv, root_envp);
|
||||||
|
else
|
||||||
|
execv(mpath, argv);
|
||||||
|
@@ -400,7 +373,8 @@ exec_mailer(int pipein)
|
||||||
|
static bool
|
||||||
|
send_mail(const struct eventlog *evlog, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
- const char *cp, *timefmt = evl_conf.time_fmt;
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const char *cp, *timefmt = evl_conf->time_fmt;
|
||||||
|
char timebuf[1024];
|
||||||
|
struct tm *tm;
|
||||||
|
time_t now;
|
||||||
|
@@ -415,11 +389,11 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
|
||||||
|
debug_decl(send_mail, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/* If mailer is disabled just return. */
|
||||||
|
- if (evl_conf.mailerpath == NULL || evl_conf.mailto == NULL)
|
||||||
|
+ if (evl_conf->mailerpath == NULL || evl_conf->mailto == NULL)
|
||||||
|
debug_return_bool(true);
|
||||||
|
|
||||||
|
/* Make sure the mailer exists and is a regular file. */
|
||||||
|
- if (stat(evl_conf.mailerpath, &sb) != 0 || !S_ISREG(sb.st_mode))
|
||||||
|
+ if (stat(evl_conf->mailerpath, &sb) != 0 || !S_ISREG(sb.st_mode))
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
@@ -516,11 +490,11 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
|
||||||
|
|
||||||
|
/* Pipes are all setup, send message. */
|
||||||
|
(void) fprintf(mail, "To: %s\nFrom: %s\nAuto-Submitted: %s\nSubject: ",
|
||||||
|
- evl_conf.mailto,
|
||||||
|
- evl_conf.mailfrom ? evl_conf.mailfrom :
|
||||||
|
+ evl_conf->mailto,
|
||||||
|
+ evl_conf->mailfrom ? evl_conf->mailfrom :
|
||||||
|
(evlog ? evlog->submituser : "root"),
|
||||||
|
"auto-generated");
|
||||||
|
- for (cp = _(evl_conf.mailsub); *cp; cp++) {
|
||||||
|
+ for (cp = _(evl_conf->mailsub); *cp; cp++) {
|
||||||
|
/* Expand escapes in the subject */
|
||||||
|
if (*cp == '%' && *(cp+1) != '%') {
|
||||||
|
switch (*(++cp)) {
|
||||||
|
@@ -576,7 +550,8 @@ static bool
|
||||||
|
json_add_timestamp(struct json_container *json, const char *name,
|
||||||
|
const struct timespec *ts)
|
||||||
|
{
|
||||||
|
- const char *timefmt = evl_conf.time_fmt;
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const char *timefmt = evl_conf->time_fmt;
|
||||||
|
struct json_value json_value;
|
||||||
|
time_t secs = ts->tv_sec;
|
||||||
|
char timebuf[1024];
|
||||||
|
@@ -880,12 +855,13 @@ bad:
|
||||||
|
static bool
|
||||||
|
do_syslog_sudo(int pri, char *logline, const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
size_t len, maxlen;
|
||||||
|
char *p, *tmp, save;
|
||||||
|
const char *fmt;
|
||||||
|
debug_decl(do_syslog_sudo, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
- evl_conf.open_log(EVLOG_SYSLOG, NULL);
|
||||||
|
+ evl_conf->open_log(EVLOG_SYSLOG, NULL);
|
||||||
|
|
||||||
|
if (evlog == NULL) {
|
||||||
|
/* Not a command, just log it as-is. */
|
||||||
|
@@ -897,7 +873,7 @@ do_syslog_sudo(int pri, char *logline, const struct eventlog *evlog)
|
||||||
|
* Log the full line, breaking into multiple syslog(3) calls if necessary
|
||||||
|
*/
|
||||||
|
fmt = _("%8s : %s");
|
||||||
|
- maxlen = evl_conf.syslog_maxlen -
|
||||||
|
+ maxlen = evl_conf->syslog_maxlen -
|
||||||
|
(strlen(fmt) - 5 + strlen(evlog->submituser));
|
||||||
|
for (p = logline; *p != '\0'; ) {
|
||||||
|
len = strlen(p);
|
||||||
|
@@ -926,11 +902,11 @@ do_syslog_sudo(int pri, char *logline, const struct eventlog *evlog)
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
fmt = _("%8s : (command continued) %s");
|
||||||
|
- maxlen = evl_conf.syslog_maxlen -
|
||||||
|
+ maxlen = evl_conf->syslog_maxlen -
|
||||||
|
(strlen(fmt) - 5 + strlen(evlog->submituser));
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
- evl_conf.close_log(EVLOG_SYSLOG, NULL);
|
||||||
|
+ evl_conf->close_log(EVLOG_SYSLOG, NULL);
|
||||||
|
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
@@ -941,6 +917,7 @@ do_syslog_json(int pri, int event_type, const char *reason,
|
||||||
|
const struct timespec *event_time,
|
||||||
|
eventlog_json_callback_t info_cb, void *info)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *json_str;
|
||||||
|
debug_decl(do_syslog_json, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
@@ -951,10 +928,10 @@ do_syslog_json(int pri, int event_type, const char *reason,
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
/* Syslog it in a sudo object with a @cee: prefix. */
|
||||||
|
- /* TODO: use evl_conf.syslog_maxlen to break up long messages. */
|
||||||
|
- evl_conf.open_log(EVLOG_SYSLOG, NULL);
|
||||||
|
+ /* TODO: use evl_conf->syslog_maxlen to break up long messages. */
|
||||||
|
+ evl_conf->open_log(EVLOG_SYSLOG, NULL);
|
||||||
|
syslog(pri, "@cee:{\"sudo\":{%s}}", json_str);
|
||||||
|
- evl_conf.close_log(EVLOG_SYSLOG, NULL);
|
||||||
|
+ evl_conf->close_log(EVLOG_SYSLOG, NULL);
|
||||||
|
free(json_str);
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
@@ -967,13 +944,14 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
eventlog_json_callback_t info_cb, void *info)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *logline = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
int pri;
|
||||||
|
debug_decl(do_syslog, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/* Sudo format logs and mailed logs use the same log line format. */
|
||||||
|
- if (evl_conf.format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
|
||||||
|
+ if (evl_conf->format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
|
||||||
|
logline = new_logline(flags, reason, errstr, evlog);
|
||||||
|
if (logline == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
@@ -992,13 +970,13 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
|
||||||
|
switch (event_type) {
|
||||||
|
case EVLOG_ACCEPT:
|
||||||
|
- pri = evl_conf.syslog_acceptpri;
|
||||||
|
+ pri = evl_conf->syslog_acceptpri;
|
||||||
|
break;
|
||||||
|
case EVLOG_REJECT:
|
||||||
|
- pri = evl_conf.syslog_rejectpri;
|
||||||
|
+ pri = evl_conf->syslog_rejectpri;
|
||||||
|
break;
|
||||||
|
case EVLOG_ALERT:
|
||||||
|
- pri = evl_conf.syslog_alertpri;
|
||||||
|
+ pri = evl_conf->syslog_alertpri;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
@@ -1012,7 +990,7 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (evl_conf.format) {
|
||||||
|
+ switch (evl_conf->format) {
|
||||||
|
case EVLOG_SUDO:
|
||||||
|
ret = do_syslog_sudo(pri, logline, evlog);
|
||||||
|
break;
|
||||||
|
@@ -1022,7 +1000,7 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
- "unexpected eventlog format %d", evl_conf.format);
|
||||||
|
+ "unexpected eventlog format %d", evl_conf->format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(logline);
|
||||||
|
@@ -1034,9 +1012,10 @@ static bool
|
||||||
|
do_logfile_sudo(const char *logline, const struct eventlog *evlog,
|
||||||
|
const struct timespec *event_time)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *full_line, timebuf[8192], *timestr = NULL;
|
||||||
|
- const char *timefmt = evl_conf.time_fmt;
|
||||||
|
- const char *logfile = evl_conf.logpath;
|
||||||
|
+ const char *timefmt = evl_conf->time_fmt;
|
||||||
|
+ const char *logfile = evl_conf->logpath;
|
||||||
|
time_t tv_sec = event_time->tv_sec;
|
||||||
|
struct tm *timeptr;
|
||||||
|
bool ret = false;
|
||||||
|
@@ -1044,7 +1023,7 @@ do_logfile_sudo(const char *logline, const struct eventlog *evlog,
|
||||||
|
int len;
|
||||||
|
debug_decl(do_logfile_sudo, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
- if ((fp = evl_conf.open_log(EVLOG_FILE, logfile)) == NULL)
|
||||||
|
+ if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
|
||||||
|
@@ -1067,7 +1046,7 @@ do_logfile_sudo(const char *logline, const struct eventlog *evlog,
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
- eventlog_writeln(fp, full_line, len, evl_conf.file_maxlen);
|
||||||
|
+ eventlog_writeln(fp, full_line, len, evl_conf->file_maxlen);
|
||||||
|
(void)fflush(fp);
|
||||||
|
if (ferror(fp)) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||||
|
@@ -1078,7 +1057,7 @@ do_logfile_sudo(const char *logline, const struct eventlog *evlog,
|
||||||
|
|
||||||
|
done:
|
||||||
|
(void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
|
||||||
|
- evl_conf.close_log(EVLOG_FILE, fp);
|
||||||
|
+ evl_conf->close_log(EVLOG_FILE, fp);
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1087,14 +1066,15 @@ do_logfile_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
eventlog_json_callback_t info_cb, void *info)
|
||||||
|
{
|
||||||
|
- const char *logfile = evl_conf.logpath;
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const char *logfile = evl_conf->logpath;
|
||||||
|
struct stat sb;
|
||||||
|
char *json_str;
|
||||||
|
int ret = false;
|
||||||
|
FILE *fp;
|
||||||
|
debug_decl(do_logfile_json, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
- if ((fp = evl_conf.open_log(EVLOG_FILE, logfile)) == NULL)
|
||||||
|
+ if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
json_str = format_json(event_type, reason, errstr, evlog, event_time,
|
||||||
|
@@ -1135,7 +1115,7 @@ do_logfile_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
done:
|
||||||
|
free(json_str);
|
||||||
|
(void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
|
||||||
|
- evl_conf.close_log(EVLOG_FILE, fp);
|
||||||
|
+ evl_conf->close_log(EVLOG_FILE, fp);
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1144,12 +1124,13 @@ do_logfile(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
eventlog_json_callback_t info_cb, void *info)
|
||||||
|
{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
bool ret = false;
|
||||||
|
char *logline = NULL;
|
||||||
|
debug_decl(do_logfile, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/* Sudo format logs and mailed logs use the same log line format. */
|
||||||
|
- if (evl_conf.format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
|
||||||
|
+ if (evl_conf->format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
|
||||||
|
logline = new_logline(flags, reason, errstr, evlog);
|
||||||
|
if (logline == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
@@ -1166,7 +1147,7 @@ do_logfile(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (evl_conf.format) {
|
||||||
|
+ switch (evl_conf->format) {
|
||||||
|
case EVLOG_SUDO:
|
||||||
|
ret = do_logfile_sudo(logline ? logline : reason, evlog, event_time);
|
||||||
|
break;
|
||||||
|
@@ -1176,7 +1157,7 @@ do_logfile(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
- "unexpected eventlog format %d", evl_conf.format);
|
||||||
|
+ "unexpected eventlog format %d", evl_conf->format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(logline);
|
||||||
|
@@ -1188,7 +1169,8 @@ bool
|
||||||
|
eventlog_accept(const struct eventlog *evlog, int flags,
|
||||||
|
eventlog_json_callback_t info_cb, void *info)
|
||||||
|
{
|
||||||
|
- const int log_type = evl_conf.type;
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const int log_type = evl_conf->type;
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_accept, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
@@ -1214,7 +1196,8 @@ bool
|
||||||
|
eventlog_reject(const struct eventlog *evlog, int flags, const char *reason,
|
||||||
|
eventlog_json_callback_t info_cb, void *info)
|
||||||
|
{
|
||||||
|
- const int log_type = evl_conf.type;
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const int log_type = evl_conf->type;
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_reject, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
@@ -1237,7 +1220,8 @@ bool
|
||||||
|
eventlog_alert(const struct eventlog *evlog, int flags,
|
||||||
|
struct timespec *alert_time, const char *reason, const char *errstr)
|
||||||
|
{
|
||||||
|
- const int log_type = evl_conf.type;
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const int log_type = evl_conf->type;
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_alert, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
@@ -1255,169 +1239,3 @@ eventlog_alert(const struct eventlog *evlog, int flags,
|
||||||
|
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
-static FILE *
|
||||||
|
-eventlog_stub_open_log(int type, const char *logfile)
|
||||||
|
-{
|
||||||
|
- debug_decl(eventlog_stub_open_log, SUDO_DEBUG_UTIL);
|
||||||
|
- sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
- "open_log not set, using stub");
|
||||||
|
- debug_return_ptr(NULL);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-eventlog_stub_close_log(int type, FILE *fp)
|
||||||
|
-{
|
||||||
|
- debug_decl(eventlog_stub_close_log, SUDO_DEBUG_UTIL);
|
||||||
|
- sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
- "close_log not set, using stub");
|
||||||
|
- debug_return;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
- * Set eventlog config settings.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_type(int type)
|
||||||
|
-{
|
||||||
|
- evl_conf.type = type;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_format(enum eventlog_format format)
|
||||||
|
-{
|
||||||
|
- evl_conf.format = format;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_syslog_acceptpri(int pri)
|
||||||
|
-{
|
||||||
|
- evl_conf.syslog_acceptpri = pri;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_syslog_rejectpri(int pri)
|
||||||
|
-{
|
||||||
|
- evl_conf.syslog_rejectpri = pri;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_syslog_alertpri(int pri)
|
||||||
|
-{
|
||||||
|
- evl_conf.syslog_alertpri = pri;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_syslog_maxlen(int len)
|
||||||
|
-{
|
||||||
|
- evl_conf.syslog_maxlen = len;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_file_maxlen(int len)
|
||||||
|
-{
|
||||||
|
- evl_conf.file_maxlen = len;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_mailuid(uid_t uid)
|
||||||
|
-{
|
||||||
|
- evl_conf.mailuid = uid;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_omit_hostname(bool omit_hostname)
|
||||||
|
-{
|
||||||
|
- evl_conf.omit_hostname = omit_hostname;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_logpath(const char *path)
|
||||||
|
-{
|
||||||
|
- evl_conf.logpath = path;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_time_fmt(const char *fmt)
|
||||||
|
-{
|
||||||
|
- evl_conf.time_fmt = fmt;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_mailerpath(const char *path)
|
||||||
|
-{
|
||||||
|
- evl_conf.mailerpath = path;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_mailerflags(const char *mflags)
|
||||||
|
-{
|
||||||
|
- evl_conf.mailerflags = mflags;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_mailfrom(const char *from_addr)
|
||||||
|
-{
|
||||||
|
- evl_conf.mailfrom = from_addr;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_mailto(const char *to_addr)
|
||||||
|
-{
|
||||||
|
- evl_conf.mailto = to_addr;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_mailsub(const char *subject)
|
||||||
|
-{
|
||||||
|
- evl_conf.mailsub = subject;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_open_log(FILE *(*fn)(int type, const char *))
|
||||||
|
-{
|
||||||
|
- evl_conf.open_log = fn;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-eventlog_set_close_log(void (*fn)(int type, FILE *))
|
||||||
|
-{
|
||||||
|
- evl_conf.close_log = fn;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-bool
|
||||||
|
-eventlog_setconf(struct eventlog_config *conf)
|
||||||
|
-{
|
||||||
|
- debug_decl(eventlog_setconf, SUDO_DEBUG_UTIL);
|
||||||
|
-
|
||||||
|
- if (conf != NULL) {
|
||||||
|
- memcpy(&evl_conf, conf, sizeof(evl_conf));
|
||||||
|
- } else {
|
||||||
|
- memset(&evl_conf, 0, sizeof(evl_conf));
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Apply default values where possible. */
|
||||||
|
- if (evl_conf.syslog_maxlen == 0)
|
||||||
|
- evl_conf.syslog_maxlen = MAXSYSLOGLEN;
|
||||||
|
- if (evl_conf.logpath == NULL)
|
||||||
|
- evl_conf.logpath = _PATH_SUDO_LOGFILE;
|
||||||
|
- if (evl_conf.time_fmt == NULL)
|
||||||
|
- evl_conf.time_fmt = "%h %e %T";
|
||||||
|
-#ifdef _PATH_SUDO_SENDMAIL
|
||||||
|
- if (evl_conf.mailerpath == NULL)
|
||||||
|
- evl_conf.mailerpath = _PATH_SUDO_SENDMAIL;
|
||||||
|
-#endif
|
||||||
|
- if (evl_conf.mailerflags == NULL)
|
||||||
|
- evl_conf.mailerflags = "-t";
|
||||||
|
- if (evl_conf.mailto == NULL)
|
||||||
|
- evl_conf.mailto = MAILTO;
|
||||||
|
- if (evl_conf.mailsub == NULL)
|
||||||
|
- evl_conf.mailsub = N_(MAILSUBJECT);
|
||||||
|
- if (evl_conf.open_log == NULL)
|
||||||
|
- evl_conf.open_log = eventlog_stub_open_log;
|
||||||
|
- if (evl_conf.close_log == NULL)
|
||||||
|
- evl_conf.close_log = eventlog_stub_close_log;
|
||||||
|
-
|
||||||
|
- debug_return_bool(true);
|
||||||
|
-}
|
||||||
|
diff --git a/lib/eventlog/eventlog_conf.c b/lib/eventlog/eventlog_conf.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..8ad03851f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/lib/eventlog/eventlog_conf.c
|
||||||
|
@@ -0,0 +1,226 @@
|
||||||
|
+/*
|
||||||
|
+ * SPDX-License-Identifier: ISC
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 1994-1996, 1998-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
+ *
|
||||||
|
+ * 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.
|
||||||
|
+ *
|
||||||
|
+ * Sponsored in part by the Defense Advanced Research Projects
|
||||||
|
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||||
|
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * 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 <sys/socket.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
+#include <netinet/in.h>
|
||||||
|
+
|
||||||
|
+#include <ctype.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#include <grp.h>
|
||||||
|
+#include <locale.h>
|
||||||
|
+#include <pwd.h>
|
||||||
|
+#include <signal.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <syslog.h>
|
||||||
|
+#include <time.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+#include "pathnames.h"
|
||||||
|
+#include "sudo_compat.h"
|
||||||
|
+#include "sudo_debug.h"
|
||||||
|
+#include "sudo_eventlog.h"
|
||||||
|
+#include "sudo_fatal.h"
|
||||||
|
+#include "sudo_gettext.h"
|
||||||
|
+#include "sudo_json.h"
|
||||||
|
+#include "sudo_queue.h"
|
||||||
|
+#include "sudo_util.h"
|
||||||
|
+
|
||||||
|
+static FILE *eventlog_stub_open_log(int type, const char *logfile);
|
||||||
|
+static void eventlog_stub_close_log(int type, FILE *fp);
|
||||||
|
+
|
||||||
|
+/* Eventlog config settings (default values). */
|
||||||
|
+static struct eventlog_config evl_conf = {
|
||||||
|
+ EVLOG_NONE, /* type */
|
||||||
|
+ EVLOG_SUDO, /* format */
|
||||||
|
+ LOG_NOTICE, /* syslog_acceptpri */
|
||||||
|
+ LOG_ALERT, /* syslog_rejectpri */
|
||||||
|
+ LOG_ALERT, /* syslog_alertpri */
|
||||||
|
+ MAXSYSLOGLEN, /* syslog_maxlen */
|
||||||
|
+ 0, /* file_maxlen */
|
||||||
|
+ ROOT_UID, /* mailuid */
|
||||||
|
+ false, /* omit_hostname */
|
||||||
|
+ _PATH_SUDO_LOGFILE, /* logpath */
|
||||||
|
+ "%h %e %T", /* time_fmt */
|
||||||
|
+#ifdef _PATH_SUDO_SENDMAIL
|
||||||
|
+ _PATH_SUDO_SENDMAIL, /* mailerpath */
|
||||||
|
+#else
|
||||||
|
+ NULL, /* mailerpath (disabled) */
|
||||||
|
+#endif
|
||||||
|
+ "-t", /* mailerflags */
|
||||||
|
+ NULL, /* mailfrom */
|
||||||
|
+ MAILTO, /* mailto */
|
||||||
|
+ N_(MAILSUBJECT), /* mailsub */
|
||||||
|
+ eventlog_stub_open_log, /* open_log */
|
||||||
|
+ eventlog_stub_close_log /* close_log */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static FILE *
|
||||||
|
+eventlog_stub_open_log(int type, const char *logfile)
|
||||||
|
+{
|
||||||
|
+ debug_decl(eventlog_stub_open_log, SUDO_DEBUG_UTIL);
|
||||||
|
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
+ "open_log not set, using stub");
|
||||||
|
+ debug_return_ptr(NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+eventlog_stub_close_log(int type, FILE *fp)
|
||||||
|
+{
|
||||||
|
+ debug_decl(eventlog_stub_close_log, SUDO_DEBUG_UTIL);
|
||||||
|
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
||||||
|
+ "close_log not set, using stub");
|
||||||
|
+ debug_return;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * eventlog config setters.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_type(int type)
|
||||||
|
+{
|
||||||
|
+ evl_conf.type = type;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_format(enum eventlog_format format)
|
||||||
|
+{
|
||||||
|
+ evl_conf.format = format;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_syslog_acceptpri(int pri)
|
||||||
|
+{
|
||||||
|
+ evl_conf.syslog_acceptpri = pri;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_syslog_rejectpri(int pri)
|
||||||
|
+{
|
||||||
|
+ evl_conf.syslog_rejectpri = pri;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_syslog_alertpri(int pri)
|
||||||
|
+{
|
||||||
|
+ evl_conf.syslog_alertpri = pri;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_syslog_maxlen(int len)
|
||||||
|
+{
|
||||||
|
+ evl_conf.syslog_maxlen = len;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_file_maxlen(int len)
|
||||||
|
+{
|
||||||
|
+ evl_conf.file_maxlen = len;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_mailuid(uid_t uid)
|
||||||
|
+{
|
||||||
|
+ evl_conf.mailuid = uid;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_omit_hostname(bool omit_hostname)
|
||||||
|
+{
|
||||||
|
+ evl_conf.omit_hostname = omit_hostname;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_logpath(const char *path)
|
||||||
|
+{
|
||||||
|
+ evl_conf.logpath = path;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_time_fmt(const char *fmt)
|
||||||
|
+{
|
||||||
|
+ evl_conf.time_fmt = fmt;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_mailerpath(const char *path)
|
||||||
|
+{
|
||||||
|
+ evl_conf.mailerpath = path;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_mailerflags(const char *mflags)
|
||||||
|
+{
|
||||||
|
+ evl_conf.mailerflags = mflags;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_mailfrom(const char *from_addr)
|
||||||
|
+{
|
||||||
|
+ evl_conf.mailfrom = from_addr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_mailto(const char *to_addr)
|
||||||
|
+{
|
||||||
|
+ evl_conf.mailto = to_addr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_mailsub(const char *subject)
|
||||||
|
+{
|
||||||
|
+ evl_conf.mailsub = subject;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_open_log(FILE *(*fn)(int type, const char *))
|
||||||
|
+{
|
||||||
|
+ evl_conf.open_log = fn;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+eventlog_set_close_log(void (*fn)(int type, FILE *))
|
||||||
|
+{
|
||||||
|
+ evl_conf.close_log = fn;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * get eventlog config.
|
||||||
|
+ */
|
||||||
|
+const struct eventlog_config *
|
||||||
|
+eventlog_getconf(void)
|
||||||
|
+{
|
||||||
|
+ return &evl_conf;
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
66
SOURCES/sudo-1.9.13-CVE-2023-28486-7-4.patch
Normal file
66
SOURCES/sudo-1.9.13-CVE-2023-28486-7-4.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
From d452678787683da6498668cd1f1cbb8000d63178 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Tue, 2 Mar 2021 18:37:35 -0700
|
||||||
|
Subject: [PATCH] Log peer address in sudo_logsrvd JSON-format logs. The peer
|
||||||
|
that connected to us might not be the same host where the log entry
|
||||||
|
originated.
|
||||||
|
|
||||||
|
---
|
||||||
|
include/sudo_eventlog.h | 3 ++-
|
||||||
|
lib/eventlog/eventlog.c | 9 ++++++++-
|
||||||
|
logsrvd/iolog_writer.c | 8 ++++++--
|
||||||
|
logsrvd/logsrvd.c | 9 +++++----
|
||||||
|
logsrvd/logsrvd.h | 4 ++--
|
||||||
|
5 files changed, 23 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h
|
||||||
|
index e40622a51..49153e173 100644
|
||||||
|
--- a/include/sudo_eventlog.h
|
||||||
|
+++ b/include/sudo_eventlog.h
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
- * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
+ * Copyright (c) 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@@ -101,6 +101,7 @@ struct eventlog {
|
||||||
|
char *runcwd;
|
||||||
|
char *rungroup;
|
||||||
|
char *runuser;
|
||||||
|
+ char *peeraddr;
|
||||||
|
char *submithost;
|
||||||
|
char *submituser;
|
||||||
|
char *submitgroup;
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index e7505d9d9..0c1e74e38 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
- * Copyright (c) 1994-1996, 1998-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
+ * Copyright (c) 1994-1996, 1998-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@@ -825,6 +825,13 @@ format_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
|
||||||
|
/* Event log info may be missing for alert messages. */
|
||||||
|
if (evlog != NULL) {
|
||||||
|
+ if (evlog->peeraddr != NULL) {
|
||||||
|
+ json_value.type = JSON_STRING;
|
||||||
|
+ json_value.u.string = evlog->peeraddr;
|
||||||
|
+ if (!sudo_json_add_value(&json, "peeraddr", &json_value))
|
||||||
|
+ goto bad;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (evlog->iolog_path != NULL) {
|
||||||
|
json_value.type = JSON_STRING;
|
||||||
|
json_value.u.string = evlog->iolog_path;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
559
SOURCES/sudo-1.9.13-CVE-2023-28486-7-5.patch
Normal file
559
SOURCES/sudo-1.9.13-CVE-2023-28486-7-5.patch
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
From b54a16e1749fc53e4ed047da72f97b8f99bf4d6a Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Fri, 9 Jul 2021 11:08:44 -0600
|
||||||
|
Subject: [PATCH] Add support for logging exit status events. For
|
||||||
|
sudo-formatted logs, this is a record with "EXIT=number" and potentially
|
||||||
|
"SIGNAL=name" after the command. For JSON-format logs, a new "exit" record
|
||||||
|
is logged which contains an "exit_value" and potentially "signal" and
|
||||||
|
"core_dumped". JSON-format logs now incude a UUID to associate the "exit"
|
||||||
|
record with the "accept" record.
|
||||||
|
|
||||||
|
---
|
||||||
|
include/sudo_eventlog.h | 2 +
|
||||||
|
lib/eventlog/eventlog.c | 255 +++++++++++++++++++++++++++-------------
|
||||||
|
2 files changed, 175 insertions(+), 82 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h
|
||||||
|
index 49153e173..07ef9dcbe 100644
|
||||||
|
--- a/include/sudo_eventlog.h
|
||||||
|
+++ b/include/sudo_eventlog.h
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
enum event_type {
|
||||||
|
EVLOG_ACCEPT,
|
||||||
|
EVLOG_REJECT,
|
||||||
|
+ EVLOG_EXIT,
|
||||||
|
EVLOG_ALERT
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -122,6 +123,7 @@ struct json_container;
|
||||||
|
typedef bool (*eventlog_json_callback_t)(struct json_container *, void *);
|
||||||
|
|
||||||
|
bool eventlog_accept(const struct eventlog *evlog, int flags, eventlog_json_callback_t info_cb, void *info);
|
||||||
|
+bool eventlog_exit(const struct eventlog *evlog, int flags, struct timespec *run_time, int exit_value, const char *signal_name, bool core_dumped, eventlog_json_callback_t info_cb, void *info);
|
||||||
|
bool eventlog_alert(const struct eventlog *evlog, int flags, struct timespec *alert_time, const char *reason, const char *errstr);
|
||||||
|
bool eventlog_reject(const struct eventlog *evlog, int flags, const char *reason, eventlog_json_callback_t info_cb, void *info);
|
||||||
|
bool eventlog_store_json(struct json_container *json, const struct eventlog *evlog);
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index 0c1e74e38..efcd6859d 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -66,6 +66,8 @@
|
||||||
|
#define LL_ENV_STR "ENV="
|
||||||
|
#define LL_CMND_STR "COMMAND="
|
||||||
|
#define LL_TSID_STR "TSID="
|
||||||
|
+#define LL_EXIT_STR "EXIT="
|
||||||
|
+#define LL_SIGNAL_STR "SIGNAL="
|
||||||
|
|
||||||
|
#define IS_SESSID(s) ( \
|
||||||
|
isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \
|
||||||
|
@@ -75,28 +77,40 @@
|
||||||
|
isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \
|
||||||
|
(s)[8] == '\0')
|
||||||
|
|
||||||
|
+struct eventlog_args {
|
||||||
|
+ const char *reason;
|
||||||
|
+ const char *errstr;
|
||||||
|
+ const char *signal_name;
|
||||||
|
+ const struct timespec *event_time;
|
||||||
|
+ int exit_value;
|
||||||
|
+ bool core_dumped;
|
||||||
|
+ eventlog_json_callback_t json_info_cb;
|
||||||
|
+ void *json_info;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Allocate and fill in a new logline.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
-new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
+new_logline(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *line = NULL, *evstr = NULL;
|
||||||
|
const char *iolog_file = evlog->iolog_file;
|
||||||
|
const char *tty, *tsid = NULL;
|
||||||
|
+ char exit_str[(((sizeof(int) * 8) + 2) / 3) + 2];
|
||||||
|
char sessid[7];
|
||||||
|
size_t len = 0;
|
||||||
|
int i;
|
||||||
|
debug_decl(new_logline, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
if (ISSET(flags, EVLOG_RAW)) {
|
||||||
|
- if (errstr != NULL) {
|
||||||
|
- if (asprintf(&line, "%s: %s", message, errstr) == -1)
|
||||||
|
+ if (args->errstr != NULL) {
|
||||||
|
+ if (asprintf(&line, "%s: %s", args->reason, args->errstr) == -1)
|
||||||
|
goto oom;
|
||||||
|
} else {
|
||||||
|
- if ((line = strdup(message)) == NULL)
|
||||||
|
+ if ((line = strdup(args->reason)) == NULL)
|
||||||
|
goto oom;
|
||||||
|
}
|
||||||
|
debug_return_str(line);
|
||||||
|
@@ -127,10 +141,10 @@ new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
/*
|
||||||
|
* Compute line length
|
||||||
|
*/
|
||||||
|
- if (message != NULL)
|
||||||
|
- len += strlen(message) + 3;
|
||||||
|
- if (errstr != NULL)
|
||||||
|
- len += strlen(errstr) + 3;
|
||||||
|
+ if (args->reason != NULL)
|
||||||
|
+ len += strlen(args->reason) + 3;
|
||||||
|
+ if (args->errstr != NULL)
|
||||||
|
+ len += strlen(args->errstr) + 3;
|
||||||
|
if (evlog->submithost != NULL && !evl_conf->omit_hostname)
|
||||||
|
len += sizeof(LL_HOST_STR) + 2 + strlen(evlog->submithost);
|
||||||
|
if (tty != NULL)
|
||||||
|
@@ -171,6 +185,12 @@ new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
for (i = 1; evlog->argv[i] != NULL; i++)
|
||||||
|
len += strlen(evlog->argv[i]) + 1;
|
||||||
|
}
|
||||||
|
+ if (event_type == EVLOG_EXIT) {
|
||||||
|
+ if (args->signal_name != NULL)
|
||||||
|
+ len += sizeof(LL_SIGNAL_STR) + 2 + strlen(args->signal_name);
|
||||||
|
+ (void)snprintf(exit_str, sizeof(exit_str), "%d", args->exit_value);
|
||||||
|
+ len += sizeof(LL_EXIT_STR) + 2 + strlen(exit_str);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -180,13 +200,13 @@ new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
goto oom;
|
||||||
|
line[0] = '\0';
|
||||||
|
|
||||||
|
- if (message != NULL) {
|
||||||
|
- if (strlcat(line, message, len) >= len ||
|
||||||
|
- strlcat(line, errstr ? " : " : " ; ", len) >= len)
|
||||||
|
+ if (args->reason != NULL) {
|
||||||
|
+ if (strlcat(line, args->reason, len) >= len ||
|
||||||
|
+ strlcat(line, args->errstr ? " : " : " ; ", len) >= len)
|
||||||
|
goto toobig;
|
||||||
|
}
|
||||||
|
- if (errstr != NULL) {
|
||||||
|
- if (strlcat(line, errstr, len) >= len ||
|
||||||
|
+ if (args->errstr != NULL) {
|
||||||
|
+ if (strlcat(line, args->errstr, len) >= len ||
|
||||||
|
strlcat(line, " ; ", len) >= len)
|
||||||
|
goto toobig;
|
||||||
|
}
|
||||||
|
@@ -252,6 +272,18 @@ new_logline(int flags, const char *message, const char *errstr,
|
||||||
|
goto toobig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (event_type == EVLOG_EXIT) {
|
||||||
|
+ if (args->signal_name != NULL) {
|
||||||
|
+ if (strlcat(line, " ; ", len) >= len ||
|
||||||
|
+ strlcat(line, LL_SIGNAL_STR, len) >= len ||
|
||||||
|
+ strlcat(line, args->signal_name, len) >= len)
|
||||||
|
+ goto toobig;
|
||||||
|
+ }
|
||||||
|
+ if (strlcat(line, " ; ", len) >= len ||
|
||||||
|
+ strlcat(line, LL_EXIT_STR, len) >= len ||
|
||||||
|
+ strlcat(line, exit_str, len) >= len)
|
||||||
|
+ goto toobig;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_return_str(line);
|
||||||
|
@@ -369,7 +401,7 @@ exec_mailer(int pipein)
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Send a message to MAILTO user */
|
||||||
|
+/* Send a message to the mailto user */
|
||||||
|
static bool
|
||||||
|
send_mail(const struct eventlog *evlog, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
@@ -548,19 +580,11 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
|
||||||
|
|
||||||
|
static bool
|
||||||
|
json_add_timestamp(struct json_container *json, const char *name,
|
||||||
|
- const struct timespec *ts)
|
||||||
|
+ const struct timespec *ts, bool format_timestamp)
|
||||||
|
{
|
||||||
|
- const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
- const char *timefmt = evl_conf->time_fmt;
|
||||||
|
struct json_value json_value;
|
||||||
|
- time_t secs = ts->tv_sec;
|
||||||
|
- char timebuf[1024];
|
||||||
|
- struct tm *tm;
|
||||||
|
debug_decl(json_add_timestamp, SUDO_DEBUG_PLUGIN);
|
||||||
|
|
||||||
|
- if ((tm = gmtime(&secs)) == NULL)
|
||||||
|
- debug_return_bool(false);
|
||||||
|
-
|
||||||
|
if (!sudo_json_open_object(json, name))
|
||||||
|
goto oom;
|
||||||
|
|
||||||
|
@@ -574,17 +598,27 @@ json_add_timestamp(struct json_container *json, const char *name,
|
||||||
|
if (!sudo_json_add_value(json, "nanoseconds", &json_value))
|
||||||
|
goto oom;
|
||||||
|
|
||||||
|
- strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tm);
|
||||||
|
- json_value.type = JSON_STRING;
|
||||||
|
- json_value.u.string = timebuf;
|
||||||
|
- if (!sudo_json_add_value(json, "iso8601", &json_value))
|
||||||
|
- goto oom;
|
||||||
|
+ if (format_timestamp) {
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const char *timefmt = evl_conf->time_fmt;
|
||||||
|
+ time_t secs = ts->tv_sec;
|
||||||
|
+ char timebuf[1024];
|
||||||
|
+ struct tm *tm;
|
||||||
|
|
||||||
|
- strftime(timebuf, sizeof(timebuf), timefmt, tm);
|
||||||
|
- json_value.type = JSON_STRING;
|
||||||
|
- json_value.u.string = timebuf;
|
||||||
|
- if (!sudo_json_add_value(json, "localtime", &json_value))
|
||||||
|
- goto oom;
|
||||||
|
+ if ((tm = gmtime(&secs)) != NULL) {
|
||||||
|
+ strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tm);
|
||||||
|
+ json_value.type = JSON_STRING;
|
||||||
|
+ json_value.u.string = timebuf;
|
||||||
|
+ if (!sudo_json_add_value(json, "iso8601", &json_value))
|
||||||
|
+ goto oom;
|
||||||
|
+
|
||||||
|
+ strftime(timebuf, sizeof(timebuf), timefmt, tm);
|
||||||
|
+ json_value.type = JSON_STRING;
|
||||||
|
+ json_value.u.string = timebuf;
|
||||||
|
+ if (!sudo_json_add_value(json, "localtime", &json_value))
|
||||||
|
+ goto oom;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (!sudo_json_close_object(json))
|
||||||
|
goto oom;
|
||||||
|
@@ -741,14 +775,15 @@ default_json_cb(struct json_container *json, void *v)
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
-format_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
- const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
- eventlog_json_callback_t info_cb, void *info, bool compact)
|
||||||
|
+format_json(int event_type, struct eventlog_args *args,
|
||||||
|
+ const struct eventlog *evlog, bool compact)
|
||||||
|
{
|
||||||
|
- const char *type_str;
|
||||||
|
- const char *time_str;
|
||||||
|
+ eventlog_json_callback_t info_cb = args->json_info_cb;
|
||||||
|
+ void *info = args->json_info;
|
||||||
|
struct json_container json = { 0 };
|
||||||
|
struct json_value json_value;
|
||||||
|
+ const char *time_str, *type_str;
|
||||||
|
+ bool format_timestamp = true;
|
||||||
|
struct timespec now;
|
||||||
|
debug_decl(format_json, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
@@ -776,6 +811,11 @@ format_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
type_str = "alert";
|
||||||
|
time_str = "alert_time";
|
||||||
|
break;
|
||||||
|
+ case EVLOG_EXIT:
|
||||||
|
+ type_str = "exit";
|
||||||
|
+ time_str = "run_time";
|
||||||
|
+ format_timestamp = false;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
"unexpected event type %d", event_type);
|
||||||
|
@@ -788,18 +828,20 @@ format_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
/* Reject and Alert events include a reason and optional error string. */
|
||||||
|
- if (reason != NULL) {
|
||||||
|
+ if (args->reason != NULL) {
|
||||||
|
char *ereason = NULL;
|
||||||
|
|
||||||
|
- if (errstr != NULL) {
|
||||||
|
- if (asprintf(&ereason, _("%s: %s"), reason, errstr) == -1) {
|
||||||
|
+ if (args->errstr != NULL) {
|
||||||
|
+ const int len = asprintf(&ereason, _("%s: %s"), args->reason,
|
||||||
|
+ args->errstr);
|
||||||
|
+ if (len == -1) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__,
|
||||||
|
U_("unable to allocate memory"));
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json_value.type = JSON_STRING;
|
||||||
|
- json_value.u.string = ereason ? ereason : reason;
|
||||||
|
+ json_value.u.string = ereason ? ereason : args->reason;
|
||||||
|
if (!sudo_json_add_value(&json, "reason", &json_value)) {
|
||||||
|
free(ereason);
|
||||||
|
goto bad;
|
||||||
|
@@ -810,19 +852,37 @@ format_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
/* XXX - create and log uuid? */
|
||||||
|
|
||||||
|
/* Log event time on server (set earlier) */
|
||||||
|
- if (!json_add_timestamp(&json, "server_time", &now)) {
|
||||||
|
+ if (!json_add_timestamp(&json, "server_time", &now, true)) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
||||||
|
"unable format timestamp");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log event time from client */
|
||||||
|
- if (!json_add_timestamp(&json, time_str, event_time)) {
|
||||||
|
+ if (!json_add_timestamp(&json, time_str, args->event_time, format_timestamp)) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
||||||
|
"unable format timestamp");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (event_type == EVLOG_EXIT) {
|
||||||
|
+ if (args->signal_name != NULL) {
|
||||||
|
+ json_value.type = JSON_STRING;
|
||||||
|
+ json_value.u.string = args->signal_name;
|
||||||
|
+ if (!sudo_json_add_value(&json, "signal", &json_value))
|
||||||
|
+ goto bad;
|
||||||
|
+
|
||||||
|
+ json_value.type = JSON_BOOL;
|
||||||
|
+ json_value.u.boolean = args->signal_name;
|
||||||
|
+ if (!sudo_json_add_value(&json, "dumped_core", &json_value))
|
||||||
|
+ goto bad;
|
||||||
|
+ }
|
||||||
|
+ json_value.type = JSON_NUMBER;
|
||||||
|
+ json_value.u.number = args->exit_value;
|
||||||
|
+ if (!sudo_json_add_value(&json, "exit_value", &json_value))
|
||||||
|
+ goto bad;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Event log info may be missing for alert messages. */
|
||||||
|
if (evlog != NULL) {
|
||||||
|
if (evlog->peeraddr != NULL) {
|
||||||
|
@@ -919,18 +979,15 @@ done:
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
-do_syslog_json(int pri, int event_type, const char *reason,
|
||||||
|
- const char *errstr, const struct eventlog *evlog,
|
||||||
|
- const struct timespec *event_time,
|
||||||
|
- eventlog_json_callback_t info_cb, void *info)
|
||||||
|
+do_syslog_json(int pri, int event_type, struct eventlog_args *args,
|
||||||
|
+ const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *json_str;
|
||||||
|
debug_decl(do_syslog_json, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/* Format as a compact JSON message (no newlines) */
|
||||||
|
- json_str = format_json(event_type, reason, errstr, evlog, event_time,
|
||||||
|
- info_cb, info, true);
|
||||||
|
+ json_str = format_json(event_type, args, evlog, true);
|
||||||
|
if (json_str == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
@@ -947,9 +1004,8 @@ do_syslog_json(int pri, int event_type, const char *reason,
|
||||||
|
* Log a message to syslog in either sudo or JSON format.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
-do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
- const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
- eventlog_json_callback_t info_cb, void *info)
|
||||||
|
+do_syslog(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
+ const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *logline = NULL;
|
||||||
|
@@ -959,7 +1015,7 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
|
||||||
|
/* Sudo format logs and mailed logs use the same log line format. */
|
||||||
|
if (evl_conf->format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
|
||||||
|
- logline = new_logline(flags, reason, errstr, evlog);
|
||||||
|
+ logline = new_logline(event_type, flags, args, evlog);
|
||||||
|
if (logline == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
@@ -977,6 +1033,7 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
|
||||||
|
switch (event_type) {
|
||||||
|
case EVLOG_ACCEPT:
|
||||||
|
+ case EVLOG_EXIT:
|
||||||
|
pri = evl_conf->syslog_acceptpri;
|
||||||
|
break;
|
||||||
|
case EVLOG_REJECT:
|
||||||
|
@@ -1002,8 +1059,7 @@ do_syslog(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
ret = do_syslog_sudo(pri, logline, evlog);
|
||||||
|
break;
|
||||||
|
case EVLOG_JSON:
|
||||||
|
- ret = do_syslog_json(pri, event_type, reason, errstr, evlog,
|
||||||
|
- event_time, info_cb, info);
|
||||||
|
+ ret = do_syslog_json(pri, event_type, args, evlog);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
@@ -1069,9 +1125,8 @@ done:
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
-do_logfile_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
- const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
- eventlog_json_callback_t info_cb, void *info)
|
||||||
|
+do_logfile_json(int event_type, struct eventlog_args *args,
|
||||||
|
+ const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
const char *logfile = evl_conf->logpath;
|
||||||
|
@@ -1084,8 +1139,7 @@ do_logfile_json(int event_type, const char *reason, const char *errstr,
|
||||||
|
if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
- json_str = format_json(event_type, reason, errstr, evlog, event_time,
|
||||||
|
- info_cb, info, false);
|
||||||
|
+ json_str = format_json(event_type, args, evlog, false);
|
||||||
|
if (json_str == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
@@ -1127,9 +1181,8 @@ done:
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
-do_logfile(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
- const struct eventlog *evlog, const struct timespec *event_time,
|
||||||
|
- eventlog_json_callback_t info_cb, void *info)
|
||||||
|
+do_logfile(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
+ const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
bool ret = false;
|
||||||
|
@@ -1138,7 +1191,7 @@ do_logfile(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
|
||||||
|
/* Sudo format logs and mailed logs use the same log line format. */
|
||||||
|
if (evl_conf->format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
|
||||||
|
- logline = new_logline(flags, reason, errstr, evlog);
|
||||||
|
+ logline = new_logline(event_type, flags, args, evlog);
|
||||||
|
if (logline == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
|
@@ -1156,11 +1209,11 @@ do_logfile(int event_type, int flags, const char *reason, const char *errstr,
|
||||||
|
|
||||||
|
switch (evl_conf->format) {
|
||||||
|
case EVLOG_SUDO:
|
||||||
|
- ret = do_logfile_sudo(logline ? logline : reason, evlog, event_time);
|
||||||
|
+ ret = do_logfile_sudo(logline ? logline : args->reason, evlog,
|
||||||
|
+ args->event_time);
|
||||||
|
break;
|
||||||
|
case EVLOG_JSON:
|
||||||
|
- ret = do_logfile_json(event_type, reason, errstr, evlog,
|
||||||
|
- event_time, info_cb, info);
|
||||||
|
+ ret = do_logfile_json(event_type, args, evlog);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
@@ -1178,21 +1231,21 @@ eventlog_accept(const struct eventlog *evlog, int flags,
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
const int log_type = evl_conf->type;
|
||||||
|
+ struct eventlog_args args = { NULL };
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_accept, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
- if (log_type == EVLOG_NONE)
|
||||||
|
- debug_return_bool(true);
|
||||||
|
+ args.event_time = &evlog->submit_time;
|
||||||
|
+ args.json_info_cb = info_cb;
|
||||||
|
+ args.json_info = info;
|
||||||
|
|
||||||
|
if (ISSET(log_type, EVLOG_SYSLOG)) {
|
||||||
|
- if (!do_syslog(EVLOG_ACCEPT, flags, NULL, NULL, evlog,
|
||||||
|
- &evlog->submit_time, info_cb, info))
|
||||||
|
+ if (!do_syslog(EVLOG_ACCEPT, flags, &args, evlog))
|
||||||
|
ret = false;
|
||||||
|
CLR(flags, EVLOG_MAIL);
|
||||||
|
}
|
||||||
|
if (ISSET(log_type, EVLOG_FILE)) {
|
||||||
|
- if (!do_logfile(EVLOG_ACCEPT, flags, NULL, NULL, evlog,
|
||||||
|
- &evlog->submit_time, info_cb, info))
|
||||||
|
+ if (!do_logfile(EVLOG_ACCEPT, flags, &args, evlog))
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1205,18 +1258,22 @@ eventlog_reject(const struct eventlog *evlog, int flags, const char *reason,
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
const int log_type = evl_conf->type;
|
||||||
|
+ struct eventlog_args args = { NULL };
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_reject, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
+ args.reason = reason;
|
||||||
|
+ args.event_time = &evlog->submit_time;
|
||||||
|
+ args.json_info_cb = info_cb;
|
||||||
|
+ args.json_info = info;
|
||||||
|
+
|
||||||
|
if (ISSET(log_type, EVLOG_SYSLOG)) {
|
||||||
|
- if (!do_syslog(EVLOG_REJECT, flags, reason, NULL, evlog,
|
||||||
|
- &evlog->submit_time, info_cb, info))
|
||||||
|
+ if (!do_syslog(EVLOG_REJECT, flags, &args, evlog))
|
||||||
|
ret = false;
|
||||||
|
CLR(flags, EVLOG_MAIL);
|
||||||
|
}
|
||||||
|
if (ISSET(log_type, EVLOG_FILE)) {
|
||||||
|
- if (!do_logfile(EVLOG_REJECT, flags, reason, NULL, evlog,
|
||||||
|
- &evlog->submit_time, info_cb, info))
|
||||||
|
+ if (!do_logfile(EVLOG_REJECT, flags, &args, evlog))
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1229,18 +1286,52 @@ eventlog_alert(const struct eventlog *evlog, int flags,
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
const int log_type = evl_conf->type;
|
||||||
|
+ struct eventlog_args args = { NULL };
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(log_alert, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
+ args.reason = reason;
|
||||||
|
+ args.errstr = errstr;
|
||||||
|
+ args.event_time = alert_time;
|
||||||
|
+
|
||||||
|
+ if (ISSET(log_type, EVLOG_SYSLOG)) {
|
||||||
|
+ if (!do_syslog(EVLOG_ALERT, flags, &args, evlog))
|
||||||
|
+ ret = false;
|
||||||
|
+ CLR(flags, EVLOG_MAIL);
|
||||||
|
+ }
|
||||||
|
+ if (ISSET(log_type, EVLOG_FILE)) {
|
||||||
|
+ if (!do_logfile(EVLOG_ALERT, flags, &args, evlog))
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ debug_return_bool(ret);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+bool
|
||||||
|
+eventlog_exit(const struct eventlog *evlog, int flags,
|
||||||
|
+ struct timespec *run_time, int exit_value, const char *signal_name,
|
||||||
|
+ bool core_dumped, eventlog_json_callback_t info_cb, void *info)
|
||||||
|
+{
|
||||||
|
+ const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
+ const int log_type = evl_conf->type;
|
||||||
|
+ struct eventlog_args args = { NULL };
|
||||||
|
+ bool ret = true;
|
||||||
|
+ debug_decl(eventlog_exit, SUDO_DEBUG_UTIL);
|
||||||
|
+
|
||||||
|
+ args.signal_name = signal_name;
|
||||||
|
+ args.core_dumped = core_dumped;
|
||||||
|
+ args.exit_value = exit_value;
|
||||||
|
+ args.event_time = run_time;
|
||||||
|
+ args.json_info_cb = info_cb;
|
||||||
|
+ args.json_info = info;
|
||||||
|
+
|
||||||
|
if (ISSET(log_type, EVLOG_SYSLOG)) {
|
||||||
|
- if (!do_syslog(EVLOG_ALERT, flags, reason, errstr, evlog, alert_time,
|
||||||
|
- NULL, NULL))
|
||||||
|
+ if (!do_syslog(EVLOG_EXIT, flags, &args, evlog))
|
||||||
|
ret = false;
|
||||||
|
CLR(flags, EVLOG_MAIL);
|
||||||
|
}
|
||||||
|
if (ISSET(log_type, EVLOG_FILE)) {
|
||||||
|
- if (!do_logfile(EVLOG_ALERT, flags, reason, errstr, evlog, alert_time,
|
||||||
|
- NULL, NULL))
|
||||||
|
+ if (!do_logfile(EVLOG_EXIT, flags, &args, evlog))
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
39
SOURCES/sudo-1.9.13-CVE-2023-28486-7-6.patch
Normal file
39
SOURCES/sudo-1.9.13-CVE-2023-28486-7-6.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From d109cd61d9ff01053f1d43b7d4fc0e5e657c8da3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Tue, 27 Jul 2021 12:19:53 -0600
|
||||||
|
Subject: [PATCH] In new_logline check for NULL args->reason for EVLOG_RAW.
|
||||||
|
This can't happen in practice since we never set EVLOG_RAW without passing in
|
||||||
|
a reason. Coverity CID 237142 237143
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/eventlog/eventlog.c | 14 ++++++++------
|
||||||
|
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index 280be7fcf..26c5f6dc7 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -106,12 +106,14 @@ new_logline(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
debug_decl(new_logline, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
if (ISSET(flags, EVLOG_RAW)) {
|
||||||
|
- if (args->errstr != NULL) {
|
||||||
|
- if (asprintf(&line, "%s: %s", args->reason, args->errstr) == -1)
|
||||||
|
- goto oom;
|
||||||
|
- } else {
|
||||||
|
- if ((line = strdup(args->reason)) == NULL)
|
||||||
|
- goto oom;
|
||||||
|
+ if (args->reason != NULL) {
|
||||||
|
+ if (args->errstr != NULL) {
|
||||||
|
+ if (asprintf(&line, "%s: %s", args->reason, args->errstr) == -1)
|
||||||
|
+ goto oom;
|
||||||
|
+ } else {
|
||||||
|
+ if ((line = strdup(args->reason)) == NULL)
|
||||||
|
+ goto oom;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
debug_return_str(line);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
42
SOURCES/sudo-1.9.13-CVE-2023-28486-7-7.patch
Normal file
42
SOURCES/sudo-1.9.13-CVE-2023-28486-7-7.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
From babb498c6ebe09723a751127b104f43ab643ee91 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Sat, 14 Aug 2021 09:24:39 -0600
|
||||||
|
Subject: [PATCH] new_logline: handle case where evlog is NULL
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/eventlog/eventlog.c | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
|
||||||
|
index 255ef1bbf..7f55859b6 100644
|
||||||
|
--- a/lib/eventlog/eventlog.c
|
||||||
|
+++ b/lib/eventlog/eventlog.c
|
||||||
|
@@ -97,7 +97,7 @@ new_logline(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
char *line = NULL, *evstr = NULL;
|
||||||
|
- const char *iolog_file = evlog->iolog_file;
|
||||||
|
+ const char *iolog_file;
|
||||||
|
const char *tty, *tsid = NULL;
|
||||||
|
char exit_str[(((sizeof(int) * 8) + 2) / 3) + 2];
|
||||||
|
char sessid[7];
|
||||||
|
@@ -105,7 +105,7 @@ new_logline(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
int i;
|
||||||
|
debug_decl(new_logline, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
- if (ISSET(flags, EVLOG_RAW)) {
|
||||||
|
+ if (ISSET(flags, EVLOG_RAW) || evlog == NULL) {
|
||||||
|
if (args->reason != NULL) {
|
||||||
|
if (args->errstr != NULL) {
|
||||||
|
if (asprintf(&line, "%s: %s", args->reason, args->errstr) == -1)
|
||||||
|
@@ -119,6 +119,7 @@ new_logline(int event_type, int flags, struct eventlog_args *args,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A TSID may be a sudoers-style session ID or a free-form string. */
|
||||||
|
+ iolog_file = evlog->iolog_file;
|
||||||
|
if (iolog_file != NULL) {
|
||||||
|
if (IS_SESSID(iolog_file)) {
|
||||||
|
sessid[0] = iolog_file[0];
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
56
SOURCES/sudo-1.9.13-CVE-2023-28486-7-8.patch
Normal file
56
SOURCES/sudo-1.9.13-CVE-2023-28486-7-8.patch
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
From 4e4b506f22006c485c7ce557c9905dae16c5c12e Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||||
|
Date: Fri, 1 Oct 2021 10:33:55 -0600
|
||||||
|
Subject: [PATCH] Sync "sudo -l" output with normal sudo log format. It now
|
||||||
|
prints runchroot and runcwd (falling back on cwd). As a result, submithost is
|
||||||
|
now printed first, matching sudo. Also avoid printing NULL pointers and skip
|
||||||
|
entries that don't have at least command, submituser and runuser set.
|
||||||
|
|
||||||
|
---
|
||||||
|
plugins/sudoers/sudoreplay.c | 22 ++++++++++++++++------
|
||||||
|
1 file changed, 16 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/sudoers/sudoreplay.c b/plugins/sudoers/sudoreplay.c
|
||||||
|
index f32d44eb5..786aae30d 100644
|
||||||
|
--- a/plugins/sudoers/sudoreplay.c
|
||||||
|
+++ b/plugins/sudoers/sudoreplay.c
|
||||||
|
@@ -1388,6 +1388,11 @@ list_session(char *log_dir, regex_t *re, const char *user, const char *tty)
|
||||||
|
if ((evlog = iolog_parse_loginfo(-1, log_dir)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
+ if (evlog->command == NULL || evlog->submituser == NULL ||
|
||||||
|
+ evlog->runuser == NULL) {
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Match on search expression if there is one. */
|
||||||
|
if (!STAILQ_EMPTY(&search_expr) && !match_expr(&search_expr, evlog, true))
|
||||||
|
goto done;
|
||||||
|
@@ -1409,13 +1414,18 @@ list_session(char *log_dir, regex_t *re, const char *user, const char *tty)
|
||||||
|
}
|
||||||
|
/* XXX - print lines + cols? */
|
||||||
|
timestr = get_timestr(evlog->submit_time.tv_sec, 1);
|
||||||
|
- printf("%s : %s : TTY=%s ; CWD=%s ; USER=%s ; ",
|
||||||
|
- timestr ? timestr : "invalid date",
|
||||||
|
- evlog->submituser, evlog->ttyname, evlog->cwd, evlog->runuser);
|
||||||
|
- if (evlog->rungroup)
|
||||||
|
- printf("GROUP=%s ; ", evlog->rungroup);
|
||||||
|
- if (evlog->submithost)
|
||||||
|
+ printf("%s : %s : ", timestr ? timestr : "invalid date", evlog->submituser);
|
||||||
|
+ if (evlog->submithost != NULL)
|
||||||
|
printf("HOST=%s ; ", evlog->submithost);
|
||||||
|
+ if (evlog->ttyname != NULL)
|
||||||
|
+ printf("TTY=%s ; ", evlog->ttyname);
|
||||||
|
+ if (evlog->runchroot != NULL)
|
||||||
|
+ printf("CHROOT=%s ; ", evlog->runchroot);
|
||||||
|
+ if (evlog->runcwd != NULL || evlog->cwd != NULL)
|
||||||
|
+ printf("CWD=%s ; ", evlog->runcwd ? evlog->runcwd : evlog->cwd);
|
||||||
|
+ printf("USER=%s ; ", evlog->runuser);
|
||||||
|
+ if (evlog->rungroup != NULL)
|
||||||
|
+ printf("GROUP=%s ; ", evlog->rungroup);
|
||||||
|
printf("TSID=%s ; COMMAND=%s\n", idstr, evlog->command);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
910
SOURCES/sudo-1.9.13-CVE-2023-28486-7-9.patch
Normal file
910
SOURCES/sudo-1.9.13-CVE-2023-28486-7-9.patch
Normal file
@ -0,0 +1,910 @@
|
|||||||
|
diff -up ./doc/sudoers.man.in.cve ./doc/sudoers.man.in
|
||||||
|
--- ./doc/sudoers.man.in.cve 2021-01-09 21:12:16.000000000 +0100
|
||||||
|
+++ ./doc/sudoers.man.in 2023-12-04 16:52:54.499061280 +0100
|
||||||
|
@@ -4978,14 +4978,31 @@ can log events via
|
||||||
|
syslog(3),
|
||||||
|
to a local log file, or both.
|
||||||
|
The log format is almost identical in both cases.
|
||||||
|
+Any control characters present in the log data are formatted in octal
|
||||||
|
+with a leading
|
||||||
|
+\(oq#\(cq
|
||||||
|
+character.
|
||||||
|
+For example, a horizontal tab is stored as
|
||||||
|
+\(oq#011\(cq
|
||||||
|
+and an embedded carriage return is stored as
|
||||||
|
+\(oq#015\(cq.
|
||||||
|
+In addition, space characters in the command path are stored as
|
||||||
|
+\(oq#040\(cq.
|
||||||
|
+Command line arguments that contain spaces are enclosed in single quotes
|
||||||
|
+('').
|
||||||
|
+This makes it possible to distinguish multiple command line arguments
|
||||||
|
+from a single argument that contains spaces.
|
||||||
|
+Literal single quotes and backslash characters
|
||||||
|
+(\(oq\e\(cq)
|
||||||
|
+in command line arguments are escaped with a backslash.
|
||||||
|
.SS "Accepted command log entries"
|
||||||
|
Commands that sudo runs are logged using the following format (split
|
||||||
|
into multiple lines for readability):
|
||||||
|
.nf
|
||||||
|
.sp
|
||||||
|
.RS 4n
|
||||||
|
-date hostname progname: username : TTY=ttyname ; PWD=cwd ; \e
|
||||||
|
- USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
|
||||||
|
+date hostname progname: username : TTY=ttyname ; CHROOT=chroot ; \e
|
||||||
|
+ PWD=cwd ; USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
|
||||||
|
ENV=env_vars COMMAND=command
|
||||||
|
.RE
|
||||||
|
.fi
|
||||||
|
@@ -5034,6 +5051,9 @@ was run on, or
|
||||||
|
\(lqunknown\(rq
|
||||||
|
if there was no terminal present.
|
||||||
|
.TP 14n
|
||||||
|
+chroot
|
||||||
|
+The root directory that the command was run in, if one was specified.
|
||||||
|
+.TP 14n
|
||||||
|
cwd
|
||||||
|
The current working directory that
|
||||||
|
\fBsudo\fR
|
||||||
|
@@ -5058,7 +5078,7 @@ A list of environment variables specifie
|
||||||
|
if specified.
|
||||||
|
.TP 14n
|
||||||
|
command
|
||||||
|
-The actual command that was executed.
|
||||||
|
+The actual command that was executed, including any command line arguments.
|
||||||
|
.PP
|
||||||
|
Messages are logged using the locale specified by
|
||||||
|
\fIsudoers_locale\fR,
|
||||||
|
@@ -5294,17 +5314,21 @@ with a few important differences:
|
||||||
|
1.\&
|
||||||
|
The
|
||||||
|
\fIprogname\fR
|
||||||
|
-and
|
||||||
|
-\fIhostname\fR
|
||||||
|
-fields are not present.
|
||||||
|
+field is not present.
|
||||||
|
.TP 5n
|
||||||
|
2.\&
|
||||||
|
-If the
|
||||||
|
-\fIlog_year\fR
|
||||||
|
-option is enabled,
|
||||||
|
-the date will also include the year.
|
||||||
|
+The
|
||||||
|
+\fIhostname\fR
|
||||||
|
+is only logged if the
|
||||||
|
+\fIlog_host\fR
|
||||||
|
+option is enabled.
|
||||||
|
.TP 5n
|
||||||
|
3.\&
|
||||||
|
+The date does not include the year unless the
|
||||||
|
+\fIlog_year\fR
|
||||||
|
+option is enabled.
|
||||||
|
+.TP 5n
|
||||||
|
+4.\&
|
||||||
|
Lines that are longer than
|
||||||
|
\fIloglinelen\fR
|
||||||
|
characters (80 by default) are word-wrapped and continued on the
|
||||||
|
diff -up ./doc/sudoers.mdoc.in.cve ./doc/sudoers.mdoc.in
|
||||||
|
--- ./doc/sudoers.mdoc.in.cve 2021-01-09 21:12:16.000000000 +0100
|
||||||
|
+++ ./doc/sudoers.mdoc.in 2023-12-04 16:52:54.500061266 +0100
|
||||||
|
@@ -4649,12 +4649,29 @@ can log events via
|
||||||
|
.Xr syslog 3 ,
|
||||||
|
to a local log file, or both.
|
||||||
|
The log format is almost identical in both cases.
|
||||||
|
+Any control characters present in the log data are formatted in octal
|
||||||
|
+with a leading
|
||||||
|
+.Ql #
|
||||||
|
+character.
|
||||||
|
+For example, a horizontal tab is stored as
|
||||||
|
+.Ql #011
|
||||||
|
+and an embedded carriage return is stored as
|
||||||
|
+.Ql #015 .
|
||||||
|
+In addition, space characters in the command path are stored as
|
||||||
|
+.Ql #040 .
|
||||||
|
+Command line arguments that contain spaces are enclosed in single quotes
|
||||||
|
+.Pq '' .
|
||||||
|
+This makes it possible to distinguish multiple command line arguments
|
||||||
|
+from a single argument that contains spaces.
|
||||||
|
+Literal single quotes and backslash characters
|
||||||
|
+.Pq Ql \e
|
||||||
|
+in command line arguments are escaped with a backslash.
|
||||||
|
.Ss Accepted command log entries
|
||||||
|
Commands that sudo runs are logged using the following format (split
|
||||||
|
into multiple lines for readability):
|
||||||
|
.Bd -literal -offset 4n
|
||||||
|
-date hostname progname: username : TTY=ttyname ; PWD=cwd ; \e
|
||||||
|
- USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
|
||||||
|
+date hostname progname: username : TTY=ttyname ; CHROOT=chroot ; \e
|
||||||
|
+ PWD=cwd ; USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
|
||||||
|
ENV=env_vars COMMAND=command
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
@@ -4697,6 +4714,8 @@ or
|
||||||
|
was run on, or
|
||||||
|
.Dq unknown
|
||||||
|
if there was no terminal present.
|
||||||
|
+.It chroot
|
||||||
|
+The root directory that the command was run in, if one was specified.
|
||||||
|
.It cwd
|
||||||
|
The current working directory that
|
||||||
|
.Nm sudo
|
||||||
|
@@ -4716,7 +4735,7 @@ option is enabled.
|
||||||
|
A list of environment variables specified on the command line,
|
||||||
|
if specified.
|
||||||
|
.It command
|
||||||
|
-The actual command that was executed.
|
||||||
|
+The actual command that was executed, including any command line arguments.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Messages are logged using the locale specified by
|
||||||
|
@@ -4938,14 +4957,17 @@ with a few important differences:
|
||||||
|
.It
|
||||||
|
The
|
||||||
|
.Em progname
|
||||||
|
-and
|
||||||
|
+field is not present.
|
||||||
|
+.It
|
||||||
|
+The
|
||||||
|
.Em hostname
|
||||||
|
-fields are not present.
|
||||||
|
+is only logged if the
|
||||||
|
+.Em log_host
|
||||||
|
+option is enabled.
|
||||||
|
.It
|
||||||
|
-If the
|
||||||
|
+The date does not include the year unless the
|
||||||
|
.Em log_year
|
||||||
|
-option is enabled,
|
||||||
|
-the date will also include the year.
|
||||||
|
+option is enabled.
|
||||||
|
.It
|
||||||
|
Lines that are longer than
|
||||||
|
.Em loglinelen
|
||||||
|
diff -up ./doc/sudoreplay.man.in.cve ./doc/sudoreplay.man.in
|
||||||
|
--- ./doc/sudoreplay.man.in.cve 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./doc/sudoreplay.man.in 2023-12-04 16:52:54.500061266 +0100
|
||||||
|
@@ -164,6 +164,15 @@ In this mode,
|
||||||
|
will list available sessions in a format similar to the
|
||||||
|
\fBsudo\fR
|
||||||
|
log file format, sorted by file name (or sequence number).
|
||||||
|
+Any control characters present in the log data are formated in octal
|
||||||
|
+with a leading
|
||||||
|
+\(oq#\(cq
|
||||||
|
+character.
|
||||||
|
+For example, a horizontal tab is displayed as
|
||||||
|
+\(oq#011\(cq
|
||||||
|
+and an embedded carriage return is displayed as
|
||||||
|
+\(oq#015\(cq.
|
||||||
|
+.sp
|
||||||
|
If a
|
||||||
|
\fIsearch expression\fR
|
||||||
|
is specified, it will be used to restrict the IDs that are displayed.
|
||||||
|
diff -up ./doc/sudoreplay.mdoc.in.cve ./doc/sudoreplay.mdoc.in
|
||||||
|
--- ./doc/sudoreplay.mdoc.in.cve 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./doc/sudoreplay.mdoc.in 2023-12-04 16:52:54.500061266 +0100
|
||||||
|
@@ -156,6 +156,16 @@ In this mode,
|
||||||
|
will list available sessions in a format similar to the
|
||||||
|
.Nm sudo
|
||||||
|
log file format, sorted by file name (or sequence number).
|
||||||
|
+Any control characters present in the log data are formatted in octal
|
||||||
|
+with a leading
|
||||||
|
+.Ql #
|
||||||
|
+character.
|
||||||
|
+For example, a horizontal tab is displayed as
|
||||||
|
+.Ql #011
|
||||||
|
+and an embedded carriage return is displayed as
|
||||||
|
+.Ql #015 .
|
||||||
|
+Space characters in the command name and arguments are also formatted in octal.
|
||||||
|
+.Pp
|
||||||
|
If a
|
||||||
|
.Ar search expression
|
||||||
|
is specified, it will be used to restrict the IDs that are displayed.
|
||||||
|
diff -up ./include/sudo_lbuf.h.cve ./include/sudo_lbuf.h
|
||||||
|
--- ./include/sudo_lbuf.h.cve 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./include/sudo_lbuf.h 2023-12-04 16:52:54.500061266 +0100
|
||||||
|
@@ -36,9 +36,15 @@ struct sudo_lbuf {
|
||||||
|
|
||||||
|
typedef int (*sudo_lbuf_output_t)(const char *);
|
||||||
|
|
||||||
|
+/* Flags for sudo_lbuf_append_esc() */
|
||||||
|
+#define LBUF_ESC_CNTRL 0x01
|
||||||
|
+#define LBUF_ESC_BLANK 0x02
|
||||||
|
+#define LBUF_ESC_QUOTE 0x04
|
||||||
|
+
|
||||||
|
sudo_dso_public void sudo_lbuf_init_v1(struct sudo_lbuf *lbuf, sudo_lbuf_output_t output, int indent, const char *continuation, int cols);
|
||||||
|
sudo_dso_public void sudo_lbuf_destroy_v1(struct sudo_lbuf *lbuf);
|
||||||
|
sudo_dso_public bool sudo_lbuf_append_v1(struct sudo_lbuf *lbuf, const char *fmt, ...) __printflike(2, 3);
|
||||||
|
+sudo_dso_public bool sudo_lbuf_append_esc_v1(struct sudo_lbuf *lbuf, int flags, const char *fmt, ...) __printflike(3, 4);
|
||||||
|
sudo_dso_public bool sudo_lbuf_append_quoted_v1(struct sudo_lbuf *lbuf, const char *set, const char *fmt, ...) __printflike(3, 4);
|
||||||
|
sudo_dso_public void sudo_lbuf_print_v1(struct sudo_lbuf *lbuf);
|
||||||
|
sudo_dso_public bool sudo_lbuf_error_v1(struct sudo_lbuf *lbuf);
|
||||||
|
@@ -47,6 +53,7 @@ sudo_dso_public void sudo_lbuf_clearerr_
|
||||||
|
#define sudo_lbuf_init(_a, _b, _c, _d, _e) sudo_lbuf_init_v1((_a), (_b), (_c), (_d), (_e))
|
||||||
|
#define sudo_lbuf_destroy(_a) sudo_lbuf_destroy_v1((_a))
|
||||||
|
#define sudo_lbuf_append sudo_lbuf_append_v1
|
||||||
|
+#define sudo_lbuf_append_esc sudo_lbuf_append_esc_v1
|
||||||
|
#define sudo_lbuf_append_quoted sudo_lbuf_append_quoted_v1
|
||||||
|
#define sudo_lbuf_print(_a) sudo_lbuf_print_v1((_a))
|
||||||
|
#define sudo_lbuf_error(_a) sudo_lbuf_error_v1((_a))
|
||||||
|
diff -up ./lib/eventlog/eventlog.c.cve ./lib/eventlog/eventlog.c
|
||||||
|
--- ./lib/eventlog/eventlog.c.cve 2023-12-04 16:52:54.497061306 +0100
|
||||||
|
+++ ./lib/eventlog/eventlog.c 2023-12-04 16:54:09.820048779 +0100
|
||||||
|
@@ -51,24 +51,13 @@
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_eventlog.h"
|
||||||
|
+#include "sudo_lbuf.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_json.h"
|
||||||
|
#include "sudo_queue.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
-#define LL_HOST_STR "HOST="
|
||||||
|
-#define LL_TTY_STR "TTY="
|
||||||
|
-#define LL_CHROOT_STR "CHROOT="
|
||||||
|
-#define LL_CWD_STR "PWD="
|
||||||
|
-#define LL_USER_STR "USER="
|
||||||
|
-#define LL_GROUP_STR "GROUP="
|
||||||
|
-#define LL_ENV_STR "ENV="
|
||||||
|
-#define LL_CMND_STR "COMMAND="
|
||||||
|
-#define LL_TSID_STR "TSID="
|
||||||
|
-#define LL_EXIT_STR "EXIT="
|
||||||
|
-#define LL_SIGNAL_STR "SIGNAL="
|
||||||
|
-
|
||||||
|
#define IS_SESSID(s) ( \
|
||||||
|
isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \
|
||||||
|
(s)[2] == '/' && \
|
||||||
|
@@ -96,26 +85,28 @@ new_logline(int event_type, int flags, s
|
||||||
|
const struct eventlog *evlog)
|
||||||
|
{
|
||||||
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
|
- char *line = NULL, *evstr = NULL;
|
||||||
|
const char *iolog_file;
|
||||||
|
const char *tty, *tsid = NULL;
|
||||||
|
char exit_str[(((sizeof(int) * 8) + 2) / 3) + 2];
|
||||||
|
char sessid[7];
|
||||||
|
- size_t len = 0;
|
||||||
|
+ struct sudo_lbuf lbuf;
|
||||||
|
int i;
|
||||||
|
debug_decl(new_logline, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
|
||||||
|
+
|
||||||
|
if (ISSET(flags, EVLOG_RAW) || evlog == NULL) {
|
||||||
|
if (args->reason != NULL) {
|
||||||
|
if (args->errstr != NULL) {
|
||||||
|
- if (asprintf(&line, "%s: %s", args->reason, args->errstr) == -1)
|
||||||
|
- goto oom;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "%s: %s",
|
||||||
|
+ args->reason, args->errstr);
|
||||||
|
} else {
|
||||||
|
- if ((line = strdup(args->reason)) == NULL)
|
||||||
|
- goto oom;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "%s", args->reason);
|
||||||
|
}
|
||||||
|
+ if (sudo_lbuf_error(&lbuf))
|
||||||
|
+ goto oom;
|
||||||
|
}
|
||||||
|
- debug_return_str(line);
|
||||||
|
+ debug_return_str(lbuf.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A TSID may be a sudoers-style session ID or a free-form string. */
|
||||||
|
@@ -142,163 +133,92 @@ new_logline(int event_type, int flags, s
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Compute line length
|
||||||
|
+ * Format the log line as an lbuf, escaping control characters is
|
||||||
|
+ * octal form (#0nn). Error checking (ENOMEM) is done at the end
|
||||||
|
*/
|
||||||
|
- if (args->reason != NULL)
|
||||||
|
- len += strlen(args->reason) + 3;
|
||||||
|
- if (args->errstr != NULL)
|
||||||
|
- len += strlen(args->errstr) + 3;
|
||||||
|
- if (evlog->submithost != NULL && !evl_conf->omit_hostname)
|
||||||
|
- len += sizeof(LL_HOST_STR) + 2 + strlen(evlog->submithost);
|
||||||
|
- if (tty != NULL)
|
||||||
|
- len += sizeof(LL_TTY_STR) + 2 + strlen(tty);
|
||||||
|
- if (evlog->runchroot != NULL)
|
||||||
|
- len += sizeof(LL_CHROOT_STR) + 2 + strlen(evlog->runchroot);
|
||||||
|
- if (evlog->runcwd != NULL)
|
||||||
|
- len += sizeof(LL_CWD_STR) + 2 + strlen(evlog->runcwd);
|
||||||
|
- if (evlog->runuser != NULL)
|
||||||
|
- len += sizeof(LL_USER_STR) + 2 + strlen(evlog->runuser);
|
||||||
|
- if (evlog->rungroup != NULL)
|
||||||
|
- len += sizeof(LL_GROUP_STR) + 2 + strlen(evlog->rungroup);
|
||||||
|
- if (tsid != NULL)
|
||||||
|
- len += sizeof(LL_TSID_STR) + 2 + strlen(tsid);
|
||||||
|
- if (evlog->env_add != NULL) {
|
||||||
|
- size_t evlen = 0;
|
||||||
|
- char * const *ep;
|
||||||
|
-
|
||||||
|
- for (ep = evlog->env_add; *ep != NULL; ep++)
|
||||||
|
- evlen += strlen(*ep) + 1;
|
||||||
|
- if (evlen != 0) {
|
||||||
|
- if ((evstr = malloc(evlen)) == NULL)
|
||||||
|
- goto oom;
|
||||||
|
- ep = evlog->env_add;
|
||||||
|
- if (strlcpy(evstr, *ep, evlen) >= evlen)
|
||||||
|
- goto toobig;
|
||||||
|
- while (*++ep != NULL) {
|
||||||
|
- if (strlcat(evstr, " ", evlen) >= evlen ||
|
||||||
|
- strlcat(evstr, *ep, evlen) >= evlen)
|
||||||
|
- goto toobig;
|
||||||
|
- }
|
||||||
|
- len += sizeof(LL_ENV_STR) + 2 + evlen;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (evlog->command != NULL) {
|
||||||
|
- len += sizeof(LL_CMND_STR) - 1 + strlen(evlog->command);
|
||||||
|
- if (evlog->argv != NULL) {
|
||||||
|
- for (i = 1; evlog->argv[i] != NULL; i++)
|
||||||
|
- len += strlen(evlog->argv[i]) + 1;
|
||||||
|
- }
|
||||||
|
- if (event_type == EVLOG_EXIT) {
|
||||||
|
- if (args->signal_name != NULL)
|
||||||
|
- len += sizeof(LL_SIGNAL_STR) + 2 + strlen(args->signal_name);
|
||||||
|
- (void)snprintf(exit_str, sizeof(exit_str), "%d", args->exit_value);
|
||||||
|
- len += sizeof(LL_EXIT_STR) + 2 + strlen(exit_str);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * Allocate and build up the line.
|
||||||
|
- */
|
||||||
|
- if ((line = malloc(++len)) == NULL)
|
||||||
|
- goto oom;
|
||||||
|
- line[0] = '\0';
|
||||||
|
-
|
||||||
|
if (args->reason != NULL) {
|
||||||
|
- if (strlcat(line, args->reason, len) >= len ||
|
||||||
|
- strlcat(line, args->errstr ? " : " : " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "%s%s", args->reason,
|
||||||
|
+ args->errstr ? " : " : " ; ");
|
||||||
|
}
|
||||||
|
if (args->errstr != NULL) {
|
||||||
|
- if (strlcat(line, args->errstr, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "%s ; ", args->errstr);
|
||||||
|
}
|
||||||
|
if (evlog->submithost != NULL && !evl_conf->omit_hostname) {
|
||||||
|
- if (strlcat(line, LL_HOST_STR, len) >= len ||
|
||||||
|
- strlcat(line, evlog->submithost, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "HOST=%s ; ",
|
||||||
|
+ evlog->submithost);
|
||||||
|
}
|
||||||
|
if (tty != NULL) {
|
||||||
|
- if (strlcat(line, LL_TTY_STR, len) >= len ||
|
||||||
|
- strlcat(line, tty, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "TTY=%s ; ", tty);
|
||||||
|
}
|
||||||
|
if (evlog->runchroot != NULL) {
|
||||||
|
- if (strlcat(line, LL_CHROOT_STR, len) >= len ||
|
||||||
|
- strlcat(line, evlog->runchroot, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "CHROOT=%s ; ",
|
||||||
|
+ evlog->runchroot);
|
||||||
|
}
|
||||||
|
if (evlog->runcwd != NULL) {
|
||||||
|
- if (strlcat(line, LL_CWD_STR, len) >= len ||
|
||||||
|
- strlcat(line, evlog->runcwd, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "PWD=%s ; ",
|
||||||
|
+ evlog->runcwd);
|
||||||
|
}
|
||||||
|
if (evlog->runuser != NULL) {
|
||||||
|
- if (strlcat(line, LL_USER_STR, len) >= len ||
|
||||||
|
- strlcat(line, evlog->runuser, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "USER=%s ; ",
|
||||||
|
+ evlog->runuser);
|
||||||
|
}
|
||||||
|
if (evlog->rungroup != NULL) {
|
||||||
|
- if (strlcat(line, LL_GROUP_STR, len) >= len ||
|
||||||
|
- strlcat(line, evlog->rungroup, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
- }
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "GROUP=%s ; ",
|
||||||
|
+ evlog->rungroup);
|
||||||
|
+ }
|
||||||
|
if (tsid != NULL) {
|
||||||
|
- if (strlcat(line, LL_TSID_STR, len) >= len ||
|
||||||
|
- strlcat(line, tsid, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
- }
|
||||||
|
- if (evstr != NULL) {
|
||||||
|
- if (strlcat(line, LL_ENV_STR, len) >= len ||
|
||||||
|
- strlcat(line, evstr, len) >= len ||
|
||||||
|
- strlcat(line, " ; ", len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
- free(evstr);
|
||||||
|
- evstr = NULL;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "TSID=%s ; ", tsid);
|
||||||
|
+ }
|
||||||
|
+ if (evlog->env_add != NULL && evlog->env_add[0] != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "ENV=%s",
|
||||||
|
+ evlog->env_add[0]);
|
||||||
|
+ for (i = 1; evlog->env_add[i] != NULL; i++) {
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, " %s",
|
||||||
|
+ evlog->env_add[i]);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (evlog->command != NULL) {
|
||||||
|
- if (strlcat(line, LL_CMND_STR, len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
- if (strlcat(line, evlog->command, len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
- if (evlog->argv != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL|LBUF_ESC_BLANK,
|
||||||
|
+ "COMMAND=%s", evlog->command);
|
||||||
|
+ if (evlog->argv != NULL && evlog->argv[0] != NULL) {
|
||||||
|
for (i = 1; evlog->argv[i] != NULL; i++) {
|
||||||
|
- if (strlcat(line, " ", len) >= len ||
|
||||||
|
- strlcat(line, evlog->argv[i], len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append(&lbuf, " ");
|
||||||
|
+ if (strchr(evlog->argv[i], ' ') != NULL) {
|
||||||
|
+ /* Wrap args containing spaces in single quotes. */
|
||||||
|
+ sudo_lbuf_append(&lbuf, "'");
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL|LBUF_ESC_QUOTE,
|
||||||
|
+ "%s", evlog->argv[i]);
|
||||||
|
+ sudo_lbuf_append(&lbuf, "'");
|
||||||
|
+ } else {
|
||||||
|
+ /* Escape quotes here too for consistency. */
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf,
|
||||||
|
+ LBUF_ESC_CNTRL|LBUF_ESC_BLANK|LBUF_ESC_QUOTE,
|
||||||
|
+ "%s", evlog->argv[i]);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+/*
|
||||||
|
if (event_type == EVLOG_EXIT) {
|
||||||
|
if (args->signal_name != NULL) {
|
||||||
|
- if (strlcat(line, " ; ", len) >= len ||
|
||||||
|
- strlcat(line, LL_SIGNAL_STR, len) >= len ||
|
||||||
|
- strlcat(line, args->signal_name, len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, " ; SIGNAL=%s",
|
||||||
|
+ evlog->signal_name);
|
||||||
|
}
|
||||||
|
- if (strlcat(line, " ; ", len) >= len ||
|
||||||
|
- strlcat(line, LL_EXIT_STR, len) >= len ||
|
||||||
|
- strlcat(line, exit_str, len) >= len)
|
||||||
|
- goto toobig;
|
||||||
|
+ if (evlog->exit_value != -1) {
|
||||||
|
+ (void)snprintf(exit_str, sizeof(exit_str), "%d",
|
||||||
|
+ evlog->exit_value);
|
||||||
|
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, " ; EXIT=%s",
|
||||||
|
+ exit_str);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
+*/
|
||||||
|
}
|
||||||
|
|
||||||
|
- debug_return_str(line);
|
||||||
|
+ if (!sudo_lbuf_error(&lbuf))
|
||||||
|
+ debug_return_str(lbuf.buf);
|
||||||
|
oom:
|
||||||
|
- free(evstr);
|
||||||
|
+ sudo_lbuf_destroy(&lbuf);
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_str(NULL);
|
||||||
|
-toobig:
|
||||||
|
- free(evstr);
|
||||||
|
- free(line);
|
||||||
|
- sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||||
|
- debug_return_str(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
diff -up ./lib/iolog/iolog_json.c.cve ./lib/iolog/iolog_json.c
|
||||||
|
--- ./lib/iolog/iolog_json.c.cve 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./lib/iolog/iolog_json.c 2023-12-04 16:52:54.500061266 +0100
|
||||||
|
@@ -443,35 +443,6 @@ iolog_parse_json_object(struct json_obje
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Merge cmd and argv as sudoreplay expects. */
|
||||||
|
- if (evlog->command != NULL && evlog->argv != NULL) {
|
||||||
|
- size_t len = strlen(evlog->command) + 1;
|
||||||
|
- char *newcmd;
|
||||||
|
- int ac;
|
||||||
|
-
|
||||||
|
- /* Skip argv[0], we use evlog->command instead. */
|
||||||
|
- for (ac = 1; evlog->argv[ac] != NULL; ac++)
|
||||||
|
- len += strlen(evlog->argv[ac]) + 1;
|
||||||
|
-
|
||||||
|
- if ((newcmd = malloc(len)) == NULL) {
|
||||||
|
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* TODO: optimize this. */
|
||||||
|
- if (strlcpy(newcmd, evlog->command, len) >= len)
|
||||||
|
- sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
- for (ac = 1; evlog->argv[ac] != NULL; ac++) {
|
||||||
|
- if (strlcat(newcmd, " ", len) >= len)
|
||||||
|
- sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
- if (strlcat(newcmd, evlog->argv[ac], len) >= len)
|
||||||
|
- sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- free(evlog->command);
|
||||||
|
- evlog->command = newcmd;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
done:
|
||||||
|
diff -up ./lib/util/lbuf.c.cve ./lib/util/lbuf.c
|
||||||
|
--- ./lib/util/lbuf.c.cve 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./lib/util/lbuf.c 2023-12-04 16:52:54.501061253 +0100
|
||||||
|
@@ -85,6 +85,112 @@ sudo_lbuf_expand(struct sudo_lbuf *lbuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Escape a character in octal form (#0n) and store it as a string
|
||||||
|
+ * in buf, which must have at least 6 bytes available.
|
||||||
|
+ * Returns the length of buf, not counting the terminating NUL byte.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+escape(unsigned char ch, char *buf)
|
||||||
|
+{
|
||||||
|
+ const int len = ch < 0100 ? (ch < 010 ? 3 : 4) : 5;
|
||||||
|
+
|
||||||
|
+ /* Work backwards from the least significant digit to most significant. */
|
||||||
|
+ switch (len) {
|
||||||
|
+ case 5:
|
||||||
|
+ buf[4] = (ch & 7) + '0';
|
||||||
|
+ ch >>= 3;
|
||||||
|
+ FALLTHROUGH;
|
||||||
|
+ case 4:
|
||||||
|
+ buf[3] = (ch & 7) + '0';
|
||||||
|
+ ch >>= 3;
|
||||||
|
+ FALLTHROUGH;
|
||||||
|
+ case 3:
|
||||||
|
+ buf[2] = (ch & 7) + '0';
|
||||||
|
+ buf[1] = '0';
|
||||||
|
+ buf[0] = '#';
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ buf[len] = '\0';
|
||||||
|
+
|
||||||
|
+ return len;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Parse the format and append strings, only %s and %% escapes are supported.
|
||||||
|
+ * Any non-printable characters are escaped in octal as #0nn.
|
||||||
|
+ */
|
||||||
|
+bool
|
||||||
|
+sudo_lbuf_append_esc_v1(struct sudo_lbuf *lbuf, int flags, const char *fmt, ...)
|
||||||
|
+{
|
||||||
|
+ unsigned int saved_len = lbuf->len;
|
||||||
|
+ bool ret = false;
|
||||||
|
+ const char *s;
|
||||||
|
+ va_list ap;
|
||||||
|
+ debug_decl(sudo_lbuf_append_esc, SUDO_DEBUG_UTIL);
|
||||||
|
+
|
||||||
|
+ if (sudo_lbuf_error(lbuf))
|
||||||
|
+ debug_return_bool(false);
|
||||||
|
+
|
||||||
|
+#define should_escape(ch) \
|
||||||
|
+ ((ISSET(flags, LBUF_ESC_CNTRL) && iscntrl((unsigned char)ch)) || \
|
||||||
|
+ (ISSET(flags, LBUF_ESC_BLANK) && isblank((unsigned char)ch)))
|
||||||
|
+#define should_quote(ch) \
|
||||||
|
+ (ISSET(flags, LBUF_ESC_QUOTE) && (ch == '\'' || ch == '\\'))
|
||||||
|
+
|
||||||
|
+ va_start(ap, fmt);
|
||||||
|
+ while (*fmt != '\0') {
|
||||||
|
+ if (fmt[0] == '%' && fmt[1] == 's') {
|
||||||
|
+ if ((s = va_arg(ap, char *)) == NULL)
|
||||||
|
+ s = "(NULL)";
|
||||||
|
+ while (*s != '\0') {
|
||||||
|
+ if (should_escape(*s)) {
|
||||||
|
+ if (!sudo_lbuf_expand(lbuf, sizeof("#0177") - 1))
|
||||||
|
+ goto done;
|
||||||
|
+ lbuf->len += escape(*s++, lbuf->buf + lbuf->len);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (should_quote(*s)) {
|
||||||
|
+ if (!sudo_lbuf_expand(lbuf, 2))
|
||||||
|
+ goto done;
|
||||||
|
+ lbuf->buf[lbuf->len++] = '\\';
|
||||||
|
+ lbuf->buf[lbuf->len++] = *s++;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (!sudo_lbuf_expand(lbuf, 1))
|
||||||
|
+ goto done;
|
||||||
|
+ lbuf->buf[lbuf->len++] = *s++;
|
||||||
|
+ }
|
||||||
|
+ fmt += 2;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (should_escape(*fmt)) {
|
||||||
|
+ if (!sudo_lbuf_expand(lbuf, sizeof("#0177") - 1))
|
||||||
|
+ goto done;
|
||||||
|
+ if (*fmt == '\'') {
|
||||||
|
+ lbuf->buf[lbuf->len++] = '\\';
|
||||||
|
+ lbuf->buf[lbuf->len++] = *fmt++;
|
||||||
|
+ } else {
|
||||||
|
+ lbuf->len += escape(*fmt++, lbuf->buf + lbuf->len);
|
||||||
|
+ }
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (!sudo_lbuf_expand(lbuf, 1))
|
||||||
|
+ goto done;
|
||||||
|
+ lbuf->buf[lbuf->len++] = *fmt++;
|
||||||
|
+ }
|
||||||
|
+ ret = true;
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+ if (!ret)
|
||||||
|
+ lbuf->len = saved_len;
|
||||||
|
+ if (lbuf->size != 0)
|
||||||
|
+ lbuf->buf[lbuf->len] = '\0';
|
||||||
|
+ va_end(ap);
|
||||||
|
+
|
||||||
|
+ debug_return_bool(ret);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* Parse the format and append strings, only %s and %% escapes are supported.
|
||||||
|
* Any characters in set are quoted with a backslash.
|
||||||
|
*/
|
||||||
|
diff -up ./lib/util/util.exp.in.cve ./lib/util/util.exp.in
|
||||||
|
--- ./lib/util/util.exp.in.cve 2021-01-09 21:12:16.000000000 +0100
|
||||||
|
+++ ./lib/util/util.exp.in 2023-12-04 16:52:54.501061253 +0100
|
||||||
|
@@ -95,6 +95,7 @@ sudo_json_get_len_v1
|
||||||
|
sudo_json_init_v1
|
||||||
|
sudo_json_open_array_v1
|
||||||
|
sudo_json_open_object_v1
|
||||||
|
+sudo_lbuf_append_esc_v1
|
||||||
|
sudo_lbuf_append_quoted_v1
|
||||||
|
sudo_lbuf_append_v1
|
||||||
|
sudo_lbuf_clearerr_v1
|
||||||
|
diff -up ./plugins/sudoers/sudoreplay.c.cve ./plugins/sudoers/sudoreplay.c
|
||||||
|
--- ./plugins/sudoers/sudoreplay.c.cve 2023-12-04 16:52:54.498061293 +0100
|
||||||
|
+++ ./plugins/sudoers/sudoreplay.c 2023-12-04 16:52:54.501061253 +0100
|
||||||
|
@@ -62,6 +62,7 @@
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_event.h"
|
||||||
|
#include "sudo_eventlog.h"
|
||||||
|
+#include "sudo_lbuf.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
@@ -363,6 +364,10 @@ main(int argc, char *argv[])
|
||||||
|
if ((evlog = iolog_parse_loginfo(iolog_dir_fd, iolog_dir)) == NULL)
|
||||||
|
goto done;
|
||||||
|
printf(_("Replaying sudo session: %s"), evlog->command);
|
||||||
|
+ if (evlog->argv != NULL && evlog->argv[0] != NULL) {
|
||||||
|
+ for (i = 1; evlog->argv[i] != NULL; i++)
|
||||||
|
+ printf(" %s", evlog->argv[i]);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Setup terminal if appropriate. */
|
||||||
|
if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))
|
||||||
|
@@ -1291,11 +1296,57 @@ parse_expr(struct search_node_list *head
|
||||||
|
debug_return_int(av - argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static char *
|
||||||
|
+expand_command(struct eventlog *evlog, char **newbuf)
|
||||||
|
+{
|
||||||
|
+ size_t len, bufsize = strlen(evlog->command) + 1;
|
||||||
|
+ char *cp, *buf;
|
||||||
|
+ int ac;
|
||||||
|
+ debug_decl(expand_command, SUDO_DEBUG_UTIL);
|
||||||
|
+
|
||||||
|
+ if (evlog->argv == NULL || evlog->argv[0] == NULL || evlog->argv[1] == NULL) {
|
||||||
|
+ /* No arguments, we can use the command as-is. */
|
||||||
|
+ *newbuf = NULL;
|
||||||
|
+ debug_return_str(evlog->command);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Skip argv[0], we use evlog->command instead. */
|
||||||
|
+ for (ac = 1; evlog->argv[ac] != NULL; ac++)
|
||||||
|
+ bufsize += strlen(evlog->argv[ac]) + 1;
|
||||||
|
+
|
||||||
|
+ if ((buf = malloc(bufsize)) == NULL)
|
||||||
|
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
+ cp = buf;
|
||||||
|
+
|
||||||
|
+ len = strlcpy(cp, evlog->command, bufsize);
|
||||||
|
+ if (len >= bufsize)
|
||||||
|
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
+ cp += len;
|
||||||
|
+ bufsize -= len;
|
||||||
|
+
|
||||||
|
+ for (ac = 1; evlog->argv[ac] != NULL; ac++) {
|
||||||
|
+ if (bufsize < 2)
|
||||||
|
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
+ *cp++ = ' ';
|
||||||
|
+ bufsize--;
|
||||||
|
+
|
||||||
|
+ len = strlcpy(cp, evlog->argv[ac], bufsize);
|
||||||
|
+ if (len >= bufsize)
|
||||||
|
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
|
||||||
|
+ cp += len;
|
||||||
|
+ bufsize -= len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *newbuf = buf;
|
||||||
|
+ debug_return_str(buf);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static bool
|
||||||
|
match_expr(struct search_node_list *head, struct eventlog *evlog, bool last_match)
|
||||||
|
{
|
||||||
|
struct search_node *sn;
|
||||||
|
bool res = false, matched = last_match;
|
||||||
|
+ char *tofree;
|
||||||
|
int rc;
|
||||||
|
debug_decl(match_expr, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
@@ -1329,13 +1380,15 @@ match_expr(struct search_node_list *head
|
||||||
|
res = strcmp(sn->u.user, evlog->submituser) == 0;
|
||||||
|
break;
|
||||||
|
case ST_PATTERN:
|
||||||
|
- rc = regexec(&sn->u.cmdre, evlog->command, 0, NULL, 0);
|
||||||
|
+ rc = regexec(&sn->u.cmdre, expand_command(evlog, &tofree),
|
||||||
|
+ 0, NULL, 0);
|
||||||
|
if (rc && rc != REG_NOMATCH) {
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
regerror(rc, &sn->u.cmdre, buf, sizeof(buf));
|
||||||
|
sudo_fatalx("%s", buf);
|
||||||
|
}
|
||||||
|
res = rc == REG_NOMATCH ? 0 : 1;
|
||||||
|
+ free(tofree);
|
||||||
|
break;
|
||||||
|
case ST_FROMDATE:
|
||||||
|
res = sudo_timespeccmp(&evlog->submit_time, &sn->u.tstamp, >=);
|
||||||
|
@@ -1356,12 +1409,13 @@ match_expr(struct search_node_list *head
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-list_session(char *log_dir, regex_t *re, const char *user, const char *tty)
|
||||||
|
+list_session(struct sudo_lbuf *lbuf, char *log_dir, regex_t *re,
|
||||||
|
+ const char *user, const char *tty)
|
||||||
|
{
|
||||||
|
char idbuf[7], *idstr, *cp;
|
||||||
|
struct eventlog *evlog = NULL;
|
||||||
|
const char *timestr;
|
||||||
|
- int ret = -1;
|
||||||
|
+ int i, ret = -1;
|
||||||
|
debug_decl(list_session, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
if ((evlog = iolog_parse_loginfo(-1, log_dir)) == NULL)
|
||||||
|
@@ -1393,23 +1447,71 @@ list_session(char *log_dir, regex_t *re,
|
||||||
|
}
|
||||||
|
/* XXX - print lines + cols? */
|
||||||
|
timestr = get_timestr(evlog->submit_time.tv_sec, 1);
|
||||||
|
- printf("%s : %s : ", timestr ? timestr : "invalid date", evlog->submituser);
|
||||||
|
- if (evlog->submithost != NULL)
|
||||||
|
- printf("HOST=%s ; ", evlog->submithost);
|
||||||
|
- if (evlog->ttyname != NULL)
|
||||||
|
- printf("TTY=%s ; ", evlog->ttyname);
|
||||||
|
- if (evlog->runchroot != NULL)
|
||||||
|
- printf("CHROOT=%s ; ", evlog->runchroot);
|
||||||
|
- if (evlog->runcwd != NULL || evlog->cwd != NULL)
|
||||||
|
- printf("CWD=%s ; ", evlog->runcwd ? evlog->runcwd : evlog->cwd);
|
||||||
|
- printf("USER=%s ; ", evlog->runuser);
|
||||||
|
- if (evlog->rungroup != NULL)
|
||||||
|
- printf("GROUP=%s ; ", evlog->rungroup);
|
||||||
|
- printf("TSID=%s ; COMMAND=%s\n", idstr, evlog->command);
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "%s : %s : ",
|
||||||
|
+ timestr ? timestr : "invalid date", evlog->submituser);
|
||||||
|
+ if (evlog->submithost != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "HOST=%s ; ",
|
||||||
|
+ evlog->submithost);
|
||||||
|
+ }
|
||||||
|
+ if (evlog->ttyname != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "TTY=%s ; ",
|
||||||
|
+ evlog->ttyname);
|
||||||
|
+ }
|
||||||
|
+ if (evlog->runchroot != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "CHROOT=%s ; ",
|
||||||
|
+ evlog->runchroot);
|
||||||
|
+ }
|
||||||
|
+ if (evlog->runcwd != NULL || evlog->cwd != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "CWD=%s ; ",
|
||||||
|
+ evlog->runcwd ? evlog->runcwd : evlog->cwd);
|
||||||
|
+ }
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "USER=%s ; ", evlog->runuser);
|
||||||
|
+ if (evlog->rungroup != NULL) {
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "GROUP=%s ; ",
|
||||||
|
+ evlog->rungroup);
|
||||||
|
+ }
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "TSID=%s ; ", idstr);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If we have both command and argv from info.json we can escape
|
||||||
|
+ * blanks in the the command and arguments. If all we have is a
|
||||||
|
+ * single string containing both the command and arguments we cannot.
|
||||||
|
+ */
|
||||||
|
+ if (evlog->argv != NULL) {
|
||||||
|
+ /* Command plus argv from the info.json file. */
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL|LBUF_ESC_BLANK,
|
||||||
|
+ "COMMAND=%s", evlog->command);
|
||||||
|
+ if (evlog->argv[0] != NULL) {
|
||||||
|
+ for (i = 1; evlog->argv[i] != NULL; i++) {
|
||||||
|
+ sudo_lbuf_append(lbuf, " ");
|
||||||
|
+ if (strchr(evlog->argv[i], ' ') != NULL) {
|
||||||
|
+ /* Wrap args containing spaces in single quotes. */
|
||||||
|
+ sudo_lbuf_append(lbuf, "'");
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL|LBUF_ESC_QUOTE,
|
||||||
|
+ "%s", evlog->argv[i]);
|
||||||
|
+ sudo_lbuf_append(lbuf, "'");
|
||||||
|
+ } else {
|
||||||
|
+ /* Escape quotes here too for consistency. */
|
||||||
|
+ sudo_lbuf_append_esc(lbuf,
|
||||||
|
+ LBUF_ESC_CNTRL|LBUF_ESC_BLANK|LBUF_ESC_QUOTE,
|
||||||
|
+ "%s", evlog->argv[i]);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ /* Single string from the legacy info file. */
|
||||||
|
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "COMMAND=%s",
|
||||||
|
+ evlog->command);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- ret = 0;
|
||||||
|
+ if (!sudo_lbuf_error(lbuf)) {
|
||||||
|
+ puts(lbuf->buf);
|
||||||
|
+ ret = 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
done:
|
||||||
|
+ lbuf->error = 0;
|
||||||
|
+ lbuf->len = 0;
|
||||||
|
eventlog_free(evlog);
|
||||||
|
debug_return_int(ret);
|
||||||
|
}
|
||||||
|
@@ -1429,6 +1531,7 @@ find_sessions(const char *dir, regex_t *
|
||||||
|
DIR *d;
|
||||||
|
struct dirent *dp;
|
||||||
|
struct stat sb;
|
||||||
|
+ struct sudo_lbuf lbuf;
|
||||||
|
size_t sdlen, sessions_len = 0, sessions_size = 0;
|
||||||
|
unsigned int i;
|
||||||
|
int len;
|
||||||
|
@@ -1440,6 +1543,8 @@ find_sessions(const char *dir, regex_t *
|
||||||
|
#endif
|
||||||
|
debug_decl(find_sessions, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
|
||||||
|
+
|
||||||
|
d = opendir(dir);
|
||||||
|
if (d == NULL)
|
||||||
|
sudo_fatal(U_("unable to open %s"), dir);
|
||||||
|
@@ -1500,7 +1605,7 @@ find_sessions(const char *dir, regex_t *
|
||||||
|
/* Check for dir with a log file. */
|
||||||
|
if (lstat(pathbuf, &sb) == 0 && S_ISREG(sb.st_mode)) {
|
||||||
|
pathbuf[sdlen + len - 4] = '\0';
|
||||||
|
- list_session(pathbuf, re, user, tty);
|
||||||
|
+ list_session(&lbuf, pathbuf, re, user, tty);
|
||||||
|
} else {
|
||||||
|
/* Strip off "/log" and recurse if a non-log dir. */
|
||||||
|
pathbuf[sdlen + len - 4] = '\0';
|
||||||
|
@@ -1511,6 +1616,7 @@ find_sessions(const char *dir, regex_t *
|
||||||
|
}
|
||||||
|
free(sessions);
|
||||||
|
}
|
||||||
|
+ sudo_lbuf_destroy(&lbuf);
|
||||||
|
|
||||||
|
debug_return_int(0);
|
||||||
|
}
|
598
SOURCES/sudo-1.9.15-CVE-2023-42465.patch
Normal file
598
SOURCES/sudo-1.9.15-CVE-2023-42465.patch
Normal file
@ -0,0 +1,598 @@
|
|||||||
|
diff -up ./plugins/sudoers/auth/passwd.c.rowhammer ./plugins/sudoers/auth/passwd.c
|
||||||
|
--- ./plugins/sudoers/auth/passwd.c.rowhammer 2020-12-17 02:33:44.000000000 +0100
|
||||||
|
+++ ./plugins/sudoers/auth/passwd.c 2024-01-22 16:01:16.331874669 +0100
|
||||||
|
@@ -62,7 +62,7 @@ sudo_passwd_verify(struct passwd *pw, ch
|
||||||
|
char sav, *epass;
|
||||||
|
char *pw_epasswd = auth->data;
|
||||||
|
size_t pw_len;
|
||||||
|
- int matched = 0;
|
||||||
|
+ int ret;
|
||||||
|
debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
|
||||||
|
|
||||||
|
/* An empty plain-text password must match an empty encrypted password. */
|
||||||
|
@@ -85,27 +85,37 @@ sudo_passwd_verify(struct passwd *pw, ch
|
||||||
|
*/
|
||||||
|
epass = (char *) crypt(pass, pw_epasswd);
|
||||||
|
pass[8] = sav;
|
||||||
|
+ ret = AUTH_FAILURE;
|
||||||
|
if (epass != NULL) {
|
||||||
|
- if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN)
|
||||||
|
- matched = !strncmp(pw_epasswd, epass, DESLEN);
|
||||||
|
- else
|
||||||
|
- matched = !strcmp(pw_epasswd, epass);
|
||||||
|
+ if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN) {
|
||||||
|
+ if (strncmp(pw_epasswd, epass, DESLEN) == 0)
|
||||||
|
+ ret = AUTH_SUCCESS;
|
||||||
|
+ } else {
|
||||||
|
+ if (strcmp(pw_epasswd, epass) == 0)
|
||||||
|
+ ret = AUTH_SUCCESS;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- debug_return_int(matched ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||||
|
+ explicit_bzero(des_pass, sizeof(des_pass));
|
||||||
|
+
|
||||||
|
+ debug_return_int(ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int
|
||||||
|
sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||||
|
{
|
||||||
|
char *pw_passwd = auth->data;
|
||||||
|
- int matched;
|
||||||
|
+ int ret;
|
||||||
|
debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
|
||||||
|
|
||||||
|
/* Simple string compare for systems without crypt(). */
|
||||||
|
matched = !strcmp(pass, pw_passwd);
|
||||||
|
+ if (strcmp(pass, pw_passwd) == 0)
|
||||||
|
+ ret = AUTH_SUCCESS;
|
||||||
|
+ else
|
||||||
|
+ ret = AUTH_FAILURE;
|
||||||
|
|
||||||
|
- debug_return_int(matched ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||||
|
+ debug_return_int(ret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff -up ./plugins/sudoers/auth/sudo_auth.c.rowhammer ./plugins/sudoers/auth/sudo_auth.c
|
||||||
|
--- ./plugins/sudoers/auth/sudo_auth.c.rowhammer 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./plugins/sudoers/auth/sudo_auth.c 2024-01-22 16:01:16.331874669 +0100
|
||||||
|
@@ -112,10 +112,16 @@ sudo_auth_init(struct passwd *pw)
|
||||||
|
if (auth->init && !IS_DISABLED(auth)) {
|
||||||
|
/* Disable if it failed to init unless there was a fatal error. */
|
||||||
|
status = (auth->init)(pw, auth);
|
||||||
|
- if (status == AUTH_FAILURE)
|
||||||
|
- SET(auth->flags, FLAG_DISABLED);
|
||||||
|
- else if (status == AUTH_FATAL)
|
||||||
|
- break; /* assume error msg already printed */
|
||||||
|
+ switch (status) {
|
||||||
|
+ case AUTH_SUCCESS:
|
||||||
|
+ break;
|
||||||
|
+ case AUTH_FAILURE:
|
||||||
|
+ SET(auth->flags, FLAG_DISABLED);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ /* Assume error msg already printed. */
|
||||||
|
+ debug_return_int(-1);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -161,7 +167,7 @@ sudo_auth_init(struct passwd *pw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- debug_return_int(status == AUTH_FATAL ? -1 : 0);
|
||||||
|
+ debug_return_int(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -202,7 +208,7 @@ sudo_auth_cleanup(struct passwd *pw, boo
|
||||||
|
for (auth = auth_switch; auth->name; auth++) {
|
||||||
|
if (auth->cleanup && !IS_DISABLED(auth)) {
|
||||||
|
int status = (auth->cleanup)(pw, auth, force);
|
||||||
|
- if (status == AUTH_FATAL) {
|
||||||
|
+ if (status != AUTH_SUCCESS) {
|
||||||
|
/* Assume error msg already printed. */
|
||||||
|
debug_return_int(-1);
|
||||||
|
}
|
||||||
|
@@ -297,7 +303,7 @@ verify_user(struct passwd *pw, char *pro
|
||||||
|
status = (auth->setup)(pw, &prompt, auth);
|
||||||
|
if (status == AUTH_FAILURE)
|
||||||
|
SET(auth->flags, FLAG_DISABLED);
|
||||||
|
- else if (status == AUTH_FATAL || user_interrupted())
|
||||||
|
+ else if (status != AUTH_SUCCESS || user_interrupted())
|
||||||
|
goto done; /* assume error msg already printed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -348,7 +354,6 @@ done:
|
||||||
|
log_auth_failure(validated, ntries);
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
- case AUTH_FATAL:
|
||||||
|
default:
|
||||||
|
log_auth_failure(validated, 0);
|
||||||
|
ret = -1;
|
||||||
|
@@ -360,24 +365,32 @@ done:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call authentication method begin session hooks.
|
||||||
|
- * Returns 1 on success and -1 on error.
|
||||||
|
+ * Returns true on success, false on failure and -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sudo_auth_begin_session(struct passwd *pw, char **user_env[])
|
||||||
|
{
|
||||||
|
sudo_auth *auth;
|
||||||
|
+ int ret = true;
|
||||||
|
debug_decl(sudo_auth_begin_session, SUDOERS_DEBUG_AUTH);
|
||||||
|
|
||||||
|
for (auth = auth_switch; auth->name; auth++) {
|
||||||
|
if (auth->begin_session && !IS_DISABLED(auth)) {
|
||||||
|
int status = (auth->begin_session)(pw, user_env, auth);
|
||||||
|
- if (status != AUTH_SUCCESS) {
|
||||||
|
- /* Assume error msg already printed. */
|
||||||
|
- debug_return_int(-1);
|
||||||
|
+ switch (status) {
|
||||||
|
+ case AUTH_SUCCESS:
|
||||||
|
+ break;
|
||||||
|
+ case AUTH_FAILURE:
|
||||||
|
+ ret = false;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ /* Assume error msg already printed. */
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- debug_return_int(1);
|
||||||
|
+ debug_return_int(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
@@ -398,25 +411,33 @@ sudo_auth_needs_end_session(void)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call authentication method end session hooks.
|
||||||
|
- * Returns 1 on success and -1 on error.
|
||||||
|
+ * Returns true on success, false on failure and -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sudo_auth_end_session(struct passwd *pw)
|
||||||
|
{
|
||||||
|
sudo_auth *auth;
|
||||||
|
+ int ret = true;
|
||||||
|
int status;
|
||||||
|
debug_decl(sudo_auth_end_session, SUDOERS_DEBUG_AUTH);
|
||||||
|
|
||||||
|
for (auth = auth_switch; auth->name; auth++) {
|
||||||
|
if (auth->end_session && !IS_DISABLED(auth)) {
|
||||||
|
status = (auth->end_session)(pw, auth);
|
||||||
|
- if (status == AUTH_FATAL) {
|
||||||
|
- /* Assume error msg already printed. */
|
||||||
|
- debug_return_int(-1);
|
||||||
|
- }
|
||||||
|
+ switch (status) {
|
||||||
|
+ case AUTH_SUCCESS:
|
||||||
|
+ break;
|
||||||
|
+ case AUTH_FAILURE:
|
||||||
|
+ ret = false;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ /* Assume error msg already printed. */
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- debug_return_int(1);
|
||||||
|
+ debug_return_int(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
diff -up ./plugins/sudoers/auth/sudo_auth.h.rowhammer ./plugins/sudoers/auth/sudo_auth.h
|
||||||
|
--- ./plugins/sudoers/auth/sudo_auth.h.rowhammer 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./plugins/sudoers/auth/sudo_auth.h 2024-01-22 16:01:16.332874679 +0100
|
||||||
|
@@ -19,11 +19,11 @@
|
||||||
|
#ifndef SUDO_AUTH_H
|
||||||
|
#define SUDO_AUTH_H
|
||||||
|
|
||||||
|
-/* Auth function return values. */
|
||||||
|
-#define AUTH_SUCCESS 0
|
||||||
|
-#define AUTH_FAILURE 1
|
||||||
|
-#define AUTH_INTR 2
|
||||||
|
-#define AUTH_FATAL 3
|
||||||
|
+/* Auth function return values (rowhammer resistent). */
|
||||||
|
+#define AUTH_SUCCESS 0x52a2925 /* 0101001010100010100100100101 */
|
||||||
|
+#define AUTH_FAILURE 0xad5d6da /* 1010110101011101011011011010 */
|
||||||
|
+#define AUTH_INTR 0x69d61fc8 /* 1101001110101100001111111001000 */
|
||||||
|
+#define AUTH_FATAL 0x1629e037 /* 0010110001010011110000000110111 */
|
||||||
|
|
||||||
|
typedef struct sudo_auth {
|
||||||
|
int flags; /* various flags, see below */
|
||||||
|
diff -up ./plugins/sudoers/cvtsudoers.c.rowhammer ./plugins/sudoers/cvtsudoers.c
|
||||||
|
--- ./plugins/sudoers/cvtsudoers.c.rowhammer 2024-01-22 18:30:09.585081693 +0100
|
||||||
|
+++ ./plugins/sudoers/cvtsudoers.c 2024-01-22 18:32:35.238519869 +0100
|
||||||
|
@@ -685,7 +685,7 @@ userlist_matches_filter(struct sudoers_p
|
||||||
|
pw.pw_uid = (uid_t)-1;
|
||||||
|
pw.pw_gid = (gid_t)-1;
|
||||||
|
|
||||||
|
- if (user_matches(parse_tree, &pw, m) == true)
|
||||||
|
+ if (user_matches(parse_tree, &pw, m) == ALLOW)
|
||||||
|
matched = true;
|
||||||
|
} else {
|
||||||
|
STAILQ_FOREACH(s, &filters->users, entries) {
|
||||||
|
@@ -711,7 +711,7 @@ userlist_matches_filter(struct sudoers_p
|
||||||
|
if (pw == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
- if (user_matches(parse_tree, pw, m) == true)
|
||||||
|
+ if (user_matches(parse_tree, pw, m) == ALLOW)
|
||||||
|
matched = true;
|
||||||
|
sudo_pw_delref(pw);
|
||||||
|
|
||||||
|
@@ -787,7 +787,7 @@ hostlist_matches_filter(struct sudoers_p
|
||||||
|
|
||||||
|
/* Only need one host in the filter to match. */
|
||||||
|
/* XXX - can't use netgroup_tuple with NULL pw */
|
||||||
|
- if (host_matches(parse_tree, NULL, lhost, shost, m) == true) {
|
||||||
|
+ if (host_matches(parse_tree, NULL, lhost, shost, m) == ALLOW) {
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff -up ./plugins/sudoers/match.c.rowhammer ./plugins/sudoers/match.c
|
||||||
|
--- ./plugins/sudoers/match.c.rowhammer 2020-12-17 02:33:44.000000000 +0100
|
||||||
|
+++ ./plugins/sudoers/match.c 2024-01-22 16:01:16.332874679 +0100
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include "parse.h"
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
@@ -70,37 +71,42 @@ user_matches(struct sudoers_parse_tree *
|
||||||
|
{
|
||||||
|
const char *lhost = parse_tree->lhost ? parse_tree->lhost : user_runhost;
|
||||||
|
const char *shost = parse_tree->shost ? parse_tree->shost : user_srunhost;
|
||||||
|
- int matched = UNSPEC;
|
||||||
|
+ int rc, matched = UNSPEC;
|
||||||
|
struct alias *a;
|
||||||
|
debug_decl(user_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
|
switch (m->type) {
|
||||||
|
case ALL:
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case NETGROUP:
|
||||||
|
if (netgr_matches(m->name,
|
||||||
|
def_netgroup_tuple ? lhost : NULL,
|
||||||
|
def_netgroup_tuple ? shost : NULL, pw->pw_name))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case USERGROUP:
|
||||||
|
if (usergr_matches(m->name, pw->pw_name, pw))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case ALIAS:
|
||||||
|
if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
|
||||||
|
/* XXX */
|
||||||
|
- int rc = userlist_matches(parse_tree, pw, &a->members);
|
||||||
|
- if (rc != UNSPEC)
|
||||||
|
- matched = m->negated ? !rc : rc;
|
||||||
|
+ rc = userlist_matches(parse_tree, pw, &a->members);
|
||||||
|
+ if (SPECIFIED(rc)) {
|
||||||
|
+ if (m->negated) {
|
||||||
|
+ matched = rc == ALLOW ? DENY : ALLOW;
|
||||||
|
+ } else {
|
||||||
|
+ matched = rc;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
alias_put(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FALLTHROUGH;
|
||||||
|
case WORD:
|
||||||
|
if (userpw_matches(m->name, pw->pw_name, pw))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_int(matched);
|
||||||
|
@@ -119,7 +125,8 @@ userlist_matches(struct sudoers_parse_tr
|
||||||
|
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
|
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||||
|
- if ((matched = user_matches(parse_tree, pw, m)) != UNSPEC)
|
||||||
|
+ matched = user_matches(parse_tree, pw, m);
|
||||||
|
+ if (SPECIFIED(matched))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_int(matched);
|
||||||
|
@@ -164,48 +171,53 @@ runaslist_matches(struct sudoers_parse_t
|
||||||
|
/* If no runas user or runas group listed in sudoers, use default. */
|
||||||
|
if (user_list == NULL && group_list == NULL) {
|
||||||
|
debug_return_int(userpw_matches(def_runas_default,
|
||||||
|
- runas_pw->pw_name, runas_pw));
|
||||||
|
+ runas_pw->pw_name, runas_pw) ? ALLOW : DENY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user_list != NULL) {
|
||||||
|
TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) {
|
||||||
|
switch (m->type) {
|
||||||
|
case ALL:
|
||||||
|
- user_matched = !m->negated;
|
||||||
|
+ user_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case NETGROUP:
|
||||||
|
if (netgr_matches(m->name,
|
||||||
|
def_netgroup_tuple ? lhost : NULL,
|
||||||
|
def_netgroup_tuple ? shost : NULL,
|
||||||
|
runas_pw->pw_name))
|
||||||
|
- user_matched = !m->negated;
|
||||||
|
+ user_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case USERGROUP:
|
||||||
|
if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
|
||||||
|
- user_matched = !m->negated;
|
||||||
|
+ user_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case ALIAS:
|
||||||
|
a = alias_get(parse_tree, m->name, RUNASALIAS);
|
||||||
|
if (a != NULL) {
|
||||||
|
rc = runaslist_matches(parse_tree, &a->members,
|
||||||
|
&empty, matching_user, NULL);
|
||||||
|
- if (rc != UNSPEC)
|
||||||
|
- user_matched = m->negated ? !rc : rc;
|
||||||
|
+ if (SPECIFIED(rc)) {
|
||||||
|
+ if (m->negated) {
|
||||||
|
+ user_matched = rc == ALLOW ? DENY : ALLOW;
|
||||||
|
+ } else {
|
||||||
|
+ user_matched = rc;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
alias_put(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FALLTHROUGH;
|
||||||
|
case WORD:
|
||||||
|
if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
|
||||||
|
- user_matched = !m->negated;
|
||||||
|
+ user_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case MYSELF:
|
||||||
|
if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
|
||||||
|
strcmp(user_name, runas_pw->pw_name) == 0)
|
||||||
|
- user_matched = !m->negated;
|
||||||
|
+ user_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (user_matched != UNSPEC) {
|
||||||
|
+ if (SPECIFIED(user_matched)) {
|
||||||
|
if (matching_user != NULL && m->type != ALIAS)
|
||||||
|
*matching_user = m;
|
||||||
|
break;
|
||||||
|
@@ -226,34 +238,40 @@ runaslist_matches(struct sudoers_parse_t
|
||||||
|
TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) {
|
||||||
|
switch (m->type) {
|
||||||
|
case ALL:
|
||||||
|
- group_matched = !m->negated;
|
||||||
|
+ group_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case ALIAS:
|
||||||
|
a = alias_get(parse_tree, m->name, RUNASALIAS);
|
||||||
|
if (a != NULL) {
|
||||||
|
rc = runaslist_matches(parse_tree, &empty,
|
||||||
|
&a->members, NULL, matching_group);
|
||||||
|
- if (rc != UNSPEC)
|
||||||
|
- group_matched = m->negated ? !rc : rc;
|
||||||
|
+ if (SPECIFIED(rc)) {
|
||||||
|
+ if (m->negated) {
|
||||||
|
+ group_matched = rc == ALLOW ? DENY : ALLOW;
|
||||||
|
+ } else {
|
||||||
|
+ group_matched = rc;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
alias_put(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FALLTHROUGH;
|
||||||
|
case WORD:
|
||||||
|
if (group_matches(m->name, runas_gr))
|
||||||
|
- group_matched = !m->negated;
|
||||||
|
+ group_matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (group_matched != UNSPEC) {
|
||||||
|
+ if (SPECIFIED(group_matched)) {
|
||||||
|
if (matching_group != NULL && m->type != ALIAS)
|
||||||
|
*matching_group = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (group_matched == UNSPEC) {
|
||||||
|
+ if (!SPECIFIED(group_matched)) {
|
||||||
|
struct gid_list *runas_groups;
|
||||||
|
/*
|
||||||
|
+ *
|
||||||
|
* The runas group was not explicitly allowed by sudoers.
|
||||||
|
* Check whether it is one of the target user's groups.
|
||||||
|
*/
|
||||||
|
@@ -295,7 +313,7 @@ hostlist_matches_int(struct sudoers_pars
|
||||||
|
|
||||||
|
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||||
|
matched = host_matches(parse_tree, pw, lhost, shost, m);
|
||||||
|
- if (matched != UNSPEC)
|
||||||
|
+ if (SPECIFIED(matched))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_int(matched);
|
||||||
|
@@ -324,37 +342,42 @@ host_matches(struct sudoers_parse_tree *
|
||||||
|
const char *lhost, const char *shost, const struct member *m)
|
||||||
|
{
|
||||||
|
struct alias *a;
|
||||||
|
- int matched = UNSPEC;
|
||||||
|
+ int rc, matched = UNSPEC;
|
||||||
|
debug_decl(host_matches, SUDOERS_DEBUG_MATCH);
|
||||||
|
|
||||||
|
switch (m->type) {
|
||||||
|
case ALL:
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case NETGROUP:
|
||||||
|
if (netgr_matches(m->name, lhost, shost,
|
||||||
|
def_netgroup_tuple ? pw->pw_name : NULL))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case NTWKADDR:
|
||||||
|
if (addr_matches(m->name))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case ALIAS:
|
||||||
|
a = alias_get(parse_tree, m->name, HOSTALIAS);
|
||||||
|
if (a != NULL) {
|
||||||
|
/* XXX */
|
||||||
|
- int rc = hostlist_matches_int(parse_tree, pw, lhost, shost,
|
||||||
|
+ rc = hostlist_matches_int(parse_tree, pw, lhost, shost,
|
||||||
|
&a->members);
|
||||||
|
- if (rc != UNSPEC)
|
||||||
|
- matched = m->negated ? !rc : rc;
|
||||||
|
+ if (SPECIFIED(rc)) {
|
||||||
|
+ if (m->negated) {
|
||||||
|
+ matched = rc == ALLOW ? DENY : ALLOW;
|
||||||
|
+ } else {
|
||||||
|
+ matched = rc;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
alias_put(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FALLTHROUGH;
|
||||||
|
case WORD:
|
||||||
|
if (hostname_matches(shost, lhost, m->name))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_int(matched);
|
||||||
|
@@ -375,7 +398,7 @@ cmndlist_matches(struct sudoers_parse_tr
|
||||||
|
|
||||||
|
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||||
|
matched = cmnd_matches(parse_tree, m, runchroot, info);
|
||||||
|
- if (matched != UNSPEC)
|
||||||
|
+ if (SPECIFIED(matched))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_int(matched);
|
||||||
|
@@ -397,21 +420,26 @@ cmnd_matches(struct sudoers_parse_tree *
|
||||||
|
switch (m->type) {
|
||||||
|
case ALL:
|
||||||
|
if (m->name == NULL) {
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FALLTHROUGH;
|
||||||
|
case COMMAND:
|
||||||
|
c = (struct sudo_command *)m->name;
|
||||||
|
if (command_matches(c->cmnd, c->args, runchroot, info, &c->digests))
|
||||||
|
- matched = !m->negated;
|
||||||
|
+ matched = m->negated ? DENY : ALLOW;
|
||||||
|
break;
|
||||||
|
case ALIAS:
|
||||||
|
a = alias_get(parse_tree, m->name, CMNDALIAS);
|
||||||
|
if (a != NULL) {
|
||||||
|
rc = cmndlist_matches(parse_tree, &a->members, runchroot, info);
|
||||||
|
- if (rc != UNSPEC)
|
||||||
|
- matched = m->negated ? !rc : rc;
|
||||||
|
+ if (SPECIFIED(rc)) {
|
||||||
|
+ if (m->negated) {
|
||||||
|
+ matched = rc == ALLOW ? DENY : ALLOW;
|
||||||
|
+ } else {
|
||||||
|
+ matched = rc;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
alias_put(a);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
diff -up ./plugins/sudoers/parse.c.rowhammer ./plugins/sudoers/parse.c
|
||||||
|
--- ./plugins/sudoers/parse.c.rowhammer 2020-12-17 02:33:43.000000000 +0100
|
||||||
|
+++ ./plugins/sudoers/parse.c 2024-01-22 16:01:16.333874689 +0100
|
||||||
|
@@ -151,7 +151,7 @@ sudoers_lookup_check(struct sudo_nss *ns
|
||||||
|
if (runas_match == ALLOW) {
|
||||||
|
cmnd_match = cmnd_matches(nss->parse_tree, cs->cmnd,
|
||||||
|
cs->runchroot, info);
|
||||||
|
- if (cmnd_match != UNSPEC) {
|
||||||
|
+ if (SPECIFIED(cmnd_match)) {
|
||||||
|
/*
|
||||||
|
* If user is running command as himself,
|
||||||
|
* set runas_pw = sudo_user.pw.
|
||||||
|
@@ -365,7 +365,7 @@ sudoers_lookup(struct sudo_nss_list *snl
|
||||||
|
}
|
||||||
|
|
||||||
|
m = sudoers_lookup_check(nss, pw, &validated, &info, &cs, &defs, now);
|
||||||
|
- if (m != UNSPEC) {
|
||||||
|
+ if (SPECIFIED(m)) {
|
||||||
|
match = m;
|
||||||
|
parse_tree = nss->parse_tree;
|
||||||
|
}
|
||||||
|
@@ -373,7 +373,7 @@ sudoers_lookup(struct sudo_nss_list *snl
|
||||||
|
if (!sudo_nss_can_continue(nss, m))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (match != UNSPEC) {
|
||||||
|
+ if (SPECIFIED(match)) {
|
||||||
|
if (info.cmnd_path != NULL) {
|
||||||
|
/* Update user_cmnd, user_stat, cmnd_status from matching entry. */
|
||||||
|
free(user_cmnd);
|
||||||
|
diff -up ./plugins/sudoers/parse.h.rowhammer ./plugins/sudoers/parse.h
|
||||||
|
--- ./plugins/sudoers/parse.h.rowhammer 2021-01-09 21:12:16.000000000 +0100
|
||||||
|
+++ ./plugins/sudoers/parse.h 2024-01-22 16:01:16.333874689 +0100
|
||||||
|
@@ -20,6 +20,9 @@
|
||||||
|
#ifndef SUDOERS_PARSE_H
|
||||||
|
#define SUDOERS_PARSE_H
|
||||||
|
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "sudo_queue.h"
|
||||||
|
|
||||||
|
@@ -31,13 +34,26 @@
|
||||||
|
|
||||||
|
#undef UNSPEC
|
||||||
|
#define UNSPEC -1
|
||||||
|
+
|
||||||
|
+/* Denied by policy (rowhammer resistent). */
|
||||||
|
#undef DENY
|
||||||
|
-#define DENY 0
|
||||||
|
+#define DENY 0xad5d6da /* 1010110101011101011011011010 */
|
||||||
|
+
|
||||||
|
+/* Allowed by policy (rowhammer resistent). */
|
||||||
|
#undef ALLOW
|
||||||
|
-#define ALLOW 1
|
||||||
|
+#define ALLOW 0x52a2925 /* 0101001010100010100100100101 */
|
||||||
|
+
|
||||||
|
#undef IMPLIED
|
||||||
|
#define IMPLIED 2
|
||||||
|
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * We must explicitly check against ALLOW and DENY instead testing
|
||||||
|
+ * that the value is not UNSPEC to avoid potential ROWHAMMER issues.
|
||||||
|
+ */
|
||||||
|
+#define SPECIFIED(_v) ((_v) == ALLOW || (_v) == DENY)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Initialize all tags to UNSPEC.
|
||||||
|
*/
|
@ -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;
|
|
||||||
+ int dfd;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The parent directory is allowed to be a symbolic
|
|
||||||
+ * link as long as *its* parent is not writable.
|
|
||||||
+ */
|
|
||||||
*slash = '\0';
|
|
||||||
- if (stat(files[i], &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
|
||||||
- memset(&sb, 0, sizeof(sb));
|
|
||||||
- rc = 0;
|
|
||||||
+ SET(command_details->flags, CD_SUDOEDIT_FOLLOW);
|
|
||||||
+ dfd = sudo_edit_open(files[i], DIR_OPEN_FLAGS,
|
|
||||||
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details);
|
|
||||||
+ command_details->flags = sflags;
|
|
||||||
+ if (dfd != -1) {
|
|
||||||
+ if (fstat(dfd, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
|
||||||
+ memset(&sb, 0, sizeof(sb));
|
|
||||||
+ rc = 0;
|
|
||||||
+ }
|
|
||||||
+ close(dfd);
|
|
||||||
}
|
|
||||||
*slash = '/';
|
|
||||||
errno = serrno;
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
|||||||
From adb4360c40df99238c17c3ecedcb1d32d76e2b2e Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
|
||||||
Date: Fri, 17 Apr 2020 19:08:56 -0600
|
|
||||||
Subject: [PATCH] Extend the original file before to the new size before
|
|
||||||
updating it. Instead of opening the original file for writing w/ tuncation,
|
|
||||||
we first extend the file with zeroes (by writing, not seeking), then
|
|
||||||
overwrite it. This should allow sudo to fail early if the disk is out of
|
|
||||||
space before it overwrites the original file.
|
|
||||||
|
|
||||||
---
|
|
||||||
src/sudo_edit.c | 93 ++++++++++++++++++++++++++++++++++++++++---------
|
|
||||||
1 file changed, 77 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/sudo_edit.c b/src/sudo_edit.c
|
|
||||||
index 28f6c6100..d99a5658a 100644
|
|
||||||
--- a/src/sudo_edit.c
|
|
||||||
+++ b/src/sudo_edit.c
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
- * Copyright (c) 2004-2008, 2010-2018 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
+ * Copyright (c) 2004-2008, 2010-2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
@@ -650,6 +650,51 @@ sudo_edit_create_tfiles(struct command_details *command_details,
|
|
||||||
debug_return_int(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Extend the given fd to the specified size in bytes.
|
|
||||||
+ * We do this to allocate disk space up-front before overwriting
|
|
||||||
+ * the original file with the temporary. Otherwise, we could
|
|
||||||
+ * we run out of disk space after truncating the original file.
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+sudo_edit_extend_file(int fd, off_t new_size)
|
|
||||||
+{
|
|
||||||
+ off_t old_size, size;
|
|
||||||
+ ssize_t nwritten;
|
|
||||||
+ char zeroes[1024] = { '\0' };
|
|
||||||
+ debug_decl(sudo_edit_extend_file, SUDO_DEBUG_EDIT);
|
|
||||||
+
|
|
||||||
+ if ((old_size = lseek(fd, 0, SEEK_END)) == -1) {
|
|
||||||
+ sudo_warn("lseek");
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: extending file from %lld to %lld",
|
|
||||||
+ __func__, (long long)old_size, (long long)new_size);
|
|
||||||
+
|
|
||||||
+ for (size = old_size; size < new_size; size += nwritten) {
|
|
||||||
+ size_t len = new_size - size;
|
|
||||||
+ if (len > sizeof(zeroes))
|
|
||||||
+ len = sizeof(zeroes);
|
|
||||||
+ nwritten = write(fd, zeroes, len);
|
|
||||||
+ if (nwritten == -1) {
|
|
||||||
+ int serrno = errno;
|
|
||||||
+ if (ftruncate(fd, old_size) == -1) {
|
|
||||||
+ sudo_debug_printf(
|
|
||||||
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
||||||
+ "unable to truncate to %lld", (long long)old_size);
|
|
||||||
+ }
|
|
||||||
+ errno = serrno;
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (lseek(fd, 0, SEEK_SET) == -1) {
|
|
||||||
+ sudo_warn("lseek");
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ debug_return_int(0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Copy the temporary files specified in tf to the originals.
|
|
||||||
* Returns the number of copy errors or 0 if completely successful.
|
|
||||||
@@ -708,38 +753,53 @@ sudo_edit_copy_tfiles(struct command_details *command_details,
|
|
||||||
switch_user(command_details->euid, command_details->egid,
|
|
||||||
command_details->ngroups, command_details->groups);
|
|
||||||
oldmask = umask(command_details->umask);
|
|
||||||
- ofd = sudo_edit_open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT,
|
|
||||||
+ ofd = sudo_edit_open(tf[i].ofile, O_WRONLY|O_CREAT,
|
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details);
|
|
||||||
umask(oldmask);
|
|
||||||
switch_user(ROOT_UID, user_details.egid,
|
|
||||||
user_details.ngroups, user_details.groups);
|
|
||||||
- if (ofd == -1) {
|
|
||||||
- sudo_warn(U_("unable to write to %s"), tf[i].ofile);
|
|
||||||
- sudo_warnx(U_("contents of edit session left in %s"), tf[i].tfile);
|
|
||||||
- close(tfd);
|
|
||||||
- errors++;
|
|
||||||
- continue;
|
|
||||||
+ if (ofd == -1)
|
|
||||||
+ goto write_error;
|
|
||||||
+ /* Extend the file to the new size if larger before copying. */
|
|
||||||
+ if (tf[i].osize > 0 && sb.st_size > tf[i].osize) {
|
|
||||||
+ if (sudo_edit_extend_file(ofd, sb.st_size) == -1)
|
|
||||||
+ goto write_error;
|
|
||||||
}
|
|
||||||
+ /* Overwrite the old file with the new contents. */
|
|
||||||
while ((nread = read(tfd, buf, sizeof(buf))) > 0) {
|
|
||||||
- if ((nwritten = write(ofd, buf, nread)) != nread) {
|
|
||||||
+ ssize_t off = 0;
|
|
||||||
+ do {
|
|
||||||
+ nwritten = write(ofd, buf + off, nread - off);
|
|
||||||
if (nwritten == -1)
|
|
||||||
- sudo_warn("%s", tf[i].ofile);
|
|
||||||
- else
|
|
||||||
- sudo_warnx(U_("%s: short write"), tf[i].ofile);
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
+ goto write_error;
|
|
||||||
+ off += nwritten;
|
|
||||||
+ } while (nread > off);
|
|
||||||
}
|
|
||||||
if (nread == 0) {
|
|
||||||
- /* success, got EOF */
|
|
||||||
+ /* success, read to EOF */
|
|
||||||
+ if (tf[i].osize > 0 && sb.st_size < tf[i].osize) {
|
|
||||||
+ /* We don't open with O_TRUNC so must truncate manually. */
|
|
||||||
+ if (ftruncate(ofd, sb.st_size) == -1) {
|
|
||||||
+ sudo_debug_printf(
|
|
||||||
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
||||||
+ "unable to truncate %s to %lld", tf[i].ofile,
|
|
||||||
+ (long long)sb.st_size);
|
|
||||||
+ goto write_error;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
unlink(tf[i].tfile);
|
|
||||||
} else if (nread < 0) {
|
|
||||||
sudo_warn(U_("unable to read temporary file"));
|
|
||||||
sudo_warnx(U_("contents of edit session left in %s"), tf[i].tfile);
|
|
||||||
+ errors++;
|
|
||||||
} else {
|
|
||||||
+write_error:
|
|
||||||
sudo_warn(U_("unable to write to %s"), tf[i].ofile);
|
|
||||||
sudo_warnx(U_("contents of edit session left in %s"), tf[i].tfile);
|
|
||||||
+ errors++;
|
|
||||||
}
|
|
||||||
- close(ofd);
|
|
||||||
+ if (ofd != -1)
|
|
||||||
+ close(ofd);
|
|
||||||
close(tfd);
|
|
||||||
}
|
|
||||||
debug_return_int(errors);
|
|
||||||
@@ -1065,6 +1125,7 @@ cleanup:
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
if (tf[i].tfile != NULL)
|
|
||||||
unlink(tf[i].tfile);
|
|
||||||
+ free(tf[i].tfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(tf);
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
@ -1,431 +0,0 @@
|
|||||||
diff -up ./src/copy_file.c.symbolic-link-attack-2 ./src/copy_file.c
|
|
||||||
--- ./src/copy_file.c.symbolic-link-attack-2 2021-02-02 15:31:20.555340446 +0100
|
|
||||||
+++ ./src/copy_file.c 2021-02-02 15:31:20.555340446 +0100
|
|
||||||
@@ -0,0 +1,128 @@
|
|
||||||
+/*
|
|
||||||
+ * SPDX-License-Identifier: ISC
|
|
||||||
+ *
|
|
||||||
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
+ *
|
|
||||||
+ * 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 <unistd.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+
|
|
||||||
+#include "sudo.h"
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Extend the given fd to the specified size in bytes.
|
|
||||||
+ * We do this to allocate disk space up-front before overwriting
|
|
||||||
+ * the original file with the temporary. Otherwise, we could
|
|
||||||
+ * we run out of disk space after truncating the original file.
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+sudo_extend_file(int fd, const char *name, off_t new_size)
|
|
||||||
+{
|
|
||||||
+ off_t old_size, size;
|
|
||||||
+ ssize_t nwritten;
|
|
||||||
+ char zeroes[BUFSIZ] = { '\0' };
|
|
||||||
+ debug_decl(sudo_extend_file, SUDO_DEBUG_UTIL);
|
|
||||||
+
|
|
||||||
+ if ((old_size = lseek(fd, 0, SEEK_END)) == -1) {
|
|
||||||
+ sudo_warn("lseek");
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: extending %s from %lld to %lld",
|
|
||||||
+ __func__, name, (long long)old_size, (long long)new_size);
|
|
||||||
+
|
|
||||||
+ for (size = old_size; size < new_size; size += nwritten) {
|
|
||||||
+ size_t len = new_size - size;
|
|
||||||
+ if (len > sizeof(zeroes))
|
|
||||||
+ len = sizeof(zeroes);
|
|
||||||
+ nwritten = write(fd, zeroes, len);
|
|
||||||
+ if (nwritten == -1) {
|
|
||||||
+ int serrno = errno;
|
|
||||||
+ if (ftruncate(fd, old_size) == -1) {
|
|
||||||
+ sudo_debug_printf(
|
|
||||||
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
||||||
+ "unable to truncate %s to %lld", name, (long long)old_size);
|
|
||||||
+ }
|
|
||||||
+ errno = serrno;
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (lseek(fd, 0, SEEK_SET) == -1) {
|
|
||||||
+ sudo_warn("lseek");
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ debug_return_int(0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Copy the contents of src_fd into dst_fd.
|
|
||||||
+ * Returns 0 on success or -1 on error.
|
|
||||||
+ */
|
|
||||||
+int
|
|
||||||
+sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst,
|
|
||||||
+ int dst_fd, off_t dst_len)
|
|
||||||
+{
|
|
||||||
+ char buf[BUFSIZ];
|
|
||||||
+ ssize_t nwritten, nread;
|
|
||||||
+ debug_decl(sudo_copy_file, SUDO_DEBUG_UTIL);
|
|
||||||
+
|
|
||||||
+ /* Extend the file to the new size if larger before copying. */
|
|
||||||
+ if (dst_len > 0 && src_len > dst_len) {
|
|
||||||
+ if (sudo_extend_file(dst_fd, dst, src_len) == -1)
|
|
||||||
+ goto write_error;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Overwrite the old file with the new contents. */
|
|
||||||
+ while ((nread = read(src_fd, buf, sizeof(buf))) > 0) {
|
|
||||||
+ ssize_t off = 0;
|
|
||||||
+ do {
|
|
||||||
+ nwritten = write(dst_fd, buf + off, nread - off);
|
|
||||||
+ if (nwritten == -1)
|
|
||||||
+ goto write_error;
|
|
||||||
+ off += nwritten;
|
|
||||||
+ } while (nread > off);
|
|
||||||
+ }
|
|
||||||
+ if (nread == 0) {
|
|
||||||
+ /* success, read to EOF */
|
|
||||||
+ if (src_len < dst_len) {
|
|
||||||
+ /* We don't open with O_TRUNC so must truncate manually. */
|
|
||||||
+ if (ftruncate(dst_fd, src_len) == -1) {
|
|
||||||
+ sudo_debug_printf(
|
|
||||||
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
||||||
+ "unable to truncate %s to %lld", dst, (long long)src_len);
|
|
||||||
+ goto write_error;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ debug_return_int(0);
|
|
||||||
+ } else if (nread < 0) {
|
|
||||||
+ sudo_warn(U_("unable to read from %s"), src);
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ } else {
|
|
||||||
+write_error:
|
|
||||||
+ sudo_warn(U_("unable to write to %s"), dst);
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff -up ./src/Makefile.in.symbolic-link-attack-2 ./src/Makefile.in
|
|
||||||
--- ./src/Makefile.in.symbolic-link-attack-2 2019-10-28 13:28:54.000000000 +0100
|
|
||||||
+++ ./src/Makefile.in 2021-02-02 15:31:20.555340446 +0100
|
|
||||||
@@ -120,16 +120,17 @@ SHELL = @SHELL@
|
|
||||||
|
|
||||||
PROGS = @PROGS@
|
|
||||||
|
|
||||||
-OBJS = conversation.o env_hooks.o exec.o exec_common.o exec_monitor.o \
|
|
||||||
- exec_nopty.o exec_pty.o get_pty.o hooks.o limits.o load_plugins.o \
|
|
||||||
- net_ifs.o parse_args.o preserve_fds.o signal.o sudo.o sudo_edit.o \
|
|
||||||
- tcsetpgrp_nobg.o tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
|
|
||||||
+OBJS = conversation.o copy_file.o env_hooks.o exec.o exec_common.o \
|
|
||||||
+ exec_monitor.o exec_nopty.o exec_pty.o get_pty.o hooks.o \
|
|
||||||
+ limits.o load_plugins.o net_ifs.o parse_args.o preserve_fds.o \
|
|
||||||
+ signal.o sudo.o sudo_edit.o tcsetpgrp_nobg.o tgetpass.o \
|
|
||||||
+ ttyname.o utmp.o @SUDO_OBJS@
|
|
||||||
|
|
||||||
IOBJS = $(OBJS:.o=.i) sesh.i
|
|
||||||
|
|
||||||
POBJS = $(IOBJS:.i=.plog)
|
|
||||||
|
|
||||||
-SESH_OBJS = sesh.o exec_common.o
|
|
||||||
+SESH_OBJS = copy_file.o exec_common.o sesh.o
|
|
||||||
|
|
||||||
CHECK_NOEXEC_OBJS = check_noexec.o exec_common.o
|
|
||||||
|
|
||||||
@@ -335,6 +336,22 @@ conversation.i: $(srcdir)/conversation.c
|
|
||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
|
||||||
conversation.plog: conversation.i
|
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/conversation.c --i-file $< --output-file $@
|
|
||||||
+copy_file.o: $(srcdir)/copy_file.c $(incdir)/compat/stdbool.h \
|
|
||||||
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
|
||||||
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
|
||||||
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
|
|
||||||
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
|
|
||||||
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/copy_file.c
|
|
||||||
+copy_file.i: $(srcdir)/copy_file.c $(incdir)/compat/stdbool.h \
|
|
||||||
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
|
||||||
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
|
||||||
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
|
|
||||||
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
|
|
||||||
+ $(CC) -E -o $@ $(CPPFLAGS) $<
|
|
||||||
+copy_file.plog: copy_file.i
|
|
||||||
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/copy_file.c --i-file $< --output-file $@
|
|
||||||
env_hooks.o: $(srcdir)/env_hooks.c $(incdir)/compat/stdbool.h \
|
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
$(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \
|
|
||||||
diff -up ./src/sesh.c.symbolic-link-attack-2 ./src/sesh.c
|
|
||||||
--- ./src/sesh.c.symbolic-link-attack-2 2019-10-28 13:28:52.000000000 +0100
|
|
||||||
+++ ./src/sesh.c 2021-02-02 15:31:20.555340446 +0100
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
- * Copyright (c) 2008, 2010-2018 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
+ * Copyright (c) 2008, 2010-2018, 2020 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
@@ -182,7 +182,7 @@ sesh_sudoedit(int argc, char *argv[])
|
|
||||||
* so that it's ensured that the temporary files are
|
|
||||||
* created by us and that we are not opening any symlinks.
|
|
||||||
*/
|
|
||||||
- oflags_dst = O_WRONLY|O_TRUNC|O_CREAT|(post ? follow : O_EXCL);
|
|
||||||
+ oflags_dst = O_WRONLY|O_CREAT|(post ? follow : O_EXCL);
|
|
||||||
for (i = 0; i < argc - 1; i += 2) {
|
|
||||||
const char *path_src = argv[i];
|
|
||||||
const char *path_dst = argv[i + 1];
|
|
||||||
@@ -214,14 +214,29 @@ sesh_sudoedit(int argc, char *argv[])
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd_src != -1) {
|
|
||||||
- while ((nread = read(fd_src, buf, sizeof(buf))) > 0) {
|
|
||||||
- if ((nwritten = write(fd_dst, buf, nread)) != nread) {
|
|
||||||
- sudo_warn("%s", path_src);
|
|
||||||
- if (post) {
|
|
||||||
- ret = SESH_ERR_SOME_FILES;
|
|
||||||
- goto nocleanup;
|
|
||||||
- } else
|
|
||||||
- goto cleanup_0;
|
|
||||||
+ off_t len_src = -1;
|
|
||||||
+ off_t len_dst = -1;
|
|
||||||
+
|
|
||||||
+ if (post) {
|
|
||||||
+ if (fstat(fd_src, &sb) != 0) {
|
|
||||||
+ ret = SESH_ERR_SOME_FILES;
|
|
||||||
+ goto nocleanup;
|
|
||||||
+ }
|
|
||||||
+ len_src = sb.st_size;
|
|
||||||
+ if (fstat(fd_dst, &sb) != 0) {
|
|
||||||
+ ret = SESH_ERR_SOME_FILES;
|
|
||||||
+ goto nocleanup;
|
|
||||||
+ }
|
|
||||||
+ len_dst = sb.st_size;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (sudo_copy_file(path_src, fd_src, len_src, path_dst, fd_dst,
|
|
||||||
+ len_dst) == -1) {
|
|
||||||
+ if (post) {
|
|
||||||
+ ret = SESH_ERR_SOME_FILES;
|
|
||||||
+ goto nocleanup;
|
|
||||||
+ } else {
|
|
||||||
+ goto cleanup_0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff -up ./src/sudo_edit.c.symbolic-link-attack-2 ./src/sudo_edit.c
|
|
||||||
--- ./src/sudo_edit.c.symbolic-link-attack-2 2021-02-02 15:31:20.554340459 +0100
|
|
||||||
+++ ./src/sudo_edit.c 2021-02-02 15:31:54.355884326 +0100
|
|
||||||
@@ -42,7 +42,6 @@
|
|
||||||
#include <grp.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <signal.h>
|
|
||||||
-#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "sudo.h"
|
|
||||||
@@ -551,8 +550,6 @@ sudo_edit_create_tfiles(struct command_d
|
|
||||||
struct tempfile *tf, char *files[], int nfiles)
|
|
||||||
{
|
|
||||||
int i, j, tfd, ofd, rc;
|
|
||||||
- char buf[BUFSIZ];
|
|
||||||
- ssize_t nwritten, nread;
|
|
||||||
struct timespec times[2];
|
|
||||||
struct stat sb;
|
|
||||||
debug_decl(sudo_edit_create_tfiles, SUDO_DEBUG_EDIT)
|
|
||||||
@@ -648,18 +645,7 @@ sudo_edit_create_tfiles(struct command_d
|
|
||||||
debug_return_int(-1);
|
|
||||||
}
|
|
||||||
if (ofd != -1) {
|
|
||||||
- while ((nread = read(ofd, buf, sizeof(buf))) > 0) {
|
|
||||||
- if ((nwritten = write(tfd, buf, nread)) != nread) {
|
|
||||||
- if (nwritten == -1)
|
|
||||||
- sudo_warn("%s", tf[j].tfile);
|
|
||||||
- else
|
|
||||||
- sudo_warnx(U_("%s: short write"), tf[j].tfile);
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- if (nread != 0) {
|
|
||||||
- if (nread < 0)
|
|
||||||
- sudo_warn("%s", files[i]);
|
|
||||||
+ if (sudo_copy_file(tf[j].ofile, ofd, tf[j].osize, tf[j].tfile, tfd, -1) == -1) {
|
|
||||||
close(ofd);
|
|
||||||
close(tfd);
|
|
||||||
debug_return_int(-1);
|
|
||||||
@@ -689,51 +675,6 @@ sudo_edit_create_tfiles(struct command_d
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Extend the given fd to the specified size in bytes.
|
|
||||||
- * We do this to allocate disk space up-front before overwriting
|
|
||||||
- * the original file with the temporary. Otherwise, we could
|
|
||||||
- * we run out of disk space after truncating the original file.
|
|
||||||
- */
|
|
||||||
-static int
|
|
||||||
-sudo_edit_extend_file(int fd, off_t new_size)
|
|
||||||
-{
|
|
||||||
- off_t old_size, size;
|
|
||||||
- ssize_t nwritten;
|
|
||||||
- char zeroes[1024] = { '\0' };
|
|
||||||
- debug_decl(sudo_edit_extend_file, SUDO_DEBUG_EDIT);
|
|
||||||
-
|
|
||||||
- if ((old_size = lseek(fd, 0, SEEK_END)) == -1) {
|
|
||||||
- sudo_warn("lseek");
|
|
||||||
- debug_return_int(-1);
|
|
||||||
- }
|
|
||||||
- sudo_debug_printf(SUDO_DEBUG_INFO, "%s: extending file from %lld to %lld",
|
|
||||||
- __func__, (long long)old_size, (long long)new_size);
|
|
||||||
-
|
|
||||||
- for (size = old_size; size < new_size; size += nwritten) {
|
|
||||||
- size_t len = new_size - size;
|
|
||||||
- if (len > sizeof(zeroes))
|
|
||||||
- len = sizeof(zeroes);
|
|
||||||
- nwritten = write(fd, zeroes, len);
|
|
||||||
- if (nwritten == -1) {
|
|
||||||
- int serrno = errno;
|
|
||||||
- if (ftruncate(fd, old_size) == -1) {
|
|
||||||
- sudo_debug_printf(
|
|
||||||
- SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
||||||
- "unable to truncate to %lld", (long long)old_size);
|
|
||||||
- }
|
|
||||||
- errno = serrno;
|
|
||||||
- debug_return_int(-1);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- if (lseek(fd, 0, SEEK_SET) == -1) {
|
|
||||||
- sudo_warn("lseek");
|
|
||||||
- debug_return_int(-1);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- debug_return_int(0);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-/*
|
|
||||||
* Copy the temporary files specified in tf to the originals.
|
|
||||||
* Returns the number of copy errors or 0 if completely successful.
|
|
||||||
*/
|
|
||||||
@@ -741,9 +682,7 @@ static int
|
|
||||||
sudo_edit_copy_tfiles(struct command_details *command_details,
|
|
||||||
struct tempfile *tf, int nfiles, struct timespec *times)
|
|
||||||
{
|
|
||||||
- int i, tfd, ofd, rc, errors = 0;
|
|
||||||
- char buf[BUFSIZ];
|
|
||||||
- ssize_t nwritten, nread;
|
|
||||||
+ int i, tfd, ofd, errors = 0;
|
|
||||||
struct timespec ts;
|
|
||||||
struct stat sb;
|
|
||||||
mode_t oldmask;
|
|
||||||
@@ -751,7 +690,7 @@ sudo_edit_copy_tfiles(struct command_det
|
|
||||||
|
|
||||||
/* Copy contents of temp files to real ones. */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
- rc = -1;
|
|
||||||
+ int rc = -1;
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
|
||||||
"seteuid(%u)", (unsigned int)user_details.uid);
|
|
||||||
if (seteuid(user_details.uid) != 0)
|
|
||||||
@@ -764,8 +703,8 @@ sudo_edit_copy_tfiles(struct command_det
|
|
||||||
"seteuid(%u)", ROOT_UID);
|
|
||||||
if (seteuid(ROOT_UID) != 0)
|
|
||||||
sudo_fatal("seteuid(ROOT_UID)");
|
|
||||||
- if (rc || !S_ISREG(sb.st_mode)) {
|
|
||||||
- if (rc)
|
|
||||||
+ if (rc == -1 || !S_ISREG(sb.st_mode)) {
|
|
||||||
+ if (rc == -1)
|
|
||||||
sudo_warn("%s", tf[i].tfile);
|
|
||||||
else
|
|
||||||
sudo_warnx(U_("%s: not a regular file"), tf[i].tfile);
|
|
||||||
@@ -796,46 +735,19 @@ sudo_edit_copy_tfiles(struct command_det
|
|
||||||
umask(oldmask);
|
|
||||||
switch_user(ROOT_UID, user_details.egid,
|
|
||||||
user_details.ngroups, user_details.groups);
|
|
||||||
- if (ofd == -1)
|
|
||||||
- goto write_error;
|
|
||||||
- /* Extend the file to the new size if larger before copying. */
|
|
||||||
- if (tf[i].osize > 0 && sb.st_size > tf[i].osize) {
|
|
||||||
- if (sudo_edit_extend_file(ofd, sb.st_size) == -1)
|
|
||||||
- goto write_error;
|
|
||||||
+ if (ofd == -1) {
|
|
||||||
+ sudo_warn(U_("unable to write to %s"), tf[i].ofile);
|
|
||||||
+ goto bad;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
/* Overwrite the old file with the new contents. */
|
|
||||||
- while ((nread = read(tfd, buf, sizeof(buf))) > 0) {
|
|
||||||
- ssize_t off = 0;
|
|
||||||
- do {
|
|
||||||
- nwritten = write(ofd, buf + off, nread - off);
|
|
||||||
- if (nwritten == -1)
|
|
||||||
- goto write_error;
|
|
||||||
- off += nwritten;
|
|
||||||
- } while (nread > off);
|
|
||||||
- }
|
|
||||||
- if (nread == 0) {
|
|
||||||
- /* success, read to EOF */
|
|
||||||
- if (tf[i].osize > 0 && sb.st_size < tf[i].osize) {
|
|
||||||
- /* We don't open with O_TRUNC so must truncate manually. */
|
|
||||||
- if (ftruncate(ofd, sb.st_size) == -1) {
|
|
||||||
- sudo_debug_printf(
|
|
||||||
- SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
||||||
- "unable to truncate %s to %lld", tf[i].ofile,
|
|
||||||
- (long long)sb.st_size);
|
|
||||||
- goto write_error;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- unlink(tf[i].tfile);
|
|
||||||
- } else if (nread < 0) {
|
|
||||||
- sudo_warn(U_("unable to read temporary file"));
|
|
||||||
- sudo_warnx(U_("contents of edit session left in %s"), tf[i].tfile);
|
|
||||||
- errors++;
|
|
||||||
- } else {
|
|
||||||
-write_error:
|
|
||||||
- sudo_warn(U_("unable to write to %s"), tf[i].ofile);
|
|
||||||
+ if (sudo_copy_file(tf[i].tfile, tfd, sb.st_size, tf[i].ofile, ofd,
|
|
||||||
+ tf[i].osize) == -1) {
|
|
||||||
+bad:
|
|
||||||
sudo_warnx(U_("contents of edit session left in %s"), tf[i].tfile);
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
if (ofd != -1)
|
|
||||||
close(ofd);
|
|
||||||
close(tfd);
|
|
||||||
diff -up ./src/sudo_exec.h.symbolic-link-attack-2 ./src/sudo_exec.h
|
|
||||||
--- ./src/sudo_exec.h.symbolic-link-attack-2 2019-10-28 13:27:39.000000000 +0100
|
|
||||||
+++ ./src/sudo_exec.h 2021-02-02 15:31:20.556340432 +0100
|
|
||||||
@@ -84,6 +84,9 @@
|
|
||||||
struct command_details;
|
|
||||||
struct command_status;
|
|
||||||
|
|
||||||
+/* copy_file.c */
|
|
||||||
+int sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst, int dst_fd, off_t dst_len);
|
|
||||||
+
|
|
||||||
/* exec.c */
|
|
||||||
void exec_cmnd(struct command_details *details, int errfd);
|
|
||||||
void terminate_command(pid_t pid, bool use_pgrp);
|
|
@ -1,345 +0,0 @@
|
|||||||
diff -up ./src/exec_monitor.c.symbolic-link-attack-3 ./src/exec_monitor.c
|
|
||||||
--- ./src/exec_monitor.c.symbolic-link-attack-3 2019-10-28 13:27:39.000000000 +0100
|
|
||||||
+++ ./src/exec_monitor.c 2021-02-02 17:11:32.382020407 +0100
|
|
||||||
@@ -613,7 +613,7 @@ exec_monitor(struct command_details *det
|
|
||||||
#ifdef HAVE_SELINUX
|
|
||||||
if (ISSET(details->flags, CD_RBAC_ENABLED)) {
|
|
||||||
if (selinux_setup(details->selinux_role, details->selinux_type,
|
|
||||||
- details->tty, io_fds[SFD_SLAVE]) == -1)
|
|
||||||
+ details->tty, io_fds[SFD_SLAVE], true) == -1)
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
diff -up ./src/exec_nopty.c.symbolic-link-attack-3 ./src/exec_nopty.c
|
|
||||||
--- ./src/exec_nopty.c.symbolic-link-attack-3 2019-10-28 13:27:39.000000000 +0100
|
|
||||||
+++ ./src/exec_nopty.c 2021-02-02 17:11:32.382020407 +0100
|
|
||||||
@@ -381,7 +381,7 @@ exec_nopty(struct command_details *detai
|
|
||||||
#ifdef HAVE_SELINUX
|
|
||||||
if (ISSET(details->flags, CD_RBAC_ENABLED)) {
|
|
||||||
if (selinux_setup(details->selinux_role, details->selinux_type,
|
|
||||||
- details->tty, -1) == -1) {
|
|
||||||
+ details->tty, -1, true) == -1) {
|
|
||||||
cstat->type = CMD_ERRNO;
|
|
||||||
cstat->val = errno;
|
|
||||||
debug_return;
|
|
||||||
diff -up ./src/selinux.c.symbolic-link-attack-3 ./src/selinux.c
|
|
||||||
--- ./src/selinux.c.symbolic-link-attack-3 2019-10-28 13:27:39.000000000 +0100
|
|
||||||
+++ ./src/selinux.c 2021-02-02 17:11:32.382020407 +0100
|
|
||||||
@@ -363,7 +363,7 @@ bad:
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
selinux_setup(const char *role, const char *type, const char *ttyn,
|
|
||||||
- int ptyfd)
|
|
||||||
+ int ptyfd, bool label_tty)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
debug_decl(selinux_setup, SUDO_DEBUG_SELINUX)
|
|
||||||
@@ -392,7 +392,7 @@ selinux_setup(const char *role, const ch
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: new context %s", __func__,
|
|
||||||
se_state.new_context);
|
|
||||||
|
|
||||||
- if (relabel_tty(ttyn, ptyfd) == -1) {
|
|
||||||
+ if (label_tty && relabel_tty(ttyn, ptyfd) == -1) {
|
|
||||||
sudo_warn(U_("unable to set tty context to %s"), se_state.new_context);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
@@ -408,6 +408,28 @@ done:
|
|
||||||
debug_return_int(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
+int
|
|
||||||
+selinux_setcon(void)
|
|
||||||
+{
|
|
||||||
+ debug_decl(selinux_setcon, SUDO_DEBUG_SELINUX);
|
|
||||||
+
|
|
||||||
+ if (setexeccon(se_state.new_context)) {
|
|
||||||
+ sudo_warn(U_("unable to set exec context to %s"), se_state.new_context);
|
|
||||||
+ if (se_state.enforcing)
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+#ifdef HAVE_SETKEYCREATECON
|
|
||||||
+ if (setkeycreatecon(se_state.new_context)) {
|
|
||||||
+ sudo_warn(U_("unable to set key creation context to %s"), se_state.new_context);
|
|
||||||
+ if (se_state.enforcing)
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+#endif /* HAVE_SETKEYCREATECON */
|
|
||||||
+
|
|
||||||
+ debug_return_int(0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
selinux_execve(int fd, const char *path, char *const argv[], char *envp[],
|
|
||||||
bool noexec)
|
|
||||||
@@ -424,19 +446,9 @@ selinux_execve(int fd, const char *path,
|
|
||||||
debug_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (setexeccon(se_state.new_context)) {
|
|
||||||
- sudo_warn(U_("unable to set exec context to %s"), se_state.new_context);
|
|
||||||
- if (se_state.enforcing)
|
|
||||||
- debug_return;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
-#ifdef HAVE_SETKEYCREATECON
|
|
||||||
- if (setkeycreatecon(se_state.new_context)) {
|
|
||||||
- sudo_warn(U_("unable to set key creation context to %s"), se_state.new_context);
|
|
||||||
- if (se_state.enforcing)
|
|
||||||
- debug_return;
|
|
||||||
- }
|
|
||||||
-#endif /* HAVE_SETKEYCREATECON */
|
|
||||||
+ /* Set SELinux exec and keycreate contexts. */
|
|
||||||
+ if (selinux_setcon() == -1)
|
|
||||||
+ debug_return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build new argv with sesh as argv[0].
|
|
||||||
diff -up ./src/sudo.c.symbolic-link-attack-3 ./src/sudo.c
|
|
||||||
--- ./src/sudo.c.symbolic-link-attack-3 2021-02-02 17:12:32.773182386 +0100
|
|
||||||
+++ ./src/sudo.c 2021-02-02 17:12:48.510964009 +0100
|
|
||||||
@@ -971,10 +971,6 @@ run_command(struct command_details *deta
|
|
||||||
case CMD_WSTATUS:
|
|
||||||
/* Command ran, exited or was killed. */
|
|
||||||
status = cstat.val;
|
|
||||||
-#ifdef HAVE_SELINUX
|
|
||||||
- if (ISSET(details->flags, CD_SUDOEDIT_COPY))
|
|
||||||
- break;
|
|
||||||
-#endif
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG,
|
|
||||||
"calling policy close with wait status %d", status);
|
|
||||||
policy_close(&policy_plugin, status, 0);
|
|
||||||
diff -up ./src/sudo_edit.c.symbolic-link-attack-3 ./src/sudo_edit.c
|
|
||||||
--- ./src/sudo_edit.c.symbolic-link-attack-3 2021-02-02 17:11:32.380020435 +0100
|
|
||||||
+++ ./src/sudo_edit.c 2021-02-02 17:11:32.382020407 +0100
|
|
||||||
@@ -757,28 +757,54 @@ bad:
|
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
|
||||||
static int
|
|
||||||
+selinux_run_helper(char *argv[], char *envp[])
|
|
||||||
+{
|
|
||||||
+ int status, ret = SESH_ERR_FAILURE;
|
|
||||||
+ const char *sesh;
|
|
||||||
+ pid_t child, pid;
|
|
||||||
+ debug_decl(selinux_run_helper, SUDO_DEBUG_EDIT);
|
|
||||||
+
|
|
||||||
+ sesh = sudo_conf_sesh_path();
|
|
||||||
+ if (sesh == NULL) {
|
|
||||||
+ sudo_warnx("internal error: sesh path not set");
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ child = sudo_debug_fork();
|
|
||||||
+ switch (child) {
|
|
||||||
+ case -1:
|
|
||||||
+ sudo_warn(U_("unable to fork"));
|
|
||||||
+ break;
|
|
||||||
+ case 0:
|
|
||||||
+ /* child runs sesh in new context */
|
|
||||||
+ if (selinux_setcon() == 0)
|
|
||||||
+ execve(sesh, argv, envp);
|
|
||||||
+ _exit(SESH_ERR_FAILURE);
|
|
||||||
+ default:
|
|
||||||
+ /* parent waits */
|
|
||||||
+ do {
|
|
||||||
+ pid = waitpid(child, &status, 0);
|
|
||||||
+ } while (pid == -1 && errno == EINTR);
|
|
||||||
+
|
|
||||||
+ ret = WIFSIGNALED(status) ? SESH_ERR_KILLED : WEXITSTATUS(status);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ debug_return_int(ret);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
selinux_edit_create_tfiles(struct command_details *command_details,
|
|
||||||
struct tempfile *tf, char *files[], int nfiles)
|
|
||||||
{
|
|
||||||
char **sesh_args, **sesh_ap;
|
|
||||||
int i, rc, sesh_nargs;
|
|
||||||
struct stat sb;
|
|
||||||
- struct command_details saved_command_details;
|
|
||||||
debug_decl(selinux_edit_create_tfiles, SUDO_DEBUG_EDIT)
|
|
||||||
-
|
|
||||||
- /* Prepare selinux stuff (setexeccon) */
|
|
||||||
- if (selinux_setup(command_details->selinux_role,
|
|
||||||
- command_details->selinux_type, NULL, -1) != 0)
|
|
||||||
- debug_return_int(-1);
|
|
||||||
|
|
||||||
if (nfiles < 1)
|
|
||||||
debug_return_int(0);
|
|
||||||
|
|
||||||
/* Construct common args for sesh */
|
|
||||||
- memcpy(&saved_command_details, command_details, sizeof(struct command_details));
|
|
||||||
- command_details->command = _PATH_SUDO_SESH;
|
|
||||||
- command_details->flags |= CD_SUDOEDIT_COPY;
|
|
||||||
-
|
|
||||||
sesh_nargs = 4 + (nfiles * 2) + 1;
|
|
||||||
sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
|
|
||||||
if (sesh_args == NULL) {
|
|
||||||
@@ -791,6 +817,7 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
*sesh_ap++ = "-h";
|
|
||||||
*sesh_ap++ = "0";
|
|
||||||
|
|
||||||
+ /* XXX - temp files should be created with user's context */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
char *tfile, *ofile = files[i];
|
|
||||||
int tfd;
|
|
||||||
@@ -820,8 +847,7 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
*sesh_ap = NULL;
|
|
||||||
|
|
||||||
/* Run sesh -e [-h] 0 <o1> <t1> ... <on> <tn> */
|
|
||||||
- command_details->argv = sesh_args;
|
|
||||||
- rc = run_command(command_details);
|
|
||||||
+ rc = selinux_run_helper(sesh_args, command_details->envp);
|
|
||||||
switch (rc) {
|
|
||||||
case SESH_SUCCESS:
|
|
||||||
break;
|
|
||||||
@@ -829,15 +855,12 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
sudo_fatalx(U_("sesh: internal error: odd number of paths"));
|
|
||||||
case SESH_ERR_NO_FILES:
|
|
||||||
sudo_fatalx(U_("sesh: unable to create temporary files"));
|
|
||||||
+ case SESH_ERR_KILLED:
|
|
||||||
+ sudo_fatalx(U_("sesh: killed by a signal"));
|
|
||||||
default:
|
|
||||||
sudo_fatalx(U_("sesh: unknown error %d"), rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Restore saved command_details. */
|
|
||||||
- command_details->command = saved_command_details.command;
|
|
||||||
- command_details->flags = saved_command_details.flags;
|
|
||||||
- command_details->argv = saved_command_details.argv;
|
|
||||||
-
|
|
||||||
/* Chown to user's UID so they can edit the temporary files. */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
if (chown(tf[i].tfile, user_details.uid, user_details.gid) != 0) {
|
|
||||||
@@ -858,24 +881,14 @@ selinux_edit_copy_tfiles(struct command_
|
|
||||||
{
|
|
||||||
char **sesh_args, **sesh_ap;
|
|
||||||
int i, rc, sesh_nargs, ret = 1;
|
|
||||||
- struct command_details saved_command_details;
|
|
||||||
struct timespec ts;
|
|
||||||
struct stat sb;
|
|
||||||
debug_decl(selinux_edit_copy_tfiles, SUDO_DEBUG_EDIT)
|
|
||||||
-
|
|
||||||
- /* Prepare selinux stuff (setexeccon) */
|
|
||||||
- if (selinux_setup(command_details->selinux_role,
|
|
||||||
- command_details->selinux_type, NULL, -1) != 0)
|
|
||||||
- debug_return_int(1);
|
|
||||||
|
|
||||||
if (nfiles < 1)
|
|
||||||
debug_return_int(0);
|
|
||||||
|
|
||||||
/* Construct common args for sesh */
|
|
||||||
- memcpy(&saved_command_details, command_details, sizeof(struct command_details));
|
|
||||||
- command_details->command = _PATH_SUDO_SESH;
|
|
||||||
- command_details->flags |= CD_SUDOEDIT_COPY;
|
|
||||||
-
|
|
||||||
sesh_nargs = 3 + (nfiles * 2) + 1;
|
|
||||||
sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
|
|
||||||
if (sesh_args == NULL) {
|
|
||||||
@@ -913,32 +926,29 @@ selinux_edit_copy_tfiles(struct command_
|
|
||||||
|
|
||||||
if (sesh_ap - sesh_args > 3) {
|
|
||||||
/* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
|
|
||||||
- command_details->argv = sesh_args;
|
|
||||||
- rc = run_command(command_details);
|
|
||||||
+ rc = selinux_run_helper(sesh_args, command_details->envp);
|
|
||||||
switch (rc) {
|
|
||||||
case SESH_SUCCESS:
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
case SESH_ERR_NO_FILES:
|
|
||||||
sudo_warnx(U_("unable to copy temporary files back to their original location"));
|
|
||||||
- sudo_warnx(U_("contents of edit session left in %s"), edit_tmpdir);
|
|
||||||
break;
|
|
||||||
case SESH_ERR_SOME_FILES:
|
|
||||||
sudo_warnx(U_("unable to copy some of the temporary files back to their original location"));
|
|
||||||
- sudo_warnx(U_("contents of edit session left in %s"), edit_tmpdir);
|
|
||||||
+ break;
|
|
||||||
+ case SESH_ERR_KILLED:
|
|
||||||
+ sudo_warnx(U_("sesh: killed by a signal"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sudo_warnx(U_("sesh: unknown error %d"), rc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
+ if (ret != 0)
|
|
||||||
+ sudo_warnx(U_("contents of edit session left in %s"), edit_tmpdir);
|
|
||||||
}
|
|
||||||
free(sesh_args);
|
|
||||||
|
|
||||||
- /* Restore saved command_details. */
|
|
||||||
- command_details->command = saved_command_details.command;
|
|
||||||
- command_details->flags = saved_command_details.flags;
|
|
||||||
- command_details->argv = saved_command_details.argv;
|
|
||||||
-
|
|
||||||
debug_return_int(ret);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_SELINUX */
|
|
||||||
@@ -990,6 +1000,15 @@ sudo_edit(struct command_details *comman
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef HAVE_SELINUX
|
|
||||||
+ /* Compute new SELinux security context. */
|
|
||||||
+ if (ISSET(command_details->flags, CD_RBAC_ENABLED)) {
|
|
||||||
+ if (selinux_setup(command_details->selinux_role,
|
|
||||||
+ command_details->selinux_type, NULL, -1, false) != 0)
|
|
||||||
+ goto cleanup;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/* Copy editor files to temporaries. */
|
|
||||||
tf = calloc(nfiles, sizeof(*tf));
|
|
||||||
if (tf == NULL) {
|
|
||||||
@@ -1025,6 +1044,7 @@ sudo_edit(struct command_details *comman
|
|
||||||
/*
|
|
||||||
* Run the editor with the invoking user's creds,
|
|
||||||
* keeping track of the time spent in the editor.
|
|
||||||
+ * XXX - should run editor with user's context
|
|
||||||
*/
|
|
||||||
if (sudo_gettime_real(×[0]) == -1) {
|
|
||||||
sudo_warn(U_("unable to read the clock"));
|
|
||||||
diff -up ./src/sudo_exec.h.symbolic-link-attack-3 ./src/sudo_exec.h
|
|
||||||
--- ./src/sudo_exec.h.symbolic-link-attack-3 2021-02-02 17:11:32.380020435 +0100
|
|
||||||
+++ ./src/sudo_exec.h 2021-02-02 17:11:32.382020407 +0100
|
|
||||||
@@ -73,6 +73,7 @@
|
|
||||||
*/
|
|
||||||
#define SESH_SUCCESS 0 /* successful operation */
|
|
||||||
#define SESH_ERR_FAILURE 1 /* unspecified error */
|
|
||||||
+#define SESH_ERR_KILLED 2 /* killed by a signal */
|
|
||||||
#define SESH_ERR_INVALID 30 /* invalid -e arg value */
|
|
||||||
#define SESH_ERR_BAD_PATHS 31 /* odd number of paths */
|
|
||||||
#define SESH_ERR_NO_FILES 32 /* copy error, no files copied */
|
|
||||||
diff -up ./src/sudo.h.symbolic-link-attack-3 ./src/sudo.h
|
|
||||||
--- ./src/sudo.h.symbolic-link-attack-3 2019-10-28 13:28:52.000000000 +0100
|
|
||||||
+++ ./src/sudo.h 2021-02-02 17:11:32.382020407 +0100
|
|
||||||
@@ -135,12 +135,11 @@ struct user_details {
|
|
||||||
#define CD_USE_PTY 0x001000
|
|
||||||
#define CD_SET_UTMP 0x002000
|
|
||||||
#define CD_EXEC_BG 0x004000
|
|
||||||
-#define CD_SUDOEDIT_COPY 0x008000
|
|
||||||
-#define CD_SUDOEDIT_FOLLOW 0x010000
|
|
||||||
-#define CD_SUDOEDIT_CHECKDIR 0x020000
|
|
||||||
-#define CD_SET_GROUPS 0x040000
|
|
||||||
-#define CD_LOGIN_SHELL 0x080000
|
|
||||||
-#define CD_OVERRIDE_UMASK 0x100000
|
|
||||||
+#define CD_SUDOEDIT_FOLLOW 0x008000
|
|
||||||
+#define CD_SUDOEDIT_CHECKDIR 0x010000
|
|
||||||
+#define CD_SET_GROUPS 0x020000
|
|
||||||
+#define CD_LOGIN_SHELL 0x040000
|
|
||||||
+#define CD_OVERRIDE_UMASK 0x080000
|
|
||||||
|
|
||||||
struct preserved_fd {
|
|
||||||
TAILQ_ENTRY(preserved_fd) entries;
|
|
||||||
@@ -240,7 +239,8 @@ int os_init_openbsd(int argc, char *argv
|
|
||||||
/* selinux.c */
|
|
||||||
int selinux_restore_tty(void);
|
|
||||||
int selinux_setup(const char *role, const char *type, const char *ttyn,
|
|
||||||
- int ttyfd);
|
|
||||||
+ int ttyfd, bool label_tty);
|
|
||||||
+int selinux_setcon(void);
|
|
||||||
void selinux_execve(int fd, const char *path, char *const argv[],
|
|
||||||
char *envp[], bool noexec);
|
|
||||||
|
|
@ -1,380 +0,0 @@
|
|||||||
diff -up ./src/copy_file.c.symbolic-link-attack-4 ./src/copy_file.c
|
|
||||||
--- ./src/copy_file.c.symbolic-link-attack-4 2021-02-02 16:35:18.453036846 +0100
|
|
||||||
+++ ./src/copy_file.c 2021-02-02 16:38:09.430731749 +0100
|
|
||||||
@@ -23,6 +23,7 @@
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
+#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
@@ -126,3 +127,35 @@ write_error:
|
|
||||||
debug_return_int(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+#ifdef HAVE_SELINUX
|
|
||||||
+bool
|
|
||||||
+sudo_check_temp_file(int tfd, const char *tfile, uid_t uid, struct stat *sb)
|
|
||||||
+{
|
|
||||||
+ struct stat sbuf;
|
|
||||||
+ debug_decl(sudo_check_temp_file, SUDO_DEBUG_UTIL);
|
|
||||||
+
|
|
||||||
+ if (sb == NULL)
|
|
||||||
+ sb = &sbuf;
|
|
||||||
+
|
|
||||||
+ if (fstat(tfd, sb) == -1) {
|
|
||||||
+ sudo_warn(U_("unable to stat %s"), tfile);
|
|
||||||
+ debug_return_bool(false);
|
|
||||||
+ }
|
|
||||||
+ if (!S_ISREG(sb->st_mode)) {
|
|
||||||
+ sudo_warnx(U_("%s: not a regular file"), tfile);
|
|
||||||
+ debug_return_bool(false);
|
|
||||||
+ }
|
|
||||||
+ if ((sb->st_mode & ALLPERMS) != (S_IRUSR|S_IWUSR)) {
|
|
||||||
+ sudo_warnx(U_("%s: bad file mode: 0%o"), tfile,
|
|
||||||
+ (unsigned int)(sb->st_mode & ALLPERMS));
|
|
||||||
+ debug_return_bool(false);
|
|
||||||
+ }
|
|
||||||
+ if (sb->st_uid != uid) {
|
|
||||||
+ sudo_warnx(U_("%s is owned by uid %u, should be %u"),
|
|
||||||
+ tfile, (unsigned int)sb->st_uid, (unsigned int)uid);
|
|
||||||
+ debug_return_bool(false);
|
|
||||||
+ }
|
|
||||||
+ debug_return_bool(true);
|
|
||||||
+}
|
|
||||||
+#endif /* SELINUX */
|
|
||||||
diff -up ./src/sesh.c.symbolic-link-attack-4 ./src/sesh.c
|
|
||||||
--- ./src/sesh.c.symbolic-link-attack-4 2021-02-02 16:35:18.450036887 +0100
|
|
||||||
+++ ./src/sesh.c 2021-02-02 16:38:52.907146897 +0100
|
|
||||||
@@ -134,7 +134,7 @@ main(int argc, char *argv[], char *envp[
|
|
||||||
static int
|
|
||||||
sesh_sudoedit(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
- int i, oflags_dst, post, ret = SESH_ERR_FAILURE;
|
|
||||||
+ int i, oflags_src, oflags_dst, post, ret = SESH_ERR_FAILURE;
|
|
||||||
int fd_src = -1, fd_dst = -1, follow = 0;
|
|
||||||
ssize_t nread, nwritten;
|
|
||||||
struct stat sb;
|
|
||||||
@@ -178,10 +178,12 @@ sesh_sudoedit(int argc, char *argv[])
|
|
||||||
debug_return_int(SESH_ERR_BAD_PATHS);
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Use O_EXCL if we are not in the post editing stage
|
|
||||||
- * so that it's ensured that the temporary files are
|
|
||||||
- * created by us and that we are not opening any symlinks.
|
|
||||||
+ * In the pre-editing stage, use O_EXCL to ensure that the temporary
|
|
||||||
+ * files are created by us and that we are not opening any symlinks.
|
|
||||||
+ * In the post-editing stage, use O_NOFOLLOW so we don't follow symlinks
|
|
||||||
+ * when opening the temporary files.
|
|
||||||
*/
|
|
||||||
+ oflags_src = O_RDONLY|(post ? O_NONBLOCK|O_NOFOLLOW : follow);
|
|
||||||
oflags_dst = O_WRONLY|O_CREAT|(post ? follow : O_EXCL);
|
|
||||||
for (i = 0; i < argc - 1; i += 2) {
|
|
||||||
const char *path_src = argv[i];
|
|
||||||
@@ -191,7 +193,7 @@ sesh_sudoedit(int argc, char *argv[])
|
|
||||||
* doesn't exist, that's OK, we'll create an empty
|
|
||||||
* destination file.
|
|
||||||
*/
|
|
||||||
- if ((fd_src = open(path_src, O_RDONLY|follow, S_IRUSR|S_IWUSR)) < 0) {
|
|
||||||
+ if ((fd_src = open(path_src, oflags_src, S_IRUSR|S_IWUSR)) < 0) {
|
|
||||||
if (errno != ENOENT) {
|
|
||||||
sudo_warn("%s", path_src);
|
|
||||||
if (post) {
|
|
||||||
@@ -201,6 +203,14 @@ sesh_sudoedit(int argc, char *argv[])
|
|
||||||
goto cleanup_0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ if (post) {
|
|
||||||
+ /* Make sure the temporary file is safe and has the proper owner. */
|
|
||||||
+ if (!sudo_check_temp_file(fd_src, path_src, geteuid(), &sb)) {
|
|
||||||
+ ret = SESH_ERR_SOME_FILES;
|
|
||||||
+ goto nocleanup;
|
|
||||||
+ }
|
|
||||||
+ fcntl(fd_src, F_SETFL, fcntl(fd_src, F_GETFL, 0) & ~O_NONBLOCK);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if ((fd_dst = open(path_dst, oflags_dst, post ?
|
|
||||||
(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IRUSR|S_IWUSR))) < 0) {
|
|
||||||
@@ -218,10 +228,7 @@ sesh_sudoedit(int argc, char *argv[])
|
|
||||||
off_t len_dst = -1;
|
|
||||||
|
|
||||||
if (post) {
|
|
||||||
- if (fstat(fd_src, &sb) != 0) {
|
|
||||||
- ret = SESH_ERR_SOME_FILES;
|
|
||||||
- goto nocleanup;
|
|
||||||
- }
|
|
||||||
+ /* sudo_check_temp_file() filled in sb for us. */
|
|
||||||
len_src = sb.st_size;
|
|
||||||
if (fstat(fd_dst, &sb) != 0) {
|
|
||||||
ret = SESH_ERR_SOME_FILES;
|
|
||||||
diff -up ./src/sudo_edit.c.symbolic-link-attack-4 ./src/sudo_edit.c
|
|
||||||
--- ./src/sudo_edit.c.symbolic-link-attack-4 2021-02-02 16:35:18.452036860 +0100
|
|
||||||
+++ ./src/sudo_edit.c 2021-02-02 16:54:25.943429580 +0100
|
|
||||||
@@ -253,8 +253,10 @@ sudo_edit_mktemp(const char *ofile, char
|
|
||||||
} else {
|
|
||||||
len = asprintf(tfile, "%s/%s.XXXXXXXX", edit_tmpdir, cp);
|
|
||||||
}
|
|
||||||
- if (len == -1)
|
|
||||||
- sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
+ if (len == -1) {
|
|
||||||
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
+ debug_return_int(-1);
|
|
||||||
+ }
|
|
||||||
tfd = mkstemps(*tfile, suff ? strlen(suff) : 0);
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
|
||||||
"%s -> %s, fd %d", ofile, *tfile, tfd);
|
|
||||||
@@ -757,7 +759,8 @@ bad:
|
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
|
||||||
static int
|
|
||||||
-selinux_run_helper(char *argv[], char *envp[])
|
|
||||||
+selinux_run_helper(uid_t uid, gid_t gid, int ngroups, GETGROUPS_T *groups,
|
|
||||||
+ char *const argv[], char *const envp[])
|
|
||||||
{
|
|
||||||
int status, ret = SESH_ERR_FAILURE;
|
|
||||||
const char *sesh;
|
|
||||||
@@ -777,8 +780,10 @@ selinux_run_helper(char *argv[], char *e
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
/* child runs sesh in new context */
|
|
||||||
- if (selinux_setcon() == 0)
|
|
||||||
+ if (selinux_setcon() == 0) {
|
|
||||||
+ switch_user(uid, gid, ngroups, groups);
|
|
||||||
execve(sesh, argv, envp);
|
|
||||||
+ }
|
|
||||||
_exit(SESH_ERR_FAILURE);
|
|
||||||
default:
|
|
||||||
/* parent waits */
|
|
||||||
@@ -797,7 +802,7 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
struct tempfile *tf, char *files[], int nfiles)
|
|
||||||
{
|
|
||||||
char **sesh_args, **sesh_ap;
|
|
||||||
- int i, rc, sesh_nargs;
|
|
||||||
+ int i, rc, error, sesh_nargs, ret = -1;
|
|
||||||
struct stat sb;
|
|
||||||
debug_decl(selinux_edit_create_tfiles, SUDO_DEBUG_EDIT)
|
|
||||||
|
|
||||||
@@ -809,7 +814,7 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
|
|
||||||
if (sesh_args == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
- debug_return_int(-1);
|
|
||||||
+ goto done;
|
|
||||||
}
|
|
||||||
*sesh_ap++ = "sesh";
|
|
||||||
*sesh_ap++ = "-e";
|
|
||||||
@@ -817,7 +822,6 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
*sesh_ap++ = "-h";
|
|
||||||
*sesh_ap++ = "0";
|
|
||||||
|
|
||||||
- /* XXX - temp files should be created with user's context */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
char *tfile, *ofile = files[i];
|
|
||||||
int tfd;
|
|
||||||
@@ -835,8 +839,7 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
if (tfd == -1) {
|
|
||||||
sudo_warn("mkstemps");
|
|
||||||
free(tfile);
|
|
||||||
- free(sesh_args);
|
|
||||||
- debug_return_int(-1);
|
|
||||||
+ goto done;
|
|
||||||
}
|
|
||||||
/* Helper will re-create temp file with proper security context. */
|
|
||||||
close(tfd);
|
|
||||||
@@ -847,8 +850,10 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
*sesh_ap = NULL;
|
|
||||||
|
|
||||||
/* Run sesh -e [-h] 0 <o1> <t1> ... <on> <tn> */
|
|
||||||
- rc = selinux_run_helper(sesh_args, command_details->envp);
|
|
||||||
- switch (rc) {
|
|
||||||
+ error = selinux_run_helper(command_details->uid, command_details->gid,
|
|
||||||
+ command_details->ngroups, command_details->groups, sesh_args,
|
|
||||||
+ command_details->envp);
|
|
||||||
+ switch (error) {
|
|
||||||
case SESH_SUCCESS:
|
|
||||||
break;
|
|
||||||
case SESH_ERR_BAD_PATHS:
|
|
||||||
@@ -858,21 +863,34 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
case SESH_ERR_KILLED:
|
|
||||||
sudo_fatalx(U_("sesh: killed by a signal"));
|
|
||||||
default:
|
|
||||||
- sudo_fatalx(U_("sesh: unknown error %d"), rc);
|
|
||||||
+ sudo_fatalx(U_("sesh: unknown error %d"), error);
|
|
||||||
+ goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Chown to user's UID so they can edit the temporary files. */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
- if (chown(tf[i].tfile, user_details.uid, user_details.gid) != 0) {
|
|
||||||
- sudo_warn("unable to chown(%s) to %d:%d for editing",
|
|
||||||
- tf[i].tfile, user_details.uid, user_details.gid);
|
|
||||||
- }
|
|
||||||
+ int tfd = open(tf[i].tfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW);
|
|
||||||
+ if (tfd == -1) {
|
|
||||||
+ sudo_warn(U_("unable to open %s"), tf[i].tfile);
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ if (!sudo_check_temp_file(tfd, tf[i].tfile, command_details->uid, NULL)) {
|
|
||||||
+ close(tfd);
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ if (fchown(tfd, user_details.uid, user_details.gid) != 0) {
|
|
||||||
+ sudo_warn("unable to chown(%s) to %d:%d for editing",
|
|
||||||
+ tf[i].tfile, user_details.uid, user_details.gid);
|
|
||||||
+ close(tfd);
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ close(tfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
+done:
|
|
||||||
/* Contents of tf will be freed by caller. */
|
|
||||||
free(sesh_args);
|
|
||||||
|
|
||||||
- return (nfiles);
|
|
||||||
+ debug_return_int(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
@@ -880,7 +898,8 @@ selinux_edit_copy_tfiles(struct command_
|
|
||||||
struct tempfile *tf, int nfiles, struct timespec *times)
|
|
||||||
{
|
|
||||||
char **sesh_args, **sesh_ap;
|
|
||||||
- int i, rc, sesh_nargs, ret = 1;
|
|
||||||
+ int i, rc, error, sesh_nargs, ret = 1;
|
|
||||||
+ int tfd = -1;
|
|
||||||
struct timespec ts;
|
|
||||||
struct stat sb;
|
|
||||||
debug_decl(selinux_edit_copy_tfiles, SUDO_DEBUG_EDIT)
|
|
||||||
@@ -901,33 +920,43 @@ selinux_edit_copy_tfiles(struct command_
|
|
||||||
|
|
||||||
/* Construct args for sesh -e 1 */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
- if (stat(tf[i].tfile, &sb) == 0) {
|
|
||||||
- mtim_get(&sb, ts);
|
|
||||||
- if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
|
|
||||||
- /*
|
|
||||||
- * If mtime and size match but the user spent no measurable
|
|
||||||
- * time in the editor we can't tell if the file was changed.
|
|
||||||
- */
|
|
||||||
- if (sudo_timespeccmp(×[0], ×[1], !=)) {
|
|
||||||
- sudo_warnx(U_("%s unchanged"), tf[i].ofile);
|
|
||||||
- unlink(tf[i].tfile);
|
|
||||||
- continue;
|
|
||||||
- }
|
|
||||||
+ if (tfd != -1)
|
|
||||||
+ close(tfd);
|
|
||||||
+ if ((tfd = open(tf[i].tfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW)) == -1) {
|
|
||||||
+ sudo_warn(U_("unable to open %s"), tf[i].tfile);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if (!sudo_check_temp_file(tfd, tf[i].tfile, user_details.uid, &sb))
|
|
||||||
+ continue;
|
|
||||||
+ mtim_get(&sb, ts);
|
|
||||||
+ if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
|
|
||||||
+ /*
|
|
||||||
+ * If mtime and size match but the user spent no measurable
|
|
||||||
+ * time in the editor we can't tell if the file was changed.
|
|
||||||
+ */
|
|
||||||
+ if (sudo_timespeccmp(×[0], ×[1], !=)) {
|
|
||||||
+ sudo_warnx(U_("%s unchanged"), tf[i].ofile);
|
|
||||||
+ unlink(tf[i].tfile);
|
|
||||||
+ continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*sesh_ap++ = tf[i].tfile;
|
|
||||||
*sesh_ap++ = tf[i].ofile;
|
|
||||||
- if (chown(tf[i].tfile, command_details->uid, command_details->gid) != 0) {
|
|
||||||
+ if (fchown(tfd, command_details->uid, command_details->gid) != 0) {
|
|
||||||
sudo_warn("unable to chown(%s) back to %d:%d", tf[i].tfile,
|
|
||||||
command_details->uid, command_details->gid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*sesh_ap = NULL;
|
|
||||||
+ if (tfd != -1)
|
|
||||||
+ close(tfd);
|
|
||||||
|
|
||||||
if (sesh_ap - sesh_args > 3) {
|
|
||||||
/* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
|
|
||||||
- rc = selinux_run_helper(sesh_args, command_details->envp);
|
|
||||||
- switch (rc) {
|
|
||||||
+ error = selinux_run_helper(command_details->uid, command_details->gid,
|
|
||||||
+ command_details->ngroups, command_details->groups, sesh_args,
|
|
||||||
+ command_details->envp);
|
|
||||||
+ switch (error) {
|
|
||||||
case SESH_SUCCESS:
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
@@ -941,7 +970,7 @@ selinux_edit_copy_tfiles(struct command_
|
|
||||||
sudo_warnx(U_("sesh: killed by a signal"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
- sudo_warnx(U_("sesh: unknown error %d"), rc);
|
|
||||||
+ sudo_warnx(U_("sesh: unknown error %d"), error);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ret != 0)
|
|
||||||
@@ -963,7 +992,7 @@ sudo_edit(struct command_details *comman
|
|
||||||
{
|
|
||||||
struct command_details saved_command_details;
|
|
||||||
char **nargv = NULL, **ap, **files = NULL;
|
|
||||||
- int errors, i, ac, nargc, rc;
|
|
||||||
+ int errors, i, ac, nargc, ret;
|
|
||||||
int editor_argc = 0, nfiles = 0;
|
|
||||||
struct timespec times[2];
|
|
||||||
struct tempfile *tf = NULL;
|
|
||||||
@@ -1058,7 +1087,7 @@ sudo_edit(struct command_details *comman
|
|
||||||
command_details->ngroups = user_details.ngroups;
|
|
||||||
command_details->groups = user_details.groups;
|
|
||||||
command_details->argv = nargv;
|
|
||||||
- rc = run_command(command_details);
|
|
||||||
+ ret = run_command(command_details);
|
|
||||||
if (sudo_gettime_real(×[1]) == -1) {
|
|
||||||
sudo_warn(U_("unable to read the clock"));
|
|
||||||
goto cleanup;
|
|
||||||
@@ -1080,14 +1109,16 @@ sudo_edit(struct command_details *comman
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
errors = sudo_edit_copy_tfiles(command_details, tf, nfiles, times);
|
|
||||||
- if (errors)
|
|
||||||
- goto cleanup;
|
|
||||||
+ if (errors) {
|
|
||||||
+ /* Preserve the edited temporary files. */
|
|
||||||
+ ret = W_EXITCODE(1, 0);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
for (i = 0; i < nfiles; i++)
|
|
||||||
free(tf[i].tfile);
|
|
||||||
free(tf);
|
|
||||||
free(nargv);
|
|
||||||
- debug_return_int(rc);
|
|
||||||
+ debug_return_int(ret);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
/* Clean up temp files and return. */
|
|
||||||
diff -up ./src/sudo_exec.h.symbolic-link-attack-4 ./src/sudo_exec.h
|
|
||||||
--- ./src/sudo_exec.h.symbolic-link-attack-4 2021-02-02 16:35:18.452036860 +0100
|
|
||||||
+++ ./src/sudo_exec.h 2021-02-02 16:35:18.454036833 +0100
|
|
||||||
@@ -1,7 +1,7 @@
|
|
||||||
/*
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
- * Copyright (c) 2010-2016 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
+ * Copyright (c) 2010-2017, 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
@@ -84,9 +84,11 @@
|
|
||||||
*/
|
|
||||||
struct command_details;
|
|
||||||
struct command_status;
|
|
||||||
+struct stat;
|
|
||||||
|
|
||||||
/* copy_file.c */
|
|
||||||
int sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst, int dst_fd, off_t dst_len);
|
|
||||||
+bool sudo_check_temp_file(int tfd, const char *tname, uid_t uid, struct stat *sb);
|
|
||||||
|
|
||||||
/* exec.c */
|
|
||||||
void exec_cmnd(struct command_details *details, int errfd);
|
|
@ -1,47 +0,0 @@
|
|||||||
diff -up ./src/copy_file.c.symbolic-link-attack-5 ./src/copy_file.c
|
|
||||||
--- ./src/copy_file.c.symbolic-link-attack-5 2021-02-02 17:18:05.355567274 +0100
|
|
||||||
+++ ./src/copy_file.c 2021-02-02 17:19:09.904671563 +0100
|
|
||||||
@@ -128,7 +128,6 @@ write_error:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-#ifdef HAVE_SELINUX
|
|
||||||
bool
|
|
||||||
sudo_check_temp_file(int tfd, const char *tfile, uid_t uid, struct stat *sb)
|
|
||||||
{
|
|
||||||
@@ -158,4 +157,3 @@ sudo_check_temp_file(int tfd, const char
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
-#endif /* SELINUX */
|
|
||||||
diff -up ./src/sudo_edit.c.symbolic-link-attack-5 ./src/sudo_edit.c
|
|
||||||
--- ./src/sudo_edit.c.symbolic-link-attack-5 2021-02-02 17:18:05.355567274 +0100
|
|
||||||
+++ ./src/sudo_edit.c 2021-02-02 17:18:05.356567260 +0100
|
|
||||||
@@ -692,24 +692,17 @@ sudo_edit_copy_tfiles(struct command_det
|
|
||||||
|
|
||||||
/* Copy contents of temp files to real ones. */
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
|
||||||
- int rc = -1;
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
|
||||||
"seteuid(%u)", (unsigned int)user_details.uid);
|
|
||||||
if (seteuid(user_details.uid) != 0)
|
|
||||||
sudo_fatal("seteuid(%u)", (unsigned int)user_details.uid);
|
|
||||||
tfd = sudo_edit_open(tf[i].tfile, O_RDONLY,
|
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, NULL);
|
|
||||||
- if (tfd != -1)
|
|
||||||
- rc = fstat(tfd, &sb);
|
|
||||||
- sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
|
||||||
- "seteuid(%u)", ROOT_UID);
|
|
||||||
if (seteuid(ROOT_UID) != 0)
|
|
||||||
sudo_fatal("seteuid(ROOT_UID)");
|
|
||||||
- if (rc == -1 || !S_ISREG(sb.st_mode)) {
|
|
||||||
- if (rc == -1)
|
|
||||||
- sudo_warn("%s", tf[i].tfile);
|
|
||||||
- else
|
|
||||||
- sudo_warnx(U_("%s: not a regular file"), tf[i].tfile);
|
|
||||||
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
|
||||||
+ "seteuid(%u)", ROOT_UID);
|
|
||||||
+ if (tfd == -1 || !sudo_check_temp_file(tfd, tf[i].tfile, user_details.uid, &sb)) {
|
|
||||||
sudo_warnx(U_("%s left unmodified"), tf[i].ofile);
|
|
||||||
if (tfd != -1)
|
|
||||||
close(tfd);
|
|
74
SOURCES/sudo-1.9.5-selinux-t.patch
Normal file
74
SOURCES/sudo-1.9.5-selinux-t.patch
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
From 73006fb25f0ebc35bc46b8f20036d40fcbb6de53 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Radovan Sroka <rsroka@redhat.com>
|
||||||
|
Date: Thu, 1 Apr 2021 21:42:03 +0200
|
||||||
|
Subject: [PATCH] Removed depricated security_context_t
|
||||||
|
|
||||||
|
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
|
||||||
|
---
|
||||||
|
src/selinux.c | 24 ++++++++++++------------
|
||||||
|
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/selinux.c b/src/selinux.c
|
||||||
|
index a2f73f8d0..c2f50aafb 100644
|
||||||
|
--- a/src/selinux.c
|
||||||
|
+++ b/src/selinux.c
|
||||||
|
@@ -58,10 +58,10 @@
|
||||||
|
#include "sudo_exec.h"
|
||||||
|
|
||||||
|
static struct selinux_state {
|
||||||
|
- security_context_t old_context;
|
||||||
|
- security_context_t new_context;
|
||||||
|
- security_context_t tty_con_raw;
|
||||||
|
- security_context_t new_tty_con_raw;
|
||||||
|
+ char * old_context;
|
||||||
|
+ char * new_context;
|
||||||
|
+ char * tty_con_raw;
|
||||||
|
+ char * new_tty_con_raw;
|
||||||
|
const char *ttyn;
|
||||||
|
int ttyfd;
|
||||||
|
int enforcing;
|
||||||
|
@@ -69,8 +69,8 @@ static struct selinux_state {
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_AUDIT
|
||||||
|
static int
|
||||||
|
-audit_role_change(const security_context_t old_context,
|
||||||
|
- const security_context_t new_context, const char *ttyn, int result)
|
||||||
|
+audit_role_change(const char * old_context,
|
||||||
|
+ const char * new_context, const char *ttyn, int result)
|
||||||
|
{
|
||||||
|
int au_fd, rc = -1;
|
||||||
|
char *message;
|
||||||
|
@@ -111,7 +111,7 @@ int
|
||||||
|
selinux_restore_tty(void)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
- security_context_t chk_tty_con_raw = NULL;
|
||||||
|
+ char * chk_tty_con_raw = NULL;
|
||||||
|
debug_decl(selinux_restore_tty, SUDO_DEBUG_SELINUX);
|
||||||
|
|
||||||
|
if (se_state.ttyfd == -1 || se_state.new_tty_con_raw == NULL) {
|
||||||
|
@@ -166,8 +166,8 @@ selinux_restore_tty(void)
|
||||||
|
static int
|
||||||
|
relabel_tty(const char *ttyn, int ptyfd)
|
||||||
|
{
|
||||||
|
- security_context_t tty_con = NULL;
|
||||||
|
- security_context_t new_tty_con = NULL;
|
||||||
|
+ char * tty_con = NULL;
|
||||||
|
+ char * new_tty_con = NULL;
|
||||||
|
struct stat sb;
|
||||||
|
int fd;
|
||||||
|
debug_decl(relabel_tty, SUDO_DEBUG_SELINUX);
|
||||||
|
@@ -308,10 +308,10 @@ relabel_tty(const char *ttyn, int ptyfd)
|
||||||
|
* Returns a new security context based on the old context and the
|
||||||
|
* specified role and type.
|
||||||
|
*/
|
||||||
|
-security_context_t
|
||||||
|
-get_exec_context(security_context_t old_context, const char *role, const char *type)
|
||||||
|
+char *
|
||||||
|
+get_exec_context(char * old_context, const char *role, const char *type)
|
||||||
|
{
|
||||||
|
- security_context_t new_context = NULL;
|
||||||
|
+ char * new_context = NULL;
|
||||||
|
context_t context = NULL;
|
||||||
|
char *typebuf = NULL;
|
||||||
|
debug_decl(get_exec_context, SUDO_DEBUG_SELINUX);
|
51
SOURCES/sudo-1.9.5-sesh-bad-condition.patch
Normal file
51
SOURCES/sudo-1.9.5-sesh-bad-condition.patch
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
From 613a8053dbc3ab43cf0cdaf09f207ffdb0b40e08 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Radovan Sroka <rsroka@redhat.com>
|
||||||
|
Date: Wed, 7 Apr 2021 14:43:40 +0200
|
||||||
|
Subject: [PATCH] Fixed bad condition for sesh args
|
||||||
|
|
||||||
|
In selinux_edit_copy_tfiles() when there is only one file and the open()
|
||||||
|
fails then number of arguments is lower than expected.
|
||||||
|
Sudo should return error with or without "Defaults !sudoedit_checkdir" set.
|
||||||
|
|
||||||
|
This was found with regression testing of CVE-2021-23240.
|
||||||
|
|
||||||
|
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
|
||||||
|
---
|
||||||
|
src/sudo_edit.c | 10 ++++++++--
|
||||||
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sudo_edit.c b/src/sudo_edit.c
|
||||||
|
index 41fc61c3a..15c75d8c4 100644
|
||||||
|
--- a/src/sudo_edit.c
|
||||||
|
+++ b/src/sudo_edit.c
|
||||||
|
@@ -529,6 +529,8 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
|
||||||
|
if (nfiles < 1)
|
||||||
|
debug_return_int(0);
|
||||||
|
|
||||||
|
+ const int check_dir = ISSET(command_details->flags, CD_SUDOEDIT_CHECKDIR);
|
||||||
|
+
|
||||||
|
/* Construct common args for sesh */
|
||||||
|
sesh_nargs = 5 + (nfiles * 2) + 1;
|
||||||
|
sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
|
||||||
|
@@ -538,7 +540,7 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
|
||||||
|
}
|
||||||
|
*sesh_ap++ = "sesh";
|
||||||
|
*sesh_ap++ = "-e";
|
||||||
|
- if (ISSET(command_details->flags, CD_SUDOEDIT_CHECKDIR)) {
|
||||||
|
+ if (check_dir) {
|
||||||
|
if ((user_str = selinux_fmt_sudo_user()) == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
goto done;
|
||||||
|
@@ -581,7 +583,11 @@ selinux_edit_copy_tfiles(struct command_details *command_details,
|
||||||
|
if (tfd != -1)
|
||||||
|
close(tfd);
|
||||||
|
|
||||||
|
- if (sesh_ap - sesh_args > 3) {
|
||||||
|
+ /*
|
||||||
|
+ * check dir adds two more args to the array
|
||||||
|
+ */
|
||||||
|
+ if ((!check_dir && sesh_ap - sesh_args > 3)
|
||||||
|
+ || (check_dir && sesh_ap - sesh_args > 5)) {
|
||||||
|
/* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
|
||||||
|
error = selinux_run_helper(command_details->cred.uid, command_details->cred.gid,
|
||||||
|
command_details->cred.ngroups, command_details->cred.groups, sesh_args,
|
@ -1,11 +0,0 @@
|
|||||||
diff -up ./src/sudo_edit.c.rest ./src/sudo_edit.c
|
|
||||||
--- ./src/sudo_edit.c.rest 2021-11-21 18:41:09.420657680 +0100
|
|
||||||
+++ ./src/sudo_edit.c 2021-11-21 18:42:23.214272777 +0100
|
|
||||||
@@ -878,6 +878,7 @@ selinux_edit_create_tfiles(struct comman
|
|
||||||
}
|
|
||||||
close(tfd);
|
|
||||||
}
|
|
||||||
+ ret = nfiles;
|
|
||||||
|
|
||||||
done:
|
|
||||||
/* Contents of tf will be freed by caller. */
|
|
19
SOURCES/sudo-1.9.5-undefined-symbol.patch
Normal file
19
SOURCES/sudo-1.9.5-undefined-symbol.patch
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
diff -up ./plugins/sudoers/audit.c.undefined ./plugins/sudoers/audit.c
|
||||||
|
--- ./plugins/sudoers/audit.c.undefined 2021-07-12 14:59:53.472306208 +0200
|
||||||
|
+++ ./plugins/sudoers/audit.c 2021-07-12 15:00:45.620620369 +0200
|
||||||
|
@@ -197,7 +197,6 @@ sudoers_audit_open(unsigned int version,
|
||||||
|
debug_return_int(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifdef SUDOERS_LOG_CLIENT
|
||||||
|
static void
|
||||||
|
audit_to_eventlog(struct eventlog *evlog, char * const command_info[],
|
||||||
|
char * const run_argv[], char * const run_envp[])
|
||||||
|
@@ -244,6 +243,7 @@ audit_to_eventlog(struct eventlog *evlog
|
||||||
|
debug_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef SUDOERS_LOG_CLIENT
|
||||||
|
static bool
|
||||||
|
log_server_accept(char * const command_info[], char * const run_argv[],
|
||||||
|
char * const run_envp[])
|
@ -1,54 +0,0 @@
|
|||||||
diff -up ./plugins/sudoers/auth/pam.c.krb5ccname ./plugins/sudoers/auth/pam.c
|
|
||||||
--- ./plugins/sudoers/auth/pam.c.krb5ccname 2019-10-28 13:27:38.000000000 +0100
|
|
||||||
+++ ./plugins/sudoers/auth/pam.c 2021-12-06 11:14:15.580226222 +0100
|
|
||||||
@@ -119,10 +119,10 @@ conv_filter_init(void)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Messages from PAM account management when trusted mode is enabled:
|
|
||||||
- * 1 Last successful login for %s: %s
|
|
||||||
- * 2 Last successful login for %s: %s on %s
|
|
||||||
- * 3 Last unsuccessful login for %s: %s
|
|
||||||
- * 4 Last unsuccessful login for %s: %s on %s
|
|
||||||
+ * 1 Last successful login for %s: %s
|
|
||||||
+ * 2 Last successful login for %s: %s on %s
|
|
||||||
+ * 3 Last unsuccessful login for %s: %s
|
|
||||||
+ * 4 Last unsuccessful login for %s: %s on %s
|
|
||||||
*/
|
|
||||||
if ((catd = catopen("pam_comsec", NL_CAT_LOCALE)) != -1) {
|
|
||||||
maxfilters += 4;
|
|
||||||
@@ -290,6 +290,7 @@ sudo_pam_init_quiet(struct passwd *pw, s
|
|
||||||
int
|
|
||||||
sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
|
|
||||||
{
|
|
||||||
+ const char *envccname;
|
|
||||||
const char *s;
|
|
||||||
int *pam_status = (int *) auth->data;
|
|
||||||
debug_decl(sudo_pam_verify, SUDOERS_DEBUG_AUTH)
|
|
||||||
@@ -298,8 +299,27 @@ sudo_pam_verify(struct passwd *pw, char
|
|
||||||
getpass_error = false; /* set by converse if user presses ^C */
|
|
||||||
conv_callback = callback; /* passed to conversation function */
|
|
||||||
|
|
||||||
+ /* Set KRB5CCNAME from the user environment if not set to propagate this
|
|
||||||
+ * information to PAM modules that may use it to authentication. */
|
|
||||||
+ envccname = sudo_getenv("KRB5CCNAME");
|
|
||||||
+ if (envccname == NULL && user_ccname != NULL) {
|
|
||||||
+ if (sudo_setenv("KRB5CCNAME", user_ccname, true) != 0) {
|
|
||||||
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
|
||||||
+ "unable to set KRB5CCNAME");
|
|
||||||
+ debug_return_int(AUTH_FAILURE);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* PAM_SILENT prevents the authentication service from generating output. */
|
|
||||||
*pam_status = pam_authenticate(pamh, PAM_SILENT);
|
|
||||||
+
|
|
||||||
+ /* Restore KRB5CCNAME to its original value. */
|
|
||||||
+ if (envccname == NULL && sudo_unsetenv("KRB5CCNAME") != 0) {
|
|
||||||
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
|
|
||||||
+ "unable to restore KRB5CCNAME");
|
|
||||||
+ debug_return_int(AUTH_FAILURE);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (getpass_error) {
|
|
||||||
/* error or ^C from tgetpass() */
|
|
||||||
debug_return_int(AUTH_INTR);
|
|
@ -1,35 +0,0 @@
|
|||||||
From 727056e0c9519d8eecde801e950b35f2f69c72e2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
|
||||||
Date: Fri, 23 Apr 2021 07:41:27 -0600
|
|
||||||
Subject: [PATCH] Make sure SIGCHLD is not ignored when sudo is executed. If
|
|
||||||
SIGCHLD is ignored there is a race condition between when the process is
|
|
||||||
executed and when the SIGCHLD handler is installed. This fixes the bug
|
|
||||||
described by GitHub PR #98
|
|
||||||
|
|
||||||
---
|
|
||||||
src/signal.c | 12 ++++++++++++
|
|
||||||
1 file changed, 12 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/signal.c b/src/signal.c
|
|
||||||
index 7f90d707b..866b64790 100644
|
|
||||||
--- a/src/signal.c
|
|
||||||
+++ b/src/signal.c
|
|
||||||
@@ -133,6 +133,18 @@ init_signals(void)
|
|
||||||
case SIGTTOU:
|
|
||||||
/* Don't install these until exec time. */
|
|
||||||
break;
|
|
||||||
+ case SIGCHLD:
|
|
||||||
+ /* Sudo needs to be able to catch SIGCHLD. */
|
|
||||||
+ if (ss->sa.sa_handler == SIG_IGN) {
|
|
||||||
+ sudo_debug_printf(SUDO_DEBUG_INFO,
|
|
||||||
+ "will restore signal %d on exec", SIGCHLD);
|
|
||||||
+ ss->restore = true;
|
|
||||||
+ }
|
|
||||||
+ if (sigaction(SIGCHLD, &sa, NULL) != 0) {
|
|
||||||
+ sudo_warn(U_("unable to set handler for signal %d"),
|
|
||||||
+ SIGCHLD);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
if (ss->sa.sa_handler != SIG_IGN) {
|
|
||||||
if (sigaction(ss->signo, &sa, NULL) != 0) {
|
|
146
SPECS/sudo.spec
146
SPECS/sudo.spec
@ -1,7 +1,7 @@
|
|||||||
Summary: Allows restricted root access for specified users
|
Summary: Allows restricted root access for specified users
|
||||||
Name: sudo
|
Name: sudo
|
||||||
Version: 1.8.29
|
Version: 1.9.5p2
|
||||||
Release: 10%{?dist}
|
Release: 1%{?dist}
|
||||||
License: ISC
|
License: ISC
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
URL: https://www.sudo.ws/
|
URL: https://www.sudo.ws/
|
||||||
@ -31,57 +31,27 @@ BuildRequires: openldap-devel
|
|||||||
BuildRequires: pam-devel
|
BuildRequires: pam-devel
|
||||||
BuildRequires: zlib-devel
|
BuildRequires: zlib-devel
|
||||||
|
|
||||||
# don't strip
|
Patch2: sudo-1.9.5-undefined-symbol.patch
|
||||||
Patch1: sudo-1.6.7p5-strip.patch
|
Patch3: sudo-1.9.5-selinux-t.patch
|
||||||
# 881258 - rpmdiff: added missing sudo-ldap.conf manpage
|
Patch4: sudo-1.9.5-sesh-bad-condition.patch
|
||||||
Patch2: sudo-1.8.23-sudoldapconfman.patch
|
Patch5: sudo-1.9.5-utmp-leak.patch
|
||||||
# env debug patch
|
Patch6: covscan.patch
|
||||||
Patch3: sudo-1.7.2p1-envdebug.patch
|
Patch7: sha-digest-calc.patch
|
||||||
# 1247591 - Sudo taking a long time when user information is stored externally.
|
Patch8: sudo-1.9.12-CVE-2023-22809.patch
|
||||||
Patch4: sudo-1.8.23-legacy-group-processing.patch
|
|
||||||
# 840980 - sudo creates a new parent process
|
|
||||||
# Adds cmnd_no_wait Defaults option
|
|
||||||
Patch5: sudo-1.8.23-nowaitopt.patch
|
|
||||||
# 1312486 - RHEL7 sudo logs username "root" instead of realuser in /var/log/secure
|
|
||||||
Patch6: sudo-1.8.6p7-logsudouser.patch
|
|
||||||
# 1786987 - CVE-2019-19232 sudo: attacker with access to a Runas ALL sudoer account
|
|
||||||
# can impersonate a nonexistent user [rhel-8]
|
|
||||||
Patch7: sudo-1.8.29-CVE-2019-19232.patch
|
|
||||||
# 1796518 - [RFE] add optional check for the target user shell
|
|
||||||
Patch8: sudo-1.8.29-CVE-2019-19234.patch
|
|
||||||
# 1798093 - CVE-2019-18634 sudo: Stack based buffer overflow in when pwfeedback is enabled [rhel-8.2.0]
|
|
||||||
Patch9: sudo-1.8.29-CVE-2019-18634.patch
|
|
||||||
|
|
||||||
# 1815164 - sudo allows privilege escalation with expire password
|
Patch9: sudo-1.9.13-CVE-2023-28486-7-1.patch
|
||||||
Patch10: sudo-1.8.29-expired-password-part1.patch
|
Patch10: sudo-1.9.13-CVE-2023-28486-7-2.patch
|
||||||
Patch11: sudo-1.8.29-expired-password-part2.patch
|
Patch11: sudo-1.9.13-CVE-2023-28486-7-3.patch
|
||||||
|
Patch12: sudo-1.9.13-CVE-2023-28486-7-4.patch
|
||||||
|
Patch13: sudo-1.9.13-CVE-2023-28486-7-5.patch
|
||||||
|
Patch14: sudo-1.9.13-CVE-2023-28486-7-6.patch
|
||||||
|
Patch15: sudo-1.9.13-CVE-2023-28486-7-7.patch
|
||||||
|
Patch16: sudo-1.9.13-CVE-2023-28486-7-8.patch
|
||||||
|
Patch17: sudo-1.9.13-CVE-2023-28486-7-9.patch
|
||||||
|
|
||||||
# 1917734 - EMBARGOED CVE-2021-3156 sudo: Heap-buffer overflow in argument parsing [rhel-8.4.0]
|
Patch18: linker.patch
|
||||||
Patch12: sudo-1.8.31-CVE-2021-3156.patch
|
|
||||||
# 1916434 - CVE-2021-23239 sudo: possible directory existence test due to race condition in sudoedit [rhel-8]
|
|
||||||
Patch13: sudo-1.9.5-CVE-2021-23239.patch
|
|
||||||
# 1917038 - CVE-2021-23240 sudo: symbolic link attack in SELinux-enabled sudoedit [rhel-8]
|
|
||||||
Patch14: sudo-1.9.5-CVE-2021-23240-1.patch
|
|
||||||
Patch15: sudo-1.9.5-CVE-2021-23240-2.patch
|
|
||||||
Patch16: sudo-1.9.5-CVE-2021-23240-3.patch
|
|
||||||
Patch17: sudo-1.9.5-CVE-2021-23240-4.patch
|
|
||||||
Patch18: sudo-1.9.5-CVE-2021-23240-5.patch
|
|
||||||
|
|
||||||
# 2029551 - sudoedit does not work with selinux args
|
Patch19: sudo-1.9.15-CVE-2023-42465.patch
|
||||||
Patch19: sudo-1.9.5-sudoedit-selinux.patch
|
|
||||||
# 1999751 - Request to backport https://www.sudo.ws/repos/sudo/rev/b4c91a0f72e7 to RHEL 8
|
|
||||||
Patch20: sudo-1.9.7-sigchild.patch
|
|
||||||
# 1917379 - [RFE] pass KRB5CCNAME to pam_authenticate environment if available
|
|
||||||
Patch21: sudo-1.9.7-krb5ccname.patch
|
|
||||||
# 1986572 - utmp resource leak in sudo
|
|
||||||
Patch22: sudo-1.9.7-utmp-leak.patch
|
|
||||||
|
|
||||||
# 2114576 - sudo digest check fails incorrectly for certain file sizes (SHA512/SHA384)
|
|
||||||
Patch23: sha-digest-calc.patch
|
|
||||||
# 2161221 - EMBARGOED CVE-2023-22809 sudo: arbitrary file write with privileges of the RunAs user [rhel-8.8.0]
|
|
||||||
Patch24: sudo-1.9.12-CVE-2023-22809-whitelist.patch
|
|
||||||
Patch25: sudo-1.9.12-CVE-2023-22809-backports.patch
|
|
||||||
Patch26: sudo-1.9.12-CVE-2023-22809.patch
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Sudo (superuser do) allows a system administrator to give certain
|
Sudo (superuser do) allows a system administrator to give certain
|
||||||
@ -106,39 +76,27 @@ plugins that use %{name}.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
|
|
||||||
%patch1 -p1 -b .strip
|
%patch -P 2 -p1 -b .undefined
|
||||||
%patch2 -p1 -b .sudoldapconfman
|
%patch -P 3 -p1 -b .selinux-t
|
||||||
%patch3 -p1 -b .env-debug
|
%patch -P 4 -p1 -b .bad-cond
|
||||||
%patch4 -p1 -b .legacy-processing
|
%patch -P 5 -p1 -b .utmp-leak
|
||||||
%patch5 -p1 -b .nowait
|
%patch -P 6 -p1 -b .covscan
|
||||||
%patch6 -p1 -b .logsudouser
|
%patch -P 7 -p1 -b .sha-digest
|
||||||
%patch7 -p1 -b .CVE-2019-19232
|
%patch -P 8 -p1 -b .cve-fix
|
||||||
%patch8 -p1 -b .target-shell
|
|
||||||
%patch9 -p1 -b .CVE-2019-18634
|
|
||||||
|
|
||||||
%patch10 -p1 -b .expired1
|
%patch -P 9 -p1 -b .cve-escape-1
|
||||||
%patch11 -p1 -b .expired2
|
%patch -P 10 -p1 -b .cve-escape-2
|
||||||
|
%patch -P 11 -p1 -b .cve-escape-3
|
||||||
|
%patch -P 12 -p1 -b .cve-escape-4
|
||||||
|
%patch -P 13 -p1 -b .cve-escape-5
|
||||||
|
%patch -P 14 -p1 -b .cve-escape-6
|
||||||
|
%patch -P 15 -p1 -b .cve-escape-7
|
||||||
|
%patch -P 16 -p1 -b .cve-escape-8
|
||||||
|
%patch -P 17 -p1 -b .cve-escape-9
|
||||||
|
|
||||||
%patch12 -p1 -b .heap-buffer
|
%patch -P 18 -p1 -b .linker
|
||||||
|
|
||||||
%patch13 -p1 -b .sudoedit-race
|
%patch -P 19 -p1 -b .rowhammer
|
||||||
|
|
||||||
%patch14 -p1 -b .symbolic-link-attack-1
|
|
||||||
%patch15 -p1 -b .symbolic-link-attack-2
|
|
||||||
%patch16 -p1 -b .symbolic-link-attack-3
|
|
||||||
%patch17 -p1 -b .symbolic-link-attack-4
|
|
||||||
%patch18 -p1 -b .symbolic-link-attack-5
|
|
||||||
|
|
||||||
%patch19 -p1 -b .sudoedit-selinux
|
|
||||||
|
|
||||||
%patch20 -p1 -b .sigchild
|
|
||||||
%patch21 -p1 -b .krb5ccname
|
|
||||||
%patch22 -p1 -b .utmp-leak
|
|
||||||
|
|
||||||
%patch23 -p1 -b .sha-digest
|
|
||||||
%patch24 -p1 -b .whitelist
|
|
||||||
%patch25 -p1 -b .backports
|
|
||||||
%patch26 -p1 -b .cve
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
# Remove bundled copy of zlib
|
# Remove bundled copy of zlib
|
||||||
@ -158,7 +116,10 @@ export CFLAGS="$RPM_OPT_FLAGS $F_PIE" LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now"
|
|||||||
--sbindir=%{_sbindir} \
|
--sbindir=%{_sbindir} \
|
||||||
--libdir=%{_libdir} \
|
--libdir=%{_libdir} \
|
||||||
--docdir=%{_pkgdocdir} \
|
--docdir=%{_pkgdocdir} \
|
||||||
|
--disable-openssl \
|
||||||
--disable-root-mailer \
|
--disable-root-mailer \
|
||||||
|
--disable-log-server \
|
||||||
|
--disable-log-client \
|
||||||
--with-logging=syslog \
|
--with-logging=syslog \
|
||||||
--with-logfac=authpriv \
|
--with-logfac=authpriv \
|
||||||
--with-pam \
|
--with-pam \
|
||||||
@ -172,6 +133,7 @@ export CFLAGS="$RPM_OPT_FLAGS $F_PIE" LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now"
|
|||||||
--with-selinux \
|
--with-selinux \
|
||||||
--with-passprompt="[sudo] password for %p: " \
|
--with-passprompt="[sudo] password for %p: " \
|
||||||
--with-linux-audit \
|
--with-linux-audit \
|
||||||
|
--disable-python \
|
||||||
--with-sssd
|
--with-sssd
|
||||||
# --without-kerb5 \
|
# --without-kerb5 \
|
||||||
# --without-kerb4
|
# --without-kerb4
|
||||||
@ -192,8 +154,18 @@ install -p -d -m 700 $RPM_BUILD_ROOT/var/db/sudo
|
|||||||
install -p -d -m 700 $RPM_BUILD_ROOT/var/db/sudo/lectured
|
install -p -d -m 700 $RPM_BUILD_ROOT/var/db/sudo/lectured
|
||||||
install -p -d -m 750 $RPM_BUILD_ROOT/etc/sudoers.d
|
install -p -d -m 750 $RPM_BUILD_ROOT/etc/sudoers.d
|
||||||
install -p -c -m 0440 %{SOURCE1} $RPM_BUILD_ROOT/etc/sudoers
|
install -p -c -m 0440 %{SOURCE1} $RPM_BUILD_ROOT/etc/sudoers
|
||||||
install -p -c -m 0640 %{SOURCE3} $RPM_BUILD_ROOT/etc/sudo.conf
|
|
||||||
install -p -c -m 0640 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/sudo-ldap.conf
|
install -p -c -m 0640 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/sudo-ldap.conf
|
||||||
|
install -p -c -m 0640 %{SOURCE3} $RPM_BUILD_ROOT/%{_sysconfdir}/sudo.conf
|
||||||
|
|
||||||
|
|
||||||
|
# create sudo-ldap.conf man
|
||||||
|
echo ".so man5/sudoers.ldap.5" > sudo-ldap.conf.5
|
||||||
|
gzip sudo-ldap.conf.5
|
||||||
|
install -p -c -m 0644 sudo-ldap.conf.5.gz $RPM_BUILD_ROOT/%{_mandir}/man5/sudo-ldap.conf.5.gz
|
||||||
|
rm -f sudo-ldap.conf.5.gz
|
||||||
|
|
||||||
|
# we are not building sendlog so we don't need this
|
||||||
|
rm -rf $RPM_BUILD_ROOT/%{_mandir}/man8/sudo_sendlog.8
|
||||||
|
|
||||||
# Add sudo to protected packages
|
# Add sudo to protected packages
|
||||||
install -p -d -m 755 $RPM_BUILD_ROOT/etc/dnf/protected.d/
|
install -p -d -m 755 $RPM_BUILD_ROOT/etc/dnf/protected.d/
|
||||||
@ -264,7 +236,9 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%dir %{_libexecdir}/sudo
|
%dir %{_libexecdir}/sudo
|
||||||
%attr(0755,root,root) %{_libexecdir}/sudo/sesh
|
%attr(0755,root,root) %{_libexecdir}/sudo/sesh
|
||||||
%attr(0644,root,root) %{_libexecdir}/sudo/sudo_noexec.so
|
%attr(0644,root,root) %{_libexecdir}/sudo/sudo_noexec.so
|
||||||
|
%attr(0644,root,root) %{_libexecdir}/sudo/audit_json.so
|
||||||
%attr(0644,root,root) %{_libexecdir}/sudo/sudoers.so
|
%attr(0644,root,root) %{_libexecdir}/sudo/sudoers.so
|
||||||
|
%attr(0644,root,root) %{_libexecdir}/sudo/sample_approval.so
|
||||||
%attr(0644,root,root) %{_libexecdir}/sudo/group_file.so
|
%attr(0644,root,root) %{_libexecdir}/sudo/group_file.so
|
||||||
%attr(0644,root,root) %{_libexecdir}/sudo/system_group.so
|
%attr(0644,root,root) %{_libexecdir}/sudo/system_group.so
|
||||||
%attr(0644,root,root) %{_libexecdir}/sudo/libsudo_util.so.?.?.?
|
%attr(0644,root,root) %{_libexecdir}/sudo/libsudo_util.so.?.?.?
|
||||||
@ -298,6 +272,16 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%{_mandir}/man8/sudo_plugin.8*
|
%{_mandir}/man8/sudo_plugin.8*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Jan 22 2024 Radovan Sroka <rsroka@redhat.com> - 1.9.5p2-1
|
||||||
|
RHEL 8.9.0.Z ERRATUM
|
||||||
|
- Rebase to 1.9.5p2
|
||||||
|
- CVE-2023-28486 sudo: Sudo does not escape control characters in log messages
|
||||||
|
Resolves: RHEL-21825
|
||||||
|
- CVE-2023-28487 sudo: Sudo does not escape control characters in sudoreplay output
|
||||||
|
Resolves: RHEL-21831
|
||||||
|
- CVE-2023-42465 sudo: Targeted Corruption of Register and Stack Variables
|
||||||
|
Resolves: RHEL-21820
|
||||||
|
|
||||||
* Wed Jan 11 2023 Radovan Sroka <rsroka@redhat.com> - 1.8.29.9
|
* Wed Jan 11 2023 Radovan Sroka <rsroka@redhat.com> - 1.8.29.9
|
||||||
RHEL 8.8.0 ERRATUM
|
RHEL 8.8.0 ERRATUM
|
||||||
- CVE-2023-22809 sudo: arbitrary file write with privileges of the RunAs user
|
- CVE-2023-22809 sudo: arbitrary file write with privileges of the RunAs user
|
||||||
|
Loading…
Reference in New Issue
Block a user