From 36f654311fcd965a53ea4dde6c25b9dbcb7da643 Mon Sep 17 00:00:00 2001 From: basebuilder_pel7ppc64bebuilder0 Date: Mon, 28 May 2018 22:34:17 +0200 Subject: [PATCH] sudo package update Signed-off-by: basebuilder_pel7ppc64bebuilder0 --- SOURCES/sudo-1.6.7p5-strip.patch | 27 + SOURCES/sudo-1.7.2p1-envdebug.patch | 27 + SOURCES/sudo-1.8.18-testsuitefix.patch | 189 +++ SOURCES/sudo-1.8.19p2-CVE-2017-1000368.patch | 66 + SOURCES/sudo-1.8.19p2-display-privs.patch | 16 + ....8.19p2-error-warning-visudo-message.patch | 53 + .../sudo-1.8.19p2-fqdn-use-after-free.patch | 124 ++ .../sudo-1.8.19p2-get_process_ttyname.patch | 76 + ...udo-1.8.19p2-ignore-unknown-defaults.patch | 142 ++ SOURCES/sudo-1.8.19p2-iologflush.patch | 317 +++++ SOURCES/sudo-1.8.19p2-iologtruncate.patch | 171 +++ SOURCES/sudo-1.8.19p2-lecture-boolean.patch | 54 + SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch | 164 +++ SOURCES/sudo-1.8.19p2-manpage-use_pty.patch | 206 +++ SOURCES/sudo-1.8.19p2-sssd-double-free.patch | 44 + SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch | 113 ++ .../sudo-1.8.19p2-upstream-testsuitefix.patch | 14 + SOURCES/sudo-1.8.21-ldap-pass2-filter.patch | 19 + ...-1.8.6p3-ALL-with-negation-manupdate.patch | 113 ++ SOURCES/sudo-1.8.6p3-aliaswarnonly.patch | 12 + SOURCES/sudo-1.8.6p3-auditeditor.patch | 29 + SOURCES/sudo-1.8.6p3-auditrolechange.patch | 45 + SOURCES/sudo-1.8.6p3-authinterrupt.patch | 26 + SOURCES/sudo-1.8.6p3-cycledetect.patch | 477 +++++++ SOURCES/sudo-1.8.6p3-doublequotefix.patch | 46 + SOURCES/sudo-1.8.6p3-emallocfail.patch | 17 + SOURCES/sudo-1.8.6p3-lbufexpandcode.patch | 138 ++ .../sudo-1.8.6p3-ldap-sssd-usermatch.patch | 24 + SOURCES/sudo-1.8.6p3-ldapconfparse.patch | 45 + SOURCES/sudo-1.8.6p3-mantypo.patch | 12 + SOURCES/sudo-1.8.6p3-mantypos-ldap.patch | 74 + SOURCES/sudo-1.8.6p3-netgrfilterfix.patch | 92 ++ SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch | 56 + SOURCES/sudo-1.8.6p3-nonehostname.patch | 13 + SOURCES/sudo-1.8.6p3-nowaitopt.patch | 161 +++ SOURCES/sudo-1.8.6p3-nprocfix.patch | 117 ++ SOURCES/sudo-1.8.6p3-sigpipefix.patch | 12 + SOURCES/sudo-1.8.6p3-sssd-noise.patch | 12 + SOURCES/sudo-1.8.6p3-sssdfixes.patch | 119 ++ SOURCES/sudo-1.8.6p3-sssdrulenames.patch | 22 + SOURCES/sudo-1.8.6p3-strictuidgid.patch | 53 + SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch | 747 ++++++++++ SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch | 12 + SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch | 333 +++++ SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch | 117 ++ SOURCES/sudo-1.8.6p7-authlogicfix.patch | 38 + SOURCES/sudo-1.8.6p7-clangfixes.patch | 46 + .../sudo-1.8.6p7-closefrom-override-fix.patch | 38 + SOURCES/sudo-1.8.6p7-constwarnfix.patch | 104 ++ ...1.8.6p7-digest-backport-checklinkfix.patch | 12 + .../sudo-1.8.6p7-digest-backport-docs.patch | 260 ++++ SOURCES/sudo-1.8.6p7-digest-backport.patch | 435 ++++++ SOURCES/sudo-1.8.6p7-digest_race_doc.patch | 88 ++ SOURCES/sudo-1.8.6p7-digestmessagesfix.patch | 43 + SOURCES/sudo-1.8.6p7-duplicatenssfix.patch | 47 + SOURCES/sudo-1.8.6p7-ipahostname.patch | 192 +++ ...-1.8.6p7-ldap_sssd_parse_whitespaces.patch | 91 ++ SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch | 119 ++ SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch | 47 + ...sudo-1.8.6p7-legacy-group-processing.patch | 224 +++ SOURCES/sudo-1.8.6p7-logsudouser.patch | 90 ++ SOURCES/sudo-1.8.6p7-manfix-usepty.patch | 107 ++ SOURCES/sudo-1.8.6p7-netgroup_tuple.patch | 194 +++ SOURCES/sudo-1.8.6p7-newbase64decoder.patch | 104 ++ SOURCES/sudo-1.8.6p7-noexec-update.patch | 422 ++++++ SOURCES/sudo-1.8.6p7-nproc-nowait.patch | 48 + SOURCES/sudo-1.8.6p7-null_exception.patch | 13 + .../sudo-1.8.6p7-pam_servicebackport.patch | 221 +++ ...udo-1.8.6p7-segfault-null-group-list.patch | 13 + SOURCES/sudo-1.8.6p7-sesh_loginshell.patch | 12 + SOURCES/sudo-1.8.6p7-strunquote.patch | 137 ++ SOURCES/sudo-1.8.6p7-sudoconfman.patch | 1263 +++++++++++++++++ SOURCES/sudo-1.8.6p7-sudoldapconfman.patch | 50 + SOURCES/sudo-1.8.6p7-tty-name-parsing.patch | 29 + .../sudo-1.8.6p7-unprivileged-list-fix.patch | 37 + SOURCES/sudo-1.8.6p7-visudocontent.patch | 20 + SOURCES/sudo-ldap.conf | 86 ++ SOURCES/sudo.conf | 57 + SOURCES/sudoers | 112 ++ 79 files changed, 9545 insertions(+) create mode 100644 SOURCES/sudo-1.6.7p5-strip.patch create mode 100644 SOURCES/sudo-1.7.2p1-envdebug.patch create mode 100644 SOURCES/sudo-1.8.18-testsuitefix.patch create mode 100644 SOURCES/sudo-1.8.19p2-CVE-2017-1000368.patch create mode 100644 SOURCES/sudo-1.8.19p2-display-privs.patch create mode 100644 SOURCES/sudo-1.8.19p2-error-warning-visudo-message.patch create mode 100644 SOURCES/sudo-1.8.19p2-fqdn-use-after-free.patch create mode 100644 SOURCES/sudo-1.8.19p2-get_process_ttyname.patch create mode 100644 SOURCES/sudo-1.8.19p2-ignore-unknown-defaults.patch create mode 100644 SOURCES/sudo-1.8.19p2-iologflush.patch create mode 100644 SOURCES/sudo-1.8.19p2-iologtruncate.patch create mode 100644 SOURCES/sudo-1.8.19p2-lecture-boolean.patch create mode 100644 SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch create mode 100644 SOURCES/sudo-1.8.19p2-manpage-use_pty.patch create mode 100644 SOURCES/sudo-1.8.19p2-sssd-double-free.patch create mode 100644 SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch create mode 100644 SOURCES/sudo-1.8.19p2-upstream-testsuitefix.patch create mode 100644 SOURCES/sudo-1.8.21-ldap-pass2-filter.patch create mode 100644 SOURCES/sudo-1.8.6p3-ALL-with-negation-manupdate.patch create mode 100644 SOURCES/sudo-1.8.6p3-aliaswarnonly.patch create mode 100644 SOURCES/sudo-1.8.6p3-auditeditor.patch create mode 100644 SOURCES/sudo-1.8.6p3-auditrolechange.patch create mode 100644 SOURCES/sudo-1.8.6p3-authinterrupt.patch create mode 100644 SOURCES/sudo-1.8.6p3-cycledetect.patch create mode 100644 SOURCES/sudo-1.8.6p3-doublequotefix.patch create mode 100644 SOURCES/sudo-1.8.6p3-emallocfail.patch create mode 100644 SOURCES/sudo-1.8.6p3-lbufexpandcode.patch create mode 100644 SOURCES/sudo-1.8.6p3-ldap-sssd-usermatch.patch create mode 100644 SOURCES/sudo-1.8.6p3-ldapconfparse.patch create mode 100644 SOURCES/sudo-1.8.6p3-mantypo.patch create mode 100644 SOURCES/sudo-1.8.6p3-mantypos-ldap.patch create mode 100644 SOURCES/sudo-1.8.6p3-netgrfilterfix.patch create mode 100644 SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch create mode 100644 SOURCES/sudo-1.8.6p3-nonehostname.patch create mode 100644 SOURCES/sudo-1.8.6p3-nowaitopt.patch create mode 100644 SOURCES/sudo-1.8.6p3-nprocfix.patch create mode 100644 SOURCES/sudo-1.8.6p3-sigpipefix.patch create mode 100644 SOURCES/sudo-1.8.6p3-sssd-noise.patch create mode 100644 SOURCES/sudo-1.8.6p3-sssdfixes.patch create mode 100644 SOURCES/sudo-1.8.6p3-sssdrulenames.patch create mode 100644 SOURCES/sudo-1.8.6p3-strictuidgid.patch create mode 100644 SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch create mode 100644 SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch create mode 100644 SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch create mode 100644 SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch create mode 100644 SOURCES/sudo-1.8.6p7-authlogicfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-clangfixes.patch create mode 100644 SOURCES/sudo-1.8.6p7-closefrom-override-fix.patch create mode 100644 SOURCES/sudo-1.8.6p7-constwarnfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-digest-backport-checklinkfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-digest-backport-docs.patch create mode 100644 SOURCES/sudo-1.8.6p7-digest-backport.patch create mode 100644 SOURCES/sudo-1.8.6p7-digest_race_doc.patch create mode 100644 SOURCES/sudo-1.8.6p7-digestmessagesfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-duplicatenssfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-ipahostname.patch create mode 100644 SOURCES/sudo-1.8.6p7-ldap_sssd_parse_whitespaces.patch create mode 100644 SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch create mode 100644 SOURCES/sudo-1.8.6p7-legacy-group-processing.patch create mode 100644 SOURCES/sudo-1.8.6p7-logsudouser.patch create mode 100644 SOURCES/sudo-1.8.6p7-manfix-usepty.patch create mode 100644 SOURCES/sudo-1.8.6p7-netgroup_tuple.patch create mode 100644 SOURCES/sudo-1.8.6p7-newbase64decoder.patch create mode 100644 SOURCES/sudo-1.8.6p7-noexec-update.patch create mode 100644 SOURCES/sudo-1.8.6p7-nproc-nowait.patch create mode 100644 SOURCES/sudo-1.8.6p7-null_exception.patch create mode 100644 SOURCES/sudo-1.8.6p7-pam_servicebackport.patch create mode 100644 SOURCES/sudo-1.8.6p7-segfault-null-group-list.patch create mode 100644 SOURCES/sudo-1.8.6p7-sesh_loginshell.patch create mode 100644 SOURCES/sudo-1.8.6p7-strunquote.patch create mode 100644 SOURCES/sudo-1.8.6p7-sudoconfman.patch create mode 100644 SOURCES/sudo-1.8.6p7-sudoldapconfman.patch create mode 100644 SOURCES/sudo-1.8.6p7-tty-name-parsing.patch create mode 100644 SOURCES/sudo-1.8.6p7-unprivileged-list-fix.patch create mode 100644 SOURCES/sudo-1.8.6p7-visudocontent.patch create mode 100644 SOURCES/sudo-ldap.conf create mode 100644 SOURCES/sudo.conf create mode 100644 SOURCES/sudoers diff --git a/SOURCES/sudo-1.6.7p5-strip.patch b/SOURCES/sudo-1.6.7p5-strip.patch new file mode 100644 index 00000000..ba00efc0 --- /dev/null +++ b/SOURCES/sudo-1.6.7p5-strip.patch @@ -0,0 +1,27 @@ +From 8a045c3880e06f5fcf69a73c4029d6725e17f7bc Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +Date: Fri, 19 Aug 2016 13:49:25 +0200 +Subject: [PATCH 01/10] We do not strip + +rebased from: +Patch1: sudo-1.6.7p5-strip.patch +--- + install-sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/install-sh b/install-sh +index 6944fba..49d383a 100755 +--- a/install-sh ++++ b/install-sh +@@ -147,7 +147,7 @@ while ${MORETODO} ; do + fi + ;; + X-s) +- STRIPIT=true ++ #STRIPIT=true + ;; + X--) + shift +-- +2.7.4 + diff --git a/SOURCES/sudo-1.7.2p1-envdebug.patch b/SOURCES/sudo-1.7.2p1-envdebug.patch new file mode 100644 index 00000000..94c719ab --- /dev/null +++ b/SOURCES/sudo-1.7.2p1-envdebug.patch @@ -0,0 +1,27 @@ +From 44a602b49365969e56c63c9f12eda197e951302f Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +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 + diff --git a/SOURCES/sudo-1.8.18-testsuitefix.patch b/SOURCES/sudo-1.8.18-testsuitefix.patch new file mode 100644 index 00000000..6c602924 --- /dev/null +++ b/SOURCES/sudo-1.8.18-testsuitefix.patch @@ -0,0 +1,189 @@ +From ea44d916b9dffe0f33c3c62d1677567bf64a26b8 Mon Sep 17 00:00:00 2001 +From: Radovan Sroka +Date: Tue, 20 Sep 2016 15:07:53 +0200 +Subject: [PATCH 10/10] Fix upstream testsuite + +--- + plugins/sudoers/regress/sudoers/test2.in | 60 --------------------------- + plugins/sudoers/regress/sudoers/test2.in_ | 60 +++++++++++++++++++++++++++ + plugins/sudoers/regress/testsudoers/test3.sh | 13 ------ + plugins/sudoers/regress/testsudoers/test3.sh_ | 13 ++++++ + 4 files changed, 73 insertions(+), 73 deletions(-) + delete mode 100644 plugins/sudoers/regress/sudoers/test2.in + create mode 100644 plugins/sudoers/regress/sudoers/test2.in_ + delete mode 100755 plugins/sudoers/regress/testsudoers/test3.sh + create mode 100755 plugins/sudoers/regress/testsudoers/test3.sh_ + +diff --git a/plugins/sudoers/regress/sudoers/test2.in b/plugins/sudoers/regress/sudoers/test2.in +deleted file mode 100644 +index cfdfaa3..0000000 +--- a/plugins/sudoers/regress/sudoers/test2.in ++++ /dev/null +@@ -1,60 +0,0 @@ +-# Check quoted user name in User_Alias +-User_Alias UA1 = "foo" +-User_Alias UA2 = "foo.bar" +-User_Alias UA3 = "foo\"" +-User_Alias UA4 = "foo:bar" +-User_Alias UA5 = "foo:bar\"" +- +-# Check quoted group name in User_Alias +-User_Alias UA6 = "%baz" +-User_Alias UA7 = "%baz.biz" +- +-# Check quoted non-Unix group name in User_Alias +-User_Alias UA8 = "%:C/non UNIX 0 c" +-User_Alias UA9 = "%:C/non\'UNIX\'1 c" +-User_Alias UA10 = "%:C/non\"UNIX\"0 c" +-User_Alias UA11 = "%:C/non_UNIX_0 c" +-User_Alias UA12 = "%:C/non\'UNIX_3 c" +- +-# Check quoted user name in Runas_Alias +-Runas_Alias RA1 = "foo" +-Runas_Alias RA2 = "foo\"" +-Runas_Alias RA3 = "foo:bar" +-Runas_Alias RA4 = "foo:bar\"" +- +-# Check quoted host name in Defaults +-Defaults@"somehost" set_home +-Defaults@"quoted\"" set_home +- +-# Check quoted user name in Defaults +-Defaults:"you" set_home +-Defaults:"us\"" set_home +-Defaults:"%them" set_home +-Defaults:"%: non UNIX 0 c" set_home +-Defaults:"+net" set_home +- +-# Check quoted runas name in Defaults +-Defaults>"someone" set_home +-Defaults>"some one" set_home +- +-# Check quoted command in Defaults +-# XXX - not currently supported +-#Defaults!"/bin/ls -l" set_home +-#Defaults!"/bin/ls -l \"foo\"" set_home +- +-# Check quoted user, runas and host name in Cmnd_Spec +-"foo" "hosta" = ("root") ALL +-"foo.bar" "hostb" = ("root") ALL +-"foo\"" "hostc" = ("root") ALL +-"foo:bar" "hostd" = ("root") ALL +-"foo:bar\"" "hoste" = ("root") ALL +- +-# Check quoted group/netgroup name in Cmnd_Spec +-"%baz" "hosta" = ("root") ALL +-"%baz.biz" "hostb" = ("root") ALL +-"%:C/non UNIX 0 c" "hostc" = ("root") ALL +-"%:C/non\'UNIX\'1 c" "hostd" = ("root") ALL +-"%:C/non\"UNIX\"0 c" "hoste" = ("root") ALL +-"%:C/non_UNIX_0 c" "hostf" = ("root") ALL +-"%:C/non\'UNIX_3 c" "hostg" = ("root") ALL +-"+netgr" "hosth" = ("root") ALL +diff --git a/plugins/sudoers/regress/sudoers/test2.in_ b/plugins/sudoers/regress/sudoers/test2.in_ +new file mode 100644 +index 0000000..cfdfaa3 +--- /dev/null ++++ b/plugins/sudoers/regress/sudoers/test2.in_ +@@ -0,0 +1,60 @@ ++# Check quoted user name in User_Alias ++User_Alias UA1 = "foo" ++User_Alias UA2 = "foo.bar" ++User_Alias UA3 = "foo\"" ++User_Alias UA4 = "foo:bar" ++User_Alias UA5 = "foo:bar\"" ++ ++# Check quoted group name in User_Alias ++User_Alias UA6 = "%baz" ++User_Alias UA7 = "%baz.biz" ++ ++# Check quoted non-Unix group name in User_Alias ++User_Alias UA8 = "%:C/non UNIX 0 c" ++User_Alias UA9 = "%:C/non\'UNIX\'1 c" ++User_Alias UA10 = "%:C/non\"UNIX\"0 c" ++User_Alias UA11 = "%:C/non_UNIX_0 c" ++User_Alias UA12 = "%:C/non\'UNIX_3 c" ++ ++# Check quoted user name in Runas_Alias ++Runas_Alias RA1 = "foo" ++Runas_Alias RA2 = "foo\"" ++Runas_Alias RA3 = "foo:bar" ++Runas_Alias RA4 = "foo:bar\"" ++ ++# Check quoted host name in Defaults ++Defaults@"somehost" set_home ++Defaults@"quoted\"" set_home ++ ++# Check quoted user name in Defaults ++Defaults:"you" set_home ++Defaults:"us\"" set_home ++Defaults:"%them" set_home ++Defaults:"%: non UNIX 0 c" set_home ++Defaults:"+net" set_home ++ ++# Check quoted runas name in Defaults ++Defaults>"someone" set_home ++Defaults>"some one" set_home ++ ++# Check quoted command in Defaults ++# XXX - not currently supported ++#Defaults!"/bin/ls -l" set_home ++#Defaults!"/bin/ls -l \"foo\"" set_home ++ ++# Check quoted user, runas and host name in Cmnd_Spec ++"foo" "hosta" = ("root") ALL ++"foo.bar" "hostb" = ("root") ALL ++"foo\"" "hostc" = ("root") ALL ++"foo:bar" "hostd" = ("root") ALL ++"foo:bar\"" "hoste" = ("root") ALL ++ ++# Check quoted group/netgroup name in Cmnd_Spec ++"%baz" "hosta" = ("root") ALL ++"%baz.biz" "hostb" = ("root") ALL ++"%:C/non UNIX 0 c" "hostc" = ("root") ALL ++"%:C/non\'UNIX\'1 c" "hostd" = ("root") ALL ++"%:C/non\"UNIX\"0 c" "hoste" = ("root") ALL ++"%:C/non_UNIX_0 c" "hostf" = ("root") ALL ++"%:C/non\'UNIX_3 c" "hostg" = ("root") ALL ++"+netgr" "hosth" = ("root") ALL +diff --git a/plugins/sudoers/regress/testsudoers/test3.sh b/plugins/sudoers/regress/testsudoers/test3.sh +deleted file mode 100755 +index c1251b9..0000000 +--- a/plugins/sudoers/regress/testsudoers/test3.sh ++++ /dev/null +@@ -1,13 +0,0 @@ +-#!/bin/sh +-# +-# Test #include facility +-# +- +-MYUID=`\ls -lnd $TESTDIR/test3.d | awk '{print $3}'` +-MYGID=`\ls -lnd $TESTDIR/test3.d | awk '{print $4}'` +-exec 2>&1 +-./testsudoers -U $MYUID -G $MYGID root id <&1 ++./testsudoers -U $MYUID -G $MYGID root id <= buf + sizeof(buf)) ++ break; ++ } ++ if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) { + /* + * Field 7 is the tty dev (0 if no tty). +- * Since the process name at field 2 "(comm)" may include spaces, +- * start at the last ')' found. ++ * Since the process name at field 2 "(comm)" may include ++ * whitespace (including newlines), start at the last ')' found. + */ +- char *cp = strrchr(line, ')'); ++ *cp = '\0'; ++ cp = strrchr(buf, ')'); + if (cp != NULL) { + char *ep = cp; + const char *errstr; +@@ -527,7 +539,8 @@ get_process_ttyname(char *name, size_t namelen) + errno = ENOENT; + + done: +- free(line); ++ if (fd != -1) ++ close(fd); + if (ret == NULL) + sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to resolve tty via %s", path); diff --git a/SOURCES/sudo-1.8.19p2-display-privs.patch b/SOURCES/sudo-1.8.19p2-display-privs.patch new file mode 100644 index 00000000..234aa8de --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-display-privs.patch @@ -0,0 +1,16 @@ +diff -up ./plugins/sudoers/sudo_nss.c.display-privs ./plugins/sudoers/sudo_nss.c +--- ./plugins/sudoers/sudo_nss.c.display-privs 2017-01-13 23:30:15.000000000 -0500 ++++ ./plugins/sudoers/sudo_nss.c 2017-08-31 07:41:02.764738698 -0400 +@@ -348,7 +348,11 @@ display_privs(struct sudo_nss_list *snl, + sudo_lbuf_destroy(&defs); + sudo_lbuf_destroy(&privs); + +- debug_return_int(count > 0); ++/* ++ * This is ok, we return 1 which is success in this case ++ * and we don't want return failure even when there is nothing to print ++ */ ++ debug_return_int(1); + bad: + sudo_lbuf_destroy(&defs); + sudo_lbuf_destroy(&privs); diff --git a/SOURCES/sudo-1.8.19p2-error-warning-visudo-message.patch b/SOURCES/sudo-1.8.19p2-error-warning-visudo-message.patch new file mode 100644 index 00000000..6d523427 --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-error-warning-visudo-message.patch @@ -0,0 +1,53 @@ +From daa728fd889680cf5294fbb0e836cade9fe1a6d8 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Wed, 22 Feb 2017 06:38:33 -0700 +Subject: [PATCH] Go back to using a Warning/Error prefix in the message + printed to stderr for alias problems. Requested by Tomas Sykora. + +--- + doc/visudo.cat | 10 +++++----- + doc/visudo.man.in | 12 ++++++------ + doc/visudo.mdoc.in | 12 ++++++------ + plugins/sudoers/regress/visudo/test2.err.ok | 2 +- + plugins/sudoers/regress/visudo/test3.err.ok | 4 ++-- + plugins/sudoers/visudo.c | 14 ++++++++++---- + 6 files changed, 30 insertions(+), 24 deletions(-) + +diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c +index 4f192b2..4793d54 100644 +--- a/plugins/sudoers/visudo.c ++++ b/plugins/sudoers/visudo.c +@@ -1137,12 +1137,17 @@ check_alias(char *name, int type, char *file, int lineno, bool strict, bool quie + } else { + if (!quiet) { + if (errno == ELOOP) { +- sudo_warnx(U_("%s:%d cycle in %s \"%s\""), ++ fprintf(stderr, strict ? ++ U_("Error: %s:%d cycle in %s \"%s\"") : ++ U_("Warning: %s:%d cycle in %s \"%s\""), + file, lineno, alias_type_to_string(type), name); + } else { +- sudo_warnx(U_("%s:%d %s \"%s\" referenced but not defined"), ++ fprintf(stderr, strict ? ++ U_("Error: %s:%d %s \"%s\" referenced but not defined") : ++ U_("Warning: %s:%d %s \"%s\" referenced but not defined"), + file, lineno, alias_type_to_string(type), name); + } ++ fputc('\n', stderr); + if (strict && errorfile == NULL) { + errorfile = rcstr_addref(file); + errorlineno = lineno; +@@ -1292,8 +1297,9 @@ print_unused(void *v1, void *v2) + { + struct alias *a = (struct alias *)v1; + +- sudo_warnx_nodebug(U_("%s:%d unused %s \"%s\""), ++ fprintf(stderr, U_("Warning: %s:%d unused %s \"%s\""), + a->file, a->lineno, alias_type_to_string(a->type), a->name); ++ fputc('\n', stderr); + return 0; + } + +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.19p2-fqdn-use-after-free.patch b/SOURCES/sudo-1.8.19p2-fqdn-use-after-free.patch new file mode 100644 index 00000000..1c44dcc4 --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-fqdn-use-after-free.patch @@ -0,0 +1,124 @@ +diff -up ./plugins/sudoers/sssd.c.fqdnafterfree ./plugins/sudoers/sssd.c +--- ./plugins/sudoers/sssd.c.fqdnafterfree 2017-01-14 05:30:15.000000000 +0100 ++++ ./plugins/sudoers/sssd.c 2017-04-25 14:23:39.655649726 +0200 +@@ -82,8 +82,8 @@ typedef void (*sss_sudo_free_values_t)(c + + struct sudo_sss_handle { + char *domainname; +- char *host; +- char *shost; ++ char *ipa_host; ++ char *ipa_shost; + struct passwd *pw; + void *ssslib; + sss_sudo_send_recv_t fn_send_recv; +@@ -385,7 +385,7 @@ sudo_sss_open(struct sudo_nss *nss) + debug_decl(sudo_sss_open, SUDOERS_DEBUG_SSSD); + + /* Create a handle container. */ +- handle = malloc(sizeof(struct sudo_sss_handle)); ++ handle = calloc(1, sizeof(struct sudo_sss_handle)); + if (handle == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_int(ENOMEM); +@@ -447,9 +447,6 @@ sudo_sss_open(struct sudo_nss *nss) + debug_return_int(EFAULT); + } + +- handle->domainname = NULL; +- handle->host = user_runhost; +- handle->shost = user_srunhost; + handle->pw = sudo_user.pw; + nss->handle = handle; + +@@ -458,7 +455,7 @@ sudo_sss_open(struct sudo_nss *nss) + * in sssd.conf and use it in preference to user_runhost. + */ + if (strcmp(user_runhost, user_host) == 0) { +- if (get_ipa_hostname(&handle->shost, &handle->host) == -1) { ++ if (get_ipa_hostname(&handle->ipa_shost, &handle->ipa_host) == -1) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + free(handle); + debug_return_int(ENOMEM); +@@ -480,7 +477,10 @@ sudo_sss_close(struct sudo_nss *nss) + if (nss && nss->handle) { + handle = nss->handle; + sudo_dso_unload(handle->ssslib); +- free(nss->handle); ++ free(handle->ipa_host); ++ free(handle->ipa_shost); ++ free(handle); ++ nss->handle = NULL; + } + debug_return_int(0); + } +@@ -585,8 +585,9 @@ sudo_sss_checkpw(struct sudo_nss *nss, s + static int + sudo_sss_check_runas_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *sss_rule, int group_matched) + { +- char **val_array = NULL; +- char *val; ++ const char *host = handle->ipa_host ? handle->ipa_host : user_runhost; ++ const char *shost = handle->ipa_shost ? handle->ipa_shost : user_srunhost; ++ char *val, **val_array = NULL; + int ret = false, i; + debug_decl(sudo_sss_check_runas_user, SUDOERS_DEBUG_SSSD); + +@@ -656,8 +657,8 @@ sudo_sss_check_runas_user(struct sudo_ss + switch (val[0]) { + case '+': + sudo_debug_printf(SUDO_DEBUG_DEBUG, "netgr_"); +- if (netgr_matches(val, def_netgroup_tuple ? handle->host : NULL, +- def_netgroup_tuple ? handle->shost : NULL, runas_pw->pw_name)) { ++ if (netgr_matches(val, def_netgroup_tuple ? host : NULL, ++ def_netgroup_tuple ? shost : NULL, runas_pw->pw_name)) { + sudo_debug_printf(SUDO_DEBUG_DEBUG, "=> match"); + ret = true; + } +@@ -762,7 +763,9 @@ sudo_sss_check_runas(struct sudo_sss_han + static bool + sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) + { +- char **val_array, *val; ++ const char *host = handle->ipa_host ? handle->ipa_host : user_runhost; ++ const char *shost = handle->ipa_shost ? handle->ipa_shost : user_srunhost; ++ char *val, **val_array; + int matched = UNSPEC; + bool negated; + int i; +@@ -792,9 +795,9 @@ sudo_sss_check_host(struct sudo_sss_hand + + /* match any or address or netgroup or hostname */ + if (strcmp(val, "ALL") == 0 || addr_matches(val) || +- netgr_matches(val, handle->host, handle->shost, ++ netgr_matches(val, host, shost, + def_netgroup_tuple ? handle->pw->pw_name : NULL) || +- hostname_matches(handle->shost, handle->host, val)) { ++ hostname_matches(shost, host, val)) { + + matched = negated ? false : true; + } +@@ -816,9 +819,10 @@ sudo_sss_check_host(struct sudo_sss_hand + static bool + sudo_sss_check_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) + { +- int ret = false; ++ const char *host = handle->ipa_host ? handle->ipa_host : user_runhost; ++ const char *shost = handle->ipa_shost ? handle->ipa_shost : user_srunhost; + char **val_array; +- int i; ++ int i, ret = false; + debug_decl(sudo_sss_check_user, SUDOERS_DEBUG_SSSD); + + if (!handle || !rule) +@@ -844,8 +848,8 @@ sudo_sss_check_user(struct sudo_sss_hand + switch (*val) { + case '+': + /* Netgroup spec found, check membership. */ +- if (netgr_matches(val, def_netgroup_tuple ? handle->host : NULL, +- def_netgroup_tuple ? handle->shost : NULL, handle->pw->pw_name)) { ++ if (netgr_matches(val, def_netgroup_tuple ? host : NULL, ++ def_netgroup_tuple ? shost : NULL, handle->pw->pw_name)) { + ret = true; + } + break; diff --git a/SOURCES/sudo-1.8.19p2-get_process_ttyname.patch b/SOURCES/sudo-1.8.19p2-get_process_ttyname.patch new file mode 100644 index 00000000..8d304d5c --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-get_process_ttyname.patch @@ -0,0 +1,76 @@ +diff -ru sudo-1.8.20/src/ttyname.c sudo-1.8.20-Q/src/ttyname.c +--- sudo-1.8.20/src/ttyname.c 2017-05-10 08:38:44.000000000 -0700 ++++ sudo-1.8.20-Q/src/ttyname.c 2017-05-19 02:15:48.442705049 -0700 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2016 Todd C. Miller ++ * Copyright (c) 2012-2017 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -159,6 +159,8 @@ + + static char *ignore_devs[] = { + "/dev/fd/", ++ "/dev/mqueue/", ++ "/dev/shm/", + "/dev/stdin", + "/dev/stdout", + "/dev/stderr", +@@ -493,28 +495,35 @@ + len = getline(&line, &linesize, fp); + fclose(fp); + if (len != -1) { +- /* Field 7 is the tty dev (0 if no tty) */ +- char *cp = line; +- char *ep = line; +- const char *errstr; +- int field = 0; +- while (*++ep != '\0') { +- if (*ep == ' ') { +- *ep = '\0'; +- if (++field == 7) { +- dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr); +- if (errstr) { +- sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, +- "%s: tty device %s: %s", path, cp, errstr); ++ /* ++ * Field 7 is the tty dev (0 if no tty). ++ * Since the process name at field 2 "(comm)" may include spaces, ++ * start at the last ')' found. ++ */ ++ char *cp = strrchr(line, ')'); ++ if (cp != NULL) { ++ char *ep = cp; ++ const char *errstr; ++ int field = 1; ++ ++ while (*++ep != '\0') { ++ if (*ep == ' ') { ++ *ep = '\0'; ++ if (++field == 7) { ++ dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr); ++ if (errstr) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, ++ "%s: tty device %s: %s", path, cp, errstr); ++ } ++ if (tdev > 0) { ++ errno = serrno; ++ ret = sudo_ttyname_dev(tdev, name, namelen); ++ goto done; ++ } ++ break; + } +- if (tdev > 0) { +- errno = serrno; +- ret = sudo_ttyname_dev(tdev, name, namelen); +- goto done; +- } +- break; ++ cp = ep + 1; + } +- cp = ep + 1; + } + } + } + diff --git a/SOURCES/sudo-1.8.19p2-ignore-unknown-defaults.patch b/SOURCES/sudo-1.8.19p2-ignore-unknown-defaults.patch new file mode 100644 index 00000000..aadb45dc --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-ignore-unknown-defaults.patch @@ -0,0 +1,142 @@ +From 93cef1efac4e2b4930c23cdc35c0b916365ccabc Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +Date: Tue, 21 Feb 2017 14:56:24 +0100 +Subject: [PATCH] Add ignore_unknown_defaults flag to ignore unknown Defaults + entries in sudoers instead of producing a warning. + +Patch: sudo-1.8.19p2-ignore-unknown-defaults.patch +Resolves: +rhbz#1413160 +--- + doc/sudoers.cat | 6 ++++++ + doc/sudoers.man.in | 11 +++++++++++ + doc/sudoers.mdoc.in | 10 ++++++++++ + plugins/sudoers/def_data.c | 4 ++++ + plugins/sudoers/def_data.h | 2 ++ + plugins/sudoers/def_data.in | 3 +++ + plugins/sudoers/defaults.c | 3 ++- + 7 files changed, 38 insertions(+), 1 deletion(-) + +diff --git a/doc/sudoers.cat b/doc/sudoers.cat +index 76dbf28..50cf78a 100644 +--- a/doc/sudoers.cat ++++ b/doc/sudoers.cat +@@ -1071,6 +1071,12 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS + meaningful for the cn=defaults section. This flag is + _o_f_f by default. + ++ ignore_unknown_defaults ++ If set, ssuuddoo will not produce a warning if it ++ encounters an unknown Defaults entry in the _^Hs_^Hu_^Hd_^Ho_^He_^Hr_^Hs ++ file or an unknown sudoOption in LDAP. This flag is ++ _o_f_f by default. ++ + insults If set, ssuuddoo will insult users when they enter an + incorrect password. This flag is _o_f_f by default. + +diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in +index 8673da0..4be3760 100644 +--- a/doc/sudoers.man.in ++++ b/doc/sudoers.man.in +@@ -2266,6 +2266,17 @@ This flag is + \fIoff\fR + by default. + .TP 18n ++ignore_unknown_defaults ++If set, ++\fBsudo\fR ++will not produce a warning if it encounters an unknown Defaults entry ++in the ++\fIsudoers\fR ++file or an unknown sudoOption in LDAP. ++This flag is ++\fIoff\fR ++by default. ++.TP 18n + insults + If set, + \fBsudo\fR +diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in +index 74b6f01..f3fe5e6 100644 +--- a/doc/sudoers.mdoc.in ++++ b/doc/sudoers.mdoc.in +@@ -2124,6 +2124,16 @@ section. + This flag is + .Em off + by default. ++.It ignore_unknown_defaults ++If set, ++.Nm sudo ++will not produce a warning if it encounters an unknown Defaults entry ++in the ++.Em sudoers ++file or an unknown sudoOption in LDAP. ++This flag is ++.Em off ++by default. + .It insults + If set, + .Nm sudo +diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c +index 3926fed..3d787c2 100644 +--- a/plugins/sudoers/def_data.c ++++ b/plugins/sudoers/def_data.c +@@ -443,6 +443,10 @@ struct sudo_defs_types sudo_defs_table[] = { + N_("Don't pre-resolve all group names"), + NULL, + }, { ++ "ignore_unknown_defaults", T_FLAG, ++ N_("Ignore unknown Defaults entries in sudoers instead of producing a warning"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h +index b5e61b4..f5773a3 100644 +--- a/plugins/sudoers/def_data.h ++++ b/plugins/sudoers/def_data.h +@@ -208,6 +208,8 @@ + #define def_cmnd_no_wait (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag) + #define I_LEGACY_GROUP_PROCESSING 104 + #define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag) ++#define I_IGNORE_UNKNOWN_DEFAULTS 105 ++#define def_ignore_unknown_defaults (sudo_defs_table[I_IGNORE_UNKNOWN_DEFAULTS].sd_un.flag) + + enum def_tuple { + never, +diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in +index f1c9265..8f63d70 100644 +--- a/plugins/sudoers/def_data.in ++++ b/plugins/sudoers/def_data.in +@@ -328,3 +328,6 @@ cmnd_no_wait + legacy_group_processing + T_FLAG + "Don't pre-resolve all group names" ++ignore_unknown_defaults ++ T_FLAG ++ "Ignore unknown Defaults entries in sudoers instead of producing a warning" +diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c +index 9e60d94..5f93f80 100644 +--- a/plugins/sudoers/defaults.c ++++ b/plugins/sudoers/defaults.c +@@ -79,6 +79,7 @@ static struct strmap priorities[] = { + }; + + static struct early_default early_defaults[] = { ++ { I_IGNORE_UNKNOWN_DEFAULTS }, + #ifdef FQDN + { I_FQDN, true }, + #else +@@ -206,7 +207,7 @@ find_default(const char *name, const char *file, int lineno, bool quiet) + if (strcmp(name, sudo_defs_table[i].name) == 0) + debug_return_int(i); + } +- if (!quiet) { ++ if (!quiet && !def_ignore_unknown_defaults) { + if (lineno > 0) { + sudo_warnx(U_("%s:%d unknown defaults entry \"%s\""), + file, lineno, name); +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.19p2-iologflush.patch b/SOURCES/sudo-1.8.19p2-iologflush.patch new file mode 100644 index 00000000..213566f4 --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-iologflush.patch @@ -0,0 +1,317 @@ +diff -up ./doc/sudoers.cat.orig ./doc/sudoers.cat +--- ./doc/sudoers.cat.orig 2017-03-21 13:31:00.953951199 +0100 ++++ ./doc/sudoers.cat 2017-03-21 14:14:18.679116865 +0100 +@@ -1549,6 +1549,16 @@ SSUUDDOOEERRSS OOPPTTIIOONN + will be truncated and overwritten unless _i_o_l_o_g___f_i_l_e + ends in six or more Xs. + ++ iolog_flush If set, ssuuddoo will flush I/O log data to disk after each ++ write instead of buffering it. This makes it possible ++ to view the logs in real-time as the program is ++ executing but may significantly reduce the ++ effectiveness of I/O log compression. This flag is _o_f_f ++ by default. ++ ++ This setting is only supported by version 1.8.20 or ++ higher. ++ + iolog_group The group name to look up when setting the group ID on + new I/O log files and directories. By default, I/O log + files and directories inherit the group ID of the +@@ -2141,10 +2151,14 @@ II//OO LLOOGG FFIILLEESS + _s_t_d_e_r_r standard error to a pipe or redirected to a file + + All files other than _l_o_g are compressed in gzip format unless the +- _c_o_m_p_r_e_s_s___i_o option has been disabled. Due to buffering, the I/O log data +- will not be complete until the ssuuddoo command has completed. The output +- portion of an I/O log file can be viewed with the sudoreplay(1m) utility, +- which can also be used to list or search the available logs. ++ _c_o_m_p_r_e_s_s___i_o flag has been disabled. Due to buffering, it is not normally ++ possible to display the I/O logs in real-time as the program is executing ++ The I/O log data will not be complete until the program run by ssuuddoo has ++ exited or has been terminated by a signal. The _i_o_l_o_g___f_l_u_s_h flag can be ++ used to disable buffering, in which case I/O log data is written to disk ++ as soon as it is available. The output portion of an I/O log file can be ++ viewed with the sudoreplay(1m) utility, which can also be used to list or ++ search the available logs. + + Note that user input may contain sensitive information such as passwords + (even if they are not echoed to the screen), which will be stored in the +diff -up ./doc/sudoers.man.in.orig ./doc/sudoers.man.in +--- ./doc/sudoers.man.in.orig 2017-03-21 14:22:33.804283190 +0100 ++++ ./doc/sudoers.man.in 2017-03-21 14:22:21.136664667 +0100 +@@ -3199,6 +3199,19 @@ ends in six or + more + \fRX\fRs. + .TP 18n ++iolog_flush ++If set, ++\fBsudo\fR ++will flush I/O log data to disk after each write instead of buffering it. ++This makes it possible to view the logs in real-time as the program ++is executing but may significantly reduce the effectiveness of I/O ++log compression. ++This flag is ++\fIoff\fR ++by default. ++.sp ++This setting is only supported by version 1.8.20 or higher. ++.TP 18n + iolog_group + The group name to look up when setting the group ID on new I/O log + files and directories. +@@ -4298,10 +4311,16 @@ All files other than + \fIlog\fR + are compressed in gzip format unless the + \fIcompress_io\fR +-option has been disabled. +-Due to buffering, the I/O log data will not be complete until the ++flag has been disabled. ++Due to buffering, it is not normally possible to display the I/O logs in ++real-time as the program is executing ++The I/O log data will not be complete until the program run by + \fBsudo\fR +-command has completed. ++has exited or has been terminated by a signal. ++The ++\fIiolog_flush\fR ++flag can be used to disable buffering, in which case I/O log data ++is written to disk as soon as it is available. + The output portion of an I/O log file can be viewed with the + sudoreplay(@mansectsu@) + utility, which can also be used to list or search the available logs. +diff -up ./doc/sudoers.mdoc.in.orig ./doc/sudoers.mdoc.in +--- ./doc/sudoers.mdoc.in.orig 2017-03-21 14:23:46.652089432 +0100 ++++ ./doc/sudoers.mdoc.in 2017-03-21 14:26:43.686758162 +0100 +@@ -2998,6 +2998,18 @@ overwritten unless + ends in six or + more + .Li X Ns s . ++.It iolog_flush ++If set, ++.Nm sudo ++will flush I/O log data to disk after each write instead of buffering it. ++This makes it possible to view the logs in real-time as the program ++is executing but may significantly reduce the effectiveness of I/O ++log compression. ++This flag is ++.Em off ++by default. ++.Pp ++This setting is only supported by version 1.8.20 or higher. + .It iolog_group + The group name to look up when setting the group ID on new I/O log + files and directories. +@@ -3991,10 +4003,16 @@ All files other than + .Pa log + are compressed in gzip format unless the + .Em compress_io +-option has been disabled. +-Due to buffering, the I/O log data will not be complete until the +-.Nm sudo +-command has completed. ++flag has been disabled. ++Due to buffering, it is not normally possible to display the I/O logs in ++real-time as the program is executing ++The I/O log data will not be complete until the program run by ++.Nm sudo ++has exited or has been terminated by a signal. ++The ++.Em iolog_flush ++flag can be used to disable buffering, in which case I/O log data ++is written to disk as soon as it is available. + The output portion of an I/O log file can be viewed with the + .Xr sudoreplay @mansectsu@ + utility, which can also be used to list or search the available logs. +diff -up ./plugins/sudoers/def_data.c.orig ./plugins/sudoers/def_data.c +--- ./plugins/sudoers/def_data.c.orig 2017-03-21 13:24:10.682064806 +0100 ++++ ./plugins/sudoers/def_data.c 2017-03-21 13:25:09.805322057 +0100 +@@ -447,6 +447,10 @@ struct sudo_defs_types sudo_defs_table[] + N_("Ignore unknown Defaults entries in sudoers instead of producing a warning"), + NULL, + }, { ++ "iolog_flush", T_FLAG, ++ N_("Flush I/O log data to disk immediately instead of buffering it"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff -up ./plugins/sudoers/def_data.h.orig ./plugins/sudoers/def_data.h +--- ./plugins/sudoers/def_data.h.orig 2017-03-21 13:25:20.489006524 +0100 ++++ ./plugins/sudoers/def_data.h 2017-03-21 13:28:09.251022290 +0100 +@@ -210,6 +210,8 @@ + #define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag) + #define I_IGNORE_UNKNOWN_DEFAULTS 105 + #define def_ignore_unknown_defaults (sudo_defs_table[I_IGNORE_UNKNOWN_DEFAULTS].sd_un.flag) ++#define I_IOLOG_FLUSH 106 ++#define def_iolog_flush (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag) + + enum def_tuple { + never, +diff -up ./plugins/sudoers/def_data.in.orig ./plugins/sudoers/def_data.in +--- ./plugins/sudoers/def_data.in.orig 2017-03-21 13:28:35.115258413 +0100 ++++ ./plugins/sudoers/def_data.in 2017-03-21 13:30:03.239655739 +0100 +@@ -331,3 +331,6 @@ legacy_group_processing + ignore_unknown_defaults + T_FLAG + "Ignore unknown Defaults entries in sudoers instead of producing a warning" ++iolog_flush ++ T_FLAG ++ "Flush I/O log data to disk immediately instead of buffering it" +diff -up ./plugins/sudoers/iolog.c.orig ./plugins/sudoers/iolog.c +--- ./plugins/sudoers/iolog.c.orig 2017-03-21 13:12:39.471464160 +0100 ++++ ./plugins/sudoers/iolog.c 2017-03-21 13:21:49.279230759 +0100 +@@ -709,6 +709,7 @@ iolog_deserialize_info(struct iolog_deta + + /* + * Write the "/log" file that contains the user and command info. ++ * This file is not compressed. + */ + static bool + write_info_log(char *pathbuf, size_t len, struct iolog_details *details, +@@ -747,6 +748,57 @@ write_info_log(char *pathbuf, size_t len + debug_return_bool(ret); + } + ++#ifdef HAVE_ZLIB_H ++static const char * ++gzstrerror(gzFile file) ++{ ++ int errnum; ++ ++ return gzerror(file, &errnum); ++} ++#endif /* HAVE_ZLIB_H */ ++ ++/* ++ * Write to an I/O log, compressing if iolog_compress is enabled. ++ * If def_iolog_flush is true, flush the buffer immediately. ++ */ ++static const char * ++iolog_write(const void *buf, unsigned int len, int idx) ++{ ++ const char *errstr = NULL; ++ debug_decl(iolog_write, SUDOERS_DEBUG_PLUGIN) ++ ++#ifdef HAVE_ZLIB_H ++ if (iolog_compress) { ++ if (gzwrite(io_log_files[idx].fd.g, buf, len) != (int)len) { ++ errstr = gzstrerror(io_log_files[idx].fd.g); ++ goto done; ++ } ++ if (def_iolog_flush) { ++ if (gzflush(io_log_files[idx].fd.g, Z_SYNC_FLUSH) != Z_OK) { ++ errstr = gzstrerror(io_log_files[idx].fd.g); ++ goto done; ++ } ++ } ++ } else ++#endif ++ { ++ if (fwrite(buf, 1, len, io_log_files[idx].fd.f) != len) { ++ errstr = strerror(errno); ++ goto done; ++ } ++ if (def_iolog_flush) { ++ if (fflush(io_log_files[idx].fd.f) != 0) { ++ errstr = strerror(errno); ++ goto done; ++ } ++ } ++ } ++ ++done: ++ debug_return_const_str(errstr); ++} ++ + static int + sudoers_io_open(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], +@@ -914,13 +966,15 @@ sudoers_io_version(int verbose) + + /* + * Generic I/O logging function. Called by the I/O logging entry points. ++ * Returns 1 on success and -1 on error. + */ + static int + sudoers_io_log(const char *buf, unsigned int len, int idx) + { + struct timeval now, delay; ++ char tbuf[1024]; + const char *errstr = NULL; +- int ret = true; ++ int ret = -1; + debug_decl(sudoers_io_version, SUDOERS_DEBUG_PLUGIN) + + if (io_log_files[idx].fd.v == NULL) { +@@ -931,41 +985,28 @@ sudoers_io_log(const char *buf, unsigned + + gettimeofday(&now, NULL); + +-#ifdef HAVE_ZLIB_H +- if (iolog_compress) { +- if (gzwrite(io_log_files[idx].fd.g, (const voidp)buf, len) != (int)len) { +- int errnum; ++ /* Write I/O log file entry. */ ++ errstr = iolog_write(buf, len, idx); ++ if (errstr != NULL) ++ goto done; + +- errstr = gzerror(io_log_files[idx].fd.g, &errnum); +- ret = -1; +- } +- } else +-#endif +- { +- if (fwrite(buf, 1, len, io_log_files[idx].fd.f) != len) { +- errstr = strerror(errno); +- ret = -1; +- } +- } ++ /* Write timing file entry. */ + sudo_timevalsub(&now, &last_time, &delay); +-#ifdef HAVE_ZLIB_H +- if (iolog_compress) { +- if (gzprintf(io_log_files[IOFD_TIMING].fd.g, "%d %f %u\n", idx, +- delay.tv_sec + ((double)delay.tv_usec / 1000000), len) == 0) { +- int errnum; +- +- errstr = gzerror(io_log_files[IOFD_TIMING].fd.g, &errnum); +- ret = -1; +- } +- } else +-#endif +- { +- if (fprintf(io_log_files[IOFD_TIMING].fd.f, "%d %f %u\n", idx, +- delay.tv_sec + ((double)delay.tv_usec / 1000000), len) < 0) { +- errstr = strerror(errno); +- ret = -1; +- } ++ len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %f %u\n", idx, ++ delay.tv_sec + ((double)delay.tv_usec / 1000000), len); ++ if (len >= sizeof(tbuf)) { ++ /* Not actually possible due to the size of tbuf[]. */ ++ errstr = strerror(EOVERFLOW); ++ goto done; + } ++ errstr = iolog_write(tbuf, len, IOFD_TIMING); ++ if (errstr != NULL) ++ goto done; ++ ++ /* Success. */ ++ ret = 1; ++ ++done: + last_time.tv_sec = now.tv_sec; + last_time.tv_usec = now.tv_usec; + +@@ -979,7 +1020,7 @@ sudoers_io_log(const char *buf, unsigned + + /* Ignore errors if they occur if the policy says so. */ + if (iolog_details.ignore_iolog_errors) +- ret = true; ++ ret = 1; + } + + debug_return_int(ret); diff --git a/SOURCES/sudo-1.8.19p2-iologtruncate.patch b/SOURCES/sudo-1.8.19p2-iologtruncate.patch new file mode 100644 index 00000000..ee358ebe --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-iologtruncate.patch @@ -0,0 +1,171 @@ +diff --git a/src/exec_pty.c b/src/exec_pty.c +index 7403506..56b2899 100644 +--- a/src/exec_pty.c ++++ b/src/exec_pty.c +@@ -711,8 +711,10 @@ io_buf_new(int rfd, int wfd, + int + fork_pty(struct command_details *details, int sv[], sigset_t *omask) + { ++ struct plugin_container *plugin; + struct command_status cstat; +- int io_pipe[3][2]; ++ int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } }; ++ bool interpose[3] = { false, false, false }; + sigaction_t sa; + sigset_t mask; + pid_t child; +@@ -738,6 +740,16 @@ fork_pty(struct command_details *details, int sv[], sigset_t *omask) + sigaddset(&ttyblock, SIGTTIN); + sigaddset(&ttyblock, SIGTTOU); + ++ /* Determine whether any of std{in,out,err} should be logged. */ ++ TAILQ_FOREACH(plugin, &io_plugins, entries) { ++ if (plugin->u.io->log_stdin) ++ interpose[STDIN_FILENO] = true; ++ if (plugin->u.io->log_stdout) ++ interpose[STDOUT_FILENO] = true; ++ if (plugin->u.io->log_stderr) ++ interpose[STDERR_FILENO] = true; ++ } ++ + /* + * Setup stdin/stdout/stderr for child, to be duped after forking. + * In background mode there is no stdin. +@@ -763,35 +775,64 @@ fork_pty(struct command_details *details, int sv[], sigset_t *omask) + } + + /* +- * If either stdin, stdout or stderr is not a tty we use a pipe +- * to interpose ourselves instead of duping the pty fd. ++ * If stdin, stdout or stderr is not a tty and logging is enabled, ++ * use a pipe to interpose ourselves instead of using the pty fd. + */ +- memset(io_pipe, 0, sizeof(io_pipe)); + if (io_fds[SFD_STDIN] == -1 || !isatty(STDIN_FILENO)) { +- sudo_debug_printf(SUDO_DEBUG_INFO, "stdin not a tty, creating a pipe"); +- pipeline = true; +- if (pipe(io_pipe[STDIN_FILENO]) != 0) +- sudo_fatal(U_("unable to create pipe")); +- io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1], +- log_stdin, &iobufs); +- io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0]; +- } +- if (io_fds[SFD_STDOUT] == -1 || !isatty(STDOUT_FILENO)) { +- sudo_debug_printf(SUDO_DEBUG_INFO, "stdout not a tty, creating a pipe"); +- pipeline = true; +- if (pipe(io_pipe[STDOUT_FILENO]) != 0) +- sudo_fatal(U_("unable to create pipe")); +- io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO, +- log_stdout, &iobufs); +- io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1]; +- } +- if (io_fds[SFD_STDERR] == -1 || !isatty(STDERR_FILENO)) { +- sudo_debug_printf(SUDO_DEBUG_INFO, "stderr not a tty, creating a pipe"); +- if (pipe(io_pipe[STDERR_FILENO]) != 0) +- sudo_fatal(U_("unable to create pipe")); +- io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO, +- log_stderr, &iobufs); +- io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1]; ++ if (!interpose[STDIN_FILENO]) { ++ /* Not logging stdin, do not interpose. */ ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "stdin not a tty, not logging"); ++ io_fds[SFD_STDIN] = dup(STDIN_FILENO); ++ if (io_fds[SFD_STDIN] == -1) ++ sudo_fatal("dup"); ++ } else { ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "stdin not a tty, creating a pipe"); ++ pipeline = true; ++ if (pipe(io_pipe[STDIN_FILENO]) != 0) ++ sudo_fatal(U_("unable to create pipe")); ++ io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1], ++ log_stdin, &iobufs); ++ io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0]; ++ } ++ } ++ if (io_fds[SFD_STDOUT] == -1 || !isatty(STDOUT_FILENO)) { ++ if (!interpose[STDOUT_FILENO]) { ++ /* Not logging stdout, do not interpose. */ ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "stdout not a tty, not logging"); ++ io_fds[SFD_STDOUT] = dup(STDOUT_FILENO); ++ if (io_fds[SFD_STDOUT] == -1) ++ sudo_fatal("dup"); ++ } else { ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "stdout not a tty, creating a pipe"); ++ pipeline = true; ++ if (pipe(io_pipe[STDOUT_FILENO]) != 0) ++ sudo_fatal(U_("unable to create pipe")); ++ io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO, ++ log_stdout, &iobufs); ++ io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1]; ++ } ++ } ++ if (io_fds[SFD_STDERR] == -1 || !isatty(STDERR_FILENO)) { ++ if (!interpose[STDERR_FILENO]) { ++ /* Not logging stderr, do not interpose. */ ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "stderr not a tty, not logging"); ++ io_fds[SFD_STDERR] = dup(STDERR_FILENO); ++ if (io_fds[SFD_STDERR] == -1) ++ sudo_fatal("dup"); ++ } else { ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "stderr not a tty, creating a pipe"); ++ if (pipe(io_pipe[STDERR_FILENO]) != 0) ++ sudo_fatal(U_("unable to create pipe")); ++ io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO, ++ log_stderr, &iobufs); ++ io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1]; ++ } + } + + /* We don't want to receive SIGTTIN/SIGTTOU, getting EIO is preferable. */ +@@ -1549,10 +1590,24 @@ exec_pty(struct command_details *details, + setpgid(0, self); + + /* Wire up standard fds, note that stdout/stderr may be pipes. */ +- if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1 || +- dup2(io_fds[SFD_STDOUT], STDOUT_FILENO) == -1 || +- dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1) +- sudo_fatal("dup2"); ++ if (io_fds[SFD_STDIN] != STDIN_FILENO) { ++ if (dup2(io_fds[SFD_STDIN], STDIN_FILENO) == -1) ++ sudo_fatal("dup2"); ++ if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE]) ++ close(io_fds[SFD_STDIN]); ++ } ++ if (io_fds[SFD_STDOUT] != STDOUT_FILENO) { ++ if (dup2(io_fds[SFD_STDOUT], STDOUT_FILENO) == -1) ++ sudo_fatal("dup2"); ++ if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE]) ++ close(io_fds[SFD_STDOUT]); ++ } ++ if (io_fds[SFD_STDERR] != STDERR_FILENO) { ++ if (dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1) ++ sudo_fatal("dup2"); ++ if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE]) ++ close(io_fds[SFD_STDERR]); ++ } + + /* Wait for parent to grant us the tty if we are foreground. */ + if (foreground && !ISSET(details->flags, CD_EXEC_BG)) { +@@ -1561,15 +1616,9 @@ exec_pty(struct command_details *details, + nanosleep(&ts, NULL); + } + +- /* We have guaranteed that the slave fd is > 2 */ ++ /* Done with the pty slave, don't leak it. */ + if (io_fds[SFD_SLAVE] != -1) + close(io_fds[SFD_SLAVE]); +- if (io_fds[SFD_STDIN] != io_fds[SFD_SLAVE]) +- close(io_fds[SFD_STDIN]); +- if (io_fds[SFD_STDOUT] != io_fds[SFD_SLAVE]) +- close(io_fds[SFD_STDOUT]); +- if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE]) +- close(io_fds[SFD_STDERR]); + + /* Execute command; only returns on error. */ + exec_cmnd(details, cstat, errfd); diff --git a/SOURCES/sudo-1.8.19p2-lecture-boolean.patch b/SOURCES/sudo-1.8.19p2-lecture-boolean.patch new file mode 100644 index 00000000..482bc6b9 --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-lecture-boolean.patch @@ -0,0 +1,54 @@ +commit 631d458b6fc7341363a121c390e086cf676ecc83 +Author: Todd C. Miller +Date: Wed May 3 09:28:36 2017 -0600 + + Allow a tuple to be set to boolean true. Regression introduced by + refactor of set_default_entry() in sudo 1.8.18. + +diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c +index 89788477..91b47eeb 100644 +--- a/plugins/sudoers/defaults.c ++++ b/plugins/sudoers/defaults.c +@@ -238,19 +238,31 @@ parse_default_entry(struct sudo_defs_types *def, const char *val, int op, + int rc; + debug_decl(parse_default_entry, SUDOERS_DEBUG_DEFAULTS) + +- if (val == NULL && !ISSET(def->type, T_FLAG)) { +- /* Check for bogus boolean usage or missing value if non-boolean. */ +- if (!ISSET(def->type, T_BOOL) || op != false) { +- if (!quiet) { +- if (lineno > 0) { +- sudo_warnx(U_("%s:%d no value specified for \"%s\""), +- file, lineno, def->name); +- } else { +- sudo_warnx(U_("%s: no value specified for \"%s\""), +- file, def->name); ++ /* ++ * If no value specified, the boolean flag must be set for non-flags. ++ * Only flags and tuples support boolean "true". ++ */ ++ if (val == NULL) { ++ switch (def->type & T_MASK) { ++ case T_FLAG: ++ break; ++ case T_TUPLE: ++ if (ISSET(def->type, T_BOOL)) ++ break; ++ /* FALLTHROUGH */ ++ default: ++ if (!ISSET(def->type, T_BOOL) || op != false) { ++ if (!quiet) { ++ if (lineno > 0) { ++ sudo_warnx(U_("%s:%d no value specified for \"%s\""), ++ file, lineno, def->name); ++ } else { ++ sudo_warnx(U_("%s: no value specified for \"%s\""), ++ file, def->name); ++ } + } ++ debug_return_bool(false); + } +- debug_return_bool(false); + } + } + diff --git a/SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch b/SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch new file mode 100644 index 00000000..af85676e --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch @@ -0,0 +1,164 @@ +diff -up ./doc/sudoers.cat.lookup ./doc/sudoers.cat +--- ./doc/sudoers.cat.lookup 2017-04-25 13:17:51.073190114 +0200 ++++ ./doc/sudoers.cat 2017-04-25 13:17:51.081190069 +0200 +@@ -1140,24 +1140,39 @@ SSUUDDOOEERRSS OOPPTTIIOONN + _o_n by default. + + match_group_by_gid +- By default, when matching groups, ssuuddooeerrss will first +- resolve all the user's group IDs to group names and +- then compare those group names to any group names +- listed in the _s_u_d_o_e_r_s file. This works well on systems +- where the number of groups listed in the _s_u_d_o_e_r_s file +- is larger than the number of groups a typical user +- belongs to. On systems where group lookups are slow, +- where users may belong to a large number of groups, and +- where the number of groups listed in the _s_u_d_o_e_r_s file +- is relatively small, it may be prohibitively expensive +- and running commands via ssuuddoo may take longer than +- normal. On such systems it may be faster to use the ++ By default, ssuuddooeerrss will look up each group the user is ++ a member of by group ID to determine the group name ++ (this is only done once). The resulting list of the ++ user's group names is used when matching groups listed ++ in the _s_u_d_o_e_r_s file. This works well on systems where ++ the number of groups listed in the _s_u_d_o_e_r_s file is ++ larger than the number of groups a typical user belongs ++ to. On systems where group lookups are slow, where ++ users may belong to a large number of groups, and where ++ the number of groups listed in the _s_u_d_o_e_r_s file is ++ relatively small, it may be prohibitively expensive and ++ running commands via ssuuddoo may take longer than normal. ++ On such systems it may be faster to use the + _m_a_t_c_h___g_r_o_u_p___b_y___g_i_d flag to avoid resolving the user's +- group IDs to group names and instead resolve all group +- names listed in the _s_u_d_o_e_r_s file, matching by group ID +- instead of by group name. The _m_a_t_c_h___g_r_o_u_p___b_y___g_i_d flag +- has no effect when _s_u_d_o_e_r_s data is stored in LDAP. +- This flag is _o_f_f by default. ++ group IDs to group names. In this case, ssuuddooeerrss must ++ look up any group name listed in the _s_u_d_o_e_r_s file and ++ use the group ID instead of the group name when ++ determining whether the user is a member of the group. ++ ++ Note that if _m_a_t_c_h___g_r_o_u_p___b_y___g_i_d is enabled, group ++ database lookups performed by ssuuddooeerrss will be keyed by ++ group name as opposed to group ID. On systems where ++ there are multiple sources for the group database, it ++ is possible to have conflicting group names or group ++ IDs in the local _/_e_t_c_/_g_r_o_u_p file and the remote group ++ database. On such systems, enabling or disabling ++ _m_a_t_c_h___g_r_o_u_p___b_y___g_i_d can be used to choose whether group ++ database queries are performed by name (enabled) or ID ++ (disabled), which may aid in working around group entry ++ conflicts. ++ ++ The _m_a_t_c_h___g_r_o_u_p___b_y___g_i_d flag has no effect when _s_u_d_o_e_r_s ++ data is stored in LDAP. This flag is _o_f_f by default. + + This setting is only supported by version 1.8.18 or + higher. +diff -up ./doc/sudoers.man.in.lookup ./doc/sudoers.man.in +--- ./doc/sudoers.man.in.lookup 2017-04-25 13:17:51.074190108 +0200 ++++ ./doc/sudoers.man.in 2017-04-25 13:17:51.082190064 +0200 +@@ -2423,10 +2423,12 @@ This flag is + by default. + .TP 18n + match_group_by_gid +-By default, when matching groups, ++By default, + \fBsudoers\fR +-will first resolve all the user's group IDs to group names and then +-compare those group names to any group names listed in the ++will look up each group the user is a member of by group ID to ++determine the group name (this is only done once). ++The resulting list of the user's group names is used when matching ++groups listed in the + \fIsudoers\fR + file. + This works well on systems where the number of groups listed in the +@@ -2442,10 +2444,29 @@ running commands via + may take longer than normal. + On such systems it may be faster to use the + \fImatch_group_by_gid\fR +-flag to avoid resolving the user's group IDs to group names and +-instead resolve all group names listed in the ++flag to avoid resolving the user's group IDs to group names. ++In this case, ++\fBsudoers\fR ++must look up any group name listed in the + \fIsudoers\fR +-file, matching by group ID instead of by group name. ++file and use the group ID instead of the group name when determining ++whether the user is a member of the group. ++.sp ++Note that if ++\fImatch_group_by_gid\fR ++is enabled, group database lookups performed by ++\fBsudoers\fR ++will be keyed by group name as opposed to group ID. ++On systems where there are multiple sources for the group database, ++it is possible to have conflicting group names or group IDs in the local ++\fI/etc/group\fR ++file and the remote group database. ++On such systems, enabling or disabling ++\fImatch_group_by_gid\fR ++can be used to choose whether group database queries are performed ++by name (enabled) or ID (disabled), which may aid in working around ++group entry conflicts. ++.sp + The + \fImatch_group_by_gid\fR + flag has no effect when +diff -up ./doc/sudoers.mdoc.in.lookup ./doc/sudoers.mdoc.in +--- ./doc/sudoers.mdoc.in.lookup 2017-04-25 13:17:51.075190102 +0200 ++++ ./doc/sudoers.mdoc.in 2017-04-25 13:17:51.082190064 +0200 +@@ -2268,10 +2268,12 @@ This flag is + .Em @mail_no_user@ + by default. + .It match_group_by_gid +-By default, when matching groups, ++By default, + .Nm +-will first resolve all the user's group IDs to group names and then +-compare those group names to any group names listed in the ++will look up each group the user is a member of by group ID to ++determine the group name (this is only done once). ++The resulting list of the user's group names is used when matching ++groups listed in the + .Em sudoers + file. + This works well on systems where the number of groups listed in the +@@ -2287,10 +2289,29 @@ running commands via + may take longer than normal. + On such systems it may be faster to use the + .Em match_group_by_gid +-flag to avoid resolving the user's group IDs to group names and +-instead resolve all group names listed in the ++flag to avoid resolving the user's group IDs to group names. ++In this case, ++.Nm ++must look up any group name listed in the + .Em sudoers +-file, matching by group ID instead of by group name. ++file and use the group ID instead of the group name when determining ++whether the user is a member of the group. ++.Pp ++Note that if ++.Em match_group_by_gid ++is enabled, group database lookups performed by ++.Nm ++will be keyed by group name as opposed to group ID. ++On systems where there are multiple sources for the group database, ++it is possible to have conflicting group names or group IDs in the local ++.Pa /etc/group ++file and the remote group database. ++On such systems, enabling or disabling ++.Em match_group_by_gid ++can be used to choose whether group database queries are performed ++by name (enabled) or ID (disabled), which may aid in working around ++group entry conflicts. ++.Pp + The + .Em match_group_by_gid + flag has no effect when diff --git a/SOURCES/sudo-1.8.19p2-manpage-use_pty.patch b/SOURCES/sudo-1.8.19p2-manpage-use_pty.patch new file mode 100644 index 00000000..acb4daa3 --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-manpage-use_pty.patch @@ -0,0 +1,206 @@ +diff -up ./doc/sudoers.cat.manpage ./doc/sudoers.cat +--- ./doc/sudoers.cat.manpage 2017-09-11 15:16:47.443869930 +0200 ++++ ./doc/sudoers.cat 2017-09-11 15:42:15.140500826 +0200 +@@ -1088,13 +1088,19 @@ SSUUDDOOEERRSS OOPPTTIIOONN + connected to the user's tty, due to I/O redirection or + because the command is part of a pipeline, that input + is also captured and stored in a separate log file. +- For more information, see the _I_/_O _L_O_G _F_I_L_E_S section. +- This flag is _o_f_f by default. ++ Anything sent to the standard input will be consumed, ++ regardless of whether or not the command run via ssuuddoo ++ is actually reading the standard input. This may have ++ unexpected results when using ssuuddoo in a shell script ++ that expects to process the standard input. For more ++ information about I/O logging, see the _I_/_O _L_O_G _F_I_L_E_S ++ section. This flag is _o_f_f by default. + + log_output If set, ssuuddoo will run the command in a pseudo-tty and + log all output that is sent to the screen, similar to +- the script(1) command. For more information, see the +- _I_/_O _L_O_G _F_I_L_E_S section. This flag is _o_f_f by default. ++ the script(1) command. For more information about I/O ++ logging, see the _I_/_O _L_O_G _F_I_L_E_S section. This flag is ++ _o_f_f by default. + + log_year If set, the four-digit year will be logged in the (non- + syslog) ssuuddoo log file. This flag is _o_f_f by default. +@@ -1396,13 +1402,18 @@ SSUUDDOOEERRSS OOPPTTIIOONN + not needed, this option can be disabled to reduce the + load on the LDAP server. This flag is _o_n by default. + +- use_pty If set, ssuuddoo will run the command in a pseudo-pty even +- if no I/O logging is being gone. A malicious program +- run under ssuuddoo could conceivably fork a background +- process that retains to the user's terminal device +- after the main program has finished executing. Use of +- this option will make that impossible. This flag is +- _o_f_f by default. ++ use_pty If set, and ssuuddoo is running in a terminal, the command ++ will be run in a pseudo-pty (even if no I/O logging is ++ being done). If the ssuuddoo process is not attached to a ++ terminal, _u_s_e___p_t_y has no effect. ++ ++ A malicious program run under ssuuddoo may be capable of ++ injecting injecting commands into the user's terminal ++ or running a background process that retains access to ++ the user's terminal device even after the main program ++ has finished executing. By running the command in a ++ separate pseudo-pty, this attack is no longer possible. ++ This flag is _o_f_f by default. + + utmp_runas If set, ssuuddoo will store the name of the runas user when + updating the utmp (or utmpx) file. By default, ssuuddoo +@@ -2135,11 +2146,11 @@ LLOOGG FFOORRMMAATT + + II//OO LLOOGG FFIILLEESS + When I/O logging is enabled, ssuuddoo will run the command in a pseudo-tty +- and log all user input and/or output. I/O is logged to the directory +- specified by the _i_o_l_o_g___d_i_r option (_/_v_a_r_/_l_o_g_/_s_u_d_o_-_i_o by default) using a +- unique session ID that is included in the ssuuddoo log line, prefixed with +- ``TSID=''. The _i_o_l_o_g___f_i_l_e option may be used to control the format of +- the session ID. ++ and log all user input and/or output, depending on which options are ++ are enabled. I/O is logged to the directory specified by the _i_o_l_o_g___d_i_r ++ option (_/_v_a_r_/_l_o_g_/_s_u_d_o_-_i_o by default) using a unique session ID that is ++ included in the ssuuddoo log line, prefixed with "TSID=". The _i_o_l_o_g___f_i_l_e ++ option may be used to control the format of the session ID. + + Each I/O log is stored in a separate directory that contains the + following files: +diff -up ./doc/sudoers.man.in.manpage ./doc/sudoers.man.in +--- ./doc/sudoers.man.in.manpage 2017-09-11 15:16:47.444869925 +0200 ++++ ./doc/sudoers.man.in 2017-09-11 15:16:47.456869864 +0200 +@@ -2300,7 +2300,14 @@ will run the command in a pseudo-tty and + If the standard input is not connected to the user's tty, due to + I/O redirection or because the command is part of a pipeline, that + input is also captured and stored in a separate log file. +-For more information, see the ++Anything sent to the standard input will be consumed, regardless of ++whether or not the command run via ++\fBsudo\fR ++is actually reading the standard input. ++This may have unexpected results when using ++\fBsudo\fR ++in a shell script that expects to process the standard input. ++For more information about I/O logging, see the + \fII/O LOG FILES\fR + section. + This flag is +@@ -2314,7 +2321,7 @@ will run the command in a pseudo-tty and + to the screen, similar to the + script(1) + command. +-For more information, see the ++For more information about I/O logging, see the + \fII/O LOG FILES\fR + section. + This flag is +@@ -2934,14 +2941,24 @@ This flag is + by default. + .TP 18n + use_pty +-If set, ++If set, and + \fBsudo\fR +-will run the command in a pseudo-pty even if no I/O logging is being gone. ++is running in a terminal, the command will be run in a pseudo-pty ++(even if no I/O logging is being done). ++If the ++\fBsudo\fR ++process is not attached to a terminal, ++\fIuse_pty\fR ++has no effect. ++.sp + A malicious program run under + \fBsudo\fR +-could conceivably fork a background process that retains to the user's +-terminal device after the main program has finished executing. +-Use of this option will make that impossible. ++may be capable of injecting injecting commands into the user's ++terminal or running a background process that retains access to the ++user's terminal device even after the main program has finished ++executing. ++By running the command in a separate pseudo-pty, this attack is ++no longer possible. + This flag is + \fIoff\fR + by default. +@@ -4281,7 +4298,8 @@ word wrap will be disabled. + .SH "I/O LOG FILES" + When I/O logging is enabled, + \fBsudo\fR +-will run the command in a pseudo-tty and log all user input and/or output. ++will run the command in a pseudo-tty and log all user input and/or output, ++depending on which options are enabled. + I/O is logged to the directory specified by the + \fIiolog_dir\fR + option +diff -up ./doc/sudoers.mdoc.in.manpage ./doc/sudoers.mdoc.in +--- ./doc/sudoers.mdoc.in.manpage 2017-09-11 15:16:47.445869920 +0200 ++++ ./doc/sudoers.mdoc.in 2017-09-11 15:16:47.456869864 +0200 +@@ -2155,7 +2155,14 @@ will run the command in a pseudo-tty and + If the standard input is not connected to the user's tty, due to + I/O redirection or because the command is part of a pipeline, that + input is also captured and stored in a separate log file. +-For more information, see the ++Anything sent to the standard input will be consumed, regardless of ++whether or not the command run via ++.Nm sudo ++is actually reading the standard input. ++This may have unexpected results when using ++.Nm sudo ++in a shell script that expects to process the standard input. ++For more information about I/O logging, see the + .Sx "I/O LOG FILES" + section. + This flag is +@@ -2168,7 +2175,7 @@ will run the command in a pseudo-tty and + to the screen, similar to the + .Xr script 1 + command. +-For more information, see the ++For more information about I/O logging, see the + .Sx "I/O LOG FILES" + section. + This flag is +@@ -2752,14 +2759,24 @@ This flag is + .Em on + by default. + .It use_pty +-If set, ++If set, and + .Nm sudo +-will run the command in a pseudo-pty even if no I/O logging is being gone. ++is running in a terminal, the command will be run in a pseudo-pty ++(even if no I/O logging is being done). ++If the ++.Nm sudo ++process is not attached to a terminal, ++.Em use_pty ++has no effect. ++.Pp + A malicious program run under + .Nm sudo +-could conceivably fork a background process that retains to the user's +-terminal device after the main program has finished executing. +-Use of this option will make that impossible. ++may be capable of injecting injecting commands into the user's ++terminal or running a background process that retains access to the ++user's terminal device even after the main program has finished ++executing. ++By running the command in a separate pseudo-pty, this attack is ++no longer possible. + This flag is + .Em off + by default. +@@ -3976,7 +3993,8 @@ word wrap will be disabled. + .Sh I/O LOG FILES + When I/O logging is enabled, + .Nm sudo +-will run the command in a pseudo-tty and log all user input and/or output. ++will run the command in a pseudo-tty and log all user input and/or output, ++depending on which options are enabled. + I/O is logged to the directory specified by the + .Em iolog_dir + option diff --git a/SOURCES/sudo-1.8.19p2-sssd-double-free.patch b/SOURCES/sudo-1.8.19p2-sssd-double-free.patch new file mode 100644 index 00000000..d53eb4c1 --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-sssd-double-free.patch @@ -0,0 +1,44 @@ + +# HG changeset patch +# User Todd C. Miller +# Date 1511893724 25200 +# Node ID 14dacdea331942a38d443a75d1b08f67eafaa5eb +# Parent b456101fe5091540e9f6429db7568fa32b6d4da8 +Avoid a double free when ipa_hostname is set in sssd.conf and it +is an unqualified host name. From Daniel Kopecek. + +Also move the "unable to allocate memory" warning into get_ipa_hostname() +itself to make it easier to see where the allocation failed in the +debug log. + +diff -r b456101fe509 -r 14dacdea3319 plugins/sudoers/sssd.c +--- a/plugins/sudoers/sssd.c Tue Nov 28 09:48:43 2017 -0700 ++++ b/plugins/sudoers/sssd.c Tue Nov 28 11:28:44 2017 -0700 +@@ -349,6 +349,8 @@ + *lhostp = lhost; + ret = true; + } else { ++ sudo_warnx(U_("%s: %s"), __func__, ++ U_("unable to allocate memory")); + free(shost); + free(lhost); + ret = -1; +@@ -456,7 +458,6 @@ + */ + if (strcmp(user_runhost, user_host) == 0) { + if (get_ipa_hostname(&handle->ipa_shost, &handle->ipa_host) == -1) { +- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + free(handle); + debug_return_int(ENOMEM); + } +@@ -478,7 +479,8 @@ + handle = nss->handle; + sudo_dso_unload(handle->ssslib); + free(handle->ipa_host); +- free(handle->ipa_shost); ++ if (handle->ipa_host != handle->ipa_shost) ++ free(handle->ipa_shost); + free(handle); + nss->handle = NULL; + } + diff --git a/SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch b/SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch new file mode 100644 index 00000000..62d0cf2d --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch @@ -0,0 +1,113 @@ +From 1f37620953699fe71b09760fe01e33eb6ada771c Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Wed, 15 Nov 2017 12:27:39 -0700 +Subject: [PATCH] When checking the results for "sudo -l" and "sudo -v", keep + checking even after we get a match since the value of doauth may depend on + evaluating all the results. From Radovan Sroka of RedHat. + +In list (-l) or verify (-v) mode, if we have a match but authentication +is required, clear FLAG_NOPASSWD so that when listpw/verifypw is +set to "all" and there are multiple sudoers sources a password will +be required unless none of the entries in all sources require +authentication. From Radovan Sroka of RedHat + +Avoid calling cmnd_matches() in list/verify mode if we already have +a match. +--- + plugins/sudoers/ldap.c | 5 ++++- + plugins/sudoers/parse.c | 10 +++++++--- + plugins/sudoers/sssd.c | 5 ++++- + 3 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c +index 46309cba..c5c18360 100644 +--- a/plugins/sudoers/ldap.c ++++ b/plugins/sudoers/ldap.c +@@ -3320,12 +3320,13 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag) + (pwcheck == all && doauth != true)) { + doauth = !!sudo_ldap_check_bool(ld, entry, "authenticate"); + } ++ if (matched == true) ++ continue; + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || + sudo_ldap_check_command(ld, entry, NULL) == true) { + matched = true; +- break; + } + } + if (matched == true || user_uid == 0) { +@@ -3339,6 +3340,8 @@ sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag) + case any: + if (doauth == false) + SET(ret, FLAG_NOPASSWD); ++ else ++ CLR(ret, FLAG_NOPASSWD); + break; + default: + break; +diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c +index 749a3eb2..a12e88c5 100644 +--- a/plugins/sudoers/parse.c ++++ b/plugins/sudoers/parse.c +@@ -182,14 +182,16 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag) + if (hostlist_matches(sudo_user.pw, &priv->hostlist) != ALLOW) + continue; + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { ++ if ((pwcheck == any && cs->tags.nopasswd == true) || ++ (pwcheck == all && cs->tags.nopasswd != true)) ++ nopass = cs->tags.nopasswd; ++ if (match == ALLOW) ++ continue; + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || + cmnd_matches(cs->cmnd) == ALLOW) + match = ALLOW; +- if ((pwcheck == any && cs->tags.nopasswd == true) || +- (pwcheck == all && cs->tags.nopasswd != true)) +- nopass = cs->tags.nopasswd; + } + } + } +@@ -202,6 +204,8 @@ sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag) + SET(validated, FLAG_CHECK_USER); + else if (nopass == true) + SET(validated, FLAG_NOPASSWD); ++ else ++ CLR(validated, FLAG_NOPASSWD); + debug_return_int(validated); + } + +diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c +index 65b4d875..09ca9fee 100644 +--- a/plugins/sudoers/sssd.c ++++ b/plugins/sudoers/sssd.c +@@ -1321,12 +1321,13 @@ sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag) + (pwcheck == all && doauth != true)) { + doauth = !!sudo_sss_check_bool(handle, rule, "authenticate"); + } ++ if (matched == true) ++ continue; + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || + sudo_sss_check_command(handle, rule, NULL) == true) { + matched = true; +- break; + } + } + } +@@ -1341,6 +1342,8 @@ sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag) + case any: + if (doauth == false) + SET(ret, FLAG_NOPASSWD); ++ else ++ CLR(ret, FLAG_NOPASSWD); + break; + default: + break; +-- +2.14.3 + diff --git a/SOURCES/sudo-1.8.19p2-upstream-testsuitefix.patch b/SOURCES/sudo-1.8.19p2-upstream-testsuitefix.patch new file mode 100644 index 00000000..ef2946ce --- /dev/null +++ b/SOURCES/sudo-1.8.19p2-upstream-testsuitefix.patch @@ -0,0 +1,14 @@ +diff -up ./plugins/sudoers/regress/visudo/test2.err.ok.orig ./plugins/sudoers/regress/visudo/test2.err.ok +--- ./plugins/sudoers/regress/visudo/test2.err.ok.orig 2017-04-10 10:12:53.003000000 -0400 ++++ ./plugins/sudoers/regress/visudo/test2.err.ok 2017-04-10 10:13:36.771000000 -0400 +@@ -1 +1 @@ +-visudo: stdin:1 cycle in User_Alias "FOO" ++Error: stdin:1 cycle in User_Alias "FOO" +diff -up ./plugins/sudoers/regress/visudo/test3.err.ok.orig ./plugins/sudoers/regress/visudo/test3.err.ok +--- ./plugins/sudoers/regress/visudo/test3.err.ok.orig 2017-04-10 10:13:12.141000000 -0400 ++++ ./plugins/sudoers/regress/visudo/test3.err.ok 2017-04-10 10:13:56.842000000 -0400 +@@ -1,2 +1,2 @@ +-visudo: stdin:1 unused User_Alias "A" +-visudo: stdin:2 unused User_Alias "B" ++Warning: stdin:1 unused User_Alias "A" ++Warning: stdin:2 unused User_Alias "B" diff --git a/SOURCES/sudo-1.8.21-ldap-pass2-filter.patch b/SOURCES/sudo-1.8.21-ldap-pass2-filter.patch new file mode 100644 index 00000000..8da9603d --- /dev/null +++ b/SOURCES/sudo-1.8.21-ldap-pass2-filter.patch @@ -0,0 +1,19 @@ +diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c +index f21a99ee..83202e28 100644 +--- a/plugins/sudoers/ldap.c ++++ b/plugins/sudoers/ldap.c +@@ -1847,12 +1847,10 @@ sudo_ldap_build_pass2(void) + ldap_conf.timed ? timebuffer : "", + (ldap_conf.timed || ldap_conf.search_filter) ? ")" : ""); + } else { +- len = asprintf(&filt, "%s%s(sudoUser=*)(sudoUser=%s*)%s%s", +- (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "", ++ len = asprintf(&filt, "(&%s(sudoUser=*)(sudoUser=%s*)%s)", + ldap_conf.search_filter ? ldap_conf.search_filter : "", + query_netgroups ? "+" : "%:", +- ldap_conf.timed ? timebuffer : "", +- (ldap_conf.timed || ldap_conf.search_filter) ? ")" : ""); ++ ldap_conf.timed ? timebuffer : ""); + } + if (len == -1) + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); diff --git a/SOURCES/sudo-1.8.6p3-ALL-with-negation-manupdate.patch b/SOURCES/sudo-1.8.6p3-ALL-with-negation-manupdate.patch new file mode 100644 index 00000000..ef468e33 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-ALL-with-negation-manupdate.patch @@ -0,0 +1,113 @@ +diff -up sudo-1.8.6p3/doc/sudoers.cat.orig sudo-1.8.6p3/doc/sudoers.cat +--- sudo-1.8.6p3/doc/sudoers.cat.orig 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/doc/sudoers.cat 2013-07-10 14:57:53.791093835 +0200 +@@ -668,11 +668,24 @@ SSUUDDOOEERRSS FFIILLEE FFO + since in a command context, it allows the user to run aannyy command on the + system. + +- An exclamation point (`!') can be used as a logical _n_o_t operator both in +- an _a_l_i_a_s and in front of a Cmnd. This allows one to exclude certain +- values. Note, however, that using a `!' in conjunction with the built-in +- AALLLL alias to allow a user to run ``all but a few'' commands rarely works +- as intended (see _S_E_C_U_R_I_T_Y _N_O_T_E_S below). ++ An exclamation point (`!') can be used as a logical _n_o_t operator in a ++ list or _a_l_i_a_s as well as in front of a Cmnd. This allows one to exclude ++ certain values. For the `!' operator to be effective, there must be ++ something for it to exclude. For example, to match all users except for ++ root one would use: ++ ++ ALL,!root ++ ++ If the AALLLL, is omitted, as in: ++ ++ !root ++ ++ it would explicitly deny root but not match any other users. This is ++ different from a true ``negation'' operator. ++ ++ Note, however, that using a `!' in conjunction with the built-in AALLLL ++ alias to allow a user to run ``all but a few'' commands rarely works as ++ intended (see _S_E_C_U_R_I_T_Y _N_O_T_E_S below). + + Long lines can be continued with a backslash (`\') as the last character + on the line. +diff -up sudo-1.8.6p3/doc/sudoers.man.in.orig sudo-1.8.6p3/doc/sudoers.man.in +--- sudo-1.8.6p3/doc/sudoers.man.in.orig 2013-07-10 13:00:20.987336061 +0200 ++++ sudo-1.8.6p3/doc/sudoers.man.in 2013-07-10 14:57:53.792093837 +0200 +@@ -1490,11 +1490,37 @@ An exclamation point + (`\&!') + can be used as a logical + \fInot\fR +-operator both in an ++operator in a list or + \fIalias\fR +-and in front of a ++as well as in front of a + \fRCmnd\fR. + This allows one to exclude certain values. ++For the ++`\&!' ++operator to be effective, there must be something for it to exclude. ++For example, to match all users except for root one would use: ++.nf ++.sp ++.RS 4n ++ALL,!root ++.RE ++.fi ++.PP ++If the ++\fBALL\fR, ++is omitted, as in: ++.nf ++.sp ++.RS 4n ++!root ++.RE ++.fi ++.PP ++it would explicitly deny root but not match any other users. ++This is different from a true ++``negation'' ++operator. ++.PP + Note, however, that using a + `\&!' + in conjunction with the built-in +diff -up sudo-1.8.6p3/doc/sudoers.mdoc.in.orig sudo-1.8.6p3/doc/sudoers.mdoc.in +--- sudo-1.8.6p3/doc/sudoers.mdoc.in.orig 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/doc/sudoers.mdoc.in 2013-07-10 14:57:53.793093839 +0200 +@@ -1393,11 +1393,31 @@ An exclamation point + .Pq Ql \&! + can be used as a logical + .Em not +-operator both in an ++operator in a list or + .Em alias +-and in front of a ++as well as in front of a + .Li Cmnd . + This allows one to exclude certain values. ++For the ++.Ql \&! ++operator to be effective, there must be something for it to exclude. ++For example, to match all users except for root one would use: ++.Bd -literal -offset 4n ++ALL,!root ++.Ed ++.Pp ++If the ++.Sy ALL , ++is omitted, as in: ++.Bd -literal -offset 4n ++!root ++.Ed ++.Pp ++it would explicitly deny root but not match any other users. ++This is different from a true ++.Dq negation ++operator. ++.Pp + Note, however, that using a + .Ql \&! + in conjunction with the built-in diff --git a/SOURCES/sudo-1.8.6p3-aliaswarnonly.patch b/SOURCES/sudo-1.8.6p3-aliaswarnonly.patch new file mode 100644 index 00000000..4f2a13b4 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-aliaswarnonly.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/visudo.c.aliaswarnonly sudo-1.8.6p3/plugins/sudoers/visudo.c +--- sudo-1.8.6p3/plugins/sudoers/visudo.c.aliaswarnonly 2012-09-25 16:19:04.995831784 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/visudo.c 2012-09-25 16:20:15.768964400 +0200 +@@ -1238,7 +1238,7 @@ check_aliases(bool strict, bool quiet) + + /* If all aliases were referenced we will have an empty tree. */ + if (!no_aliases() && !quiet) +- alias_apply(print_unused, strict ? "Error" : "Warning"); ++ alias_apply(print_unused, "Warning"); + + debug_return_int(strict ? errors : 0); + } diff --git a/SOURCES/sudo-1.8.6p3-auditeditor.patch b/SOURCES/sudo-1.8.6p3-auditeditor.patch new file mode 100644 index 00000000..db2c96fe --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-auditeditor.patch @@ -0,0 +1,29 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/sudoers.c.auditeditor sudo-1.8.6p3/plugins/sudoers/sudoers.c +--- sudo-1.8.6p3/plugins/sudoers/sudoers.c.auditeditor 2012-09-24 16:16:07.577331344 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/sudoers.c 2012-09-24 16:30:16.738174293 +0200 +@@ -709,7 +709,24 @@ sudoers_policy_main(int argc, char * con + #endif /* HAVE_SELINUX */ + + /* Must audit before uid change. */ +- audit_success(NewArgv); ++ if (ISSET(sudo_mode, MODE_EDIT)) { ++ /* ++ * Build a new argv, argc for the audit system ++ * so that the editor being invoked is visible ++ * in audit messages. ++ */ ++ char *editor = NULL; ++ char **editor_argv = NULL; ++ ++ editor = find_editor(NewArgc - 1, NewArgv + 1, &editor_argv); ++ ++ if (editor) { ++ audit_success(editor_argv); ++ efree(editor_argv); ++ } else ++ errorx(1, _("Can't find an editor")); ++ } else ++ audit_success(NewArgv); + + *command_infop = command_info; + diff --git a/SOURCES/sudo-1.8.6p3-auditrolechange.patch b/SOURCES/sudo-1.8.6p3-auditrolechange.patch new file mode 100644 index 00000000..90e73316 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-auditrolechange.patch @@ -0,0 +1,45 @@ +diff -up sudo-1.8.6p3/src/selinux.c.auditrolechange sudo-1.8.6p3/src/selinux.c +--- sudo-1.8.6p3/src/selinux.c.auditrolechange 2012-09-25 16:29:58.090826474 +0200 ++++ sudo-1.8.6p3/src/selinux.c 2012-09-25 16:33:53.953084178 +0200 +@@ -63,7 +63,7 @@ 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) ++ const security_context_t new_context, const char *ttyn, int result) + { + int au_fd, rc = -1; + char *message; +@@ -80,7 +80,7 @@ audit_role_change(const security_context + easprintf(&message, "newrole: old-context=%s new-context=%s", + old_context, new_context); + rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, +- message, NULL, NULL, ttyn, 1); ++ message, NULL, NULL, ttyn, result); + if (rc <= 0) + warning(_("unable to send audit message")); + efree(message); +@@ -335,8 +335,13 @@ selinux_setup(const char *role, const ch + warningx("your old context was %s", se_state.old_context); + #endif + se_state.new_context = get_exec_context(se_state.old_context, role, type); +- if (!se_state.new_context) ++ if (!se_state.new_context) { ++#ifdef HAVE_LINUX_AUDIT ++ audit_role_change(se_state.old_context, "?", ++ se_state.ttyn, 0); ++#endif + goto done; ++ } + + if (relabel_tty(ttyn, ptyfd) < 0) { + warning(_("unable to setup tty context for %s"), se_state.new_context); +@@ -352,7 +357,7 @@ selinux_setup(const char *role, const ch + + #ifdef HAVE_LINUX_AUDIT + audit_role_change(se_state.old_context, se_state.new_context, +- se_state.ttyn); ++ se_state.ttyn, 1); + #endif + + rval = 0; diff --git a/SOURCES/sudo-1.8.6p3-authinterrupt.patch b/SOURCES/sudo-1.8.6p3-authinterrupt.patch new file mode 100644 index 00000000..18923d4c --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-authinterrupt.patch @@ -0,0 +1,26 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/auth/pam.c.authinterrupt sudo-1.8.6p3/plugins/sudoers/auth/pam.c +--- sudo-1.8.6p3/plugins/sudoers/auth/pam.c.authinterrupt 2014-05-22 13:46:31.204706184 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/auth/pam.c 2014-05-22 13:47:06.729830043 +0200 +@@ -167,13 +167,13 @@ sudo_pam_verify(struct passwd *pw, char + /* FALLTHROUGH */ + case PAM_AUTH_ERR: + case PAM_AUTHINFO_UNAVAIL: ++ case PAM_PERM_DENIED: + if (getpass_error) { + /* error or ^C from tgetpass() */ + debug_return_int(AUTH_INTR); + } + /* FALLTHROUGH */ + case PAM_MAXTRIES: +- case PAM_PERM_DENIED: + debug_return_int(AUTH_FAILURE); + default: + if ((s = pam_strerror(pamh, *pam_status))) +@@ -343,6 +343,7 @@ converse(int num_msg, PAM_CONST struct p + if (pass == NULL) { + /* Error (or ^C) reading password, don't try again. */ + getpass_error = 1; ++ ret = PAM_CONV_ERR; + #if (defined(__darwin__) || defined(__APPLE__)) && !defined(OPENPAM_VERSION) + pass = ""; + #else diff --git a/SOURCES/sudo-1.8.6p3-cycledetect.patch b/SOURCES/sudo-1.8.6p3-cycledetect.patch new file mode 100644 index 00000000..e2c9b879 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-cycledetect.patch @@ -0,0 +1,477 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/alias.c.cycledetect sudo-1.8.6p3/plugins/sudoers/alias.c +--- sudo-1.8.6p3/plugins/sudoers/alias.c.cycledetect 2012-09-18 15:56:29.000000000 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/alias.c 2013-08-09 10:52:04.785860905 +0200 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2004-2005, 2007-2011 ++ * Copyright (c) 2004-2005, 2007-2013 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any +@@ -50,7 +50,6 @@ + * Globals + */ + struct rbtree *aliases; +-unsigned int alias_seqno; + + /* + * Comparison function for the red-black tree. +@@ -76,29 +75,31 @@ alias_compare(const void *v1, const void + /* + * Search the tree for an alias with the specified name and type. + * Returns a pointer to the alias structure or NULL if not found. ++ * Caller is responsible for calling alias_put() on the returned ++ * alias to mark it as unused. + */ + struct alias * +-alias_find(char *name, int type) ++alias_get(char *name, int type) + { + struct alias key; + struct rbnode *node; + struct alias *a = NULL; +- debug_decl(alias_find, SUDO_DEBUG_ALIAS) ++ debug_decl(alias_get, SUDO_DEBUG_ALIAS) + + key.name = name; + key.type = type; + if ((node = rbfind(aliases, &key)) != NULL) { + /* +- * Compare the global sequence number with the one stored +- * in the alias. If they match then we've seen this alias +- * before and found a loop. ++ * Check whether this alias is already in use. ++ * If so, we've detected a loop. If not, set the flag, ++ * which the caller should clear with a call to alias_put(). + */ + a = node->data; +- if (a->seqno == alias_seqno) { ++ if (a->used) { + errno = ELOOP; + debug_return_ptr(NULL); + } +- a->seqno = alias_seqno; ++ a->used = true; + } else { + errno = ENOENT; + } +@@ -106,6 +107,17 @@ alias_find(char *name, int type) + } + + /* ++ * Clear the "used" flag in an alias once the caller is done with it. ++ */ ++void ++alias_put(struct alias *a) ++{ ++ debug_decl(alias_put, SUDO_DEBUG_ALIAS) ++ a->used = false; ++ debug_return; ++} ++ ++/* + * Add an alias to the aliases redblack tree. + * Returns NULL on success and an error string on failure. + */ +@@ -119,7 +131,7 @@ alias_add(char *name, int type, struct m + a = ecalloc(1, sizeof(*a)); + a->name = name; + a->type = type; +- /* a->seqno = 0; */ ++ /* a->used = false; */ + list2tq(&a->members, members); + if (rbinsert(aliases, a)) { + snprintf(errbuf, sizeof(errbuf), _("Alias `%s' already defined"), name); +diff -up sudo-1.8.6p3/plugins/sudoers/match.c.cycledetect sudo-1.8.6p3/plugins/sudoers/match.c +--- sudo-1.8.6p3/plugins/sudoers/match.c.cycledetect 2013-08-09 10:52:04.783860895 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/match.c 2013-08-09 10:52:04.785860905 +0200 +@@ -101,13 +101,13 @@ static bool command_matches_normal(char + * Check for user described by pw in a list of members. + * Returns ALLOW, DENY or UNSPEC. + */ +-static int +-_userlist_matches(struct passwd *pw, struct member_list *list) ++int ++userlist_matches(struct passwd *pw, struct member_list *list) + { + struct member *m; + struct alias *a; + int rval, matched = UNSPEC; +- debug_decl(_userlist_matches, SUDO_DEBUG_MATCH) ++ debug_decl(userlist_matches, SUDO_DEBUG_MATCH) + + tq_foreach_rev(list, m) { + switch (m->type) { +@@ -123,10 +123,11 @@ _userlist_matches(struct passwd *pw, str + matched = !m->negated; + break; + case ALIAS: +- if ((a = alias_find(m->name, USERALIAS)) != NULL) { +- rval = _userlist_matches(pw, &a->members); ++ if ((a = alias_get(m->name, USERALIAS)) != NULL) { ++ rval = userlist_matches(pw, &a->members); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; ++ alias_put(a); + break; + } + /* FALLTHROUGH */ +@@ -141,20 +142,13 @@ _userlist_matches(struct passwd *pw, str + debug_return_bool(matched); + } + +-int +-userlist_matches(struct passwd *pw, struct member_list *list) +-{ +- alias_seqno++; +- return _userlist_matches(pw, list); +-} +- + /* + * Check for user described by pw in a list of members. + * If both lists are empty compare against def_runas_default. + * Returns ALLOW, DENY or UNSPEC. + */ +-static int +-_runaslist_matches(struct member_list *user_list, ++int ++runaslist_matches(struct member_list *user_list, + struct member_list *group_list, struct member **matching_user, + struct member **matching_group) + { +@@ -163,7 +157,7 @@ _runaslist_matches(struct member_list *u + int rval; + int user_matched = UNSPEC; + int group_matched = UNSPEC; +- debug_decl(_runaslist_matches, SUDO_DEBUG_MATCH) ++ debug_decl(runaslist_matches, SUDO_DEBUG_MATCH) + + if (runas_pw != NULL) { + /* If no runas user or runas group listed in sudoers, use default. */ +@@ -184,11 +178,12 @@ _runaslist_matches(struct member_list *u + user_matched = !m->negated; + break; + case ALIAS: +- if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { +- rval = _runaslist_matches(&a->members, &empty, ++ if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { ++ rval = runaslist_matches(&a->members, &empty, + matching_user, NULL); + if (rval != UNSPEC) + user_matched = m->negated ? !rval : rval; ++ alias_put(a); + break; + } + /* FALLTHROUGH */ +@@ -221,11 +216,12 @@ _runaslist_matches(struct member_list *u + group_matched = !m->negated; + break; + case ALIAS: +- if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { +- rval = _runaslist_matches(&empty, &a->members, ++ if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { ++ rval = runaslist_matches(&empty, &a->members, + NULL, matching_group); + if (rval != UNSPEC) + group_matched = m->negated ? !rval : rval; ++ alias_put(a); + break; + } + /* FALLTHROUGH */ +@@ -253,27 +249,17 @@ _runaslist_matches(struct member_list *u + debug_return_int(UNSPEC); + } + +-int +-runaslist_matches(struct member_list *user_list, +- struct member_list *group_list, struct member **matching_user, +- struct member **matching_group) +-{ +- alias_seqno++; +- return _runaslist_matches(user_list ? user_list : &empty, +- group_list ? group_list : &empty, matching_user, matching_group); +-} +- + /* + * Check for host and shost in a list of members. + * Returns ALLOW, DENY or UNSPEC. + */ +-static int +-_hostlist_matches(struct member_list *list) ++int ++hostlist_matches(struct member_list *list) + { + struct member *m; + struct alias *a; + int rval, matched = UNSPEC; +- debug_decl(_hostlist_matches, SUDO_DEBUG_MATCH) ++ debug_decl(hostlist_matches, SUDO_DEBUG_MATCH) + + tq_foreach_rev(list, m) { + switch (m->type) { +@@ -289,10 +275,11 @@ _hostlist_matches(struct member_list *li + matched = !m->negated; + break; + case ALIAS: +- if ((a = alias_find(m->name, HOSTALIAS)) != NULL) { +- rval = _hostlist_matches(&a->members); ++ if ((a = alias_get(m->name, HOSTALIAS)) != NULL) { ++ rval = hostlist_matches(&a->members); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; ++ alias_put(a); + break; + } + /* FALLTHROUGH */ +@@ -307,23 +294,16 @@ _hostlist_matches(struct member_list *li + debug_return_bool(matched); + } + +-int +-hostlist_matches(struct member_list *list) +-{ +- alias_seqno++; +- return _hostlist_matches(list); +-} +- + /* + * Check for cmnd and args in a list of members. + * Returns ALLOW, DENY or UNSPEC. + */ +-static int +-_cmndlist_matches(struct member_list *list) ++int ++cmndlist_matches(struct member_list *list) + { + struct member *m; + int matched = UNSPEC; +- debug_decl(_cmndlist_matches, SUDO_DEBUG_MATCH) ++ debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH) + + tq_foreach_rev(list, m) { + matched = cmnd_matches(m); +@@ -333,13 +313,6 @@ _cmndlist_matches(struct member_list *li + debug_return_bool(matched); + } + +-int +-cmndlist_matches(struct member_list *list) +-{ +- alias_seqno++; +- return _cmndlist_matches(list); +-} +- + /* + * Check cmnd and args. + * Returns ALLOW, DENY or UNSPEC. +@@ -357,11 +330,11 @@ cmnd_matches(struct member *m) + matched = !m->negated; + break; + case ALIAS: +- alias_seqno++; +- if ((a = alias_find(m->name, CMNDALIAS)) != NULL) { +- rval = _cmndlist_matches(&a->members); ++ if ((a = alias_get(m->name, CMNDALIAS)) != NULL) { ++ rval = cmndlist_matches(&a->members); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; ++ alias_put(a); + } + break; + case COMMAND: +diff -up sudo-1.8.6p3/plugins/sudoers/parse.c.cycledetect sudo-1.8.6p3/plugins/sudoers/parse.c +--- sudo-1.8.6p3/plugins/sudoers/parse.c.cycledetect 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/parse.c 2013-08-09 10:52:04.785860905 +0200 +@@ -676,13 +676,14 @@ _print_member(struct lbuf *lbuf, char *n + } + break; + case ALIAS: +- if ((a = alias_find(name, alias_type)) != NULL) { ++ if ((a = alias_get(name, alias_type)) != NULL) { + tq_foreach_fwd(&a->members, m) { + if (m != tq_first(&a->members)) + lbuf_append(lbuf, ", "); + _print_member(lbuf, m->name, m->type, + negated ? !m->negated : m->negated, alias_type); + } ++ alias_put(a); + break; + } + /* FALLTHROUGH */ +@@ -697,6 +698,5 @@ static void + print_member(struct lbuf *lbuf, char *name, int type, int negated, + int alias_type) + { +- alias_seqno++; + _print_member(lbuf, name, type, negated, alias_type); + } +diff -up sudo-1.8.6p3/plugins/sudoers/parse.h.cycledetect sudo-1.8.6p3/plugins/sudoers/parse.h +--- sudo-1.8.6p3/plugins/sudoers/parse.h.cycledetect 2012-09-18 15:56:29.000000000 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/parse.h 2013-08-09 10:54:30.984565529 +0200 +@@ -148,7 +148,7 @@ struct runascontainer { + struct alias { + char *name; /* alias name */ + unsigned short type; /* {USER,HOST,RUNAS,CMND}ALIAS */ +- unsigned short seqno; /* sequence number */ ++ bool used; /* "used" flag for cycle detection */ + struct member_list members; /* list of alias members */ + }; + +@@ -170,35 +170,39 @@ struct defaults { + extern struct userspec_list userspecs; + extern struct defaults_list defaults; + +-/* +- * Alias sequence number to avoid loops. +- */ +-extern unsigned int alias_seqno; +- +-/* +- * Prototypes +- */ +-char *alias_add(char *, int, struct member *); +-bool addr_matches(char *); +-int cmnd_matches(struct member *); +-int cmndlist_matches(struct member_list *); +-bool command_matches(char *, char *); +-int hostlist_matches(struct member_list *); +-bool hostname_matches(char *, char *, char *); +-bool netgr_matches(char *, char *, char *, char *); ++/* alias.c */ + bool no_aliases(void); +-int runaslist_matches(struct member_list *, struct member_list *, struct member **, struct member **); +-int userlist_matches(struct passwd *, struct member_list *); +-bool usergr_matches(char *, char *, struct passwd *); +-bool userpw_matches(char *, char *, struct passwd *); +-bool group_matches(char *, struct group *); +-struct alias *alias_find(char *, int); +-struct alias *alias_remove(char *, int); +-void alias_free(void *); +-void alias_apply(int (*)(void *, void *), void *); ++char *alias_add(char *name, int type, struct member *members); ++int alias_compare(const void *a1, const void *a2); ++struct alias *alias_get(char *name, int type); ++struct alias *alias_remove(char *name, int type); ++void alias_apply(int (*func)(void *, void *), void *cookie); ++void alias_free(void *a); ++void alias_put(struct alias *a); + void init_aliases(void); +-void init_lexer(void); ++/* gram.c */ + void init_parser(const char *, bool); +-int alias_compare(const void *, const void *); ++ ++/* match_addr.c */ ++bool addr_matches(char *n); ++ ++/* match.c */ ++bool command_matches(char *sudoers_cmnd, char *sudoers_args); ++bool group_matches(char *sudoers_group, struct group *gr); ++bool hostname_matches(char *shost, char *lhost, char *pattern); ++bool netgr_matches(char *netgr, char *lhost, char *shost, char *user); ++bool usergr_matches(char *group, char *user, struct passwd *pw); ++bool userpw_matches(char *sudoers_user, char *user, struct passwd *pw); ++int cmnd_matches(struct member *m); ++int cmndlist_matches(struct member_list *list); ++int hostlist_matches(struct member_list *list); ++int runaslist_matches(struct member_list *user_list, struct member_list *group_list, struct member **matching_user, struct member **matching_group); ++int userlist_matches(struct passwd *pw, struct member_list *list); ++ ++/* toke.c */ ++ void init_lexer(void); ++ ++/* base64.c */ ++ size_t base64_decode(const char *str, unsigned char *dst, size_t dsize); + + #endif /* _SUDO_PARSE_H */ +diff -up sudo-1.8.6p3/plugins/sudoers/visudo.c.cycledetect sudo-1.8.6p3/plugins/sudoers/visudo.c +--- sudo-1.8.6p3/plugins/sudoers/visudo.c.cycledetect 2013-08-09 10:52:04.759860779 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/visudo.c 2013-08-09 10:52:04.786860910 +0200 +@@ -1084,7 +1084,6 @@ alias_remove_recursive(char *name, int t + } + rbinsert(alias_freelist, a); + } +- alias_seqno++; + debug_return_bool(rval); + } + +@@ -1096,12 +1095,13 @@ check_alias(char *name, int type, int st + int errors = 0; + debug_decl(check_alias, SUDO_DEBUG_ALIAS) + +- if ((a = alias_find(name, type)) != NULL) { ++ if ((a = alias_get(name, type)) != NULL) { + /* check alias contents */ + tq_foreach_fwd(&a->members, m) { + if (m->type == ALIAS) + errors += check_alias(m->name, type, strict, quiet); + } ++ alias_put(a); + } else { + if (!quiet) { + char *fmt; +@@ -1146,26 +1146,22 @@ check_aliases(bool strict, bool quiet) + tq_foreach_fwd(&userspecs, us) { + tq_foreach_fwd(&us->users, m) { + if (m->type == ALIAS) { +- alias_seqno++; + errors += check_alias(m->name, USERALIAS, strict, quiet); + } + } + tq_foreach_fwd(&us->privileges, priv) { + tq_foreach_fwd(&priv->hostlist, m) { + if (m->type == ALIAS) { +- alias_seqno++; + errors += check_alias(m->name, HOSTALIAS, strict, quiet); + } + } + tq_foreach_fwd(&priv->cmndlist, cs) { + tq_foreach_fwd(&cs->runasuserlist, m) { + if (m->type == ALIAS) { +- alias_seqno++; + errors += check_alias(m->name, RUNASALIAS, strict, quiet); + } + } + if ((m = cs->cmnd)->type == ALIAS) { +- alias_seqno++; + errors += check_alias(m->name, CMNDALIAS, strict, quiet); + } + } +@@ -1176,7 +1172,6 @@ check_aliases(bool strict, bool quiet) + tq_foreach_fwd(&userspecs, us) { + tq_foreach_fwd(&us->users, m) { + if (m->type == ALIAS) { +- alias_seqno++; + if (!alias_remove_recursive(m->name, USERALIAS)) + errors++; + } +@@ -1184,7 +1179,6 @@ check_aliases(bool strict, bool quiet) + tq_foreach_fwd(&us->privileges, priv) { + tq_foreach_fwd(&priv->hostlist, m) { + if (m->type == ALIAS) { +- alias_seqno++; + if (!alias_remove_recursive(m->name, HOSTALIAS)) + errors++; + } +@@ -1192,13 +1186,11 @@ check_aliases(bool strict, bool quiet) + tq_foreach_fwd(&priv->cmndlist, cs) { + tq_foreach_fwd(&cs->runasuserlist, m) { + if (m->type == ALIAS) { +- alias_seqno++; + if (!alias_remove_recursive(m->name, RUNASALIAS)) + errors++; + } + } + if ((m = cs->cmnd)->type == ALIAS) { +- alias_seqno++; + if (!alias_remove_recursive(m->name, CMNDALIAS)) + errors++; + } +@@ -1225,7 +1217,6 @@ check_aliases(bool strict, bool quiet) + tq_foreach_fwd(&d->binding, binding) { + for (m = binding; m != NULL; m = m->next) { + if (m->type == ALIAS) { +- alias_seqno++; + if (!alias_remove_recursive(m->name, atype)) + errors++; + } diff --git a/SOURCES/sudo-1.8.6p3-doublequotefix.patch b/SOURCES/sudo-1.8.6p3-doublequotefix.patch new file mode 100644 index 00000000..c0280171 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-doublequotefix.patch @@ -0,0 +1,46 @@ +From 1b16310c7ec5ba23fbe066c7d000016e534b4448 Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +Date: Tue, 16 Aug 2016 09:54:06 +0200 +Subject: [PATCH] Double quotes are not accepted in sudoers + +Regression in sudo 1.8.6p3-7 package, double quotes are not accepted in sudoers + +Rebased from: +Patch25: sudo-1.8.6p3-doublequotefix.patch + +Resolves: +rhbz#1092499 +--- + plugins/sudoers/toke.c | 2 +- + plugins/sudoers/toke.l | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plugins/sudoers/toke.c b/plugins/sudoers/toke.c +index e5b4d97..3b510bb 100644 +--- a/plugins/sudoers/toke.c ++++ b/plugins/sudoers/toke.c +@@ -2385,7 +2385,7 @@ YY_RULE_SETUP + LEXTRACE("ERROR "); /* empty string */ + LEXRETURN(ERROR); + } +- if (prev_state == INITIAL) { ++ if (prev_state == INITIAL || prev_state == GOTDEFS) { + switch (sudoerslval.string[0]) { + case '%': + if (sudoerslval.string[1] == '\0' || +diff --git a/plugins/sudoers/toke.l b/plugins/sudoers/toke.l +index b63edd0..82724aa 100644 +--- a/plugins/sudoers/toke.l ++++ b/plugins/sudoers/toke.l +@@ -185,7 +185,7 @@ DEFVAR [a-z_]+ + LEXTRACE("ERROR "); /* empty string */ + LEXRETURN(ERROR); + } +- if (prev_state == INITIAL) { ++ if (prev_state == INITIAL || prev_state == GOTDEFS) { + switch (sudoerslval.string[0]) { + case '%': + if (sudoerslval.string[1] == '\0' || +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.6p3-emallocfail.patch b/SOURCES/sudo-1.8.6p3-emallocfail.patch new file mode 100644 index 00000000..91792df5 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-emallocfail.patch @@ -0,0 +1,17 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.emallocfail sudo-1.8.6p3/plugins/sudoers/sssd.c +--- sudo-1.8.6p3/plugins/sudoers/sssd.c.emallocfail 2012-11-23 15:58:20.139417659 +0100 ++++ sudo-1.8.6p3/plugins/sudoers/sssd.c 2012-11-23 15:58:26.732437421 +0100 +@@ -212,7 +212,12 @@ sudo_sss_filter_result(struct sudo_sss_h + sudo_debug_printf(SUDO_DEBUG_DEBUG, + "reallocating result: %p (count: %u -> %u)", out_res->rules, + in_res->num_rules, l); +- out_res->rules = erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule)); ++ if (l > 0) ++ out_res->rules = erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule)); ++ else { ++ efree(out_res->rules); ++ out_res->rules = NULL; ++ } + } + + out_res->num_rules = l; diff --git a/SOURCES/sudo-1.8.6p3-lbufexpandcode.patch b/SOURCES/sudo-1.8.6p3-lbufexpandcode.patch new file mode 100644 index 00000000..70a4c136 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-lbufexpandcode.patch @@ -0,0 +1,138 @@ +diff -up sudo-1.8.6p3/common/lbuf.c.lbufexpandcode sudo-1.8.6p3/common/lbuf.c +--- sudo-1.8.6p3/common/lbuf.c.lbufexpandcode 2013-08-12 17:28:52.429562473 +0200 ++++ sudo-1.8.6p3/common/lbuf.c 2013-08-12 17:29:21.486668465 +0200 +@@ -77,6 +77,17 @@ lbuf_destroy(struct lbuf *lbuf) + debug_return; + } + ++static void ++lbuf_expand(struct lbuf *lbuf, size_t extra) ++{ ++ if (lbuf->len + extra + 1 >= lbuf->size) { ++ do { ++ lbuf->size += 256; ++ } while (lbuf->len + extra + 1 >= lbuf->size); ++ lbuf->buf = erealloc(lbuf->buf, lbuf->size); ++ } ++} ++ + /* + * Parse the format and append strings, only %s and %% escapes are supported. + * Any characters in set are quoted with a backslash. +@@ -86,47 +97,40 @@ lbuf_append_quoted(struct lbuf *lbuf, co + { + va_list ap; + int len; +- char *cp, *s = NULL; ++ char *cp, *s; + debug_decl(lbuf_append_quoted, SUDO_DEBUG_UTIL) + + va_start(ap, fmt); + while (*fmt != '\0') { +- len = 1; + if (fmt[0] == '%' && fmt[1] == 's') { +- s = va_arg(ap, char *); +- len = strlen(s); +- } +- /* Assume worst case that all chars must be escaped. */ +- if (lbuf->len + (len * 2) + 1 >= lbuf->size) { +- do { +- lbuf->size += 256; +- } while (lbuf->len + len + 1 >= lbuf->size); +- lbuf->buf = erealloc(lbuf->buf, lbuf->size); +- } +- if (*fmt == '%') { +- if (*(++fmt) == 's') { +- while ((cp = strpbrk(s, set)) != NULL) { +- len = (int)(cp - s); +- memcpy(lbuf->buf + lbuf->len, s, len); +- lbuf->len += len; +- lbuf->buf[lbuf->len++] = '\\'; +- lbuf->buf[lbuf->len++] = *cp; +- s = cp + 1; +- } +- if (*s != '\0') { +- len = strlen(s); +- memcpy(lbuf->buf + lbuf->len, s, len); +- lbuf->len += len; +- } +- fmt++; +- continue; ++ if ((s = va_arg(ap, char *)) == NULL) ++ goto done; ++ while ((cp = strpbrk(s, set)) != NULL) { ++ len = (int)(cp - s); ++ lbuf_expand(lbuf, len + 2); ++ memcpy(lbuf->buf + lbuf->len, s, len); ++ lbuf->len += len; ++ lbuf->buf[lbuf->len++] = '\\'; ++ lbuf->buf[lbuf->len++] = *cp; ++ s = cp + 1; + } ++ if (*s != '\0') { ++ len = strlen(s); ++ lbuf_expand(lbuf, len); ++ memcpy(lbuf->buf + lbuf->len, s, len); ++ lbuf->len += len; ++ } ++ fmt += 2; ++ continue; + } ++ lbuf_expand(lbuf, 2); + if (strchr(set, *fmt) != NULL) + lbuf->buf[lbuf->len++] = '\\'; + lbuf->buf[lbuf->len++] = *fmt++; + } +- lbuf->buf[lbuf->len] = '\0'; ++done: ++ if (lbuf->size != 0) ++ lbuf->buf[lbuf->len] = '\0'; + va_end(ap); + + debug_return; +@@ -140,33 +144,27 @@ lbuf_append(struct lbuf *lbuf, const cha + { + va_list ap; + int len; +- char *s = NULL; ++ char *s; + debug_decl(lbuf_append, SUDO_DEBUG_UTIL) + + va_start(ap, fmt); + while (*fmt != '\0') { +- len = 1; + if (fmt[0] == '%' && fmt[1] == 's') { +- s = va_arg(ap, char *); ++ if ((s = va_arg(ap, char *)) == NULL) ++ goto done; + len = strlen(s); ++ lbuf_expand(lbuf, len); ++ memcpy(lbuf->buf + lbuf->len, s, len); ++ lbuf->len += len; ++ fmt += 2; ++ continue; + } +- if (lbuf->len + len + 1 >= lbuf->size) { +- do { +- lbuf->size += 256; +- } while (lbuf->len + len + 1 >= lbuf->size); +- lbuf->buf = erealloc(lbuf->buf, lbuf->size); +- } +- if (*fmt == '%') { +- if (*(++fmt) == 's') { +- memcpy(lbuf->buf + lbuf->len, s, len); +- lbuf->len += len; +- fmt++; +- continue; +- } +- } ++ lbuf_expand(lbuf, 1); + lbuf->buf[lbuf->len++] = *fmt++; + } +- lbuf->buf[lbuf->len] = '\0'; ++done: ++ if (lbuf->size != 0) ++ lbuf->buf[lbuf->len] = '\0'; + va_end(ap); + + debug_return; diff --git a/SOURCES/sudo-1.8.6p3-ldap-sssd-usermatch.patch b/SOURCES/sudo-1.8.6p3-ldap-sssd-usermatch.patch new file mode 100644 index 00000000..1058cd27 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-ldap-sssd-usermatch.patch @@ -0,0 +1,24 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/ldap.c.usermatch sudo-1.8.6p3/plugins/sudoers/ldap.c +--- sudo-1.8.6p3/plugins/sudoers/ldap.c.usermatch 2012-11-23 15:57:00.084176086 +0100 ++++ sudo-1.8.6p3/plugins/sudoers/ldap.c 2012-11-23 15:57:21.491239877 +0100 +@@ -742,7 +742,7 @@ sudo_ldap_check_runas_user(LDAP *ld, LDA + } + /* FALLTHROUGH */ + default: +- if (strcasecmp(val, runas_pw->pw_name) == 0) ++ if (userpw_matches(val, runas_pw->pw_name, runas_pw)) + ret = true; + break; + } +diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.usermatch sudo-1.8.6p3/plugins/sudoers/sssd.c +--- sudo-1.8.6p3/plugins/sudoers/sssd.c.usermatch 2012-11-23 15:57:12.234211662 +0100 ++++ sudo-1.8.6p3/plugins/sudoers/sssd.c 2012-11-23 15:57:21.492239881 +0100 +@@ -466,7 +466,7 @@ sudo_sss_check_runas_user(struct sudo_ss + /* FALLTHROUGH */ + sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH"); + default: +- if (strcasecmp(val, runas_pw->pw_name) == 0) { ++ if (userpw_matches(val, runas_pw->pw_name, runas_pw)) { + sudo_debug_printf(SUDO_DEBUG_DEBUG, + "%s == %s (pw_name) => match", val, runas_pw->pw_name); + ret = true; diff --git a/SOURCES/sudo-1.8.6p3-ldapconfparse.patch b/SOURCES/sudo-1.8.6p3-ldapconfparse.patch new file mode 100644 index 00000000..b73ae0f7 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-ldapconfparse.patch @@ -0,0 +1,45 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/ldap.c.confparse sudo-1.8.6p3/plugins/sudoers/ldap.c +--- sudo-1.8.6p3/plugins/sudoers/ldap.c.confparse 2012-11-23 15:46:41.801008370 +0100 ++++ sudo-1.8.6p3/plugins/sudoers/ldap.c 2012-11-23 15:46:07.903885738 +0100 +@@ -1343,6 +1343,32 @@ sudo_ldap_parse_keyword(const char *keyw + debug_return_bool(false); + } + ++/* ++ * Read a line of input, remove whole line comments and strip off leading ++ * and trailing spaces. Returns static storage that is reused. ++ */ ++static char * ++sudo_ldap_parseln(FILE *fp) ++{ ++ size_t len; ++ char *cp = NULL; ++ static char buf[LINE_MAX]; ++ ++ if (fgets(buf, sizeof(buf), fp) != NULL) { ++ /* Remove comments */ ++ if (*buf == '#') ++ *buf = '\0'; ++ ++ /* Trim leading and trailing whitespace/newline */ ++ len = strlen(buf); ++ while (len > 0 && isspace((unsigned char)buf[len - 1])) ++ buf[--len] = '\0'; ++ for (cp = buf; isblank(*cp); cp++) ++ continue; ++ } ++ return(cp); ++} ++ + static bool + sudo_ldap_read_config(void) + { +@@ -1364,7 +1390,7 @@ sudo_ldap_read_config(void) + if ((fp = fopen(_PATH_LDAP_CONF, "r")) == NULL) + debug_return_bool(false); + +- while ((cp = sudo_parseln(fp)) != NULL) { ++ while ((cp = sudo_ldap_parseln(fp)) != NULL) { + if (*cp == '\0') + continue; /* skip empty line */ + diff --git a/SOURCES/sudo-1.8.6p3-mantypo.patch b/SOURCES/sudo-1.8.6p3-mantypo.patch new file mode 100644 index 00000000..8b79d91e --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-mantypo.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p3/doc/sudoers.man.in.mantypo sudo-1.8.6p3/doc/sudoers.man.in +--- sudo-1.8.6p3/doc/sudoers.man.in.mantypo 2012-09-24 16:38:33.946465411 +0200 ++++ sudo-1.8.6p3/doc/sudoers.man.in 2012-09-24 16:39:01.400941691 +0200 +@@ -1408,7 +1408,7 @@ to include the file + The + \fR#includedir\fR + directive can be used to create a +-\fIsudo.d\fR ++\fIsudoers.d\fR + directory that the system package manager can drop + \fIsudoers\fR + rules diff --git a/SOURCES/sudo-1.8.6p3-mantypos-ldap.patch b/SOURCES/sudo-1.8.6p3-mantypos-ldap.patch new file mode 100644 index 00000000..57fbfba0 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-mantypos-ldap.patch @@ -0,0 +1,74 @@ +diff -up sudo-1.8.6p3/doc/sudoers.ldap.cat.mantypos-ldap sudo-1.8.6p3/doc/sudoers.ldap.cat +--- sudo-1.8.6p3/doc/sudoers.ldap.cat.mantypos-ldap 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/doc/sudoers.ldap.cat 2015-04-16 11:24:08.277692534 +0200 +@@ -119,7 +119,7 @@ DDEESSCCRRIIPPTTIIOONN + ssuuddooNNoottAAfftteerr + A timestamp in the form yyyymmddHHMMSSZ that indicates an + expiration date/time, after which the sudoRole will no longer be +- valid. If multiple sudoNotBefore entries are present, the last one ++ valid. If multiple sudoNotAfter entries are present, the last one + is used. Note that timestamps must be in Coordinated Universal + Time (UTC), not the local timezone. The minute and seconds + portions are optional, but some LDAP servers require that they be +@@ -134,8 +134,8 @@ DDEESSCCRRIIPPTTIIOONN + inherent order. The sudoOrder attribute is an integer (or floating + point value for LDAP servers that support it) that is used to sort + the matching entries. This allows LDAP-based sudoers entries to +- more closely mimic the behaviour of the sudoers file, where the of +- the entries influences the result. If multiple entries match, the ++ more closely mimic the behaviour of the sudoers file, where the order ++ of the entries influences the result. If multiple entries match, the + entry with the highest sudoOrder attribute is chosen. This + corresponds to the ``last match'' behavior of the sudoers file. If + the sudoOrder attribute is not present, a value of 0 is assumed. +diff -up sudo-1.8.6p3/doc/sudoers.ldap.man.in.mantypos-ldap sudo-1.8.6p3/doc/sudoers.ldap.man.in +--- sudo-1.8.6p3/doc/sudoers.ldap.man.in.mantypos-ldap 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/doc/sudoers.ldap.man.in 2015-04-16 11:24:08.277692534 +0200 +@@ -238,7 +238,7 @@ that indicates an expiration date/time, + \fRsudoRole\fR + will no longer be valid. + If multiple +-\fRsudoNotBefore\fR ++\fRsudoNotAfter\fR + entries are present, the last one is used. + Note that timestamps must be in Coordinated Universal Time (UTC), + not the local timezone. +@@ -264,7 +264,7 @@ The + attribute is an integer (or floating point value for LDAP servers + that support it) that is used to sort the matching entries. + This allows LDAP-based sudoers entries to more closely mimic the behaviour +-of the sudoers file, where the of the entries influences the result. ++of the sudoers file, where the order of the entries influences the result. + If multiple entries match, the entry with the highest + \fRsudoOrder\fR + attribute is chosen. +diff -up sudo-1.8.6p3/doc/sudoers.ldap.mdoc.in.mantypos-ldap sudo-1.8.6p3/doc/sudoers.ldap.mdoc.in +--- sudo-1.8.6p3/doc/sudoers.ldap.mdoc.in.mantypos-ldap 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/doc/sudoers.ldap.mdoc.in 2015-04-16 11:32:51.574469447 +0200 +@@ -15,7 +15,7 @@ + .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + .\" + .Dd July 12, 2012 +-.Dt SUDOERS.LDAP @mansectsu@ ++.Dt SUDOERS.LDAP @mansectform@ + .Os Sudo @PACKAGE_VERSION@ + .Sh NAME + .Nm sudoers.ldap +@@ -224,7 +224,7 @@ that indicates an expiration date/time, + .Li sudoRole + will no longer be valid. + If multiple +-.Li sudoNotBefore ++.Li sudoNotAfter + entries are present, the last one is used. + Note that timestamps must be in Coordinated Universal Time (UTC), + not the local timezone. +@@ -249,7 +249,7 @@ The + attribute is an integer (or floating point value for LDAP servers + that support it) that is used to sort the matching entries. + This allows LDAP-based sudoers entries to more closely mimic the behaviour +-of the sudoers file, where the of the entries influences the result. ++of the sudoers file, where the order of the entries influences the result. + If multiple entries match, the entry with the highest + .Li sudoOrder + attribute is chosen. diff --git a/SOURCES/sudo-1.8.6p3-netgrfilterfix.patch b/SOURCES/sudo-1.8.6p3-netgrfilterfix.patch new file mode 100644 index 00000000..0118511a --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-netgrfilterfix.patch @@ -0,0 +1,92 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.netgrfilterfix sudo-1.8.6p3/plugins/sudoers/sssd.c +--- sudo-1.8.6p3/plugins/sudoers/sssd.c.netgrfilterfix 2014-07-30 13:29:47.713823996 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/sssd.c 2014-07-30 13:30:08.917436088 +0200 +@@ -614,16 +615,13 @@ sudo_sss_check_host(struct sudo_sss_hand + } + + /* +- * Look for netgroup specifcations in the sudoUser attribute and +- * if found, filter according to netgroup membership. +- * returns: +- * true -> netgroup spec found && negroup member +- * false -> netgroup spec found && not a meber of netgroup +- * true -> netgroup spec not found (filtered by SSSD already, netgroups are an exception) ++ * SSSD doesn't handle netgroups, we have to ensure they are correctly filtered ++ * in sudo. The rules may contain mixed sudoUser specification so we have to check ++ * not only for netgroup membership but also for user and group matches. + */ +-bool sudo_sss_filter_user_netgroup(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) ++bool sudo_sss_filter_sudoUser(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) + { +- bool ret = false, netgroup_spec_found = false; ++ bool ret = false; + char **val_array, *val; + int i; + debug_decl(sudo_sss_check_user_netgroup, SUDO_DEBUG_SSSD); +@@ -641,21 +639,48 @@ bool sudo_sss_filter_user_netgroup(struc + sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoUser): != 0"); + debug_return_bool(ret); + } +- ++ /* ++ * Scan sudoUser values and look for netgroup specs. ++ * Netgroup-only rule specification should be filtered ++ * out if the user isn't member of any specified netgroup. ++ */ + for (i = 0; val_array[i] != NULL && !ret; ++i) { + val = val_array[i]; +- if (*val == '+') { +- netgroup_spec_found = true; +- } + sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val); +- if (strcmp(val, "ALL") == 0 || netgr_matches(val, NULL, NULL, user_name)) { +- ret = true; +- sudo_debug_printf(SUDO_DEBUG_DIAG, +- "sssd/ldap sudoUser '%s' ... MATCH! (%s)", val, user_name); ++ if (*val == '+') { ++ /* Netgroup spec found, check netgroup membership */ ++ if (netgr_matches(val, NULL, NULL, handle->pw->pw_name)) { ++ ret = true; ++ sudo_debug_printf(SUDO_DEBUG_DIAG, ++ "sssd/ldap sudoUser '%s' ... MATCH! (%s)", val, handle->pw->pw_name); ++ } ++ } else { ++ /* ++ * Non-netgroup sudoUser value ++ */ ++ if (strcmp(val, "ALL") == 0) { ++ ret = true; ++ } else { ++ const char *match_val = (*val == '!' ? val + 1 : val); ++ const bool negated = (*val == '!' ? true : false); ++ const bool group_spec = (*match_val == '%' ? true : false); ++ ++ if (group_spec) { ++ if (usergr_matches(match_val, ++ handle->pw->pw_name, handle->pw)) { ++ ret = !negated; ++ } ++ } else { ++ if (userpw_matches(match_val, ++ handle->pw->pw_name, handle->pw)) { ++ ret = !negated; ++ } ++ } ++ } + } + } + handle->fn_free_values(val_array); +- debug_return_bool(netgroup_spec_found ? ret : true); ++ debug_return_bool(ret); + } + + static int +@@ -666,7 +691,7 @@ sudo_sss_result_filterp(struct sudo_sss_ + debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD); + + if (sudo_sss_check_host(handle, rule) && +- sudo_sss_filter_user_netgroup(handle, rule)) ++ sudo_sss_filter_sudoUser(handle, rule)) + debug_return_int(1); + else + debug_return_int(0); diff --git a/SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch b/SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch new file mode 100644 index 00000000..010699dc --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch @@ -0,0 +1,56 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/match.c.netgrmatchtrace sudo-1.8.6p3/plugins/sudoers/match.c +--- sudo-1.8.6p3/plugins/sudoers/match.c.netgrmatchtrace 2013-08-12 14:42:56.498247674 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/match.c 2013-08-12 14:43:01.009264127 +0200 +@@ -713,6 +713,10 @@ netgr_matches(char *netgr, char *lhost, + #ifdef HAVE_GETDOMAINNAME + static int initialized; + #endif ++#ifdef HAVE_INNETGR ++ bool innetgr_lhost = false; ++ bool innetgr_shost = false; ++#endif + debug_decl(netgr_matches, SUDO_DEBUG_MATCH) + + /* make sure we have a valid netgroup, sudo style */ +@@ -733,9 +737,39 @@ netgr_matches(char *netgr, char *lhost, + + #ifdef HAVE_INNETGR + if (innetgr(netgr, lhost, user, domain)) +- debug_return_bool(true); ++ innetgr_lhost = true; + else if (lhost != shost && innetgr(netgr, shost, user, domain)) +- debug_return_bool(true); ++ innetgr_shost = true; ++ ++ if (innetgr_lhost) { ++ sudo_debug_printf(SUDO_DEBUG_TRACE, ++ "(%s, %s, %s) found in netgroup %s\n", ++ shost ? shost : "*", ++ user ? user : "*", ++ domain ? domain : "*", ++ netgr); ++ } else if (innetgr_shost) { ++ sudo_debug_printf(SUDO_DEBUG_TRACE, ++ "(%s, %s, %s) found in netgroup %s\n", ++ lhost ? lhost : "*", ++ user ? user : "*", ++ domain ? domain : "*", ++ netgr); ++ } else { ++ sudo_debug_printf(SUDO_DEBUG_TRACE, ++ "(%s, %s, %s) NOT found in netgroup %s\n", ++ shost ? shost : "*", ++ user ? user : "*", ++ domain ? domain : "*", ++ netgr); ++ sudo_debug_printf(SUDO_DEBUG_TRACE, ++ "(%s, %s, %s) NOT found in netgroup %s\n", ++ lhost ? lhost : "*", ++ user ? user : "*", ++ domain ? domain : "*", ++ netgr); ++ } ++ debug_return_bool(innetgr_lhost || innetgr_shost); + #endif /* HAVE_INNETGR */ + + debug_return_bool(false); diff --git a/SOURCES/sudo-1.8.6p3-nonehostname.patch b/SOURCES/sudo-1.8.6p3-nonehostname.patch new file mode 100644 index 00000000..5e170d2d --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-nonehostname.patch @@ -0,0 +1,13 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/match.c.nonehostname sudo-1.8.6p3/plugins/sudoers/match.c +--- sudo-1.8.6p3/plugins/sudoers/match.c.nonehostname 2014-05-19 12:50:08.412313041 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/match.c 2014-05-19 12:50:17.787348134 +0200 +@@ -727,7 +727,8 @@ netgr_matches(char *netgr, char *lhost, + /* get the domain name (if any) */ + if (!initialized) { + domain = (char *) emalloc(MAXHOSTNAMELEN + 1); +- if (getdomainname(domain, MAXHOSTNAMELEN + 1) == -1 || *domain == '\0') { ++ if (getdomainname(domain, MAXHOSTNAMELEN + 1) == -1 || *domain == '\0' ++ || strncmp (domain, "(none)", 7) == 0) { + efree(domain); + domain = NULL; + } diff --git a/SOURCES/sudo-1.8.6p3-nowaitopt.patch b/SOURCES/sudo-1.8.6p3-nowaitopt.patch new file mode 100644 index 00000000..df515002 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-nowaitopt.patch @@ -0,0 +1,161 @@ +From 9b1f0f16bfe7552810b4adb6b17ac3674da660f9 Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +Date: Mon, 15 Aug 2016 15:13:31 +0200 +Subject: [PATCH] Backport direct exec of command from sudo + +Added cmnd_no_wait option +Sudo does not run command in a new child process, +when cmnd_no_wait is enabled. + +!!! +Upstream can do that too now in 1.8.17 with combination of +pam_session, pam_setcred and use_pty option. +They must be disabled and I/O logging must not be configured. +See "man sudoers". + +rebased from: +Patch8: sudo-1.8.6p3-nowaitopt.patch + +Resolves: +rhbz#840980 +--- + plugins/sudoers/def_data.c | 4 ++++ + plugins/sudoers/def_data.h | 2 ++ + plugins/sudoers/def_data.in | 3 +++ + plugins/sudoers/policy.c | 4 ++++ + src/exec.c | 34 ++++++++++++++++++++++++++++++++++ + src/sudo.c | 5 +++++ + src/sudo.h | 1 + + 7 files changed, 53 insertions(+) + +diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c +index 00caa8b..d8b1ada 100644 +--- a/plugins/sudoers/def_data.c ++++ b/plugins/sudoers/def_data.c +@@ -435,6 +435,10 @@ struct sudo_defs_types sudo_defs_table[] = { + N_("File mode to use for the I/O log files: 0%o"), + 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 --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h +index d83d2c3..1b6be3d 100644 +--- a/plugins/sudoers/def_data.h ++++ b/plugins/sudoers/def_data.h +@@ -204,6 +204,8 @@ + #define def_iolog_group (sudo_defs_table[I_IOLOG_GROUP].sd_un.str) + #define I_IOLOG_MODE 102 + #define def_iolog_mode (sudo_defs_table[I_IOLOG_MODE].sd_un.mode) ++#define I_CMND_NO_WAIT 103 ++#define def_cmnd_no_wait (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag) + + enum def_tuple { + never, +diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in +index 9f069f1..5200fe3 100644 +--- a/plugins/sudoers/def_data.in ++++ b/plugins/sudoers/def_data.in +@@ -322,3 +322,6 @@ iolog_group + iolog_mode + T_MODE + "File mode to use for the I/O log files: 0%o" ++cmnd_no_wait ++ T_FLAG ++ "Don't fork and wait for the command to finish, just exec it" +diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c +index 4ee1e28..93df1dd 100644 +--- a/plugins/sudoers/policy.c ++++ b/plugins/sudoers/policy.c +@@ -564,6 +564,10 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask, + if ((command_info[info_len++] = strdup("use_pty=true")) == NULL) + goto oom; + } ++ if (def_cmnd_no_wait) { ++ if ((command_info[info_len++] = strdup("cmnd_no_wait=true")) == NULL) ++ goto oom; ++ } + if (def_utmp_runas) { + if ((command_info[info_len++] = sudo_new_key_val("utmp_user", runas_pw->pw_name)) == NULL) + goto oom; +diff --git a/src/exec.c b/src/exec.c +index 56da013..08bc86d 100644 +--- a/src/exec.c ++++ b/src/exec.c +@@ -384,6 +384,41 @@ sudo_execute(struct command_details *details, struct command_status *cstat) + } + + /* ++ * If we don't want to wait for the command to exit, then just exec it. ++ * THIS WILL BREAK SEVERAL THINGS including SELinux, PAM sessions and I/O ++ * logging. Implemented because of rhbz#840980 (backwards compatibility). ++ * In 1.8.x branch this is even harder to get back, since the nowait code ++ * was completely removed. ++ */ ++ if (details->flags & CD_DONTWAIT) { ++ if (exec_setup(details, NULL, -1) == true) { ++ restore_signals(); ++ /* headed for execve() */ ++ sudo_debug_execve(SUDO_DEBUG_INFO, details->command, ++ details->argv, details->envp); ++ if (details->closefrom >= 0) { ++ closefrom(details->closefrom); ++ } ++#ifdef HAVE_SELINUX ++ if (ISSET(details->flags, CD_RBAC_ENABLED)) { ++ selinux_execve(-1, details->command, details->argv, details->envp, ++ ISSET(details->flags, CD_NOEXEC)); ++ } else ++#endif ++ { ++ sudo_execve(-1, details->command, details->argv, details->envp, ++ ISSET(details->flags, CD_NOEXEC)); ++ } ++ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s", ++ details->command, strerror(errno)); ++ } ++ cstat->type = CMD_ERRNO; ++ cstat->val = errno; ++ return 127; ++ } ++ ++ ++ /* + * We communicate with the child over a bi-directional pair of sockets. + * Parent sends signal info to child and child sends back wait status. + */ +diff --git a/src/sudo.c b/src/sudo.c +index 5dd090d..0606a19 100644 +--- a/src/sudo.c ++++ b/src/sudo.c +@@ -670,6 +670,11 @@ command_info_to_details(char * const info[], struct command_details *details) + sudo_fatalx(U_("%s: %s"), info[i], U_(errstr)); + break; + } ++ if (strncmp("cmnd_no_wait=", info[i], sizeof("cmnd_no_wait=") - 1) == 0) { ++ if (sudo_strtobool(info[i] + sizeof("cmnd_no_wait=") - 1) == true) ++ SET(details->flags, CD_DONTWAIT); ++ break; ++ } + break; + case 'e': + SET_FLAG("exec_background=", CD_EXEC_BG) +diff --git a/src/sudo.h b/src/sudo.h +index 3ac2c9d..f07ba11 100644 +--- a/src/sudo.h ++++ b/src/sudo.h +@@ -130,6 +130,7 @@ struct user_details { + #define CD_SUDOEDIT_FOLLOW 0x10000 + #define CD_SUDOEDIT_CHECKDIR 0x20000 + #define CD_SET_GROUPS 0x40000 ++#define CD_DONTWAIT 0x80000 + + struct preserved_fd { + TAILQ_ENTRY(preserved_fd) entries; +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.6p3-nprocfix.patch b/SOURCES/sudo-1.8.6p3-nprocfix.patch new file mode 100644 index 00000000..5ffd56be --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-nprocfix.patch @@ -0,0 +1,117 @@ +diff -up sudo-1.8.6p3/src/exec.c.nprocfix sudo-1.8.6p3/src/exec.c +--- sudo-1.8.6p3/src/exec.c.nprocfix 2013-07-11 12:55:10.686308050 +0200 ++++ sudo-1.8.6p3/src/exec.c 2013-07-11 12:54:21.159160553 +0200 +@@ -132,6 +132,15 @@ static int fork_cmnd(struct command_deta + if (policy_init_session(details) != true) + errorx(1, _("policy plugin failed session initialization")); + ++ /* ++ * See the comment in unlimit_nproc. It is important to call ++ * this function AFTER policy_init_session, because the PAM ++ * subsystem, if used, may change the RLIMIT_NPROC limit to ++ * unlimited (infinity) and we would not be able to distinguish ++ * between our temporary change and the change done by PAM. ++ */ ++ unlimit_nproc(); ++ + cmnd_pid = sudo_debug_fork(); + switch (cmnd_pid) { + case -1: +diff -up sudo-1.8.6p3/src/exec_pty.c.nprocfix sudo-1.8.6p3/src/exec_pty.c +--- sudo-1.8.6p3/src/exec_pty.c.nprocfix 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/src/exec_pty.c 2013-07-11 12:37:41.811202301 +0200 +@@ -678,6 +678,15 @@ fork_pty(struct command_details *details + errorx(1, _("policy plugin failed session initialization")); + + /* ++ * See the comment in unlimit_nproc. It is important to call ++ * this function AFTER policy_init_session, because the PAM ++ * subsystem, if used, may change the RLIMIT_NPROC limit to ++ * unlimited (infinity) and we would not be able to distinguish ++ * between our temporary change and the change done by PAM. ++ */ ++ unlimit_nproc(); ++ ++ /* + * Block some signals until cmnd_pid is set in the parent to avoid a + * race between exec of the command and receipt of a fatal signal from it. + */ +diff -up sudo-1.8.6p3/src/sudo.c.nprocfix sudo-1.8.6p3/src/sudo.c +--- sudo-1.8.6p3/src/sudo.c.nprocfix 2013-07-11 12:37:41.767202170 +0200 ++++ sudo-1.8.6p3/src/sudo.c 2013-07-11 12:37:41.811202301 +0200 +@@ -808,25 +808,11 @@ sudo_check_suid(const char *path) + static void + disable_coredumps(void) + { +-#if defined(__linux__) || defined(RLIMIT_CORE) +- struct rlimit rl; ++#if defined(RLIMIT_CORE) ++ struct rlimit rl; + #endif + debug_decl(disable_coredumps, SUDO_DEBUG_UTIL) + +-#if defined(__linux__) +- /* +- * Unlimit the number of processes since Linux's setuid() will +- * apply resource limits when changing uid and return EAGAIN if +- * nproc would be violated by the uid switch. +- */ +- (void) getrlimit(RLIMIT_NPROC, &nproclimit); +- rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; +- if (setrlimit(RLIMIT_NPROC, &rl)) { +- memcpy(&rl, &nproclimit, sizeof(struct rlimit)); +- rl.rlim_cur = rl.rlim_max; +- (void)setrlimit(RLIMIT_NPROC, &rl); +- } +-#endif /* __linux__ */ + #ifdef RLIMIT_CORE + /* + * Turn off core dumps? +@@ -841,6 +827,28 @@ disable_coredumps(void) + debug_return; + } + ++void ++unlimit_nproc(void) ++{ ++ debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL) ++#if defined(__linux__) ++ struct rlimit rl; ++ /* ++ * Unlimit the number of processes since Linux's setuid() will ++ * apply resource limits when changing uid and return EAGAIN if ++ * nproc would be violated by the uid switch. ++ */ ++ (void) getrlimit(RLIMIT_NPROC, &nproclimit); ++ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; ++ if (setrlimit(RLIMIT_NPROC, &rl)) { ++ memcpy(&rl, &nproclimit, sizeof(struct rlimit)); ++ rl.rlim_cur = rl.rlim_max; ++ (void)setrlimit(RLIMIT_NPROC, &rl); ++ } ++#endif /* __linux__ */ ++ debug_return; ++} ++ + #ifdef HAVE_PROJECT_H + static void + set_project(struct passwd *pw) +@@ -1082,7 +1090,6 @@ exec_setup(struct command_details *detai + errno = 0; + l = sysconf(_SC_CHILD_MAX); + if (l == -1 && errno == 0 && getrlimit(RLIMIT_NPROC, &rl) == 0) { +- if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY) + (void) setrlimit(RLIMIT_NPROC, &nproclimit); + } + } +diff -up sudo-1.8.6p3/src/sudo.h.nprocfix sudo-1.8.6p3/src/sudo.h +--- sudo-1.8.6p3/src/sudo.h.nprocfix 2013-07-11 12:37:41.768202173 +0200 ++++ sudo-1.8.6p3/src/sudo.h 2013-07-11 12:37:41.811202301 +0200 +@@ -219,6 +219,7 @@ int policy_init_session(struct command_d + int run_command(struct command_details *details); + extern const char *list_user, *runas_user, *runas_group; + extern struct user_details user_details; ++void unlimit_nproc(void); + + /* sudo_edit.c */ + int sudo_edit(struct command_details *details); diff --git a/SOURCES/sudo-1.8.6p3-sigpipefix.patch b/SOURCES/sudo-1.8.6p3-sigpipefix.patch new file mode 100644 index 00000000..ce4886bb --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-sigpipefix.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p3/src/tgetpass.c.sigpipefix sudo-1.8.6p3/src/tgetpass.c +--- sudo-1.8.6p3/src/tgetpass.c.sigpipefix 2015-03-03 10:23:23.219038693 +0100 ++++ sudo-1.8.6p3/src/tgetpass.c 2015-03-03 10:23:43.089813184 +0100 +@@ -173,7 +173,7 @@ restore: + (void) sigaction(SIGTSTP, &savetstp, NULL); + (void) sigaction(SIGTTIN, &savettin, NULL); + (void) sigaction(SIGTTOU, &savettou, NULL); +- (void) sigaction(SIGTTOU, &savepipe, NULL); ++ (void) sigaction(SIGPIPE, &savepipe, NULL); + if (input != STDIN_FILENO) + (void) close(input); + diff --git a/SOURCES/sudo-1.8.6p3-sssd-noise.patch b/SOURCES/sudo-1.8.6p3-sssd-noise.patch new file mode 100644 index 00000000..dd7bed0d --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-sssd-noise.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.sssd-noise sudo-1.8.6p3/plugins/sudoers/sssd.c +--- sudo-1.8.6p3/plugins/sudoers/sssd.c.sssd-noise 2012-11-29 13:23:43.332760956 +0100 ++++ sudo-1.8.6p3/plugins/sudoers/sssd.c 2012-11-29 13:23:57.548816054 +0100 +@@ -350,7 +350,7 @@ static int sudo_sss_setdefs(struct sudo_ + + if (sss_error == ENOENT) { + sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD."); +- debug_return_int(-1); ++ debug_return_int(0); + } else if(sss_error != 0) { + sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error); + debug_return_int(-1); diff --git a/SOURCES/sudo-1.8.6p3-sssdfixes.patch b/SOURCES/sudo-1.8.6p3-sssdfixes.patch new file mode 100644 index 00000000..07062e35 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-sssdfixes.patch @@ -0,0 +1,119 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.sssdfixes sudo-1.8.6p3/plugins/sudoers/sssd.c +--- sudo-1.8.6p3/plugins/sudoers/sssd.c.sssdfixes 2013-08-13 15:20:39.558187669 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/sssd.c 2013-08-13 16:24:27.209064162 +0200 +@@ -534,30 +534,31 @@ sudo_sss_check_runas_group(struct sudo_s + * Walk through search results and return true if we have a runas match, + * else false. RunAs info is optional. + */ +-static int ++static bool + sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) + { +- int ret; ++ bool ret; + debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD); + + if (rule == NULL) +- debug_return_int(false); ++ debug_return_bool(false); + + ret = sudo_sss_check_runas_user(handle, rule) != false && + sudo_sss_check_runas_group(handle, rule) != false; + +- debug_return_int(ret); ++ debug_return_bool(ret); + } + +-static int ++static bool + sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) + { + char **val_array, *val; +- int ret = false, i; ++ bool ret = false; ++ int i; + debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD); + + if (rule == NULL) +- debug_return_int(ret); ++ debug_return_bool(ret); + + /* get the values from the rule */ + switch (handle->fn_get_values(rule, "sudoHost", &val_array)) +@@ -566,10 +567,10 @@ sudo_sss_check_host(struct sudo_sss_hand + break; + case ENOENT: + sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); +- debug_return_int(false); ++ debug_return_bool(false); + default: + sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0"); +- debug_return_int(ret); ++ debug_return_bool(ret); + } + + /* walk through values */ +@@ -589,7 +590,52 @@ sudo_sss_check_host(struct sudo_sss_hand + + handle->fn_free_values(val_array); + +- debug_return_int(ret); ++ debug_return_bool(ret); ++} ++ ++/* ++ * Look for netgroup specifcations in the sudoUser attribute and ++ * if found, filter according to netgroup membership. ++ * returns: ++ * true -> netgroup spec found && negroup member ++ * false -> netgroup spec found && not a meber of netgroup ++ * true -> netgroup spec not found (filtered by SSSD already, netgroups are an exception) ++ */ ++bool sudo_sss_filter_user_netgroup(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) ++{ ++ bool ret = false, netgroup_spec_found = false; ++ char **val_array, *val; ++ int i; ++ debug_decl(sudo_sss_check_user_netgroup, SUDO_DEBUG_SSSD); ++ ++ if (!handle || !rule) ++ debug_return_bool(ret); ++ ++ switch (handle->fn_get_values(rule, "sudoUser", &val_array)) { ++ case 0: ++ break; ++ case ENOENT: ++ sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); ++ debug_return_bool(ret); ++ default: ++ sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoUser): != 0"); ++ debug_return_bool(ret); ++ } ++ ++ for (i = 0; val_array[i] != NULL && !ret; ++i) { ++ val = val_array[i]; ++ if (*val == '+') { ++ netgroup_spec_found = true; ++ } ++ sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val); ++ if (strcmp(val, "ALL") == 0 || netgr_matches(val, NULL, NULL, user_name)) { ++ ret = true; ++ sudo_debug_printf(SUDO_DEBUG_DIAG, ++ "sssd/ldap sudoUser '%s' ... MATCH! (%s)", val, user_name); ++ } ++ } ++ handle->fn_free_values(val_array); ++ debug_return_bool(netgroup_spec_found ? ret : true); + } + + static int +@@ -599,7 +645,8 @@ sudo_sss_result_filterp(struct sudo_sss_ + (void)unused; + debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD); + +- if (sudo_sss_check_host(handle, rule)) ++ if (sudo_sss_check_host(handle, rule) && ++ sudo_sss_filter_user_netgroup(handle, rule)) + debug_return_int(1); + else + debug_return_int(0); diff --git a/SOURCES/sudo-1.8.6p3-sssdrulenames.patch b/SOURCES/sudo-1.8.6p3-sssdrulenames.patch new file mode 100644 index 00000000..84081d1a --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-sssdrulenames.patch @@ -0,0 +1,22 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.rulenames sudo-1.8.6p3/plugins/sudoers/sssd.c +--- sudo-1.8.6p3/plugins/sudoers/sssd.c.rulenames 2014-05-21 12:33:21.000768420 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/sssd.c 2014-05-21 12:38:13.779864718 +0200 +@@ -1180,6 +1180,18 @@ sudo_sss_display_entry_long(struct sudo_ + int count = 0, i; + debug_decl(sudo_sss_display_entry_long, SUDO_DEBUG_SSSD); + ++ switch(handle->fn_get_values(rule, "cn", &val_array)) { ++ case 0: ++ if (val_array[0]) { ++ lbuf_append(lbuf, _("\nSSSD Role: %s\n"), val_array[0]); ++ } ++ handle->fn_free_values(val_array); ++ val_array = NULL; ++ break; ++ default: ++ lbuf_append(lbuf, _("\nSSSD Role: UNKNOWN\n")); ++ } ++ + /* get the RunAsUser Values from the entry */ + lbuf_append(lbuf, " RunAsUsers: "); + switch (handle->fn_get_values(rule, "sudoRunAsUser", &val_array)) { diff --git a/SOURCES/sudo-1.8.6p3-strictuidgid.patch b/SOURCES/sudo-1.8.6p3-strictuidgid.patch new file mode 100644 index 00000000..0553cd73 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-strictuidgid.patch @@ -0,0 +1,53 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/match.c.strictuidgid sudo-1.8.6p3/plugins/sudoers/match.c +--- sudo-1.8.6p3/plugins/sudoers/match.c.strictuidgid 2012-09-18 15:56:29.000000000 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/match.c 2013-08-08 16:22:00.413281960 +0200 +@@ -650,14 +650,16 @@ hostname_matches(char *shost, char *lhos + bool + userpw_matches(char *sudoers_user, char *user, struct passwd *pw) + { +- debug_decl(userpw_matches, SUDO_DEBUG_MATCH) +- +- if (pw != NULL && *sudoers_user == '#') { +- uid_t uid = (uid_t) atoi(sudoers_user + 1); +- if (uid == pw->pw_uid) +- debug_return_bool(true); +- } +- debug_return_bool(strcmp(sudoers_user, user) == 0); ++ debug_decl(userpw_matches, SUDO_DEBUG_MATCH) ++ if (pw != NULL && *sudoers_user == '#') { ++ char *end = NULL; ++ uid_t uid = (uid_t) strtol(sudoers_user + 1, &end, 10); ++ if (end != NULL && (sudoers_user[1] != '\0' && *end == '\0')) { ++ if (uid == pw->pw_uid) ++ debug_return_bool(true); ++ } ++ } ++ debug_return_bool(strcmp(sudoers_user, user) == 0); + } + + /* +@@ -667,14 +669,16 @@ userpw_matches(char *sudoers_user, char + bool + group_matches(char *sudoers_group, struct group *gr) + { +- debug_decl(group_matches, SUDO_DEBUG_MATCH) +- +- if (*sudoers_group == '#') { +- gid_t gid = (gid_t) atoi(sudoers_group + 1); +- if (gid == gr->gr_gid) +- debug_return_bool(true); +- } +- debug_return_bool(strcmp(gr->gr_name, sudoers_group) == 0); ++ debug_decl(group_matches, SUDO_DEBUG_MATCH) ++ if (*sudoers_group == '#') { ++ char *end = NULL; ++ gid_t gid = (gid_t) strtol(sudoers_group + 1, &end, 10); ++ if (end != NULL && (sudoers_group[1] != '\0' && *end == '\0')) { ++ if (gid == gr->gr_gid) ++ debug_return_bool(true); ++ } ++ } ++ debug_return_bool(strcmp(gr->gr_name, sudoers_group) == 0); + } + + /* diff --git a/SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch b/SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch new file mode 100644 index 00000000..e816fdb6 --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch @@ -0,0 +1,747 @@ +diff -up sudo-1.8.6p3/src/sesh.c.sudoedit-selinux sudo-1.8.6p3/src/sesh.c +--- sudo-1.8.6p3/src/sesh.c.sudoedit-selinux 2012-09-18 15:56:30.000000000 +0200 ++++ sudo-1.8.6p3/src/sesh.c 2012-09-25 16:06:33.408584649 +0200 +@@ -34,6 +34,10 @@ + # include "compat/stdbool.h" + #endif /* HAVE_STDBOOL_H */ + ++#include ++#include ++#include ++ + #include "missing.h" + #include "alloc.h" + #include "error.h" +@@ -43,6 +47,16 @@ + #include "sudo_exec.h" + #include "sudo_plugin.h" + ++/* ++ * Return codes: ++ * EXIT_FAILURE ... unspecified error ++ * 0 ... everything ok ++ * 30 ... invalid -e arg value ++ * 31 ... odd number of paths ++ * 32 ... copy operation failed, no files copied ++ * 33 ... copy operation failed, some files copied ++ */ ++ + sudo_conv_t sudo_conv; /* NULL in non-plugin */ + + /* +@@ -77,19 +91,134 @@ main(int argc, char *argv[], char *envp[ + if ((cp = strrchr(argv[0], '-')) != NULL && cp != argv[0]) + noexec = strcmp(cp, "-noexec") == 0; + +- /* Shift argv and make a copy of the command to execute. */ +- argv++; +- argc--; +- cmnd = estrdup(argv[0]); +- +- /* If invoked as a login shell, modify argv[0] accordingly. */ +- if (argv[-1][0] == '-') { +- if ((cp = strrchr(argv[0], '/')) == NULL) +- cp = argv[0]; +- *cp = '-'; ++ /* check the first argument, if it's `-e' then we are in sudoedit mode */ ++ if (strncmp(argv[1], "-e", 3) == 0) { ++ int fd_src, fd_dst, post, n, ret = -1; ++ ssize_t nread, nwritten; ++ char *path_src, *path_dst, buf[BUFSIZ]; ++ ++ if (argc < 3) ++ return EXIT_FAILURE; ++ ++ /* ++ * We need to know whether we are performing the copy operation ++ * before or after the editing. Without this we would not know ++ * which files are temporary and which are the originals. ++ * post = 0 ... before ++ * post = 1 ... after ++ */ ++ if (strncmp(argv[2], "0", 2) == 0) ++ post = 0; ++ else if (strncmp(argv[2], "1", 2) == 0) ++ post = 1; ++ else /* invalid value */ ++ return 30; ++ ++ /* align argv & argc to the beggining of the file list */ ++ argv += 3; ++ argc -= 3; ++ ++ /* no files specified, nothing to do */ ++ if (argc == 0) ++ return 0; ++ /* odd number of paths specified */ ++ if (argc % 2 == 1) ++ return 31; ++ ++ for (n = 0; n < argc - 1; n += 2) { ++ path_src = argv[n]; ++ path_dst = argv[n+1]; ++ /* ++ * Try to open the source file for reading. If it ++ * doesn't exist, it's ok, we'll create an empty ++ * destination file. ++ */ ++ if ((fd_src = open(path_src, O_RDONLY, 0600)) < 0) { ++ if (errno == ENOENT) { ++ /* new file */ ++ } else { ++ warning(_("open(%s)"), path_src); ++ if (post) { ++ ret = 33; ++ goto nocleanup; ++ } else ++ goto cleanup_0; ++ } ++ } ++ ++ /* ++ * 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 sym- ++ * links. ++ */ ++ if ((fd_dst = open(path_dst, (post ? 0 : O_EXCL) | ++ O_WRONLY|O_TRUNC|O_CREAT, post ? 0644 : 0600)) < 0) ++ { ++ /* error - cleanup */ ++ warning(_("open(%s%s)"), path_dst, post ? "" : ", O_EXCL"); ++ if (post) { ++ ret = 33; ++ goto nocleanup; ++ } else ++ goto cleanup_0; ++ } ++ ++ if (fd_src != -1) { ++ while ((nread = read(fd_src, buf, sizeof(buf))) > 0) { ++ if ((nwritten = write(fd_dst, buf, nread)) != nread) { ++ warning(_("write")); ++ if (post) { ++ ret = 33; ++ goto nocleanup; ++ } else ++ goto cleanup_0; ++ } ++ } ++ } ++ ++ if (fd_dst != -1) ++ close(fd_dst); ++ if (fd_src != -1) ++ close(fd_src); ++ fd_dst = fd_src = -1; ++ } ++ ++ ret = 0; ++ /* remove temporary files (post=1) */ ++ for (n = 0; n < argc - 1; n += 2) ++ unlink(argv[n]); ++nocleanup: ++ if (fd_dst != -1) ++ close(fd_dst); ++ if (fd_src != -1) ++ close(fd_src); ++ _exit(ret); ++cleanup_0: ++ /* remove temporary files (post=0) */ ++ for (n = 0; n < argc - 1; n += 2) ++ unlink(argv[n+1]); ++ if (fd_dst != -1) ++ close(fd_dst); ++ if (fd_src != -1) ++ close(fd_src); ++ _exit(32); ++ } else { ++ ++ /* Shift argv and make a copy of the command to execute. */ ++ argv++; ++ argc--; ++ cmnd = estrdup(argv[0]); ++ ++ /* If invoked as a login shell, modify argv[0] accordingly. */ ++ if (argv[-1][0] == '-') { ++ if ((cp = strrchr(argv[0], '/')) == NULL) ++ cp = argv[0]; ++ *cp = '-'; ++ } ++ sudo_execve(cmnd, argv, envp, noexec); ++ warning(_("unable to execute %s"), argv[0]); ++ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, EXIT_FAILURE); + } +- sudo_execve(cmnd, argv, envp, noexec); +- warning(_("unable to execute %s"), argv[0]); +- sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, EXIT_FAILURE); + _exit(EXIT_FAILURE); + } +diff -up sudo-1.8.6p3/src/sudo.c.sudoedit-selinux sudo-1.8.6p3/src/sudo.c +--- sudo-1.8.6p3/src/sudo.c.sudoedit-selinux 2012-09-18 15:57:43.000000000 +0200 ++++ sudo-1.8.6p3/src/sudo.c 2012-09-25 16:04:36.687422997 +0200 +@@ -915,6 +915,10 @@ exec_setup(struct command_details *detai + if (selinux_setup(details->selinux_role, details->selinux_type, + ptyname ? ptyname : user_details.tty, ptyfd) == -1) + goto done; ++ if (details->flags & CD_SUDOEDIT_COPY) { ++ rval = true; ++ goto done; ++ } + } + #endif + +@@ -1116,6 +1120,8 @@ run_command(struct command_details *deta + break; + case CMD_WSTATUS: + /* Command ran, exited or was killed. */ ++ if (details->flags & CD_SUDOEDIT_COPY) ++ break; + sudo_debug_printf(SUDO_DEBUG_DEBUG, + "calling policy close with wait status %d", cstat.val); + policy_close(&policy_plugin, cstat.val, 0); +diff -up sudo-1.8.6p3/src/sudo_edit.c.sudoedit-selinux sudo-1.8.6p3/src/sudo_edit.c +--- sudo-1.8.6p3/src/sudo_edit.c.sudoedit-selinux 2012-09-18 15:56:30.000000000 +0200 ++++ sudo-1.8.6p3/src/sudo_edit.c 2012-09-25 16:06:19.108564255 +0200 +@@ -49,11 +49,284 @@ + #if TIME_WITH_SYS_TIME + # include + #endif ++#ifdef HAVE_SELINUX ++# include ++#endif + + #include "sudo.h" + + #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) + ++struct tempfile { ++ char *tfile; ++ char *ofile; ++ struct timeval omtim; ++ off_t osize; ++}; ++ ++static int ++selinux_edit_copy(struct command_details *command_details, struct tempfile *tf, char **files, int nfiles, const char *tmpdir, int tmplen, int tval_isset) ++{ ++ char **sesh_args; ++ int i, sesh_nargs, ret; ++ struct command_details sesh_details; ++ debug_decl(selinux_edit_copy, SUDO_DEBUG_EDIT); ++ ++ /* Prepare selinux stuff (setexeccon) */ ++ if (selinux_setup(command_details->selinux_role, ++ command_details->selinux_type, NULL, -1) != 0) ++ return -1; ++ ++ if (nfiles < 1) ++ return 1; ++ ++ /* Construct common args for sesh */ ++ memcpy(&sesh_details, command_details, sizeof(sesh_details)); ++ sesh_details.command = _PATH_SUDO_SESH; ++ sesh_details.flags |= CD_SUDOEDIT_COPY; ++ ++ sesh_nargs = (nfiles * 2) + 4 + 1; ++ sesh_args = (char **)emalloc2(sesh_nargs, sizeof(char *)); ++ sesh_args++; ++ sesh_args[0] = "sesh"; ++ sesh_args[1] = "-e"; ++ ++ if (files != NULL) { ++ sesh_args[2] = "0"; ++ ++ for (i = 2; i < nfiles+2; ++i) { ++ sesh_args[2*i-1] = files[i-2]; ++ tf[i-2].ofile = files[i-2]; ++ /* ++ * O_CREAT | O_EXCL is used in the sesh helper, so the ++ * usage of the tempnam function here is safe. ++ */ ++ sesh_args[2*i] = tempnam(tmpdir, "sudo."); ++ tf[i-2].tfile = sesh_args[2*i]; ++ //tf[i-2].omtim = 0; ++ tf[i-2].osize = 0; ++ } ++ ++ sesh_args[2*i-1] = NULL; ++ ++ /* Run sesh -e 0 ... */ ++ sesh_details.argv = sesh_args; ++ switch(run_command(&sesh_details)) { ++ case 0: ++ break; ++ case 31: ++ error(1, _("sesh: internal error: odd number of paths")); ++ case 32: ++ error(1, _("sesh: unable to create temporary files")); ++ } ++ ++ /* Chown to user's UID so he can edit the temporary files */ ++ for (i = 2; i < nfiles+2; ++i) { ++ if (chown(tf[i-2].tfile, user_details.uid, user_details.gid) != 0) { ++ warning("Unable to chown(%s) to %d:%d for editing", ++ tf[i-2].tfile, user_details.uid, user_details.gid); ++ } ++ } ++ } else { ++ sesh_args[2] = "1"; ++ ++ /* Construct args for sesh -e 1 */ ++ for (i = 2; i < nfiles+2; ++i) { ++ sesh_args[2*i-1] = tf[i-2].tfile; ++ sesh_args[2*i] = tf[i-2].ofile; ++ ++ if (chown(tf[i-2].tfile, sesh_details.uid, sesh_details.gid) != 0) { ++ warning("Unable to chown(%s) back to %d:%d", ++ tf[i-2].tfile, sesh_details.uid, sesh_details.gid); ++ } ++ } ++ ++ sesh_args[2*i-1] = NULL; ++ ++ /* Run sesh -e 1 ... */ ++ sesh_details.argv = sesh_args; ++ switch(run_command(&sesh_details)) { ++ case 0: ++ break; ++ case 32: ++ warning(_("Copying the temporary files back to its original place failed. The files were left in %s"), tmpdir); ++ break; ++ case 33: ++ warning(_("Copying of some of the temporary files back to its original place failed and they were left in %s"), ++ tmpdir); ++ break; ++ } ++ } ++ ++ return (nfiles); ++} ++ ++static void switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups); ++ ++static int sudo_edit_copy(struct command_details *command_details, struct tempfile *tf, char **files, int nfiles, const char *tmpdir, int tmplen, int tval_isset) ++{ ++ int i, j, tfd, ofd, rc; ++ char *cp, *suff, buf[BUFSIZ]; ++ ssize_t nwritten, nread; ++ struct stat sb; ++ struct timeval tv; ++ debug_decl(sudo_edit_copy, SUDO_DEBUG_EDIT); ++ ++ if (files != NULL) { ++ /* Create temporary copies */ ++ for (i = 0, j = 0; i < nfiles; i++) { ++ rc = -1; ++ switch_user(command_details->euid, command_details->egid, ++ command_details->ngroups, command_details->groups); ++ if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) { ++ if (ofd == -1) { ++ zero_bytes(&sb, sizeof(sb)); /* new file */ ++ rc = 0; ++ } else { ++ rc = fstat(ofd, &sb); ++ } ++ } ++ switch_user(ROOT_UID, user_details.egid, ++ user_details.ngroups, user_details.groups); ++ if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) { ++ if (rc) ++ warning("%s", files[i]); ++ else ++ warningx(_("%s: not a regular file"), files[i]); ++ if (ofd != -1) ++ close(ofd); ++ continue; ++ } ++ tf[j].ofile = files[i]; ++ tf[j].osize = sb.st_size; ++ mtim_get(&sb, &tf[j].omtim); ++ if ((cp = strrchr(tf[j].ofile, '/')) != NULL) ++ cp++; ++ else ++ cp = tf[j].ofile; ++ suff = strrchr(cp, '.'); ++ if (suff != NULL) { ++ easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir, ++ (int)(size_t)(suff - cp), cp, suff); ++ } else { ++ easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp); ++ } ++ if (seteuid(user_details.uid) != 0) ++ error(1, "seteuid(%d)", (int)user_details.uid); ++ tfd = mkstemps(tf[j].tfile, suff ? strlen(suff) : 0); ++ if (seteuid(ROOT_UID) != 0) ++ error(1, "seteuid(ROOT_UID)"); ++ if (tfd == -1) { ++ warning("mkstemps"); ++ goto cleanup; ++ } ++ if (ofd != -1) { ++ while ((nread = read(ofd, buf, sizeof(buf))) != 0) { ++ if ((nwritten = write(tfd, buf, nread)) != nread) { ++ if (nwritten == -1) ++ warning("%s", tf[j].tfile); ++ else ++ warningx(_("%s: short write"), tf[j].tfile); ++ goto cleanup; ++ } ++ } ++ close(ofd); ++ } ++ /* ++ * We always update the stashed mtime because the time ++ * resolution of the filesystem the temporary file is on may ++ * not match that of the filesystem where the file to be edited ++ * resides. It is OK if touch() fails since we only use the info ++ * to determine whether or not a file has been modified. ++ */ ++ (void) touch(tfd, NULL, &tf[j].omtim); ++ rc = fstat(tfd, &sb); ++ if (!rc) ++ mtim_get(&sb, &tf[j].omtim); ++ close(tfd); ++ j++; ++ } ++ if ((nfiles = j) == 0) ++ goto cleanup; /* no files readable, you lose */ ++ } else { ++ /* Copy contents of temp files to real ones */ ++ for (i = 0; i < nfiles; i++) { ++ rc = -1; ++ if (seteuid(user_details.uid) != 0) ++ error(1, "seteuid(%d)", (int)user_details.uid); ++ if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) { ++ rc = fstat(tfd, &sb); ++ } ++ if (seteuid(ROOT_UID) != 0) ++ error(1, "seteuid(ROOT_UID)"); ++ if (rc || !S_ISREG(sb.st_mode)) { ++ if (rc) ++ warning("%s", tf[i].tfile); ++ else ++ warningx(_("%s: not a regular file"), tf[i].tfile); ++ warningx(_("%s left unmodified"), tf[i].ofile); ++ if (tfd != -1) ++ close(tfd); ++ continue; ++ } ++ mtim_get(&sb, &tv); ++ if (tf[i].osize == sb.st_size && timevalcmp(&tf[i].omtim, &tv, ==)) { ++ /* ++ * 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 (tval_isset) { ++ warningx(_("%s unchanged"), tf[i].ofile); ++ unlink(tf[i].tfile); ++ close(tfd); ++ continue; ++ } ++ } ++ switch_user(command_details->euid, command_details->egid, ++ command_details->ngroups, command_details->groups); ++ ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644); ++ switch_user(ROOT_UID, user_details.egid, ++ user_details.ngroups, user_details.groups); ++ if (ofd == -1) { ++ warning(_("unable to write to %s"), tf[i].ofile); ++ warningx(_("contents of edit session left in %s"), tf[i].tfile); ++ close(tfd); ++ continue; ++ } ++ while ((nread = read(tfd, buf, sizeof(buf))) > 0) { ++ if ((nwritten = write(ofd, buf, nread)) != nread) { ++ if (nwritten == -1) ++ warning("%s", tf[i].ofile); ++ else ++ warningx(_("%s: short write"), tf[i].ofile); ++ break; ++ } ++ } ++ if (nread == 0) { ++ /* success, got EOF */ ++ unlink(tf[i].tfile); ++ } else if (nread < 0) { ++ warning(_("unable to read temporary file")); ++ warningx(_("contents of edit session left in %s"), tf[i].tfile); ++ } else { ++ warning(_("unable to write to %s"), tf[i].ofile); ++ warningx(_("contents of edit session left in %s"), tf[i].tfile); ++ } ++ close(ofd); ++ } ++ j = 0; ++ } ++ ++ debug_return_int(j); ++cleanup: ++ for (i = 0; i < nfiles; i++) { ++ if (tf[i].tfile != NULL) ++ unlink(tf[i].tfile); ++ } ++ ++ debug_return_int(-1); ++} ++ + static void + switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups) + { +@@ -87,20 +360,17 @@ int + sudo_edit(struct command_details *command_details) + { + struct command_details editor_details; +- ssize_t nread, nwritten; + const char *tmpdir; +- char *cp, *suff, **nargv, **ap, **files = NULL; +- char buf[BUFSIZ]; +- int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen; +- int editor_argc = 0, nfiles = 0; ++ char **ap; ++ char **nargv, **files = NULL; ++ int editor_argc = 0; ++ int i, ac, nargc, rval, nfiles = 0, tmplen; + struct stat sb; +- struct timeval tv, tv1, tv2; +- struct tempfile { +- char *tfile; +- char *ofile; +- struct timeval omtim; +- off_t osize; +- } *tf = NULL; ++ struct timeval tv1, tv2; ++ struct tempfile *tf; ++#ifdef HAVE_SELINUX ++ int rbac_enabled; ++#endif + debug_decl(sudo_edit, SUDO_DEBUG_EDIT) + + /* +@@ -109,7 +379,7 @@ sudo_edit(struct command_details *comman + */ + if (setuid(ROOT_UID) != 0) { + warning(_("unable to change uid to root (%u)"), ROOT_UID); +- goto cleanup; ++ return 1; + } + + /* +@@ -127,6 +397,9 @@ sudo_edit(struct command_details *comman + while (tmplen > 0 && tmpdir[tmplen - 1] == '/') + tmplen--; + ++#ifdef HAVE_SELINUX ++ rbac_enabled = is_selinux_enabled() > 0 && command_details->selinux_role != NULL; ++#endif + /* + * The user's editor must be separated from the files to be + * edited by a "--" option. +@@ -141,7 +414,7 @@ sudo_edit(struct command_details *comman + } + if (nfiles == 0) { + warningx(_("plugin error: missing file list for sudoedit")); +- goto cleanup; ++ return 1; + } + + /* +@@ -150,81 +423,18 @@ sudo_edit(struct command_details *comman + */ + tf = emalloc2(nfiles, sizeof(*tf)); + zero_bytes(tf, nfiles * sizeof(*tf)); +- for (i = 0, j = 0; i < nfiles; i++) { +- rc = -1; +- switch_user(command_details->euid, command_details->egid, +- command_details->ngroups, command_details->groups); +- if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) { +- if (ofd == -1) { +- zero_bytes(&sb, sizeof(sb)); /* new file */ +- rc = 0; +- } else { +- rc = fstat(ofd, &sb); +- } +- } +- switch_user(ROOT_UID, user_details.egid, +- user_details.ngroups, user_details.groups); +- if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) { +- if (rc) +- warning("%s", files[i]); +- else +- warningx(_("%s: not a regular file"), files[i]); +- if (ofd != -1) +- close(ofd); +- continue; +- } +- tf[j].ofile = files[i]; +- tf[j].osize = sb.st_size; +- mtim_get(&sb, &tf[j].omtim); +- if ((cp = strrchr(tf[j].ofile, '/')) != NULL) +- cp++; +- else +- cp = tf[j].ofile; +- suff = strrchr(cp, '.'); +- if (suff != NULL) { +- easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir, +- (int)(size_t)(suff - cp), cp, suff); +- } else { +- easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp); +- } +- if (seteuid(user_details.uid) != 0) +- error(1, "seteuid(%d)", (int)user_details.uid); +- tfd = mkstemps(tf[j].tfile, suff ? strlen(suff) : 0); +- if (seteuid(ROOT_UID) != 0) +- error(1, "seteuid(ROOT_UID)"); +- if (tfd == -1) { +- warning("mkstemps"); +- goto cleanup; +- } +- if (ofd != -1) { +- while ((nread = read(ofd, buf, sizeof(buf))) != 0) { +- if ((nwritten = write(tfd, buf, nread)) != nread) { +- if (nwritten == -1) +- warning("%s", tf[j].tfile); +- else +- warningx(_("%s: short write"), tf[j].tfile); +- goto cleanup; +- } +- } +- close(ofd); +- } +- /* +- * We always update the stashed mtime because the time +- * resolution of the filesystem the temporary file is on may +- * not match that of the filesystem where the file to be edited +- * resides. It is OK if touch() fails since we only use the info +- * to determine whether or not a file has been modified. +- */ +- (void) touch(tfd, NULL, &tf[j].omtim); +- rc = fstat(tfd, &sb); +- if (!rc) +- mtim_get(&sb, &tf[j].omtim); +- close(tfd); +- j++; +- } +- if ((nfiles = j) == 0) +- goto cleanup; /* no files readable, you lose */ ++ ++ /* Make temporary copies of the original files */ ++ if (!rbac_enabled) ++ nfiles = sudo_edit_copy(command_details, tf, files, nfiles, tmpdir, tmplen, 0); ++ else ++ nfiles = selinux_edit_copy(command_details, tf, files, nfiles, tmpdir, tmplen, 0); + ++ if (nfiles <= 0) ++ return 1; ++ ++ switch_user(ROOT_UID, user_details.egid, ++ user_details.ngroups, user_details.groups); + /* + * Allocate space for the new argument vector and fill it in. + * We concatenate the editor with its args and the file list +@@ -253,84 +463,18 @@ sudo_edit(struct command_details *comman + editor_details.argv = nargv; + rval = run_command(&editor_details); + gettimeofday(&tv2, NULL); ++ timevalsub(&tv1, &tv2); + +- /* Copy contents of temp files to real ones */ +- for (i = 0; i < nfiles; i++) { +- rc = -1; +- if (seteuid(user_details.uid) != 0) +- error(1, "seteuid(%d)", (int)user_details.uid); +- if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) { +- rc = fstat(tfd, &sb); +- } +- if (seteuid(ROOT_UID) != 0) +- error(1, "seteuid(ROOT_UID)"); +- if (rc || !S_ISREG(sb.st_mode)) { +- if (rc) +- warning("%s", tf[i].tfile); +- else +- warningx(_("%s: not a regular file"), tf[i].tfile); +- warningx(_("%s left unmodified"), tf[i].ofile); +- if (tfd != -1) +- close(tfd); +- continue; +- } +- mtim_get(&sb, &tv); +- if (tf[i].osize == sb.st_size && timevalcmp(&tf[i].omtim, &tv, ==)) { +- /* +- * If mtime and size match but the user spent no measurable +- * time in the editor we can't tell if the file was changed. +- */ +- timevalsub(&tv1, &tv2); +- if (timevalisset(&tv2)) { +- warningx(_("%s unchanged"), tf[i].ofile); +- unlink(tf[i].tfile); +- close(tfd); +- continue; +- } +- } +- switch_user(command_details->euid, command_details->egid, +- command_details->ngroups, command_details->groups); +- ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644); +- switch_user(ROOT_UID, user_details.egid, +- user_details.ngroups, user_details.groups); +- if (ofd == -1) { +- warning(_("unable to write to %s"), tf[i].ofile); +- warningx(_("contents of edit session left in %s"), tf[i].tfile); +- close(tfd); +- continue; +- } +- while ((nread = read(tfd, buf, sizeof(buf))) > 0) { +- if ((nwritten = write(ofd, buf, nread)) != nread) { +- if (nwritten == -1) +- warning("%s", tf[i].ofile); +- else +- warningx(_("%s: short write"), tf[i].ofile); +- break; +- } +- } +- if (nread == 0) { +- /* success, got EOF */ +- unlink(tf[i].tfile); +- } else if (nread < 0) { +- warning(_("unable to read temporary file")); +- warningx(_("contents of edit session left in %s"), tf[i].tfile); +- } else { +- warning(_("unable to write to %s"), tf[i].ofile); +- warningx(_("contents of edit session left in %s"), tf[i].tfile); +- } +- close(ofd); +- } ++ switch_user(ROOT_UID, user_details.egid, ++ user_details.ngroups, user_details.groups); ++ ++ /* Copy the temporary files back to originals */ ++ if (!rbac_enabled) ++ nfiles = sudo_edit_copy(command_details, tf, NULL, nfiles, NULL, 0, timevalisset(&tv2)); ++ else ++ nfiles = selinux_edit_copy(command_details, tf, NULL, nfiles, NULL, 0, timevalisset(&tv2)); ++ + debug_return_int(rval); +- +-cleanup: +- /* Clean up temp files and return. */ +- if (tf != NULL) { +- for (i = 0; i < nfiles; i++) { +- if (tf[i].tfile != NULL) +- unlink(tf[i].tfile); +- } +- } +- debug_return_int(1); + } + + #else /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ +diff -up sudo-1.8.6p3/src/sudo.h.sudoedit-selinux sudo-1.8.6p3/src/sudo.h +--- sudo-1.8.6p3/src/sudo.h.sudoedit-selinux 2012-09-18 15:56:30.000000000 +0200 ++++ sudo-1.8.6p3/src/sudo.h 2012-09-25 16:04:36.690423001 +0200 +@@ -130,6 +130,7 @@ struct user_details { + #define CD_RBAC_ENABLED 0x0800 + #define CD_USE_PTY 0x1000 + #define CD_SET_UTMP 0x2000 ++#define CD_SUDOEDIT_COPY 0x4000 + + struct command_details { + uid_t uid; diff --git a/SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch b/SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch new file mode 100644 index 00000000..30c4eefe --- /dev/null +++ b/SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p3/plugins/sudoers/visudo.c.fix sudo-1.8.6p3/plugins/sudoers/visudo.c +--- sudo-1.8.6p3/plugins/sudoers/visudo.c.fix 2015-07-22 11:29:03.899122767 +0200 ++++ sudo-1.8.6p3/plugins/sudoers/visudo.c 2015-07-22 11:29:33.001826535 +0200 +@@ -201,7 +201,7 @@ main(int argc, char *argv[]) + strict = true; /* strict mode */ + break; + case 'q': +- quiet = false; /* quiet mode */ ++ quiet = true; /* quiet mode */ + break; + default: + usage(1); diff --git a/SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch b/SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch new file mode 100644 index 00000000..64cfdb9a --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch @@ -0,0 +1,333 @@ +diff -up sudo-1.8.6p7/aclocal.m4.CVE-2014-9680 sudo-1.8.6p7/aclocal.m4 +--- sudo-1.8.6p7/aclocal.m4.CVE-2014-9680 2013-02-25 20:42:44.000000000 +0100 ++++ sudo-1.8.6p7/aclocal.m4 2015-07-05 13:44:11.610596042 +0200 +@@ -156,6 +156,25 @@ AC_DEFUN([SUDO_IO_LOGDIR], [ + AC_MSG_RESULT($iolog_dir) + ])dnl + ++dnl Detect time zone file directory, if any. ++dnl ++AC_DEFUN([SUDO_TZDIR], [AC_MSG_CHECKING(time zone data directory) ++tzdir="$with_tzdir" ++if test -z "$tzdir"; then ++ tzdir=no ++ for d in /usr/share /usr/share/lib /usr/lib /etc; do ++ if test -d "$d/zoneinfo"; then ++ tzdir="$d/zoneinfo" ++ break ++ fi ++ done ++fi ++AC_MSG_RESULT([$tzdir]) ++if test "${tzdir}" != "no"; then ++ SUDO_DEFINE_UNQUOTED(_PATH_ZONEINFO, "$tzdir") ++fi ++])dnl ++ + dnl + dnl check for working fnmatch(3) + dnl +diff -up sudo-1.8.6p7/configure.in.CVE-2014-9680 sudo-1.8.6p7/configure.in +--- sudo-1.8.6p7/configure.in.CVE-2014-9680 2015-07-05 13:44:11.598596222 +0200 ++++ sudo-1.8.6p7/configure.in 2015-07-05 13:44:11.610596042 +0200 +@@ -776,6 +776,12 @@ AC_ARG_WITH(iologdir, [AS_HELP_STRING([- + ;; + esac]) + ++AC_ARG_WITH(tzdir, [AS_HELP_STRING([--with-tzdir=DIR], [path to the time zone data directory])], ++[case $with_tzdir in ++ yes) AC_MSG_ERROR(["must give --with-tzdir an argument."]) ++ ;; ++esac]) ++ + AC_ARG_WITH(sendmail, [AS_HELP_STRING([--with-sendmail], [set path to sendmail]) + AS_HELP_STRING([--without-sendmail], [do not send mail at all])], + [case $with_sendmail in +@@ -3250,6 +3256,7 @@ fi + SUDO_LOGFILE + SUDO_TIMEDIR + SUDO_IO_LOGDIR ++SUDO_TZDIR + + dnl + dnl Turn warnings into errors. +diff -up sudo-1.8.6p7/doc/sudoers.cat.CVE-2014-9680 sudo-1.8.6p7/doc/sudoers.cat +--- sudo-1.8.6p7/doc/sudoers.cat.CVE-2014-9680 2015-07-05 13:44:11.586596402 +0200 ++++ sudo-1.8.6p7/doc/sudoers.cat 2015-07-05 13:44:11.610596042 +0200 +@@ -1421,20 +1421,36 @@ SSUUDDOOEERRSS OOPPTTIIOONN + + LLiissttss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt: + +- env_check Environment variables to be removed from the user's +- environment if the variable's value contains `%' or `/' ++ env_check Environment variables to be removed from the user's ++ environment if unless they are considered ``safe''. ++ For all variables except TZ, ``safe'' means that the ++ variable's value does not contain any `%' or `/' + characters. This can be used to guard against printf- + style format vulnerabilities in poorly-written +- programs. The argument may be a double-quoted, space- +- separated list or a single value without double-quotes. +- The list can be replaced, added to, deleted from, or +- disabled by using the =, +=, -=, and ! operators +- respectively. Regardless of whether the env_reset +- option is enabled or disabled, variables specified by +- env_check will be preserved in the environment if they +- pass the aforementioned check. The default list of +- environment variables to check is displayed when ssuuddoo +- is run by root with the --VV option. ++ programs. The TZ variable is considerd unsafe if any ++ of the following are true: ++ ++ ++oo It consists of a fully-qualified path name, ++ optionally prefixed with a colon (`:'), that does ++ not match the location of the _z_o_n_e_i_n_f_o directory. ++ ++ ++oo It contains a _._. path element. ++ ++ ++oo It contains white space or non-printable ++ characters. ++ ++ ++oo It is longer than the value of PATH_MAX. ++ ++ The argument may be a double-quoted, space-separated ++ list or a single value without double-quotes. The list ++ can be replaced, added to, deleted from, or disabled by ++ using the =, +=, -=, and ! operators respectively. ++ Regardless of whether the env_reset option is enabled ++ or disabled, variables specified by env_check will be ++ preserved in the environment if they pass the ++ aforementioned check. The default list of environment ++ variables to check is displayed when ssuuddoo is run by ++ root with the --VV option. + + env_delete Environment variables to be removed from the user's + environment when the _e_n_v___r_e_s_e_t option is not in effect. +diff -up sudo-1.8.6p7/doc/sudoers.man.in.CVE-2014-9680 sudo-1.8.6p7/doc/sudoers.man.in +--- sudo-1.8.6p7/doc/sudoers.man.in.CVE-2014-9680 2015-07-05 13:44:11.586596402 +0200 ++++ sudo-1.8.6p7/doc/sudoers.man.in 2015-07-05 13:44:11.611596027 +0200 +@@ -3002,14 +3002,47 @@ The default value is + \fBLists that can be used in a boolean context\fR: + .TP 18n + env_check +-Environment variables to be removed from the user's environment if +-the variable's value contains +-`%' ++ Environment variables to be removed from the user's environment if ++unless they are considered ++\(lqsafe\(rq. ++For all variables except ++\fRTZ\fR, ++\(lqsafe\(rq ++means that the variable's value does not contain any ++\(oq%\(cq + or +-`/' ++\(oq/\(cq + characters. + This can be used to guard against printf-style format vulnerabilities + in poorly-written programs. ++The ++\fRTZ\fR ++variable is considerd unsafe if any of the following are true: ++.PP ++.RS 18n ++.PD 0 ++.TP 4n ++\fB\(bu\fR ++It consists of a fully-qualified path name, ++optionally prefixed with a colon ++(\(oq:\&\(cq), ++that does not match the location of the ++\fIzoneinfo\fR ++directory. ++.PD ++.TP 4n ++\fB\(bu\fR ++It contains a ++\fI..\fR ++path element. ++.TP 4n ++\fB\(bu\fR ++It contains white space or non-printable characters. ++.TP 4n ++\fB\(bu\fR ++It is longer than the value of ++\fRPATH_MAX\fR. ++.PP + The argument may be a double-quoted, space-separated list or a + single value without double-quotes. + The list can be replaced, added to, deleted from, or disabled by using +@@ -3031,6 +3064,7 @@ is run by root with + the + \fB\-V\fR + option. ++.RE + .TP 18n + env_delete + Environment variables to be removed from the user's environment when the +diff -up sudo-1.8.6p7/doc/sudoers.mdoc.in.CVE-2014-9680 sudo-1.8.6p7/doc/sudoers.mdoc.in +--- sudo-1.8.6p7/doc/sudoers.mdoc.in.CVE-2014-9680 2015-07-05 13:44:11.586596402 +0200 ++++ sudo-1.8.6p7/doc/sudoers.mdoc.in 2015-07-05 13:44:11.611596027 +0200 +@@ -2791,13 +2791,40 @@ The default value is + .Bl -tag -width 16n + .It env_check + Environment variables to be removed from the user's environment if +-the variable's value contains ++unless they are considered ++.Dq safe . ++For all variables except ++.Li TZ , ++.Dq safe ++means that the variable's value does not contain any + .Ql % + or + .Ql / + characters. + This can be used to guard against printf-style format vulnerabilities + in poorly-written programs. ++The ++.Li TZ ++variable is considerd unsafe if any of the following are true: ++.Bl -bullet ++.It ++It consists of a fully-qualified path name, ++optionally prefixed with a colon ++.Pq Ql :\& , ++that does not match the location of the ++.Pa zoneinfo ++directory. ++.It ++It contains a ++.Pa .. ++path element. ++.It ++It contains white space or non-printable characters. ++.It ++It is longer than the value of ++.Li PATH_MAX . ++.El ++.Pp + The argument may be a double-quoted, space-separated list or a + single value without double-quotes. + The list can be replaced, added to, deleted from, or disabled by using +diff -up sudo-1.8.6p7/INSTALL.CVE-2014-9680 sudo-1.8.6p7/INSTALL +--- sudo-1.8.6p7/INSTALL.CVE-2014-9680 2013-02-25 20:42:43.000000000 +0100 ++++ sudo-1.8.6p7/INSTALL 2015-07-05 13:44:11.611596027 +0200 +@@ -461,6 +461,16 @@ The following options are also configura + Override the default location of the sudo timestamp directory and + use "path" instead. + ++ --with-tzdir=DIR ++ Set the directory to the system's time zone data files. This ++ is only used when sanitizing the TZ environment variable to ++ allow for fully-qualified paths in TZ. ++ By default, configure will look for an existing "zoneinfo" ++ directory in the following locations: ++ /usr/share /usr/share/lib /usr/lib /etc ++ If no zoneinfo directory is found, the TZ variable may not ++ contain a fully-qualified path. ++ + --with-sendmail=PATH + Override configure's guess as to the location of sendmail. + +diff -up sudo-1.8.6p7/pathnames.h.in.CVE-2014-9680 sudo-1.8.6p7/pathnames.h.in +--- sudo-1.8.6p7/pathnames.h.in.CVE-2014-9680 2012-09-18 15:56:28.000000000 +0200 ++++ sudo-1.8.6p7/pathnames.h.in 2015-07-05 13:44:11.612596011 +0200 +@@ -168,3 +168,7 @@ + #ifndef _PATH_NETSVC_CONF + #undef _PATH_NETSVC_CONF + #endif /* _PATH_NETSVC_CONF */ ++ ++#ifndef _PATH_ZONEINFO ++# undef _PATH_ZONEINFO ++#endif /* _PATH_ZONEINFO */ +diff -up sudo-1.8.6p7/plugins/sudoers/env.c.CVE-2014-9680 sudo-1.8.6p7/plugins/sudoers/env.c +--- sudo-1.8.6p7/plugins/sudoers/env.c.CVE-2014-9680 2013-02-25 20:42:44.000000000 +0100 ++++ sudo-1.8.6p7/plugins/sudoers/env.c 2015-07-05 13:44:11.612596011 +0200 +@@ -198,6 +198,7 @@ static const char *initial_checkenv_tabl + "LC_*", + "LINGUAS", + "TERM", ++ "TZ", + NULL + }; + +@@ -213,7 +214,6 @@ static const char *initial_keepenv_table + "PATH", + "PS1", + "PS2", +- "TZ", + "XAUTHORITY", + "XAUTHORIZATION", + NULL +@@ -584,6 +584,54 @@ matches_env_delete(const char *var) + } + + /* ++ * Sanity-check the TZ environment variable. ++ * On many systems it is possible to set this to a pathname. ++ */ ++static bool ++tz_is_sane(const char *tzval) ++{ ++ const char *cp; ++ char lastch; ++ debug_decl(tz_is_sane, SUDO_DEBUG_ENV) ++ ++ /* tzcode treats a value beginning with a ':' as a path. */ ++ if (tzval[0] == ':') ++ tzval++; ++ ++ /* Reject fully-qualified TZ that doesn't being with the zoneinfo dir. */ ++ if (tzval[0] == '/') { ++#ifdef _PATH_ZONEINFO ++ if (strncmp(tzval, _PATH_ZONEINFO, sizeof(_PATH_ZONEINFO) - 1) != 0 || ++ tzval[sizeof(_PATH_ZONEINFO) - 1] != '/') ++ debug_return_bool(false); ++#else ++ /* Assume the worst. */ ++ debug_return_bool(false); ++#endif ++ } ++ ++ /* ++ * Make sure TZ only contains printable non-space characters ++ * and does not contain a '..' path element. ++ */ ++ lastch = '/'; ++ for (cp = tzval; *cp != '\0'; cp++) { ++ if (isspace((unsigned char)*cp) || !isprint((unsigned char)*cp)) ++ debug_return_bool(false); ++ if (lastch == '/' && cp[0] == '.' && cp[1] == '.' && ++ (cp[2] == '/' || cp[2] == '\0')) ++ debug_return_bool(false); ++ lastch = *cp; ++ } ++ ++ /* Reject extra long TZ values (even if not a path). */ ++ if ((size_t)(cp - tzval) >= PATH_MAX) ++ debug_return_bool(false); ++ ++ debug_return_bool(true); ++} ++ ++/* + * Apply the env_check list. + * Returns true if the variable is allowed, false if denied + * or -1 if no match. +@@ -607,8 +655,13 @@ matches_env_check(const char *var) + iswild = false; + if (strncmp(cur->value, var, len) == 0 && + (iswild || var[len] == '=')) { ++ if (strncmp(var, "TZ=", 3) == 0 ) { ++ /* Sperial case for TZ */ ++ keepit = tz_is_sane(var + 3); ++ } else { + keepit = !strpbrk(var, "/%"); +- break; ++ } ++ break; + } + } + debug_return_bool(keepit); diff --git a/SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch b/SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch new file mode 100644 index 00000000..27ad7ba1 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch @@ -0,0 +1,117 @@ +diff --git a/src/ttyname.c b/src/ttyname.c +index 32f093c..d8858f7 100644 +--- a/src/ttyname.c ++++ b/src/ttyname.c +@@ -414,53 +414,80 @@ get_process_ttyname(void) + } + #elif defined(__linux__) + /* +- * Return a string from ttyname() containing the tty to which the process is +- * attached or NULL if there is no tty associated with the process (or its +- * parent). First tries field 7 in /proc/pid/stat, then /proc/ppid/stat. +- * Falls back on ttyname of std{in,out,err} if that fails. ++ * Store the name of the tty to which the process is attached in name. ++ * Returns name on success and NULL on failure, setting errno. + */ + char * + get_process_ttyname(void) + { +- char *line = NULL, *tty = NULL; +- size_t linesize = 0; +- ssize_t len; +- int i; ++ const char path[] = "/proc/self/stat"; ++ char *cp, buf[1024]; ++ char *ret = NULL; ++ int serrno = errno; ++ ssize_t nread; ++ int fd; + debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) + +- /* Try to determine the tty from tty_nr in /proc/pid/stat. */ +- for (i = 0; tty == NULL && i < 2; i++) { +- FILE *fp; +- char path[PATH_MAX]; +- (void)snprintf(path, sizeof(path), "/proc/%u/stat", +- i ? (unsigned int)getppid() : (unsigned int)getpid()); +- if ((fp = fopen(path, "r")) == NULL) +- continue; +- len = getline(&line, &linesize, fp); +- fclose(fp); +- if (len != -1) { ++ /* ++ * Try to determine the tty from tty_nr in /proc/self/stat. ++ * Ignore /proc/self/stat if it contains embedded NUL bytes. ++ */ ++ if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) { ++ cp = buf; ++ while ((nread = read(fd, cp, buf + sizeof(buf) - cp)) != 0) { ++ if (nread == -1) { ++ if (errno == EAGAIN || errno == EINTR) ++ continue; ++ break; ++ } ++ cp += nread; ++ if (cp >= buf + sizeof(buf)) ++ break; ++ } ++ if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) { + /* + * Field 7 is the tty dev (0 if no tty). +- * Since the process name at field 2 "(comm)" may include spaces, +- * start at the last ')' found. ++ * Since the process name at field 2 "(comm)" may include ++ * whitespace (including newlines), start at the last ')' found. + */ +- char *cp = strrchr(line, ')'); +- int field = 2; +- while (*cp != '\0') { +- if (*cp++ == ' ') { +- if (++field == 7) { +- dev_t tdev = (dev_t)atoi(cp); +- if (tdev > 0) +- tty = sudo_ttyname_dev(tdev); +- break; ++ *cp = '\0'; ++ cp = strrchr(buf, ')'); ++ if (cp != NULL) { ++ char *ep = cp; ++ int field = 1; ++ ++ while (*++ep != '\0') { ++ if (*ep == ' ') { ++ *ep = '\0'; ++ if (++field == 7) { ++ dev_t tdev = (dev_t)strtol(cp, NULL, 10); ++ if (tdev == 0 || errno == ERANGE || errno == EINVAL) { ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, ++ "%s: tty device %s: %s", path, cp, strerror(errno)); ++ } ++ if (tdev > 0) { ++ errno = serrno; ++ ret = sudo_ttyname_dev(tdev); ++ goto done; ++ } ++ break; ++ } ++ cp = ep + 1; + } + } + } + } + } +- efree(line); ++ errno = ENOENT; + +- debug_return_str(tty); ++done: ++ if (fd != -1) ++ close(fd); ++ if (ret == NULL) ++ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, ++ "unable to resolve tty via %s", path); ++ ++ debug_return_str(ret); + } + #else + /* diff --git a/SOURCES/sudo-1.8.6p7-authlogicfix.patch b/SOURCES/sudo-1.8.6p7-authlogicfix.patch new file mode 100644 index 00000000..f7215892 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-authlogicfix.patch @@ -0,0 +1,38 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.authlogicfix sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.authlogicfix 2015-07-05 13:40:15.389145839 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2015-07-05 13:40:15.413145478 +0200 +@@ -2392,9 +2392,13 @@ sudo_ldap_lookup(struct sudo_nss *nss, i + for (i = 0; i < lres->nentries; i++) { + entry = lres->entries[i].entry; + if ((pwcheck == any && doauth != false) || +- (pwcheck == all && doauth == false)) { +- doauth = sudo_ldap_check_bool(ld, entry, "authenticate"); ++ (pwcheck == all && doauth != true)) { ++ doauth = !!sudo_ldap_check_bool(ld, entry, "authenticate"); + } ++ } ++ ++ for (i = 0; i < lres->nentries; i++) { ++ entry = lres->entries[i].entry; + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.authlogicfix sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.authlogicfix 2015-07-05 13:40:15.412145494 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2015-07-05 13:40:15.414145463 +0200 +@@ -970,9 +970,13 @@ sudo_sss_lookup(struct sudo_nss *nss, in + for (i = 0; i < sss_result->num_rules; i++) { + rule = sss_result->rules + i; + if ((pwcheck == any && doauth != false) || +- (pwcheck == all && doauth == false)) { +- doauth = sudo_sss_check_bool(handle, rule, "authenticate"); ++ (pwcheck == all && doauth != true)) { ++ doauth = !!sudo_sss_check_bool(handle, rule, "authenticate"); + } ++ } ++ ++ for (i = 0; i < sss_result->num_rules; i++) { ++ rule = sss_result->rules + i; + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || diff --git a/SOURCES/sudo-1.8.6p7-clangfixes.patch b/SOURCES/sudo-1.8.6p7-clangfixes.patch new file mode 100644 index 00000000..70d9aff7 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-clangfixes.patch @@ -0,0 +1,46 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.clangfixes sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.clangfixes 2014-09-30 10:31:43.920885432 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2014-09-30 10:32:39.413228871 +0200 +@@ -313,9 +313,9 @@ static int sudo_sss_close(struct sudo_ns + if (nss && nss->handle) { + handle = nss->handle; + dlclose(handle->ssslib); ++ efree(nss->handle); + } + +- efree(nss->handle); + debug_return_int(0); + } + +@@ -755,12 +755,15 @@ sudo_sss_result_get(struct sudo_nss *nss + *state |= _SUDO_SSS_STATE_HOSTMATCH; + } + } ++ sudo_debug_printf(SUDO_DEBUG_DEBUG, ++ "u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result, ++ u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules); ++ } else { ++ sudo_debug_printf(SUDO_DEBUG_DEBUG, ++ "u_sss_result=(%p, %u) => f_sss_result=NULL", u_sss_result, ++ u_sss_result->num_rules); + } + +- sudo_debug_printf(SUDO_DEBUG_DEBUG, +- "u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result, +- u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules); +- + handle->fn_free_result(u_sss_result); + + debug_return_ptr(f_sss_result); +diff -up sudo-1.8.6p7/plugins/sudoers/visudo.c.clangfixes sudo-1.8.6p7/plugins/sudoers/visudo.c +--- sudo-1.8.6p7/plugins/sudoers/visudo.c.clangfixes 2014-09-30 10:34:08.689174020 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/visudo.c 2014-09-30 11:00:15.215654285 +0200 +@@ -544,7 +544,7 @@ reparse_sudoers(char *editor, char *args + continue; + edit_sudoers(sp, editor, args, errorlineno); + } +- } while (parse_error); ++ } while (parse_error && sp != NULL); + + debug_return; + } diff --git a/SOURCES/sudo-1.8.6p7-closefrom-override-fix.patch b/SOURCES/sudo-1.8.6p7-closefrom-override-fix.patch new file mode 100644 index 00000000..73fc84cd --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-closefrom-override-fix.patch @@ -0,0 +1,38 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/sudoers.c.closefrom-override-fix sudo-1.8.6p7/plugins/sudoers/sudoers.c +--- sudo-1.8.6p7/plugins/sudoers/sudoers.c.closefrom-override-fix 2016-02-15 10:31:11.694164366 +0100 ++++ sudo-1.8.6p7/plugins/sudoers/sudoers.c 2016-02-15 10:33:47.711362062 +0100 +@@ -336,15 +336,6 @@ sudoers_policy_main(int argc, char * con + goto bad; + } + +- /* Check for -C overriding def_closefrom. */ +- if (user_closefrom >= 0 && user_closefrom != def_closefrom) { +- if (!def_closefrom_override) { +- warningx(_("you are not permitted to use the -C option")); +- goto bad; +- } +- def_closefrom = user_closefrom; +- } +- + set_perms(PERM_INITIAL); + + /* Environment variables specified on the command line. */ +@@ -374,8 +365,17 @@ sudoers_policy_main(int argc, char * con + if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) + def_preserve_groups = true; + +- /* Find command in path */ ++ /* Find command in path and apply per-command Defaults. */ + cmnd_status = set_cmnd(); ++ ++ /* Check for -C overriding def_closefrom. */ ++ if (user_closefrom >= 0 && user_closefrom != def_closefrom) { ++ if (!def_closefrom_override) { ++ warningx(_("you are not permitted to use the -C option")); ++ goto bad; ++ } ++ def_closefrom = user_closefrom; ++ } + + #ifdef HAVE_SETLOCALE + if (!setlocale(LC_ALL, def_sudoers_locale)) { diff --git a/SOURCES/sudo-1.8.6p7-constwarnfix.patch b/SOURCES/sudo-1.8.6p7-constwarnfix.patch new file mode 100644 index 00000000..5e3a6f67 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-constwarnfix.patch @@ -0,0 +1,104 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/match.c.constwarnfix sudo-1.8.6p7/plugins/sudoers/match.c +--- sudo-1.8.6p7/plugins/sudoers/match.c.constwarnfix 2014-09-29 15:55:50.996485025 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/match.c 2014-09-29 15:55:51.002484954 +0200 +@@ -599,7 +599,7 @@ command_matches_dir(char *sudoers_dir, s + * Returns true if the hostname matches the pattern, else false + */ + bool +-hostname_matches(char *shost, char *lhost, char *pattern) ++hostname_matches(const char *shost, const char *lhost, const char *pattern) + { + debug_decl(hostname_matches, SUDO_DEBUG_MATCH) + +@@ -621,7 +621,7 @@ hostname_matches(char *shost, char *lhos + * else returns false. + */ + bool +-userpw_matches(char *sudoers_user, char *user, struct passwd *pw) ++userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw) + { + debug_decl(userpw_matches, SUDO_DEBUG_MATCH) + if (pw != NULL && *sudoers_user == '#') { +@@ -640,7 +640,7 @@ userpw_matches(char *sudoers_user, char + * else returns false. + */ + bool +-group_matches(char *sudoers_group, struct group *gr) ++group_matches(const char *sudoers_group, const struct group *gr) + { + debug_decl(group_matches, SUDO_DEBUG_MATCH) + if (*sudoers_group == '#') { +@@ -659,7 +659,7 @@ group_matches(char *sudoers_group, struc + * else returns false. + */ + bool +-usergr_matches(char *group, char *user, struct passwd *pw) ++usergr_matches(const char *group, const char *user, const struct passwd *pw) + { + int matched = false; + struct passwd *pw0 = NULL; +@@ -707,7 +707,7 @@ done: + * XXX - swap order of host & shost + */ + bool +-netgr_matches(char *netgr, char *lhost, char *shost, char *user) ++netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user) + { + static char *domain; + #ifdef HAVE_GETDOMAINNAME +diff -up sudo-1.8.6p7/plugins/sudoers/parse.h.constwarnfix sudo-1.8.6p7/plugins/sudoers/parse.h +--- sudo-1.8.6p7/plugins/sudoers/parse.h.constwarnfix 2014-09-29 15:55:50.992485072 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/parse.h 2014-09-29 15:55:51.002484954 +0200 +@@ -188,11 +188,11 @@ bool addr_matches(char *n); + + /* match.c */ + bool command_matches(char *sudoers_cmnd, char *sudoers_args); +-bool group_matches(char *sudoers_group, struct group *gr); +-bool hostname_matches(char *shost, char *lhost, char *pattern); +-bool netgr_matches(char *netgr, char *lhost, char *shost, char *user); +-bool usergr_matches(char *group, char *user, struct passwd *pw); +-bool userpw_matches(char *sudoers_user, char *user, struct passwd *pw); ++bool group_matches(const char *sudoers_group, const struct group *gr); ++bool hostname_matches(const char *shost, const char *lhost, const char *pattern); ++bool netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user); ++bool usergr_matches(const char *group, const char *user, const struct passwd *pw); ++bool userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw); + int cmnd_matches(struct member *m); + int cmndlist_matches(struct member_list *list); + int hostlist_matches(struct member_list *list); +diff -up sudo-1.8.6p7/plugins/sudoers/pwutil.c.constwarnfix sudo-1.8.6p7/plugins/sudoers/pwutil.c +--- sudo-1.8.6p7/plugins/sudoers/pwutil.c.constwarnfix 2013-02-25 20:42:44.000000000 +0100 ++++ sudo-1.8.6p7/plugins/sudoers/pwutil.c 2014-09-29 15:55:51.003484942 +0200 +@@ -841,7 +841,7 @@ sudo_endgrent(void) + } + + struct group_list * +-sudo_get_grlist(struct passwd *pw) ++sudo_get_grlist(const struct passwd *pw) + { + struct cache_item key, *item; + struct rbnode *node; +@@ -905,7 +905,7 @@ done: + } + + bool +-user_in_group(struct passwd *pw, const char *group) ++user_in_group(const struct passwd *pw, const char *group) + { + struct group_list *grlist; + struct group *grp = NULL; +diff -up sudo-1.8.6p7/plugins/sudoers/sudoers.h.constwarnfix sudo-1.8.6p7/plugins/sudoers/sudoers.h +--- sudo-1.8.6p7/plugins/sudoers/sudoers.h.constwarnfix 2013-02-25 20:49:09.000000000 +0100 ++++ sudo-1.8.6p7/plugins/sudoers/sudoers.h 2014-09-29 15:55:51.003484942 +0200 +@@ -288,9 +288,9 @@ __dso_public struct group *sudo_getgrgid + __dso_public struct group *sudo_getgrnam(const char *); + __dso_public void sudo_gr_addref(struct group *); + __dso_public void sudo_gr_delref(struct group *); +-bool user_in_group(struct passwd *, const char *); ++bool user_in_group(const struct passwd *, const char *); + struct group *sudo_fakegrnam(const char *); +-struct group_list *sudo_get_grlist(struct passwd *pw); ++struct group_list *sudo_get_grlist(const struct passwd *pw); + struct passwd *sudo_fakepwnam(const char *, gid_t); + struct passwd *sudo_fakepwnamid(const char *user, uid_t uid, gid_t gid); + struct passwd *sudo_getpwnam(const char *); diff --git a/SOURCES/sudo-1.8.6p7-digest-backport-checklinkfix.patch b/SOURCES/sudo-1.8.6p7-digest-backport-checklinkfix.patch new file mode 100644 index 00000000..feeeb6c2 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-digest-backport-checklinkfix.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/Makefile.in.digest-backport-checklinkfix sudo-1.8.6p7/plugins/sudoers/Makefile.in +--- sudo-1.8.6p7/plugins/sudoers/Makefile.in.digest-backport-checklinkfix 2015-08-25 14:31:24.889199953 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/Makefile.in 2015-08-25 14:32:34.817198098 +0200 +@@ -146,7 +146,7 @@ TEST_OBJS = interfaces.o testsudoers.o t + + CHECK_ADDR_OBJS = check_addr.o match_addr.o interfaces.o error.o + +-CHECK_FILL_OBJS = check_fill.o toke_util.o error.o ++CHECK_FILL_OBJS = check_fill.o toke_util.o error.o hexchar.o + + CHECK_IOLOG_PATH_OBJS = check_iolog_path.o error.o iolog_path.o pwutil.o \ + redblack.o diff --git a/SOURCES/sudo-1.8.6p7-digest-backport-docs.patch b/SOURCES/sudo-1.8.6p7-digest-backport-docs.patch new file mode 100644 index 00000000..2b99b26b --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-digest-backport-docs.patch @@ -0,0 +1,260 @@ +diff -up sudo-1.8.6p7/doc/sudoers.cat.digest-backport-docs sudo-1.8.6p7/doc/sudoers.cat +--- sudo-1.8.6p7/doc/sudoers.cat.digest-backport-docs 2015-07-07 13:06:11.078653045 +0200 ++++ sudo-1.8.6p7/doc/sudoers.cat 2015-07-07 13:12:05.170955417 +0200 +@@ -260,6 +260,14 @@ SSUUDDOOEERRSS FFIILLEE FFO + ``localhost'' will only match if that is the actual host name, which is + usually only the case for non-networked systems. + ++ digest ::= [A-Fa-f0-9]+ | ++ [[A-Za-z0-9+/=]+ ++ ++ Digest_Spec ::= "sha224" ':' digest | ++ "sha256" ':' digest | ++ "sha384" ':' digest | ++ "sha512" ':' digest ++ + Cmnd_List ::= Cmnd | + Cmnd ',' Cmnd_List + +@@ -267,7 +275,7 @@ SSUUDDOOEERRSS FFIILLEE FFO + file name args | + file name '""' + +- Cmnd ::= '!'* command name | ++ Cmnd ::= Digest_Spec? '!'* command name | + '!'* directory | + '!'* "sudoedit" | + '!'* Cmnd_Alias +@@ -291,6 +299,26 @@ SSUUDDOOEERRSS FFIILLEE FFO + to permit a user to run ssuuddoo with the --ee option (or as ssuuddooeeddiitt). It may + take command line arguments just as a normal command does. + ++ If a command name is prefixed with a Digest_Spec, the command will only ++ match successfully if it can be verified using the specified SHA-2 ++ digest. This may be useful in situations where the user invoking ssuuddoo ++ has write access to the command or its parent directory. The following ++ digest formats are supported: sha224, sha256, sha384 and sha512. The ++ string may be specified in either hex or base64 format (base64 is more ++ compact). There are several utilities capable of generating SHA-2 ++ digests in hex format such as openssl, shasum, sha224sum, sha256sum, ++ sha384sum, sha512sum. ++ ++ For example, using openssl: ++ ++ $ openssl dgst -sha224 /bin/ls ++ SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25 ++ ++ It is also possible to use openssl to generate base64 output: ++ ++ $ openssl dgst -binary -sha224 /bin/ls | openssl base64 ++ EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ== ++ + DDeeffaauullttss + Certain configuration options may be changed from their default values at + run-time via one or more Default_Entry lines. These may affect all users +@@ -1797,7 +1825,9 @@ EEXXAAMMPPLLEESS + + # Cmnd alias specification + Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\ +- /usr/sbin/restore, /usr/sbin/rrestore ++ /usr/sbin/restore, /usr/sbin/rrestore\ ++ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \ ++ /home/operator/bin/start_backups + Cmnd_Alias KILL = /usr/bin/kill + Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm + Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown +@@ -1867,7 +1897,11 @@ EEXXAAMMPPLLEESS + The ooppeerraattoorr user may run commands limited to simple maintenance. Here, + those are commands related to backups, killing processes, the printing + system, shutting down the system, and any commands in the directory +- _/_u_s_r_/_o_p_e_r_/_b_i_n_/. ++ _/_u_s_r_/_o_p_e_r_/_b_i_n_/. Note that one command in the DUMPS Cmnd_Alias includes a ++ sha224 digest, _/_h_o_m_e_/_o_p_e_r_a_t_o_r_/_b_i_n_/_s_t_a_r_t___b_a_c_k_u_p_s. This is because the ++ directory containing the script is writable by the operator user. If the ++ script is modified (resulting in a digest mismatch) it will no longer be ++ possible to run it via ssuuddoo. + + joe ALL = /usr/bin/su operator + +diff -up sudo-1.8.6p7/doc/sudoers.man.in.digest-backport-docs sudo-1.8.6p7/doc/sudoers.man.in +--- sudo-1.8.6p7/doc/sudoers.man.in.digest-backport-docs 2015-07-07 13:06:28.363472547 +0200 ++++ sudo-1.8.6p7/doc/sudoers.man.in 2015-07-07 13:16:05.250448374 +0200 +@@ -602,6 +602,14 @@ only the case for non-networked systems. + .nf + .sp + .RS 0n ++digest ::= [A-Fa-f0-9]+ | ++ [[A-Za-z0-9\+/=]+ ++ ++Digest_Spec ::= "sha224" ':' digest | ++ "sha256" ':' digest | ++ "sha384" ':' digest | ++ "sha512" ':' digest ++ + Cmnd_List ::= Cmnd | + Cmnd ',' Cmnd_List + +@@ -609,7 +617,7 @@ command name ::= file name | + file name args | + file name '""' + +-Cmnd ::= '!'* command name | ++Cmnd ::= Digest_Spec? '!'* command name | + '!'* directory | + '!'* "sudoedit" | + '!'* Cmnd_Alias +@@ -664,6 +672,39 @@ with the + option (or as + \fBsudoedit\fR). + It may take command line arguments just as a normal command does. ++.PP ++If a ++\fRcommand name\fR ++is prefixed with a ++\fRDigest_Spec\fR, ++the command will only match successfully if it can be verified ++using the specified SHA-2 digest. ++This may be useful in situations where the user invoking ++\fBsudo\fR ++has write access to the command or its parent directory. ++The following digest formats are supported: sha224, sha256, sha384 and sha512. ++The string may be specified in either hex or base64 format ++(base64 is more compact). ++There are several utilities capable of generating SHA-2 digests in hex ++format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum. ++.PP ++For example, using openssl: ++.nf ++.sp ++.RS 0n ++$ openssl dgst -sha224 /bin/ls ++SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25 ++.RE ++.fi ++.PP ++It is also possible to use openssl to generate base64 output: ++.nf ++.sp ++.RS 0n ++$ openssl dgst -binary -sha224 /bin/ls | openssl base64 ++EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ== ++.RE ++.fi + .SS "Defaults" + Certain configuration options may be changed from their default + values at run-time via one or more +@@ -3684,7 +3725,9 @@ Host_Alias CDROM = orion, perseus, hercu + + # Cmnd alias specification + Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e +- /usr/sbin/restore, /usr/sbin/rrestore ++ /usr/sbin/restore, /usr/sbin/rrestore\e ++ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \e ++ /home/operator/bin/start_backups + Cmnd_Alias KILL = /usr/bin/kill + Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm + Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown +@@ -3836,6 +3879,15 @@ Here, those are commands related to back + printing system, shutting down the system, and any commands in the + directory + \fI/usr/oper/bin/\fR. ++Note that one command in the ++\fRDUMPS\fR ++Cmnd_Alias includes a sha224 digest, ++\fI/home/operator/bin/start_backups\fR. ++This is because the directory containing the script is writable by the ++operator user. ++If the script is modified (resulting in a digest mismatch) it will no longer ++be possible to run it via ++\fBsudo\fR. + .nf + .sp + .RS 0n +diff -up sudo-1.8.6p7/doc/sudoers.mdoc.in.digest-backport-docs sudo-1.8.6p7/doc/sudoers.mdoc.in +--- sudo-1.8.6p7/doc/sudoers.mdoc.in.digest-backport-docs 2015-07-07 13:06:18.919571166 +0200 ++++ sudo-1.8.6p7/doc/sudoers.mdoc.in 2015-07-07 13:23:45.072854748 +0200 +@@ -579,6 +579,14 @@ Also, the host name + will only match if that is the actual host name, which is usually + only the case for non-networked systems. + .Bd -literal ++digest ::= [A-Fa-f0-9]+ | ++ [[A-Za-z0-9\+/=]+ ++ ++Digest_Spec ::= "sha224" ':' digest | ++ "sha256" ':' digest | ++ "sha384" ':' digest | ++ "sha512" ':' digest ++ + Cmnd_List ::= Cmnd | + Cmnd ',' Cmnd_List + +@@ -586,7 +594,7 @@ command name ::= file name | + file name args | + file name '""' + +-Cmnd ::= '!'* command name | ++Cmnd ::= Digest_Spec? '!'* command name | + '!'* directory | + '!'* "sudoedit" | + '!'* Cmnd_Alias +@@ -640,6 +648,33 @@ with the + option (or as + .Nm sudoedit ) . + It may take command line arguments just as a normal command does. ++.Pp ++If a ++.Li command name ++is prefixed with a ++.Li Digest_Spec , ++the command will only match successfully if it can be verified ++using the specified SHA-2 digest. ++This may be useful in situations where the user invoking ++.Nm sudo ++has write access to the command or its parent directory. ++The following digest formats are supported: sha224, sha256, sha384 and sha512. ++The string may be specified in either hex or base64 format ++(base64 is more compact). ++There are several utilities capable of generating SHA-2 digests in hex ++format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum. ++.Pp ++For example, using openssl: ++.Bd -literal ++$ openssl dgst -sha224 /bin/ls ++SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25 ++.Ed ++.Pp ++It is also possible to use openssl to generate base64 output: ++.Bd -literal ++$ openssl dgst -binary -sha224 /bin/ls | openssl base64 ++EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ== ++.Ed + .Ss Defaults + Certain configuration options may be changed from their default + values at run-time via one or more +@@ -3407,7 +3442,9 @@ Host_Alias CDROM = orion, perseus, hercu + + # Cmnd alias specification + Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e +- /usr/sbin/restore, /usr/sbin/rrestore ++ /usr/sbin/restore, /usr/sbin/rrestore\e ++ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \e ++ /home/operator/bin/start_backups + Cmnd_Alias KILL = /usr/bin/kill + Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm + Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown +@@ -3540,6 +3577,15 @@ Here, those are commands related to back + printing system, shutting down the system, and any commands in the + directory + .Pa /usr/oper/bin/ . ++Note that one command in the ++.Li DUMPS ++Cmnd_Alias includes a sha224 digest, ++.Pa /home/operator/bin/start_backups . ++This is because the directory containing the script is writable by the ++operator user. ++If the script is modified (resulting in a digest mismatch) it will no longer ++be possible to run it via ++.Nm sudo . + .Bd -literal + joe ALL = /usr/bin/su operator + .Ed diff --git a/SOURCES/sudo-1.8.6p7-digest-backport.patch b/SOURCES/sudo-1.8.6p7-digest-backport.patch new file mode 100644 index 00000000..a814b2c8 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-digest-backport.patch @@ -0,0 +1,435 @@ +From c8a6eecf768d8102a9a77f5fdb5b516e571d462e Mon Sep 17 00:00:00 2001 +From: Radovan Sroka +Date: Tue, 23 Aug 2016 13:43:08 +0200 +Subject: [PATCH] Using libgcrypt + +Using libgcrypt and not sudo implementation of SHA... + +Rebased patch of digest backport. +Added option --with-gcrypt + +Rebased from: +Patch35: sudo-1.8.6p7-digest-backport.patch + +Resolves: +rhbz#1183818 +--- + configure.ac | 16 +++++++ + plugins/sudoers/Makefile.in | 9 +++- + plugins/sudoers/filedigest.c | 104 +++++++++++++++++++++++++++++++++++++++++++ + plugins/sudoers/filedigest.h | 17 +++++++ + plugins/sudoers/match.c | 94 ++++++++++++++++++++++++++++++-------- + 5 files changed, 219 insertions(+), 21 deletions(-) + create mode 100644 plugins/sudoers/filedigest.c + create mode 100644 plugins/sudoers/filedigest.h + +diff --git a/configure.ac b/configure.ac +index 13c3c1b..54929b2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -35,6 +35,7 @@ AC_SUBST([SUDO_OBJS]) + AC_SUBST([LIBS]) + AC_SUBST([SUDO_LIBS]) + AC_SUBST([SUDOERS_LIBS]) ++AC_SUBST([LIBPARSESUDOERS_LIBS]) + AC_SUBST([STATIC_SUDOERS]) + AC_SUBST([NET_LIBS]) + AC_SUBST([AFS_LIBS]) +@@ -1517,6 +1518,19 @@ AC_ARG_WITH(selinux, [AS_HELP_STRING([--with-selinux], [enable SELinux support]) + ;; + esac], [with_selinux=no]) + ++AC_ARG_WITH(gcrypt, [AS_HELP_STRING([--with-gcrypt], [enable libgcrypt support])], ++[case $with_gcrypt in ++ yes) ++ AC_DEFINE(HAVE_LIBGCRYPT) ++ LIBPARSESUDOERS_LIBS="${LIBPARSESUDOERS_LIBS} -lgcrypt" ++ AC_CHECK_LIB([gcrypt], [gcry_md_open], ++ [AC_DEFINE(HAVE_GCRY_MD_OPEN)]) ++ ;; ++ no) ;; ++ *) AC_MSG_ERROR(["--with-gcrypt does not take an argument."]) ++ ;; ++esac]) ++ + dnl + dnl gss_krb5_ccache_name() may not work on Heimdal so we don't use it by default + dnl +@@ -4344,6 +4358,8 @@ AH_TEMPLATE(HAVE_PROJECT_H, [Define to 1 if you have the header file + AH_TEMPLATE(HAVE_SECURID, [Define to 1 if you use SecurID for authentication.]) + AH_TEMPLATE(HAVE_SELINUX, [Define to 1 to enable SELinux RBAC support.]) + AH_TEMPLATE(HAVE_SETKEYCREATECON, [Define to 1 if you have the `setkeycreatecon' function.]) ++AH_TEMPLATE(HAVE_LIBGCRYPT, [Define to 1 to enable libgcrypt support.]) ++AH_TEMPLATE(HAVE_GCRY_MD_OPEN, [Define to 1 if you have the `gcry_md_open' function.]) + AH_TEMPLATE(HAVE_SHL_LOAD, [Define to 1 if you have the `shl_load' function.]) + AH_TEMPLATE(HAVE_SKEY, [Define to 1 if you use S/Key.]) + AH_TEMPLATE(HAVE_SKEYACCESS, [Define to 1 if your S/Key library has skeyaccess().]) +diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in +index f36f9ef..32c0ed0 100644 +--- a/plugins/sudoers/Makefile.in ++++ b/plugins/sudoers/Makefile.in +@@ -55,6 +55,7 @@ LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la + LIBS = $(LT_LIBS) + NET_LIBS = @NET_LIBS@ + SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) @ZLIB@ @LIBMD@ ++LIBPARSESUDOERS_LIBS = @LIBPARSESUDOERS_LIBS@ + REPLAY_LIBS = @REPLAY_LIBS@ @ZLIB@ + VISUDO_LIBS = $(NET_LIBS) @LIBMD@ + TESTSUDOERS_LIBS = $(NET_LIBS) @LIBMD@ +@@ -153,7 +154,7 @@ AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@ + LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo hexchar.lo \ + gram.lo match.lo match_addr.lo pwutil.lo pwutil_impl.lo \ + rcstr.lo redblack.lo sudoers_debug.lo timestr.lo \ +- toke.lo toke_util.lo ++ toke.lo toke_util.lo filedigest.lo + + SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo find_path.lo \ + gc.lo goodpath.lo group_plugin.lo interfaces.lo iolog.lo \ +@@ -217,7 +218,7 @@ Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file plugins/sudoers/Makefile) + + libparsesudoers.la: $(LIBPARSESUDOERS_OBJS) +- $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) -no-install ++ $(LIBTOOL) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) $(LIBPARSESUDOERS_LIBS) -no-install + + sudoers.la: $(SUDOERS_OBJS) $(LT_LIBS) libparsesudoers.la @LT_LDDEP@ + case "$(LT_LDFLAGS)" in \ +@@ -656,6 +657,10 @@ env.lo: $(srcdir)/env.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ + $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h + $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/env.c ++filedigest.lo: $(srcdir)/filedigest.c $(top_builddir)/config.h \ ++ $(incdir)/sudo_debug.h ++ $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/filedigest.c ++filedigest.o: filedigest.lo + find_path.lo: $(srcdir)/find_path.c $(devdir)/def_data.h \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ +diff --git a/plugins/sudoers/filedigest.c b/plugins/sudoers/filedigest.c +new file mode 100644 +index 0000000..c173741 +--- /dev/null ++++ b/plugins/sudoers/filedigest.c +@@ -0,0 +1,104 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "filedigest.h" ++#include "sudo_compat.h" ++#include "sudo_debug.h" ++ ++#if defined(HAVE_LIBGCRYPT) ++#include ++ ++static int sudo_filedigest_gcrypt(int fd, int algo, unsigned char **dvalue, size_t *dvalue_size) ++{ ++ char buffer[4096]; ++ gcry_md_hd_t ctx; ++ int gcry_algo; ++ debug_decl(sudo_filedigest_gcrypt, SUDO_DEBUG_UTIL); ++ ++ switch(algo) { ++ case SUDO_DIGEST_SHA224: ++ gcry_algo = GCRY_MD_SHA224; break; ++ case SUDO_DIGEST_SHA256: ++ gcry_algo = GCRY_MD_SHA256; break; ++ case SUDO_DIGEST_SHA384: ++ gcry_algo = GCRY_MD_SHA384; break; ++ case SUDO_DIGEST_SHA512: ++ gcry_algo = GCRY_MD_SHA512; break; ++ default: ++ debug_return_int(-1); ++ } ++ ++ gcry_md_open(&ctx, gcry_algo, 0); ++ ++ /* Read block of data from fd and digest them */ ++ while (1) { ++ const ssize_t read_bytes = read(fd, buffer, sizeof buffer); ++ ++ if (read_bytes < 0) { ++ /* Error */ ++ gcry_md_close(ctx); ++ debug_return_int(-1); ++ } ++ else if (read_bytes > 0) { ++ /* Some data read -- update the digest */ ++ gcry_md_write(ctx, buffer, (size_t)read_bytes); ++ } ++ else { ++ /* EOF */ ++ break; ++ } ++ } ++ ++ /* ++ * All data digested. Finalize the digest value. ++ */ ++ const unsigned char *value = gcry_md_read(ctx, gcry_algo); ++ ++ if (value == NULL) { ++ debug_return_int(-1); ++ } ++ ++ /* ++ * Make a copy of the digest value. The pointer ++ * returned from gcry_md_read cannot be used after ++ * gcry_md_close was called ++ */ ++ (*dvalue_size) = gcry_md_get_algo_dlen(gcry_algo); ++ (*dvalue) = malloc(*dvalue_size); ++ ++ if (*dvalue == NULL) { ++ debug_return_int(-1); ++ } ++ ++ memcpy(*dvalue, value, *dvalue_size); ++ gcry_md_close(ctx); ++ ++ debug_return_int(0); ++} ++#endif ++ ++#include ++ ++int sudo_filedigest(const char *path, int algo, unsigned char **dvalue, size_t *dvalue_size) ++{ ++ int rc = -1; ++ int fd = -1; ++ debug_decl(sudo_filedigest, SUDO_DEBUG_UTIL); ++ ++ if ((fd = open(path, O_RDONLY)) < 0) { ++ debug_return_int(rc); ++ } ++ ++#if defined(HAVE_LIBGCRYPT) ++ rc = sudo_filedigest_gcrypt(fd, algo, dvalue, dvalue_size); ++ close(fd); ++#else ++ rc = -1; ++ errno = ENOTSUP; ++#endif ++ debug_return_int(rc); ++} +diff --git a/plugins/sudoers/filedigest.h b/plugins/sudoers/filedigest.h +new file mode 100644 +index 0000000..437f02f +--- /dev/null ++++ b/plugins/sudoers/filedigest.h +@@ -0,0 +1,17 @@ ++#include ++ ++#define SUDO_DIGEST_SHA224 0 ++#define SUDO_DIGEST_SHA256 1 ++#define SUDO_DIGEST_SHA384 2 ++#define SUDO_DIGEST_SHA512 3 ++#define SUDO_DIGEST_INVALID 4 ++ ++#define SUDO_SHA224_DIGEST_LENGTH 28 ++#define SUDO_SHA256_DIGEST_LENGTH 32 ++#define SUDO_SHA384_DIGEST_LENGTH 48 ++#define SUDO_SHA512_DIGEST_LENGTH 64 ++ ++/* ++ * Compute a digest of a given file. Returns 0 on success, -1 otherwise. ++ */ ++int sudo_filedigest(const char *path, int algo, unsigned char **dvalue, size_t *dvalue_size); +diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c +index 1916bde..2a9ea4b 100644 +--- a/plugins/sudoers/match.c ++++ b/plugins/sudoers/match.c +@@ -62,6 +62,7 @@ + + #include "sudoers.h" + #include "parse.h" ++#include "filedigest.h" + #include + + #ifdef HAVE_FNMATCH +@@ -576,6 +577,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const + } + #else /* !SUDOERS_NAME_MATCH */ + ++#ifndef HAVE_LIBGCRYPT /* !!! */ + static struct digest_function { + const char *digest_name; + const unsigned int digest_len; +@@ -616,24 +618,43 @@ static struct digest_function { + NULL + } + }; ++#endif /* !HAVE_LIBGCRYPT */ ++ ++static const char *digesttype2str(int digest_type) ++{ ++ switch(digest_type) { ++ case SUDO_DIGEST_SHA224: ++ return "SHA224"; ++ case SUDO_DIGEST_SHA256: ++ return "SHA256"; ++ case SUDO_DIGEST_SHA384: ++ return "SHA384"; ++ case SUDO_DIGEST_SHA512: ++ return "SHA512"; ++ } ++ return ""; ++} + + static bool + digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + { +- unsigned char file_digest[SHA512_DIGEST_LENGTH]; +- unsigned char sudoers_digest[SHA512_DIGEST_LENGTH]; ++ unsigned char * file_digest = NULL; ++ unsigned char * sudoers_digest = NULL; ++ size_t digest_size; + unsigned char buf[32 * 1024]; +- struct digest_function *func = NULL; + #ifdef HAVE_FEXECVE + bool first = true; + bool is_script = false; + #endif /* HAVE_FEXECVE */ + size_t nread; +- SHA2_CTX ctx; + FILE *fp; + unsigned int i; + debug_decl(digest_matches, SUDOERS_DEBUG_MATCH) + ++#ifndef HAVE_LIBGCRYPT /* !!! */ ++ ++ SHA2_CTX ctx; ++ struct digest_function *func = NULL; + for (i = 0; digest_functions[i].digest_name != NULL; i++) { + if (sd->digest_type == i) { + func = &digest_functions[i]; +@@ -644,9 +665,33 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + sudo_warnx(U_("unsupported digest type %d for %s"), sd->digest_type, file); + debug_return_bool(false); + } +- if (strlen(sd->digest_str) == func->digest_len * 2) { ++ ++ digest_size = func->digest_len; ++ ++ file_digest = malloc(digest_size); ++ if (file_digest == NULL) { ++ debug_return_bool(false); ++ } ++ ++#elif HAVE_LIBGCRYPT ++ ++ if (sudo_filedigest(file, sd->digest_type, ++ &file_digest, &digest_size) != 0) { ++ sudo_warnx(U_("Cannot compute digest type %d for %s"), sd->digest_type, file); ++ goto clean_up; ++ } ++ ++#endif /* !HAVE_LIBGCRYPT */ ++ ++ sudoers_digest = malloc(digest_size); ++ if (sudoers_digest == NULL) { ++ free(file_digest); ++ debug_return_bool(false); ++ } ++ ++ if (strlen(sd->digest_str) == digest_size * 2) { + /* Convert the command digest from ascii hex to binary. */ +- for (i = 0; i < func->digest_len; i++) { ++ for (i = 0; i < digest_size ; i++) { + const int h = hexchar(&sd->digest_str[i + i]); + if (h == -1) + goto bad_format; +@@ -654,11 +699,11 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + } + } else { + size_t len = base64_decode(sd->digest_str, sudoers_digest, +- sizeof(sudoers_digest)); +- if (len != func->digest_len) { ++ digest_size); ++ if (len != digest_size) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, +- "incorrect length for digest, expected %u, got %zu", +- func->digest_len, len); ++ "incorrect length for digest, expected %zu, got %zu", ++ digest_size, len); + goto bad_format; + } + } +@@ -666,10 +711,11 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + if ((fp = fopen(file, "r")) == NULL) { + sudo_debug_printf(SUDO_DEBUG_INFO, "unable to open %s: %s", + file, strerror(errno)); +- debug_return_bool(false); ++ goto clean_up; + } +- ++#ifndef HAVE_LIBGCRYPT + func->init(&ctx); ++#endif /* !HAVE_LIBGCRYPT */ + while ((nread = fread(buf, 1, sizeof(buf), fp)) != 0) { + #ifdef HAVE_FEXECVE + /* Check for #! cookie and set is_script. */ +@@ -679,21 +725,24 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + is_script = true; + } + #endif /* HAVE_FEXECVE */ ++#ifndef HAVE_LIBGCRYPT + func->update(&ctx, buf, nread); ++#endif /* !HAVE_LIBGCRYPT */ + } + if (ferror(fp)) { + sudo_warnx(U_("%s: read error"), file); + fclose(fp); +- debug_return_bool(false); ++ goto clean_up; + } ++#ifndef HAVE_LIBGCRYPT + func->final(file_digest, &ctx); +- +- if (memcmp(file_digest, sudoers_digest, func->digest_len) != 0) { ++#endif /* !HAVE_LIBGCRYPT */ ++ if (memcmp(file_digest, sudoers_digest, digest_size) != 0) { + fclose(fp); + sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO, + "%s digest mismatch for %s, expecting %s", +- func->digest_name, file, sd->digest_str); +- debug_return_bool(false); ++ digesttype2str(sd->digest_type), file, sd->digest_str); ++ goto clean_up; + } + + #ifdef HAVE_FEXECVE +@@ -705,7 +754,7 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + sudo_debug_printf(SUDO_DEBUG_INFO, "unable to dup %s: %s", + file, strerror(errno)); + fclose(fp); +- debug_return_bool(false); ++ goto clean_up; + } + /* + * Shell scripts go through namei twice and so we can't set the close +@@ -715,10 +764,17 @@ digest_matches(const char *file, const struct sudo_digest *sd, int *fd) + (void)fcntl(*fd, F_SETFD, FD_CLOEXEC); + #endif /* HAVE_FEXECVE */ + fclose(fp); ++ free(file_digest); ++ free(sudoers_digest); + debug_return_bool(true); + bad_format: + sudo_warnx(U_("digest for %s (%s) is not in %s form"), file, +- sd->digest_str, func->digest_name); ++ sd->digest_str, digesttype2str(sd->digest_type)); ++clean_up: ++ if (file_digest) ++ free(file_digest); ++ if (sudoers_digest) ++ free(sudoers_digest); + debug_return_bool(false); + } + +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.6p7-digest_race_doc.patch b/SOURCES/sudo-1.8.6p7-digest_race_doc.patch new file mode 100644 index 00000000..32544b36 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-digest_race_doc.patch @@ -0,0 +1,88 @@ +diff -up sudo-1.8.6p7/doc/sudoers.cat.digest_race_doc sudo-1.8.6p7/doc/sudoers.cat +--- sudo-1.8.6p7/doc/sudoers.cat.digest_race_doc 2016-05-11 13:53:51.125141217 +0200 ++++ sudo-1.8.6p7/doc/sudoers.cat 2016-05-11 13:56:10.678178899 +0200 +@@ -301,13 +301,11 @@ SSUUDDOOEERRSS FFIILLEE FFO + + If a command name is prefixed with a Digest_Spec, the command will only + match successfully if it can be verified using the specified SHA-2 +- digest. This may be useful in situations where the user invoking ssuuddoo +- has write access to the command or its parent directory. The following +- digest formats are supported: sha224, sha256, sha384 and sha512. The +- string may be specified in either hex or base64 format (base64 is more +- compact). There are several utilities capable of generating SHA-2 +- digests in hex format such as openssl, shasum, sha224sum, sha256sum, +- sha384sum, sha512sum. ++ digest. The following digest formats are supported: sha224, sha256, ++ sha384 and sha512. The string may be specified in either hex or base64 ++ format (base64 is more compact). There are several utilities capable of ++ generating SHA-2 digests in hex format such as openssl, shasum, ++ sha224sum, sha256sum, sha384sum, sha512sum. + + For example, using openssl: + +@@ -319,6 +317,11 @@ SSUUDDOOEERRSS FFIILLEE FFO + $ openssl dgst -binary -sha224 /bin/ls | openssl base64 + EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ== + ++ If the user has write access to either the command itself or the ++ directory in which the command is located (directly or via a ssuuddoo ++ command) it may be possible for the user to replace the command after the ++ digest check has been performed but before the command is executed. ++ + DDeeffaauullttss + Certain configuration options may be changed from their default values at + run-time via one or more Default_Entry lines. These may affect all users +diff -up sudo-1.8.6p7/doc/sudoers.man.in.digest_race_doc sudo-1.8.6p7/doc/sudoers.man.in +--- sudo-1.8.6p7/doc/sudoers.man.in.digest_race_doc 2016-05-11 13:54:01.005002291 +0200 ++++ sudo-1.8.6p7/doc/sudoers.man.in 2016-05-11 13:58:28.541240345 +0200 +@@ -679,9 +679,6 @@ is prefixed with a + \fRDigest_Spec\fR, + the command will only match successfully if it can be verified + using the specified SHA-2 digest. +-This may be useful in situations where the user invoking +-\fBsudo\fR +-has write access to the command or its parent directory. + The following digest formats are supported: sha224, sha256, sha384 and sha512. + The string may be specified in either hex or base64 format + (base64 is more compact). +@@ -705,6 +702,13 @@ $ openssl dgst -binary -sha224 /bin/ls | + EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ== + .RE + .fi ++.PP ++If the user has write access to either the command itself or the ++directory in which the command is located (directly or via a ++\fBsudo\fR ++command) it may be possible for the user to replace the command ++after the digest check has been performed but before the command ++is executed. + .SS "Defaults" + Certain configuration options may be changed from their default + values at run-time via one or more +diff -up sudo-1.8.6p7/doc/sudoers.mdoc.in.digest_race_doc sudo-1.8.6p7/doc/sudoers.mdoc.in +--- sudo-1.8.6p7/doc/sudoers.mdoc.in.digest_race_doc 2016-05-11 13:54:07.749907447 +0200 ++++ sudo-1.8.6p7/doc/sudoers.mdoc.in 2016-05-11 13:59:22.263484933 +0200 +@@ -655,9 +655,6 @@ is prefixed with a + .Li Digest_Spec , + the command will only match successfully if it can be verified + using the specified SHA-2 digest. +-This may be useful in situations where the user invoking +-.Nm sudo +-has write access to the command or its parent directory. + The following digest formats are supported: sha224, sha256, sha384 and sha512. + The string may be specified in either hex or base64 format + (base64 is more compact). +@@ -675,6 +672,13 @@ It is also possible to use openssl to ge + $ openssl dgst -binary -sha224 /bin/ls | openssl base64 + EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ== + .Ed ++.Pp ++If the user has write access to either the command itself or the ++directory in which the command is located (directly or via a ++.Nm sudo ++command) it may be possible for the user to replace the command ++after the digest check has been performed but before the command ++is executed. + .Ss Defaults + Certain configuration options may be changed from their default + values at run-time via one or more diff --git a/SOURCES/sudo-1.8.6p7-digestmessagesfix.patch b/SOURCES/sudo-1.8.6p7-digestmessagesfix.patch new file mode 100644 index 00000000..929d526a --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-digestmessagesfix.patch @@ -0,0 +1,43 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/match.c.digestmessagesfix sudo-1.8.6p7/plugins/sudoers/match.c +--- sudo-1.8.6p7/plugins/sudoers/match.c.digestmessagesfix 2015-09-01 15:33:27.493054381 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/match.c 2015-09-01 15:33:31.327054279 +0200 +@@ -566,6 +566,21 @@ base64_decode(const char *in, unsigned c + return io; + } + ++static const char *digesttype2str(int digest_type) ++{ ++ switch(digest_type) { ++ case SUDO_DIGEST_SHA224: ++ return "SHA224"; ++ case SUDO_DIGEST_SHA256: ++ return "SHA256"; ++ case SUDO_DIGEST_SHA384: ++ return "SHA384"; ++ case SUDO_DIGEST_SHA512: ++ return "SHA512"; ++ } ++ return ""; ++} ++ + static bool + digest_matches(char *file, struct sudo_digest *sd) + { +@@ -597,7 +612,7 @@ digest_matches(char *file, struct sudo_d + if (!isxdigit((unsigned char)sd->digest_str[i + i]) || + !isxdigit((unsigned char)sd->digest_str[i + i + 1])) { + warningx(_("digest for %s (%s) is not in %s form"), file, +- sd->digest_str, sd->digest_str); ++ sd->digest_str, digesttype2str(sd->digest_type)); + goto bad_format; + } + sudoers_digest[i] = hexchar(&sd->digest_str[i + i]); +@@ -619,7 +634,7 @@ digest_matches(char *file, struct sudo_d + debug_return_bool(match); + bad_format: + warningx(_("digest for %s (%s) is not in %s form"), file, +- sd->digest_str, sd->digest_str); ++ sd->digest_str, digesttype2str(sd->digest_type)); + if (sudoers_digest) + efree(sudoers_digest); + if (file_digest) diff --git a/SOURCES/sudo-1.8.6p7-duplicatenssfix.patch b/SOURCES/sudo-1.8.6p7-duplicatenssfix.patch new file mode 100644 index 00000000..547eb41b --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-duplicatenssfix.patch @@ -0,0 +1,47 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/sudo_nss.c.duplicatenssfix sudo-1.8.6p7/plugins/sudoers/sudo_nss.c +--- sudo-1.8.6p7/plugins/sudoers/sudo_nss.c.duplicatenssfix 2014-09-29 15:30:35.243303099 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sudo_nss.c 2014-09-29 15:33:13.669439300 +0200 +@@ -88,16 +88,16 @@ sudo_read_nss(void) + for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) { + if (strcasecmp(cp, "files") == 0 && !saw_files) { + tq_append(&snl, &sudo_nss_file); +- got_match = true; ++ got_match = saw_files = true; + #ifdef HAVE_LDAP + } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) { + tq_append(&snl, &sudo_nss_ldap); +- got_match = true; ++ got_match = saw_ldap = true; + #endif + #ifdef HAVE_SSSD + } else if (strcasecmp(cp, "sss") == 0 && !saw_sss) { + tq_append(&snl, &sudo_nss_sss); +- got_match = true; ++ got_match = saw_sss = true; + #endif + } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { + /* NOTFOUND affects the most recent entry */ +@@ -171,20 +171,20 @@ sudo_read_nss(void) + if (!saw_files && strncasecmp(cp, "files", 5) == 0 && + (isspace((unsigned char)cp[5]) || cp[5] == '\0')) { + tq_append(&snl, &sudo_nss_file); +- got_match = true; ++ got_match = saw_files = true; + ep = &cp[5]; + #ifdef HAVE_LDAP + } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 && + (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { + tq_append(&snl, &sudo_nss_ldap); +- got_match = true; ++ got_match = saw_ldap = true; + ep = &cp[4]; + #endif + #ifdef HAVE_SSSD + } else if (!saw_sss && strncasecmp(cp, "sss", 3) == 0 && + (isspace((unsigned char)cp[3]) || cp[3] == '\0')) { + tq_append(&snl, &sudo_nss_sss); +- got_match = true; ++ got_match = saw_sss = true; + ep = &cp[3]; + #endif + } else { diff --git a/SOURCES/sudo-1.8.6p7-ipahostname.patch b/SOURCES/sudo-1.8.6p7-ipahostname.patch new file mode 100644 index 00000000..c17b78b0 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-ipahostname.patch @@ -0,0 +1,192 @@ +diff -up sudo-1.8.6p7/configure.in.ipahostname sudo-1.8.6p7/configure.in +--- sudo-1.8.6p7/configure.in.ipahostname 2014-09-29 11:14:38.393846226 +0200 ++++ sudo-1.8.6p7/configure.in 2014-09-29 11:14:38.428845807 +0200 +@@ -309,7 +309,7 @@ dnl Handle SSSD support. + dnl + AC_ARG_WITH(sssd, [AS_HELP_STRING([--with-sssd], [enable SSSD support])], + [case $with_sssd in +- yes) SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo" ++ yes) SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo ipa_hostname.lo" + AC_DEFINE(HAVE_SSSD) + ;; + no) ;; +diff -up sudo-1.8.6p7/plugins/sudoers/ipa_hostname.c.ipahostname sudo-1.8.6p7/plugins/sudoers/ipa_hostname.c +--- sudo-1.8.6p7/plugins/sudoers/ipa_hostname.c.ipahostname 2014-09-29 11:14:38.429845795 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ipa_hostname.c 2014-09-29 11:14:38.429845795 +0200 +@@ -0,0 +1,88 @@ ++/* ++ * Copyright 2013 Red Hat Inc., Durham, North Carolina. ++ * All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Authors: ++ * Daniel Kopecek ++ */ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++ ++static const char *sssd_conf_path = "/etc/sssd/sssd.conf"; ++ ++char *ipa_hostname(void) ++{ ++ static char hname[MAXHOSTNAMELEN+1]; ++ size_t hname_len = 0; ++ char *line = NULL; ++ ssize_t line_len = 0; ++ size_t line_buflen = 0; ++ FILE *fp; ++ ++ if ((fp = fopen(sssd_conf_path, "r")) == NULL) ++ return NULL; ++ while ((line_len = getline(&line, &line_buflen, fp)) > 0) { ++ char *keyword_loc; ++ if ((keyword_loc = strstr(line, "ipa_hostname")) != NULL) { ++ size_t i; ++ char *value_loc; ++ size_t value_len; ++ ++ value_loc = keyword_loc + strlen("ipa_hostname") + 1; ++ value_len = line_len - (size_t)(value_loc - line); ++ ++ /* Skip spaces and the assignment operator */ ++ for (i = 0; i < value_len; ++i) { ++ if (isspace(value_loc[i]) || value_loc[i] == '=') { ++ continue; ++ } else { ++ break; ++ } ++ } ++ ++ value_loc += i; ++ value_len -= i; ++ ++ if (value_len <= MAXHOSTNAMELEN) { ++ memcpy(hname, value_loc, value_len * sizeof(char)); ++ free(line); ++ fclose(fp); ++ hname_len = value_len; ++ hname[hname_len] = '\0'; ++ /* Remove spaces from the end of the string */ ++ for (i = hname_len - 1; i > 0; --i) { ++ if (isspace(hname[i])) { ++ hname[i] = '\0'; ++ --hname_len; ++ } else { ++ break; ++ } ++ } ++ return hname; ++ } ++ } ++ free(line); ++ line = NULL; ++ } ++ ++ fclose(fp); ++ return NULL; ++} +diff -up sudo-1.8.6p7/plugins/sudoers/ipa_hostname.h.ipahostname sudo-1.8.6p7/plugins/sudoers/ipa_hostname.h +--- sudo-1.8.6p7/plugins/sudoers/ipa_hostname.h.ipahostname 2014-09-29 11:14:38.429845795 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ipa_hostname.h 2014-09-29 11:14:38.429845795 +0200 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright 2013 Red Hat Inc., Durham, North Carolina. ++ * All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Authors: ++ * Daniel Kopecek ++ */ ++#ifndef _IPA_HOSTNAME_H_ ++#define _IPA_HOSTNAME_H_ ++ ++char *ipa_hostname(void); ++ ++#endif /* _IPA_HOSTNAME_H_ */ +diff -up sudo-1.8.6p7/plugins/sudoers/Makefile.in.ipahostname sudo-1.8.6p7/plugins/sudoers/Makefile.in +--- sudo-1.8.6p7/plugins/sudoers/Makefile.in.ipahostname 2014-09-29 11:14:38.429845795 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/Makefile.in 2014-09-29 11:16:54.923210160 +0200 +@@ -728,6 +728,9 @@ sia.lo: $(authdir)/sia.c $(top_builddir) + $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ + $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(authdir)/sia.c ++ipa_hostname.lo: $(srcdir)/ipa_hostname.c $(srcdir)/ipa_hostname.h ++ $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ipa_hostname.c ++ + sssd.lo: $(srcdir)/sssd.c $(top_builddir)/config.h \ + $(top_srcdir)/compat/dlfcn.h $(srcdir)/sudoers.h \ + $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \ +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.ipahostname sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.ipahostname 2014-09-29 11:14:38.424845855 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2014-09-29 11:14:38.429845795 +0200 +@@ -60,6 +60,7 @@ + #include "parse.h" + #include "lbuf.h" + #include "sudo_debug.h" ++#include "ipa_hostname.h" + + /* SSSD <--> SUDO interface - do not change */ + struct sss_sudo_attr { +@@ -549,6 +550,24 @@ sudo_sss_check_runas(struct sudo_sss_han + debug_return_bool(ret); + } + ++static bool sudo_sss_ipa_hostname_matches(const char *hostname_val) ++{ ++ bool ret = false; ++ char *ipa_hostname_val; ++ debug_decl(sudo_sss_ipa_hostname_matches, SUDO_DEBUG_SSSD) ++ ++ if ((ipa_hostname_val = ipa_hostname()) != NULL) { ++ ret = hostname_matches(ipa_hostname_val, ipa_hostname_val, hostname_val) || \ ++ netgr_matches(hostname_val, ipa_hostname_val, ipa_hostname_val, NULL); ++ } ++ ++ sudo_debug_printf(SUDO_DEBUG_TRACE, "IPA hostname (%s) matches %s => %s", ++ ipa_hostname_val ? ipa_hostname_val : "", hostname_val, ++ ret ? "true" : "false"); ++ ++ debug_return_bool(ret); ++} ++ + static bool + sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) + { +@@ -580,6 +599,7 @@ sudo_sss_check_host(struct sudo_sss_hand + + /* match any or address or netgroup or hostname */ + if (!strcmp(val, "ALL") || addr_matches(val) || ++ sudo_sss_ipa_hostname_matches(val) || + netgr_matches(val, user_host, user_shost, NULL) || + hostname_matches(user_shost, user_host, val)) + ret = true; diff --git a/SOURCES/sudo-1.8.6p7-ldap_sssd_parse_whitespaces.patch b/SOURCES/sudo-1.8.6p7-ldap_sssd_parse_whitespaces.patch new file mode 100644 index 00000000..5f0a575d --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-ldap_sssd_parse_whitespaces.patch @@ -0,0 +1,91 @@ +diff -up sudo-1.8.6p7/common/fmt_string.c.ldap_sssd_parse_whitespaces sudo-1.8.6p7/common/fmt_string.c +--- sudo-1.8.6p7/common/fmt_string.c.ldap_sssd_parse_whitespaces 2013-02-25 20:42:44.000000000 +0100 ++++ sudo-1.8.6p7/common/fmt_string.c 2016-05-11 10:31:30.206090322 +0200 +@@ -38,6 +38,8 @@ + # include + #endif /* HAVE_STRINGS_H */ + ++#include ++ + #include "missing.h" + #include "sudo_debug.h" + +@@ -64,3 +66,17 @@ fmt_string(const char *var, const char * + + debug_return_str(str); + } ++ ++char * rm_whitespaces(char * str){ ++ int state = 1; ++ char * c; ++ for (c = str ; *c != '\0' ; c++){ ++ if (state && isspace(*c))str++; ++ else if (!isspace(*c))state = 0; ++ else if (!state && isspace(*c)){ ++ *c = '\0'; ++ break; ++ } ++ } ++ return str; ++} +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.ldap_sssd_parse_whitespaces sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.ldap_sssd_parse_whitespaces 2016-05-11 10:31:30.202090379 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2016-05-11 10:31:30.207090307 +0200 +@@ -1012,17 +1012,17 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMe + if (op == '+' || op == '-') { + *(val - 2) = '\0'; /* found, remove extra char */ + /* case var+=val or var-=val */ +- set_default(var, strunquote(val), (int) op); ++ set_default(rm_whitespaces(var), strunquote(val), (int) op); + } else { + /* case var=val */ +- set_default(var, strunquote(val), true); ++ set_default(rm_whitespaces(var), strunquote(val), true); + } + } else if (*var == '!') { + /* case !var Boolean False */ +- set_default(var + 1, NULL, false); ++ set_default(rm_whitespaces(var + 1), NULL, false); + } else { + /* case var Boolean True */ +- set_default(var, NULL, true); ++ set_default(rm_whitespaces(var), NULL, true); + } + efree(var); + } +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.ldap_sssd_parse_whitespaces sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.ldap_sssd_parse_whitespaces 2016-05-11 10:31:30.202090379 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2016-05-11 10:31:30.207090307 +0200 +@@ -1004,17 +1004,17 @@ sudo_sss_parse_options(struct sudo_sss_h + if (op == '+' || op == '-') { + *(val - 2) = '\0'; /* found, remove extra char */ + /* case var+=val or var-=val */ +- set_default(v, strunquote(val), (int) op); ++ set_default(rm_whitespaces(v), strunquote(val), (int) op); + } else { + /* case var=val */ +- set_default(v, strunquote(val), true); ++ set_default(rm_whitespaces(v), strunquote(val), true); + } + } else if (*v == '!') { + /* case !var Boolean False */ +- set_default(v + 1, NULL, false); ++ set_default(rm_whitespaces(v + 1), NULL, false); + } else { + /* case var Boolean True */ +- set_default(v, NULL, true); ++ set_default(rm_whitespaces(v), NULL, true); + } + efree(v); + } +diff -up sudo-1.8.6p7/plugins/sudoers/sudoers.h.ldap_sssd_parse_whitespaces sudo-1.8.6p7/plugins/sudoers/sudoers.h +--- sudo-1.8.6p7/plugins/sudoers/sudoers.h.ldap_sssd_parse_whitespaces 2016-05-11 10:31:30.204090350 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sudoers.h 2016-05-11 10:31:30.207090307 +0200 +@@ -346,6 +346,7 @@ int sudoers_hook_unsetenv(const char *na + + /* fmt_string.c */ + char *fmt_string(const char *, const char *); ++char *rm_whitespaces(char * str); + + /* sudoers.c */ + void plugin_cleanup(int); diff --git a/SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch b/SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch new file mode 100644 index 00000000..d3991f0f --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch @@ -0,0 +1,119 @@ +From b1f3fcf8d6e9a8e5326771a12fac8e08ed81f766 Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +Date: Fri, 19 Aug 2016 10:21:27 +0200 +Subject: [PATCH] Sudo with ldap doesn't work with 'user id' + +in sudoUser option. + +Rebased from: +Patch39: sudo-1.8.6p7-ldapsearchuidfix.patch + +Resolves: +rhbz#1135539 +--- + plugins/sudoers/def_data.c | 4 ++++ + plugins/sudoers/def_data.h | 2 ++ + plugins/sudoers/def_data.in | 3 +++ + plugins/sudoers/defaults.c | 2 ++ + plugins/sudoers/ldap.c | 10 ++++++++-- + plugins/sudoers/sudoers.c | 4 ++++ + 6 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c +index d8b1ada..3926fed 100644 +--- a/plugins/sudoers/def_data.c ++++ b/plugins/sudoers/def_data.c +@@ -439,6 +439,10 @@ struct sudo_defs_types sudo_defs_table[] = { + N_("Don't fork and wait for the command to finish, just exec it"), + NULL, + }, { ++ "legacy_group_processing", T_FLAG, ++ N_("Don't pre-resolve all group names"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h +index 1b6be3d..5246e41 100644 +--- a/plugins/sudoers/def_data.h ++++ b/plugins/sudoers/def_data.h +@@ -206,6 +206,8 @@ + #define def_iolog_mode (sudo_defs_table[I_IOLOG_MODE].sd_un.mode) + #define I_CMND_NO_WAIT 103 + #define def_cmnd_no_wait (sudo_defs_table[I_CMND_NO_WAIT].sd_un.flag) ++#define I_LEGACY_GROUP_PROCESSING 104 ++#define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag) + + enum def_tuple { + never, +diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in +index 5200fe3..f1c9265 100644 +--- a/plugins/sudoers/def_data.in ++++ b/plugins/sudoers/def_data.in +@@ -325,3 +325,6 @@ iolog_mode + cmnd_no_wait + T_FLAG + "Don't fork and wait for the command to finish, just exec it" ++legacy_group_processing ++ T_FLAG ++ "Don't pre-resolve all group names" +diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c +index 5eaf8ea..9e60d94 100644 +--- a/plugins/sudoers/defaults.c ++++ b/plugins/sudoers/defaults.c +@@ -450,6 +450,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 --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c +index 3fe27c7..96a0709 100644 +--- a/plugins/sudoers/ldap.c ++++ b/plugins/sudoers/ldap.c +@@ -1666,8 +1666,8 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw) + if (ldap_conf.search_filter) + sz += strlen(ldap_conf.search_filter); + +- /* Then add (|(sudoUser=USERNAME)(sudoUser=ALL)) + NUL */ +- sz += 29 + sudo_ldap_value_len(pw->pw_name); ++ /* Then add (|(sudoUser=USERNAME)(sudoUser=#uid)(sudoUser=ALL)) + NUL */ ++ sz += 29 + (12 + MAX_UID_T_LEN) + sudo_ldap_value_len(pw->pw_name); + + /* Add space for primary and supplementary groups and gids */ + if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) { +@@ -1730,6 +1730,12 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw) + CHECK_LDAP_VCAT(buf, pw->pw_name, sz); + CHECK_STRLCAT(buf, ")", sz); + ++ /* Append user uid */ ++ (void) snprintf(gidbuf, sizeof(gidbuf), "%u", (unsigned int)pw->pw_uid); ++ (void) strlcat(buf, "(sudoUser=#", sz); ++ (void) strlcat(buf, gidbuf, sz); ++ (void) strlcat(buf, ")", sz); ++ + /* Append primary group and gid */ + if (grp != NULL) { + CHECK_STRLCAT(buf, "(sudoUser=%", sz); +diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c +index 539177a..673ee5d 100644 +--- a/plugins/sudoers/sudoers.c ++++ b/plugins/sudoers/sudoers.c +@@ -208,6 +208,10 @@ sudoers_policy_init(void *info, char * const envp[]) + 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; +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch b/SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch new file mode 100644 index 00000000..c9229244 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch @@ -0,0 +1,47 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.ldapusermatchfix sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.ldapusermatchfix 2016-05-09 15:33:10.933510674 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2016-05-09 15:33:10.937510618 +0200 +@@ -2735,22 +2735,37 @@ sudo_ldap_result_get(struct sudo_nss *ns + result = NULL; + rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt, + NULL, 0, NULL, NULL, tvp, 0, &result); +- if (rc != LDAP_SUCCESS) { ++ if (rc != LDAP_SUCCESS || result == NULL) { + DPRINTF(("nothing found for '%s'", filt), 1); + continue; + } +- lres->user_matches = true; ++ ++ DPRINTF(("search result has %d entries (do_netgr=%s)", ++ ldap_count_entries(ld, result), do_netgr ? "true" : "false"), 1); ++ /* ++ * Only set user_matches if we got some results back and if we are ++ * NOT searching for netgroup entries. For the netgroup case, user_maches ++ * will be set only if a netgroup match was found. ++ */ ++ lres->user_matches = lres->user_matches ? true : ldap_count_entries(ld, result) > 0 && !do_netgr; + + /* Add the seach result to list of search results. */ + DPRINTF(("adding search result"), 1); + sudo_ldap_result_add_search(lres, ld, result); + LDAP_FOREACH(entry, ld, result) { +- if ((!do_netgr || +- sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && ++ if (do_netgr) { ++ if (sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name) && + sudo_ldap_check_host(ld, entry)) { +- lres->host_matches = true; +- sudo_ldap_result_add_entry(lres, entry); ++ lres->host_matches = true; ++ lres->user_matches = true; ++ sudo_ldap_result_add_entry(lres, entry); ++ } ++ } else { ++ if (sudo_ldap_check_host(ld, entry)) { ++ lres->host_matches = true; ++ sudo_ldap_result_add_entry(lres, entry); + } ++ } + } + DPRINTF(("result now has %d entries", lres->nentries), 1); + } diff --git a/SOURCES/sudo-1.8.6p7-legacy-group-processing.patch b/SOURCES/sudo-1.8.6p7-legacy-group-processing.patch new file mode 100644 index 00000000..3e018fb1 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-legacy-group-processing.patch @@ -0,0 +1,224 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/defaults.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/defaults.c +--- sudo-1.8.6p7/plugins/sudoers/defaults.c.legacy-group-processing 2013-02-25 20:42:44.000000000 +0100 ++++ sudo-1.8.6p7/plugins/sudoers/defaults.c 2015-08-28 10:52:13.658671686 +0200 +@@ -362,6 +362,7 @@ init_defaults(void) + } + + /* First initialize the flags. */ ++ def_legacy_group_processing = true; + #ifdef LONG_OTP_PROMPT + def_long_otp_prompt = true; + #endif +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/def_data.c +--- sudo-1.8.6p7/plugins/sudoers/def_data.c.legacy-group-processing 2015-08-28 10:52:13.604671687 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.c 2015-08-28 10:52:13.658671686 +0200 +@@ -355,6 +355,10 @@ struct sudo_defs_types sudo_defs_table[] + N_("Don't fork and wait for the command to finish, just exec it"), + NULL, + }, { ++ "legacy_group_processing", T_FLAG, ++ N_("Don't pre-resolve all group names"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.h.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/def_data.h +--- sudo-1.8.6p7/plugins/sudoers/def_data.h.legacy-group-processing 2015-08-28 10:52:13.604671687 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.h 2015-08-28 10:52:13.658671686 +0200 +@@ -164,6 +164,8 @@ + #define I_LIMITPRIVS 81 + #define def_cmnd_no_wait (sudo_defs_table[82].sd_un.flag) + #define I_CMND_NO_WAIT 82 ++#define def_legacy_group_processing (sudo_defs_table[83].sd_un.flag) ++#define I_LEGACY_GROUP_PROCESSING 83 + + enum def_tuple { + never, +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.legacy-group-processing 2015-08-28 10:52:13.656671686 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2015-08-28 10:52:13.659671686 +0200 +@@ -1220,6 +1220,15 @@ sudo_ldap_build_pass1(struct passwd *pw) + } + sz += 13 + MAX_UID_T_LEN; + if ((grlist = sudo_get_grlist(pw)) != NULL) { ++ if (!grlist->groups_resolved) { ++ int rc = sudo_resolve_gids(grlist->gids, grlist->ngids, ++ grlist->groups, grlist->groups_buffer); ++ if (rc < 0) { ++ return NULL; ++ } ++ grlist->ngroups = rc; ++ grlist->groups_resolved = true; ++ } + for (i = 0; i < grlist->ngroups; i++) { + if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0) + continue; +diff -up sudo-1.8.6p7/plugins/sudoers/pwutil.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/pwutil.c +--- sudo-1.8.6p7/plugins/sudoers/pwutil.c.legacy-group-processing 2015-08-28 10:52:13.633671686 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/pwutil.c 2015-08-28 10:52:13.659671686 +0200 +@@ -542,10 +542,9 @@ static struct cache_item * + make_grlist_item(const char *user, GETGROUPS_T *gids, int ngids) + { + char *cp; +- size_t i, nsize, ngroups, total, len; ++ size_t i, nsize, total; + struct cache_item_grlist *grlitem; + struct group_list *grlist; +- struct group *grp; + debug_decl(make_grlist_item, SUDO_DEBUG_NSS) + + #ifdef HAVE_SETAUTHDB +@@ -559,7 +558,6 @@ make_grlist_item(const char *user, GETGR + total += sizeof(gid_t *) * ngids; + total += GROUPNAME_LEN * ngids; + +-again: + grlitem = ecalloc(1, total); + + /* +@@ -587,27 +585,26 @@ again: + for (i = 0; i < ngids; i++) + grlist->gids[i] = gids[i]; + grlist->ngids = ngids; ++ grlist->groups_buffer = cp; + + /* +- * Resolve and store group names by ID. ++ * Resolve and store group names by ID if legacy_group_processing is off. + */ +- ngroups = 0; +- for (i = 0; i < ngids; i++) { +- if ((grp = sudo_getgrgid(gids[i])) != NULL) { +- len = strlen(grp->gr_name) + 1; +- if (cp - (char *)grlitem + len > total) { +- total += len + GROUPNAME_LEN; +- efree(grlitem); +- sudo_gr_delref(grp); +- goto again; +- } +- memcpy(cp, grp->gr_name, len); +- grlist->groups[ngroups++] = cp; +- cp += len; +- sudo_gr_delref(grp); +- } ++ if (def_legacy_group_processing) { ++ for (i = 0; i < ngids; i++) { ++ grlist->groups[i] = NULL; ++ } ++ grlist->ngroups = 0; ++ grlist->groups_resolved = false; ++ } else { ++ int rc = sudo_resolve_gids(gids, ngids, grlist->groups, grlist->groups_buffer); ++ if (rc < 0) { ++ efree(grlitem); ++ return NULL; ++ } ++ grlist->ngroups = rc; ++ grlist->groups_resolved = true; + } +- grlist->ngroups = ngroups; + + #ifdef HAVE_SETAUTHDB + aix_restoreauthdb(); +@@ -616,6 +613,35 @@ again: + debug_return_ptr(&grlitem->cache); + } + ++int sudo_resolve_gids(GETGROUPS_T *gids, int ngids, char **groups, char *group_buffer) ++{ ++ struct group *grp; ++ int space_left = ngids * GROUPNAME_LEN; ++ int ngroups = 0; ++ int i; ++ char *cp = group_buffer; ++ debug_decl(sudo_resolve_gids, SUDO_DEBUG_NSS) ++ ++ for (i = 0; i < ngids; i++) { ++ if ((grp = sudo_getgrgid(gids[i])) != NULL) { ++ int len = strlen(grp->gr_name) + 1; ++ ++ if (space_left < len) { ++ sudo_gr_delref(grp); ++ debug_return_int(-1); ++ } ++ ++ memcpy(cp, grp->gr_name, len); ++ groups[ngroups++] = cp; ++ cp += len; ++ space_left -= len; ++ sudo_gr_delref(grp); ++ } ++ } ++ ++ debug_return_int(ngroups); ++} ++ + void + sudo_gr_addref(struct group *gr) + { +@@ -917,8 +943,22 @@ user_in_group(const struct passwd *pw, c + /* + * If it could be a sudo-style group ID check gids first. + */ ++ bool do_gid_lookup = false; ++ gid_t gid; ++ + if (group[0] == '#') { +- gid_t gid = atoi(group + 1); ++ gid = atoi(group + 1); ++ do_gid_lookup = true; ++ } else if (def_legacy_group_processing) { ++ struct group *grent = sudo_getgrnam(group); ++ if (grent == NULL) { ++ goto done; ++ } ++ gid = grent->gr_gid; ++ do_gid_lookup = true; ++ } ++ ++ if (do_gid_lookup) { + if (gid == pw->pw_gid) { + matched = true; + goto done; +@@ -931,6 +971,19 @@ user_in_group(const struct passwd *pw, c + } + } + ++ if (def_legacy_group_processing) { ++ goto done; ++ } ++ if (!grlist->groups_resolved) { ++ int rc = sudo_resolve_gids(grlist->gids, grlist->ngids, ++ grlist->groups, grlist->groups_buffer); ++ if (rc < 0) { ++ goto done; ++ } ++ grlist->ngroups = rc; ++ grlist->groups_resolved = true; ++ } ++ + /* + * Next check the supplementary group vector. + * It usually includes the password db group too. +diff -up sudo-1.8.6p7/plugins/sudoers/sudoers.h.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/sudoers.h +--- sudo-1.8.6p7/plugins/sudoers/sudoers.h.legacy-group-processing 2015-08-28 10:52:13.634671686 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sudoers.h 2015-08-28 10:52:13.659671686 +0200 +@@ -52,6 +52,8 @@ struct group_list { + GETGROUPS_T *gids; + int ngroups; + int ngids; ++ int groups_resolved; ++ char *groups_buffer; + }; + + /* +@@ -289,6 +291,8 @@ __dso_public struct group *sudo_getgrnam + __dso_public void sudo_gr_addref(struct group *); + __dso_public void sudo_gr_delref(struct group *); + bool user_in_group(const struct passwd *, const char *); ++int sudo_resolve_gids(GETGROUPS_T *gids, int ngids, char **groups, char *group_buffer); ++ + struct group *sudo_fakegrnam(const char *); + struct group_list *sudo_get_grlist(const struct passwd *pw); + struct passwd *sudo_fakepwnam(const char *, gid_t); diff --git a/SOURCES/sudo-1.8.6p7-logsudouser.patch b/SOURCES/sudo-1.8.6p7-logsudouser.patch new file mode 100644 index 00000000..c3742a09 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-logsudouser.patch @@ -0,0 +1,90 @@ +From 06b46ae226fecd4188af372ac0ccd7aa582e21c8 Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +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 + diff --git a/SOURCES/sudo-1.8.6p7-manfix-usepty.patch b/SOURCES/sudo-1.8.6p7-manfix-usepty.patch new file mode 100644 index 00000000..0da67eca --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-manfix-usepty.patch @@ -0,0 +1,107 @@ +diff -up sudo-1.8.6p7/doc/fixmdoc.sh.manfix-usepty sudo-1.8.6p7/doc/fixmdoc.sh +--- sudo-1.8.6p7/doc/fixmdoc.sh.manfix-usepty 2015-07-07 09:06:37.893592317 +0200 ++++ sudo-1.8.6p7/doc/fixmdoc.sh 2015-07-07 09:07:40.575602754 +0200 +@@ -1,4 +1,19 @@ + #!/bin/sh ++# ++# Copyright (c) 2012-2014 Todd C. Miller ++# ++# Permission to use, copy, modify, and distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# + + OUTFILE="$1" + rm -f "$OUTFILE" +@@ -18,11 +33,9 @@ case "$OUTFILE" in + # BSD auth + BA_FLAG= + if [ X"$BAMAN" != X"1" ]; then +- BA_FLAG='/^.*\n\.Op Fl a Ar auth_type/{;N;/^.*\n\.Ek$/d;};' ++ BA_FLAG='/^.*\n\.Op Fl a Ar type/{;N;/^.*\n\.Ek$/d;};' + cat >>"$OUTFILE" <<-'EOF' +- /^\.It Fl a Ar type/,/BSD authentication\.$/ { +- d +- } ++ /^\.It Fl a Ar type/,/BSD authentication\.$/d + EOF + fi + +@@ -31,9 +44,7 @@ case "$OUTFILE" in + if [ X"$LCMAN" != X"1" ]; then + LC_FLAG='/^.*\n\.Op Fl c Ar class/{;N;/^.*\n\.Ek$/d;};' + cat >>"$OUTFILE" <<-'EOF' +- /^\.It Fl c Ar class/,/BSD login classes\.$/ { +- d +- } ++ /^\.It Fl c Ar class/,/BSD login classes\.$/d + /^\.Xr login_cap 3 ,$/d + /^BSD login class$/ { + N +@@ -47,12 +58,8 @@ case "$OUTFILE" in + if [ X"$SEMAN" != X"1" ]; then + SE_FLAG='/^.*\n\.Op Fl r Ar role/{;N;/^.*\n\.Ek$/d;};/^.*\n\.Op Fl t Ar type/{;N;/^.*\n\.Ek$/d;};' + cat >>"$OUTFILE" <<-'EOF' +- /^\.It Fl r Ar role/,/newline character\.$/ { +- d +- } +- /^\.It Fl t Ar type/,/specified role\.$/ { +- d +- } ++ /^\.It Fl r Ar role/,/^\.Ar role \.$/d ++ /^\.It Fl t Ar type/,/derived from the role\.$/d + /^SELinux role and type$/ { + N + /^SELinux role and type\n\.It$/d +@@ -103,12 +110,8 @@ case "$OUTFILE" in + # BSD login class + if [ X"$LCMAN" != X"1" ]; then + cat >>"$OUTFILE" <<-'EOF' +- /^On BSD systems/,/\.$/ { +- d +- } +- /^\.It use_loginclass$/,/^\.It/ { +- /^\.It [^u][^s][^e][^_][^l]/!d +- } ++ /^On BSD systems/,/\.$/d ++ /^\.It use_loginclass$/,/^by default\./d + EOF + fi + +@@ -120,15 +123,8 @@ case "$OUTFILE" in + N + d + } +- /^\.It limitprivs$/,/^\.It/ { +- /^\.It [^l][^i][^m][^i][^t]/!d +- } +- /^\.It privs$/,/^\.It/ { +- /^\.It [^p][^r][^i][^v][^s]$/!d +- } +- /^On Solaris 10/,/^\.Pp/ { +- d +- } ++ /^\.It \(limit\)*privs$/,/is built on Solaris 10 or higher\.$/d ++ /^On Solaris 10/,/^\.Pp/d + EOF + fi + +@@ -140,9 +136,7 @@ case "$OUTFILE" in + N + d + } +- /^\.It [rt][oy][lp]e$/,/^\.It/ { +- /^\.It [^rt][^oy][^lp][^e]$/!d +- } ++ /^\.It [rt][oy][lp]e$/,/is built with SELinux support\.$/d + EOF + fi + ;; diff --git a/SOURCES/sudo-1.8.6p7-netgroup_tuple.patch b/SOURCES/sudo-1.8.6p7-netgroup_tuple.patch new file mode 100644 index 00000000..42f3ac28 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-netgroup_tuple.patch @@ -0,0 +1,194 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/defaults.c.netgroup_tuple sudo-1.8.6p7/plugins/sudoers/defaults.c +--- sudo-1.8.6p7/plugins/sudoers/defaults.c.netgroup_tuple 2016-05-09 15:34:41.059246583 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/defaults.c 2016-05-09 15:34:41.066246485 +0200 +@@ -362,6 +362,7 @@ init_defaults(void) + } + + /* First initialize the flags. */ ++ def_netgroup_tuple = false; + def_legacy_group_processing = true; + #ifdef LONG_OTP_PROMPT + def_long_otp_prompt = true; +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.c.netgroup_tuple sudo-1.8.6p7/plugins/sudoers/def_data.c +--- sudo-1.8.6p7/plugins/sudoers/def_data.c.netgroup_tuple 2016-05-09 15:34:41.059246583 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.c 2016-05-09 15:34:41.066246485 +0200 +@@ -359,6 +359,10 @@ struct sudo_defs_types sudo_defs_table[] + N_("Don't pre-resolve all group names"), + NULL, + }, { ++ "netgroup_tuple", T_FLAG, ++ N_("Use both user and host/domain fields when matching netgroups"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.h.netgroup_tuple sudo-1.8.6p7/plugins/sudoers/def_data.h +--- sudo-1.8.6p7/plugins/sudoers/def_data.h.netgroup_tuple 2016-05-09 15:34:41.059246583 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.h 2016-05-09 15:34:41.066246485 +0200 +@@ -166,6 +166,8 @@ + #define I_CMND_NO_WAIT 82 + #define def_legacy_group_processing (sudo_defs_table[83].sd_un.flag) + #define I_LEGACY_GROUP_PROCESSING 83 ++#define def_netgroup_tuple (sudo_defs_table[84].sd_un.flag) ++#define I_NETGROUP_TUPLE 84 + + enum def_tuple { + never, +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.netgroup_tuple sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.netgroup_tuple 2016-05-09 15:34:41.065246499 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2016-05-09 15:34:41.066246485 +0200 +@@ -636,8 +636,12 @@ sudo_ldap_check_user_netgroup(LDAP *ld, + for (p = bv; *p != NULL && !ret; p++) { + val = (*p)->bv_val; + /* match any */ +- if (netgr_matches(val, NULL, NULL, user)) +- ret = true; ++ if (netgr_matches(val, ++ def_netgroup_tuple ? user_host : NULL, ++ def_netgroup_tuple ? user_shost : NULL, ++ user)) { ++ ret = true; ++ } + DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val, + ret ? "MATCH!" : "not"), 2 + ((ret) ? 0 : 1)); + } +@@ -652,7 +656,7 @@ sudo_ldap_check_user_netgroup(LDAP *ld, + * host match, else false. + */ + static bool +-sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry) ++sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry, char *user) + { + struct berval **bv, **p; + char *val; +@@ -672,7 +676,7 @@ sudo_ldap_check_host(LDAP *ld, LDAPMessa + val = (*p)->bv_val; + /* match any or address or netgroup or hostname */ + if (!strcmp(val, "ALL") || addr_matches(val) || +- netgr_matches(val, user_host, user_shost, NULL) || ++ netgr_matches(val, user_host, user_shost, def_netgroup_tuple ? user : NULL) || + hostname_matches(user_shost, user_host, val)) + ret = true; + DPRINTF(("ldap sudoHost '%s' ... %s", val, +@@ -729,7 +733,10 @@ sudo_ldap_check_runas_user(LDAP *ld, LDA + val = (*p)->bv_val; + switch (val[0]) { + case '+': +- if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) ++ if (netgr_matches(val, ++ def_netgroup_tuple ? user_host : NULL, ++ def_netgroup_tuple ? user_shost : NULL, ++ runas_pw->pw_name)) + ret = true; + break; + case '%': +@@ -2755,13 +2762,13 @@ sudo_ldap_result_get(struct sudo_nss *ns + LDAP_FOREACH(entry, ld, result) { + if (do_netgr) { + if (sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name) && +- sudo_ldap_check_host(ld, entry)) { ++ sudo_ldap_check_host(ld, entry, pw->pw_name)) { + lres->host_matches = true; + lres->user_matches = true; + sudo_ldap_result_add_entry(lres, entry); + } + } else { +- if (sudo_ldap_check_host(ld, entry)) { ++ if (sudo_ldap_check_host(ld, entry, pw->pw_name)) { + lres->host_matches = true; + sudo_ldap_result_add_entry(lres, entry); + } +diff -up sudo-1.8.6p7/plugins/sudoers/match.c.netgroup_tuple sudo-1.8.6p7/plugins/sudoers/match.c +--- sudo-1.8.6p7/plugins/sudoers/match.c.netgroup_tuple 2016-05-09 15:34:41.062246541 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/match.c 2016-05-09 15:34:41.067246471 +0200 +@@ -117,7 +117,10 @@ userlist_matches(struct passwd *pw, stru + matched = !m->negated; + break; + case NETGROUP: +- if (netgr_matches(m->name, NULL, NULL, pw->pw_name)) ++ if (netgr_matches(m->name, ++ def_netgroup_tuple ? user_host : NULL, ++ def_netgroup_tuple ? user_shost : NULL, ++ pw->pw_name)) + matched = !m->negated; + break; + case USERGROUP: +@@ -172,7 +175,10 @@ runaslist_matches(struct member_list *us + user_matched = !m->negated; + break; + case NETGROUP: +- if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) ++ if (netgr_matches(m->name, ++ def_netgroup_tuple ? user_host : NULL, ++ def_netgroup_tuple ? user_shost : NULL, ++ runas_pw->pw_name)) + user_matched = !m->negated; + break; + case USERGROUP: +@@ -269,7 +275,7 @@ hostlist_matches(struct member_list *lis + matched = !m->negated; + break; + case NETGROUP: +- if (netgr_matches(m->name, user_host, user_shost, NULL)) ++ if (netgr_matches(m->name, user_host, user_shost, def_netgroup_tuple ? user_name : NULL)) + matched = !m->negated; + break; + case NTWKADDR: +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.netgroup_tuple sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.netgroup_tuple 2016-05-09 15:34:41.056246625 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2016-05-09 15:34:41.067246471 +0200 +@@ -452,7 +452,10 @@ sudo_sss_check_runas_user(struct sudo_ss + switch (val[0]) { + case '+': + sudo_debug_printf(SUDO_DEBUG_DEBUG, "netgr_"); +- if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) { ++ if (netgr_matches(val, ++ def_netgroup_tuple ? user_host : NULL, ++ def_netgroup_tuple ? user_shost : NULL, ++ runas_pw->pw_name)) { + sudo_debug_printf(SUDO_DEBUG_DEBUG, "=> match"); + ret = true; + } +@@ -551,7 +554,7 @@ sudo_sss_check_runas(struct sudo_sss_han + debug_return_bool(ret); + } + +-static bool sudo_sss_ipa_hostname_matches(const char *hostname_val) ++static bool sudo_sss_ipa_hostname_matches(const char *hostname_val, char *user) + { + bool ret = false; + char *ipa_hostname_val; +@@ -559,7 +562,7 @@ static bool sudo_sss_ipa_hostname_matche + + if ((ipa_hostname_val = ipa_hostname()) != NULL) { + ret = hostname_matches(ipa_hostname_val, ipa_hostname_val, hostname_val) || \ +- netgr_matches(hostname_val, ipa_hostname_val, ipa_hostname_val, NULL); ++ netgr_matches(hostname_val, ipa_hostname_val, ipa_hostname_val, def_netgroup_tuple ? user : NULL); + } + + sudo_debug_printf(SUDO_DEBUG_TRACE, "IPA hostname (%s) matches %s => %s", +@@ -600,8 +603,9 @@ sudo_sss_check_host(struct sudo_sss_hand + + /* match any or address or netgroup or hostname */ + if (!strcmp(val, "ALL") || addr_matches(val) || +- sudo_sss_ipa_hostname_matches(val) || +- netgr_matches(val, user_host, user_shost, NULL) || ++ sudo_sss_ipa_hostname_matches(val, handle->pw->pw_name) || ++ netgr_matches(val, user_host, user_shost, ++ def_netgroup_tuple ? handle->pw->pw_name : NULL) || + hostname_matches(user_shost, user_host, val)) + ret = true; + +@@ -649,7 +653,10 @@ bool sudo_sss_filter_sudoUser(struct sud + sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val); + if (*val == '+') { + /* Netgroup spec found, check netgroup membership */ +- if (netgr_matches(val, NULL, NULL, handle->pw->pw_name)) { ++ if (netgr_matches(val, ++ def_netgroup_tuple ? user_host : NULL, ++ def_netgroup_tuple ? user_shost : NULL, ++ handle->pw->pw_name)) { + ret = true; + sudo_debug_printf(SUDO_DEBUG_DIAG, + "sssd/ldap sudoUser '%s' ... MATCH! (%s)", val, handle->pw->pw_name); diff --git a/SOURCES/sudo-1.8.6p7-newbase64decoder.patch b/SOURCES/sudo-1.8.6p7-newbase64decoder.patch new file mode 100644 index 00000000..d224f3c2 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-newbase64decoder.patch @@ -0,0 +1,104 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/match.c.newbase64decoder sudo-1.8.6p7/plugins/sudoers/match.c +--- sudo-1.8.6p7/plugins/sudoers/match.c.newbase64decoder 2015-09-01 13:35:42.746241825 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/match.c 2015-09-01 13:40:52.360233611 +0200 +@@ -510,53 +510,60 @@ command_matches_glob(char *sudoers_cmnd, + } + + /* ++ * base64 decoder ++ * PUBLIC DOMAIN - Jon Mayo - November 13, 2003 ++ */ ++static const uint8_t base64dec_tab[256]= { ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, ++ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, ++ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ++ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, ++ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, ++ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++}; ++ ++/* + * Decode a NUL-terminated string in base64 format and store the + * result in dst. + */ + size_t +-base64_decode(const char *str, unsigned char *dst, size_t dsize) ++base64_decode(const char *in, unsigned char *out, size_t out_len) + { +- static const char b64[] = +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +- const unsigned char *dst0 = dst; +- const unsigned char *dend = dst + dsize; +- unsigned char ch[4]; +- char *pos; +- int i; +- debug_decl(base64_decode, SUDO_DEBUG_MATCH) ++ size_t in_len = strlen(in); ++ size_t ii, io; ++ uint_least32_t v; ++ size_t rem; + +- /* +- * Convert from base64 to binary. Each base64 char holds 6 bits of data +- * so 4 base64 chars equals 3 chars of data. +- * Padding (with the '=' char) may or may not be present. +- */ +- while (*str != '\0') { +- for (i = 0; i < 4; i++) { +- switch (*str) { +- case '=': +- str++; +- /* FALLTHROUGH */ +- case '\0': +- ch[i] = '='; +- break; +- default: +- if ((pos = strchr(b64, *str++)) == NULL) +- debug_return_size_t((size_t)-1); +- ch[i] = (unsigned char)(pos - b64); +- break; +- } +- } +- if (ch[0] == '=' || ch[1] == '=' || dst == dend) +- break; +- *dst++ = (ch[0] << 2) | ((ch[1] & 0x30) >> 4); +- if (ch[2] == '=' || dst == dend) +- break; +- *dst++ = ((ch[1] & 0x0f) << 4) | ((ch[2] & 0x3c) >> 2); +- if (ch[3] == '=' || dst == dend) +- break; +- *dst++ = ((ch[2] & 0x03) << 6) | ch[3]; ++ for(io=0,ii=0,v=0,rem=0;ii=8) { ++ rem-=8; ++ if(io>=out_len) return -1; /* truncation is failure */ ++ out[io++]=(v>>rem)&255; + } +- debug_return_size_t((size_t)(dst - dst0)); ++ } ++ if(rem>=8) { ++ rem-=8; ++ if(io>=out_len) return -1; /* truncation is failure */ ++ out[io++]=(v>>rem)&255; ++ } ++ return io; + } + + static bool diff --git a/SOURCES/sudo-1.8.6p7-noexec-update.patch b/SOURCES/sudo-1.8.6p7-noexec-update.patch new file mode 100644 index 00000000..4005794d --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-noexec-update.patch @@ -0,0 +1,422 @@ +diff --git a/config.h.in b/config.h.in +index 106af3a..30c3928 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -87,6 +87,10 @@ + don't. */ + #undef HAVE_DECL_H_ERRNO + ++/* Define to 1 if you have the declaration of `SECCOMP_SET_MODE_FILTER', and ++ to 0 if you don't. */ ++#undef HAVE_DECL_SECCOMP_SET_MODE_FILTER ++ + /* Define to 1 if you have the declaration of `sys_sigabbrev', and to 0 if you + don't. */ + #undef HAVE_DECL_SYS_SIGABBREV +@@ -134,9 +138,21 @@ + /* Define to 1 if the compiler supports the __visibility__ attribute. */ + #undef HAVE_DSO_VISIBILITY + ++/* Define to 1 if you have the `exect' function. */ ++#undef HAVE_EXECT ++ ++/* Define to 1 if you have the `execvp' function. */ ++#undef HAVE_EXECVP ++ ++/* Define to 1 if you have the `execvpe' function. */ ++#undef HAVE_EXECVPE ++ + /* Define to 1 if your system has the F_CLOSEM fcntl. */ + #undef HAVE_FCNTL_CLOSEM + ++/* Define to 1 if you have the `fexecve' function. */ ++#undef HAVE_FEXECVE ++ + /* Define to 1 if you have the `fgetln' function. */ + #undef HAVE_FGETLN + +@@ -421,6 +437,12 @@ + /* Define to 1 if you have the `posix_openpt' function. */ + #undef HAVE_POSIX_OPENPT + ++/* Define to 1 if you have the `posix_spawn' function. */ ++#undef HAVE_POSIX_SPAWN ++ ++/* Define to 1 if you have the `posix_spawnp' function. */ ++#undef HAVE_POSIX_SPAWNP ++ + /* Define to 1 if you have the `priv_set' function. */ + #undef HAVE_PRIV_SET + +@@ -703,6 +725,12 @@ + /* Define to 1 if you have the `vsnprintf' function. */ + #undef HAVE_VSNPRINTF + ++/* Define to 1 if you have the `wordexp' function. */ ++#undef HAVE_WORDEXP ++ ++/* Define to 1 if you have the header file. */ ++#undef HAVE_WORDEXP_H ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_ZLIB_H + +diff --git a/configure.in b/configure.in +index 06b4722..945284e 100644 +--- a/configure.in ++++ b/configure.in +@@ -1824,6 +1824,14 @@ case "$host" in + shadow_funcs="getspnam" + shadow_libs_optional="-lshadow" + test -z "$with_pam" && AUTH_EXCL_DEF="PAM" ++ # Check for SECCOMP_SET_MODE_FILTER in linux/seccomp.h ++ AC_CHECK_DECLS([SECCOMP_SET_MODE_FILTER], [], [], [ ++#include ++#include ++#include ++#include ++#include ++ ]) + ;; + *-convex-bsd*) + OSDEFS="${OSDEFS} -D_CONVEX_SOURCE" +@@ -2091,7 +2099,7 @@ AC_HEADER_DIRENT + AC_HEADER_TIME + AC_HEADER_STDBOOL + AC_HEADER_MAJOR +-AC_CHECK_HEADERS(malloc.h netgroup.h paths.h spawn.h utime.h utmpx.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h) ++AC_CHECK_HEADERS(malloc.h netgroup.h paths.h spawn.h utime.h utmpx.h wordexp.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h) + AC_CHECK_HEADERS([procfs.h] [sys/procfs.h], [AC_CHECK_MEMBERS(struct psinfo.pr_ttydev, [AC_CHECK_FUNCS(_ttyname_dev)], [], [AC_INCLUDES_DEFAULT + #ifdef HAVE_PROCFS_H + #include +@@ -2226,7 +2234,8 @@ dnl + AC_FUNC_GETGROUPS + AC_CHECK_FUNCS(glob strrchr sysconf tzset strftime setenv \ + regcomp setlocale nl_langinfo mbr_check_membership \ +- setrlimit64) ++ setrlimit64 \ ++ wordexp exect execvp execvpe fexecve posix_spawn posix_spawnp) + AC_REPLACE_FUNCS(getgrouplist) + AC_CHECK_FUNCS(getline, [], [ + AC_LIBOBJ(getline) +diff --git a/include/missing.h b/include/missing.h +index fda151b..cac8088 100644 +--- a/include/missing.h ++++ b/include/missing.h +@@ -198,6 +198,13 @@ typedef struct sigaction sigaction_t; + #endif + + /* ++ * The nitems macro may be defined in sys/param.h ++ */ ++#ifndef nitems ++# define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) ++#endif ++ ++/* + * If dirfd() does not exists, hopefully dd_fd does. + */ + #if !defined(HAVE_DIRFD) && defined(HAVE_DD_FD) +diff --git a/src/Makefile.in b/src/Makefile.in +index 918cf04..079aa3e 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -109,7 +109,7 @@ sudo: $(OBJS) $(LT_LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(OBJS) $(LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) + + libsudo_noexec.la: sudo_noexec.lo +- $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LT_LDFLAGS) -o $@ sudo_noexec.lo -avoid-version -rpath $(noexecdir) ++ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LT_LDFLAGS) @LIBDL@ -o $@ sudo_noexec.lo -avoid-version -rpath $(noexecdir) + + sesh: sesh.o error.o exec_common.o @LIBINTL@ $(LT_LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ sesh.o error.o exec_common.o $(LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) @LIBINTL@ $(LIBS) +diff --git a/src/sudo_noexec.c b/src/sudo_noexec.c +index 2872501..f04b277 100644 +--- a/src/sudo_noexec.c ++++ b/src/sudo_noexec.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2004-2005, 2010-2011 Todd C. Miller ++ * Copyright (c) 2004-2005, 2010-2016 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -18,20 +18,64 @@ + + #include + ++#if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER ++# include ++# include ++# include ++# include ++#endif ++ + #include + #include ++#include ++#include ++#include + #ifdef HAVE_SPAWN_H + #include + #endif ++#ifdef HAVE_STRING_H ++# include ++#endif /* HAVE_STRING_H */ ++#ifdef HAVE_STRINGS_H ++# include ++#endif /* HAVE_STRINGS_H */ ++#ifdef HAVE_WORDEXP_H ++#include ++#endif ++#if defined(HAVE_SHL_LOAD) ++# include ++#elif defined(HAVE_DLOPEN) ++# include ++#endif + + #include "missing.h" ++#include "pathnames.h" + ++#ifdef HAVE___INTERPOSE + /* +- * Dummy versions of the execve() family of syscalls. We don't need +- * to stub out all of them, just the ones that correspond to actual +- * system calls (which varies by OS). Note that it is still possible +- * to access the real syscalls via the syscall() interface but very +- * few programs actually do that. ++ * Mac OS X 10.4 and above has support for library symbol interposition. ++ * There is a good explanation of this in the Mac OS X Internals book. ++ */ ++typedef struct interpose_s { ++ void *new_func; ++ void *orig_func; ++} interpose_t; ++ ++# define FN_NAME(fn) dummy_ ## fn ++# define INTERPOSE(fn) \ ++ __attribute__((__used__)) static const interpose_t interpose_ ## fn \ ++ __attribute__((__section__("__DATA,__interpose"))) = \ ++ { (void *)dummy_ ## fn, (void *)fn }; ++#else ++# define FN_NAME(fn) fn ++# define INTERPOSE(fn) ++#endif ++ ++/* ++ * Dummy versions of the exec(3) family of syscalls. It is not enough to ++ * just dummy out execve(2) since many C libraries do not call the public ++ * execve(2) interface. Note that it is still possible to access the real ++ * syscalls via the syscall(2) interface, but that is rarely done. + */ + + #define DUMMY_BODY \ +@@ -40,61 +84,172 @@ + return -1; \ + } + ++#define DUMMY1(fn, t1) \ ++__dso_public int \ ++FN_NAME(fn)(t1 a1) \ ++DUMMY_BODY \ ++INTERPOSE(fn) ++ + #define DUMMY2(fn, t1, t2) \ + __dso_public int \ +-fn(t1 a1, t2 a2) \ +-DUMMY_BODY ++FN_NAME(fn)(t1 a1, t2 a2) \ ++DUMMY_BODY \ ++INTERPOSE(fn) + + #define DUMMY3(fn, t1, t2, t3) \ + __dso_public int \ +-fn(t1 a1, t2 a2, t3 a3) \ +-DUMMY_BODY ++FN_NAME(fn)(t1 a1, t2 a2, t3 a3) \ ++DUMMY_BODY \ ++INTERPOSE(fn) + + #define DUMMY6(fn, t1, t2, t3, t4, t5, t6) \ + __dso_public int \ +-fn(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \ +-DUMMY_BODY ++FN_NAME(fn)(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \ ++DUMMY_BODY \ ++INTERPOSE(fn) + + #define DUMMY_VA(fn, t1, t2) \ + __dso_public int \ +-fn(t1 a1, t2 a2, ...) \ +-DUMMY_BODY ++FN_NAME(fn)(t1 a1, t2 a2, ...) \ ++DUMMY_BODY \ ++INTERPOSE(fn) + ++/* ++ * Standard exec(3) family of functions. ++ */ + DUMMY_VA(execl, const char *, const char *) +-DUMMY_VA(_execl, const char *, const char *) +-DUMMY_VA(__execl, const char *, const char *) + DUMMY_VA(execle, const char *, const char *) +-DUMMY_VA(_execle, const char *, const char *) +-DUMMY_VA(__execle, const char *, const char *) + DUMMY_VA(execlp, const char *, const char *) +-DUMMY_VA(_execlp, const char *, const char *) +-DUMMY_VA(__execlp, const char *, const char *) +-DUMMY3(exect, const char *, char * const *, char * const *) +-DUMMY3(_exect, const char *, char * const *, char * const *) +-DUMMY3(__exect, const char *, char * const *, char * const *) + DUMMY2(execv, const char *, char * const *) +-DUMMY2(_execv, const char *, char * const *) +-DUMMY2(__execv, const char *, char * const *) + DUMMY2(execvp, const char *, char * const *) +-DUMMY2(_execvp, const char *, char * const *) +-DUMMY2(__execvp, const char *, char * const *) +-DUMMY3(execvP, const char *, const char *, char * const *) +-DUMMY3(_execvP, const char *, const char *, char * const *) +-DUMMY3(__execvP, const char *, const char *, char * const *) + DUMMY3(execve, const char *, char * const *, char * const *) +-DUMMY3(_execve, const char *, char * const *, char * const *) +-DUMMY3(__execve, const char *, char * const *, char * const *) ++ ++/* ++ * Non-standard exec(3) functions and corresponding private versions. ++ */ ++#ifdef HAVE_EXECVP ++DUMMY3(execvP, const char *, const char *, char * const *) ++#endif ++#ifdef HAVE_EXECVPE + DUMMY3(execvpe, const char *, char * const *, char * const *) +-DUMMY3(_execvpe, const char *, char * const *, char * const *) +-DUMMY3(__execvpe, const char *, char * const *, char * const *) ++#endif ++#ifdef HAVE_EXECT ++DUMMY3(exect, const char *, char * const *, char * const *) ++#endif ++ ++/* ++ * Not all systems support fexecve(2), posix_spawn(2) and posix_spawnp(2). ++ */ ++#ifdef HAVE_FEXECVE + DUMMY3(fexecve, int , char * const *, char * const *) +-DUMMY3(_fexecve, int , char * const *, char * const *) +-DUMMY3(__fexecve, int , char * const *, char * const *) +-#ifdef HAVE_SPAWN_H ++#endif ++#ifdef HAVE_POSIX_SPAWN + DUMMY6(posix_spawn, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *) +-DUMMY6(_posix_spawn, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *) +-DUMMY6(__posix_spawn, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *) ++#endif ++#ifdef HAVE_POSIX_SPAWNP + DUMMY6(posix_spawnp, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *) +-DUMMY6(_posix_spawnp, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *) +-DUMMY6(__posix_spawnp, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *) +-#endif /* HAVE_SPAWN_H */ ++#endif ++ ++/* ++ * system(3) and popen(3). ++ * We can't use a wrapper for popen since it returns FILE *, not int. ++ */ ++DUMMY1(system, const char *) ++ ++__dso_public FILE * ++FN_NAME(popen)(const char *c, const char *t) ++{ ++ errno = EACCES; ++ return NULL; ++} ++INTERPOSE(popen) ++ ++#if defined(HAVE_WORDEXP) && (defined(RTLD_NEXT) || defined(HAVE_SHL_LOAD) || defined(HAVE___INTERPOSE)) ++/* ++ * We can't use a wrapper for wordexp(3) since we still want to call ++ * the real wordexp(3) but with WRDE_NOCMD added to the flags argument. ++ */ ++typedef int (*sudo_fn_wordexp_t)(const char *, wordexp_t *, int); ++ ++__dso_public int ++FN_NAME(wordexp)(const char *words, wordexp_t *we, int flags) ++{ ++#if defined(HAVE___INTERPOSE) ++ return wordexp(words, we, flags | WRDE_NOCMD); ++#else ++# if defined(HAVE_DLOPEN) ++ void *fn = dlsym(RTLD_NEXT, "wordexp"); ++# elif defined(HAVE_SHL_LOAD) ++ const char *name, *myname = _PATH_SUDO_NOEXEC; ++ struct shl_descriptor *desc; ++ void *fn = NULL; ++ int idx = 0; ++ ++ name = strrchr(myname, '/'); ++ if (name != NULL) ++ myname = name + 1; ++ ++ /* Search for wordexp() but skip this shared object. */ ++ while (shl_get(idx++, &desc) == 0) { ++ name = strrchr(desc->filename, '/'); ++ if (name == NULL) ++ name = desc->filename; ++ else ++ name++; ++ if (strcmp(name, myname) == 0) ++ continue; ++ if (shl_findsym(&desc->handle, "wordexp", TYPE_PROCEDURE, &fn) == 0) ++ break; ++ } ++# else ++ void *fn = NULL; ++# endif ++ if (fn == NULL) { ++ errno = EACCES; ++ return -1; ++ } ++ return ((sudo_fn_wordexp_t)fn)(words, we, flags | WRDE_NOCMD); ++#endif /* HAVE___INTERPOSE */ ++} ++INTERPOSE(wordexp) ++#endif /* HAVE_WORDEXP && (RTLD_NEXT || HAVE_SHL_LOAD || HAVE___INTERPOSE) */ ++ ++/* ++ * On Linux we can use a seccomp() filter to disable exec. ++ */ ++#if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER ++ ++/* Older systems may not support execveat(2). */ ++#ifndef __NR_execveat ++# define __NR_execveat -1 ++#endif ++ ++static void noexec_ctor(void) __attribute__((constructor)); ++ ++static void ++noexec_ctor(void) ++{ ++ struct sock_filter exec_filter[] = { ++ /* Load syscall number into the accumulator */ ++ BPF_STMT(BPF_LD | BPF_ABS, offsetof(struct seccomp_data, nr)), ++ /* Jump to deny for execve/execveat */ ++ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execve, 2, 0), ++ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execveat, 1, 0), ++ /* Allow non-matching syscalls */ ++ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), ++ /* Deny execve/execveat syscall */ ++ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EACCES & SECCOMP_RET_DATA)) ++ }; ++ const struct sock_fprog exec_fprog = { ++ nitems(exec_filter), ++ exec_filter ++ }; ++ ++ /* ++ * SECCOMP_MODE_FILTER will fail unless the process has ++ * CAP_SYS_ADMIN or the no_new_privs bit is set. ++ */ ++ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0) ++ (void)prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &exec_fprog); ++} ++#endif /* HAVE_DECL_SECCOMP_SET_MODE_FILTER */ diff --git a/SOURCES/sudo-1.8.6p7-nproc-nowait.patch b/SOURCES/sudo-1.8.6p7-nproc-nowait.patch new file mode 100644 index 00000000..0d750312 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-nproc-nowait.patch @@ -0,0 +1,48 @@ +diff -up sudo-1.8.6p7/src/exec.c.nproc-nowait sudo-1.8.6p7/src/exec.c +--- sudo-1.8.6p7/src/exec.c.nproc-nowait 2016-05-11 12:56:58.694022525 +0200 ++++ sudo-1.8.6p7/src/exec.c 2016-05-11 12:56:58.759021618 +0200 +@@ -298,6 +298,7 @@ sudo_execute(struct command_details *det + */ + if (details->flags & CD_DONTWAIT) { + if (exec_setup(details, NULL, -1) == true) { ++ restore_nproc(); + /* headed for execve() */ + sudo_debug_execve(SUDO_DEBUG_INFO, details->command, + details->argv, details->envp); +diff -up sudo-1.8.6p7/src/sudo.c.nproc-nowait sudo-1.8.6p7/src/sudo.c +--- sudo-1.8.6p7/src/sudo.c.nproc-nowait 2016-05-11 12:56:58.758021632 +0200 ++++ sudo-1.8.6p7/src/sudo.c 2016-05-11 13:12:21.833116202 +0200 +@@ -145,6 +145,7 @@ static struct rlimit corelimit; + #endif /* RLIMIT_CORE */ + #if defined(__linux__) + static struct rlimit nproclimit; ++static struct rlimit orig_nproc_limit; + #endif + + int +@@ -853,6 +854,17 @@ unlimit_nproc(void) + debug_return; + } + ++void restore_nproc(void) ++{ ++ debug_decl(restore_nproc, SUDO_DEBUG_EXEC); ++#if defined(__linux__) ++ if (setrlimit(RLIMIT_NPROC, &orig_nproc_limit) != 0) { ++ errorx(1, _("Cannot restore nproc rlimit: errno=%d"), errno); ++ } ++#endif ++ debug_return; ++} ++ + #ifdef HAVE_PROJECT_H + static void + set_project(struct passwd *pw) +@@ -1089,6 +1101,7 @@ exec_setup(struct command_details *detai + */ + #if defined(__linux__) && defined(_SC_CHILD_MAX) + { ++ getrlimit(RLIMIT_NPROC, &orig_nproc_limit); + struct rlimit rl; + long l; + errno = 0; diff --git a/SOURCES/sudo-1.8.6p7-null_exception.patch b/SOURCES/sudo-1.8.6p7-null_exception.patch new file mode 100644 index 00000000..f48b9524 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-null_exception.patch @@ -0,0 +1,13 @@ +diff -up sudo-1.8.6p7/src/sudo.c.null_exception sudo-1.8.6p7/src/sudo.c +--- sudo-1.8.6p7/src/sudo.c.null_exception 2016-05-11 10:39:56.466888652 +0200 ++++ sudo-1.8.6p7/src/sudo.c 2016-05-11 10:39:56.530887742 +0200 +@@ -483,6 +483,9 @@ get_user_info(struct user_details *ud) + errorx(1, _("unable to allocate memory")); + ud->cwd = user_info[i] + sizeof("cwd=") - 1; + } ++ else { ++ errorx(1, _("unable to resolve current working directory")); ++ } + + if ((cp = get_process_ttyname()) != NULL) { + user_info[++i] = fmt_string("tty", cp); diff --git a/SOURCES/sudo-1.8.6p7-pam_servicebackport.patch b/SOURCES/sudo-1.8.6p7-pam_servicebackport.patch new file mode 100644 index 00000000..53017f21 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-pam_servicebackport.patch @@ -0,0 +1,221 @@ +diff -up sudo-1.8.6p7/configure.in.pam_servicebackport sudo-1.8.6p7/configure.in +--- sudo-1.8.6p7/configure.in.pam_servicebackport 2016-05-09 15:36:30.213715598 +0200 ++++ sudo-1.8.6p7/configure.in 2016-05-09 15:36:30.237715261 +0200 +@@ -121,6 +121,7 @@ AC_SUBST([nsswitch_conf]) + AC_SUBST([netsvc_conf]) + AC_SUBST([secure_path]) + AC_SUBST([editor]) ++AC_SUBST([pam_login_service]) + # + # Begin initial values for man page substitution + # +@@ -160,6 +161,7 @@ netsvc_conf=/etc/netsvc.conf + noexec_file=/usr/local/libexec/sudo_noexec.so + nsswitch_conf=/etc/nsswitch.conf + secure_path="not set" ++pam_login_service=sudo + # + # End initial values for man page substitution + # +@@ -2717,6 +2719,7 @@ if test ${with_pam-"no"} != "no"; then + yes) AC_DEFINE([HAVE_PAM_LOGIN]) + AC_MSG_CHECKING(whether to use PAM login) + AC_MSG_RESULT(yes) ++ pam_login_service="sudo-i" + ;; + no) ;; + *) AC_MSG_ERROR(["--with-pam-login does not take an argument."]) +diff -up sudo-1.8.6p7/configure.pam_servicebackport sudo-1.8.6p7/configure +--- sudo-1.8.6p7/configure.pam_servicebackport 2013-02-25 20:48:02.000000000 +0100 ++++ sudo-1.8.6p7/configure 2016-05-09 15:36:30.238715247 +0200 +@@ -658,6 +658,7 @@ OBJEXT + EXEEXT + ac_ct_CC + CC ++pam_login_service + editor + secure_path + netsvc_conf +@@ -2959,6 +2960,7 @@ netsvc_conf=/etc/netsvc.conf + noexec_file=/usr/local/libexec/sudo_noexec.so + nsswitch_conf=/etc/nsswitch.conf + secure_path="not set" ++pam_login_service=sudo + # + # End initial values for man page substitution + # +@@ -18631,6 +18633,7 @@ if test "${with_pam_login+set}" = set; t + $as_echo_n "checking whether to use PAM login... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + $as_echo "yes" >&6; } ++ pam_login_service="sudo-i" + ;; + no) ;; + *) as_fn_error $? "\"--with-pam-login does not take an argument.\"" "$LINENO" 5 +diff -up sudo-1.8.6p7/doc/sudoers.cat.pam_servicebackport sudo-1.8.6p7/doc/sudoers.cat +--- sudo-1.8.6p7/doc/sudoers.cat.pam_servicebackport 2016-05-09 15:36:30.222715472 +0200 ++++ sudo-1.8.6p7/doc/sudoers.cat 2016-05-09 15:36:30.239715233 +0200 +@@ -1245,6 +1245,18 @@ SSUUDDOOEERRSS OOPPTTIIOONN + noexec file should now be set in the _/_e_t_c_/_s_u_d_o_._c_o_n_f + file. + ++ pam_login_service ++ On systems that use PAM for authentication, this is the ++ service name used when the -^H-i^Hi option is specified. The ++ default value is ``sudo''. See the description of ++ _^Hp_^Ha_^Hm_^H__^Hs_^He_^Hr_^Hv_^Hi_^Hc_^He for more information. ++ ++ pam_service On systems that use PAM for authentication, the service ++ name specifies the PAM policy to apply. This usually ++ corresponds to an entry in the _^Hp_^Ha_^Hm_^H._^Hc_^Ho_^Hn_^Hf file or a fi ++ in the _^H/_^He_^Ht_^Hc_^H/_^Hp_^Ha_^Hm_^H._^Hd directory. The default valu ++ ``sudo''. ++ + passprompt The default prompt to use when asking for a password; + can be overridden via the --pp option or the SUDO_PROMPT + environment variable. The following percent (`%') +diff -up sudo-1.8.6p7/doc/sudoers.man.in.pam_servicebackport sudo-1.8.6p7/doc/sudoers.man.in +--- sudo-1.8.6p7/doc/sudoers.man.in.pam_servicebackport 2016-05-09 15:36:30.223715458 +0200 ++++ sudo-1.8.6p7/doc/sudoers.man.in 2016-05-09 15:36:30.239715233 +0200 +@@ -2628,6 +2628,29 @@ The path to the noexec file should now b + \fI@sysconfdir@/sudo.conf\fR + file. + .TP 18n ++pam_login_service ++.br ++On systems that use PAM for authentication, this is the service ++name used when the ++\fB\-i\fR ++option is specified. ++The default value is ++``\fR@pam_login_service@\fR''. ++See the description of ++\fIpam_service\fR ++for more information. ++.TP 18n ++pam_service ++On systems that use PAM for authentication, the service name ++specifies the PAM policy to apply. ++This usually corresponds to an entry in the ++\fIpam.conf\fR ++file or a file in the ++\fI/etc/pam.d\fR ++directory. ++The default value is ++``\fRsudo\fR''. ++.TP 18n + passprompt + The default prompt to use when asking for a password; can be overridden via the + \fB\-p\fR +diff -up sudo-1.8.6p7/doc/sudoers.mdoc.in.pam_servicebackport sudo-1.8.6p7/doc/sudoers.mdoc.in +--- sudo-1.8.6p7/doc/sudoers.mdoc.in.pam_servicebackport 2016-05-09 15:36:30.223715458 +0200 ++++ sudo-1.8.6p7/doc/sudoers.mdoc.in 2016-05-09 15:36:30.240715219 +0200 +@@ -2464,6 +2464,26 @@ This option is no longer supported. + The path to the noexec file should now be set in the + .Pa @sysconfdir@/sudo.conf + file. ++.It pam_login_service ++On systems that use PAM for authentication, this is the service ++name used when the ++.Fl i ++option is specified. ++The default value is ++.Dq Li @pam_login_service@ . ++See the description of ++.Em pam_service ++for more information. ++.It pam_service ++On systems that use PAM for authentication, the service name ++specifies the PAM policy to apply. ++This usually corresponds to an entry in the ++.Pa pam.conf ++file or a file in the ++.Pa /etc/pam.d ++directory. ++The default value is ++.Dq Li sudo . + .It passprompt + The default prompt to use when asking for a password; can be overridden via the + .Fl p +diff -up sudo-1.8.6p7/plugins/sudoers/auth/pam.c.pam_servicebackport sudo-1.8.6p7/plugins/sudoers/auth/pam.c +--- sudo-1.8.6p7/plugins/sudoers/auth/pam.c.pam_servicebackport 2016-05-09 15:36:30.202715752 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/auth/pam.c 2016-05-09 15:36:30.240715219 +0200 +@@ -90,12 +90,8 @@ sudo_pam_init(struct passwd *pw, sudo_au + if (auth != NULL) + auth->data = (void *) &pam_status; + pam_conv.conv = converse; +-#ifdef HAVE_PAM_LOGIN +- if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) +- pam_status = pam_start("sudo-i", pw->pw_name, &pam_conv, &pamh); +- else +-#endif +- pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); ++ pam_status = pam_start(ISSET(sudo_mode, MODE_LOGIN_SHELL) ? ++ def_pam_login_service : def_pam_service, pw->pw_name, &pam_conv, &pamh); + if (pam_status != PAM_SUCCESS) { + log_error(USE_ERRNO|NO_MAIL, _("unable to initialize PAM")); + debug_return_int(AUTH_FATAL); +diff -up sudo-1.8.6p7/plugins/sudoers/defaults.c.pam_servicebackport sudo-1.8.6p7/plugins/sudoers/defaults.c +--- sudo-1.8.6p7/plugins/sudoers/defaults.c.pam_servicebackport 2016-05-09 15:36:30.234715304 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/defaults.c 2016-05-09 15:36:30.240715219 +0200 +@@ -424,6 +424,13 @@ init_defaults(void) + def_env_reset = ENV_RESET; + def_set_logname = true; + def_closefrom = STDERR_FILENO + 1; ++ def_pam_service = estrdup("sudo"); ++#ifdef HAVE_PAM_LOGIN ++ def_pam_login_service = estrdup("sudo-i"); ++#else ++ def_pam_login_service = estrdup("sudo"); ++#endif ++ + + /* Syslog options need special care since they both strings and ints */ + #if (LOGGING & SLOG_SYSLOG) +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.c.pam_servicebackport sudo-1.8.6p7/plugins/sudoers/def_data.c +--- sudo-1.8.6p7/plugins/sudoers/def_data.c.pam_servicebackport 2016-05-09 15:36:30.234715304 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.c 2016-05-09 15:36:30.240715219 +0200 +@@ -363,6 +363,14 @@ struct sudo_defs_types sudo_defs_table[] + N_("Use both user and host/domain fields when matching netgroups"), + NULL, + }, { ++ "pam_service", T_STR, ++ N_("PAM service name to use"), ++ NULL, ++ }, { ++ "pam_login_service", T_STR, ++ N_("PAM service name to use for login shells"), ++ NULL, ++ }, { + NULL, 0, NULL + } + }; +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.h.pam_servicebackport sudo-1.8.6p7/plugins/sudoers/def_data.h +--- sudo-1.8.6p7/plugins/sudoers/def_data.h.pam_servicebackport 2016-05-09 15:36:30.235715289 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.h 2016-05-09 15:36:30.240715219 +0200 +@@ -168,6 +168,11 @@ + #define I_LEGACY_GROUP_PROCESSING 83 + #define def_netgroup_tuple (sudo_defs_table[84].sd_un.flag) + #define I_NETGROUP_TUPLE 84 ++#define def_pam_service (sudo_defs_table[85].sd_un.str) ++#define I_PAM_SERVICE 85 ++#define def_pam_login_service (sudo_defs_table[86].sd_un.str) ++#define I_PAM_LOGIN_SERVICE 86 ++ + + enum def_tuple { + never, +diff -up sudo-1.8.6p7/plugins/sudoers/def_data.in.pam_servicebackport sudo-1.8.6p7/plugins/sudoers/def_data.in +--- sudo-1.8.6p7/plugins/sudoers/def_data.in.pam_servicebackport 2013-02-25 20:42:44.000000000 +0100 ++++ sudo-1.8.6p7/plugins/sudoers/def_data.in 2016-05-09 15:36:30.240715219 +0200 +@@ -259,3 +259,10 @@ privs + limitprivs + T_STR + "Set of limit privileges" ++pam_service ++ T_STR ++ "PAM service name to use" ++pam_login_service ++ T_STR ++ "PAM service name to use for login shells" ++ diff --git a/SOURCES/sudo-1.8.6p7-segfault-null-group-list.patch b/SOURCES/sudo-1.8.6p7-segfault-null-group-list.patch new file mode 100644 index 00000000..609c872c --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-segfault-null-group-list.patch @@ -0,0 +1,13 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/match.c.segfault-null-group-list sudo-1.8.6p7/plugins/sudoers/match.c +--- sudo-1.8.6p7/plugins/sudoers/match.c.segfault-null-group-list 2016-05-11 10:22:29.201786896 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/match.c 2016-05-11 10:22:29.212786739 +0200 +@@ -164,6 +164,9 @@ runaslist_matches(struct member_list *us + int group_matched = UNSPEC; + debug_decl(runaslist_matches, SUDO_DEBUG_MATCH) + ++ if (user_list == NULL)user_list = ∅ ++ if (group_list == NULL)group_list = ∅ ++ + if (runas_pw != NULL) { + /* If no runas user or runas group listed in sudoers, use default. */ + if (tq_empty(user_list) && tq_empty(group_list)) diff --git a/SOURCES/sudo-1.8.6p7-sesh_loginshell.patch b/SOURCES/sudo-1.8.6p7-sesh_loginshell.patch new file mode 100644 index 00000000..dde94914 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-sesh_loginshell.patch @@ -0,0 +1,12 @@ +diff -up sudo-1.8.6p7/src/sesh.c.sesh_loginshell sudo-1.8.6p7/src/sesh.c +--- sudo-1.8.6p7/src/sesh.c.sesh_loginshell 2014-02-26 12:37:59.735214882 +0100 ++++ sudo-1.8.6p7/src/sesh.c 2014-02-26 12:38:05.535235487 +0100 +@@ -214,6 +214,8 @@ cleanup_0: + if (argv[-1][0] == '-') { + if ((cp = strrchr(argv[0], '/')) == NULL) + cp = argv[0]; ++ else ++ argv[0] = cp; + *cp = '-'; + } + sudo_execve(cmnd, argv, envp, noexec); diff --git a/SOURCES/sudo-1.8.6p7-strunquote.patch b/SOURCES/sudo-1.8.6p7-strunquote.patch new file mode 100644 index 00000000..63aa9645 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-strunquote.patch @@ -0,0 +1,137 @@ +diff -up sudo-1.8.6p7/common/Makefile.in.strunquote sudo-1.8.6p7/common/Makefile.in +--- sudo-1.8.6p7/common/Makefile.in.strunquote 2013-02-25 20:46:09.000000000 +0100 ++++ sudo-1.8.6p7/common/Makefile.in 2015-07-07 14:30:09.267181200 +0200 +@@ -63,7 +63,7 @@ SHELL = @SHELL@ + + LTOBJS = alloc.lo atobool.lo fileops.lo fmt_string.lo lbuf.lo list.lo \ + secure_path.lo setgroups.lo sudo_conf.lo sudo_debug.lo term.lo \ +- ttysize.lo zero_bytes.lo @COMMON_OBJS@ ++ ttysize.lo zero_bytes.lo strunquote.lo @COMMON_OBJS@ + + all: libcommon.la + +@@ -164,3 +164,6 @@ ttysize.lo: $(srcdir)/ttysize.c $(top_bu + zero_bytes.lo: $(srcdir)/zero_bytes.c $(top_builddir)/config.h \ + $(incdir)/missing.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/zero_bytes.c ++strunquote.lo: $(srcdir)/strunquote.c $(top_builddir)/config.h \ ++ $(incdir)/missing.h ++ $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/strunquote.c +diff -up sudo-1.8.6p7/common/strunquote.c.strunquote sudo-1.8.6p7/common/strunquote.c +--- sudo-1.8.6p7/common/strunquote.c.strunquote 2015-07-07 14:30:09.267181200 +0200 ++++ sudo-1.8.6p7/common/strunquote.c 2015-07-07 14:31:05.403649285 +0200 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2015 Daniel Kopecek ++ * ++ * 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. ++ */ ++#include ++#include ++ ++char *strunquote(char *arg) ++{ ++ char *str = arg; ++ if (str == NULL) { ++ return NULL; ++ } ++ const size_t len = strlen(str); ++ char *strend = str + len - 1; ++ ++ /* Remove blanks */ ++ for (; isblank((unsigned char)*str); str++); ++ for (; isblank((unsigned char)*strend) && strend > str; strend--); ++ /* ++ * Check that the string is double-quoted. ++ * If not, we are done. ++ */ ++ if (*str != '"' || *strend != '"' || str == strend) { ++ /* Return the original argument if we didn't touch it */ ++ return arg; ++ } ++ ++ /* Remove the double-quotes */ ++ *strend = '\0'; ++ ++str; ++ ++ return str; ++} +diff -up sudo-1.8.6p7/include/strunquote.h.strunquote sudo-1.8.6p7/include/strunquote.h +--- sudo-1.8.6p7/include/strunquote.h.strunquote 2015-07-07 14:30:09.267181200 +0200 ++++ sudo-1.8.6p7/include/strunquote.h 2015-07-07 14:30:09.267181200 +0200 +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (c) 2015 Daniel Kopecek ++ * ++ * 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. ++ */ ++ ++char *strunquote(char *arg); +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.strunquote sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.strunquote 2015-07-07 14:30:09.259181276 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2015-07-07 14:30:09.267181200 +0200 +@@ -79,6 +79,7 @@ + #include "sudoers.h" + #include "parse.h" + #include "lbuf.h" ++#include "strunquote.h" + + /* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */ + #if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(HAVE_LDAP_SSL_H) && !defined(HAVE_MPS_LDAP_SSL_H) +@@ -1004,10 +1005,10 @@ sudo_ldap_parse_options(LDAP *ld, LDAPMe + if (op == '+' || op == '-') { + *(val - 2) = '\0'; /* found, remove extra char */ + /* case var+=val or var-=val */ +- set_default(var, val, (int) op); ++ set_default(var, strunquote(val), (int) op); + } else { + /* case var=val */ +- set_default(var, val, true); ++ set_default(var, strunquote(val), true); + } + } else if (*var == '!') { + /* case !var Boolean False */ +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.strunquote sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.strunquote 2015-07-07 14:30:09.260181267 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2015-07-07 14:30:09.268181191 +0200 +@@ -61,6 +61,7 @@ + #include "lbuf.h" + #include "sudo_debug.h" + #include "ipa_hostname.h" ++#include "strunquote.h" + + /* SSSD <--> SUDO interface - do not change */ + struct sss_sudo_attr { +@@ -996,10 +997,10 @@ sudo_sss_parse_options(struct sudo_sss_h + if (op == '+' || op == '-') { + *(val - 2) = '\0'; /* found, remove extra char */ + /* case var+=val or var-=val */ +- set_default(v, val, (int) op); ++ set_default(v, strunquote(val), (int) op); + } else { + /* case var=val */ +- set_default(v, val, true); ++ set_default(v, strunquote(val), true); + } + } else if (*v == '!') { + /* case !var Boolean False */ diff --git a/SOURCES/sudo-1.8.6p7-sudoconfman.patch b/SOURCES/sudo-1.8.6p7-sudoconfman.patch new file mode 100644 index 00000000..3d621ce4 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-sudoconfman.patch @@ -0,0 +1,1263 @@ +diff -up sudo-1.8.6p7/doc/Makefile.in.sudoconfman sudo-1.8.6p7/doc/Makefile.in +--- sudo-1.8.6p7/doc/Makefile.in.sudoconfman 2013-07-30 13:57:00.000004193 +0200 ++++ sudo-1.8.6p7/doc/Makefile.in 2013-07-30 13:58:25.732323525 +0200 +@@ -64,12 +64,13 @@ DEVEL = @DEVEL@ + + SHELL = @SHELL@ + +-DOCS = sudo.$(mantype) visudo.$(mantype) sudoers.$(mantype) \ +- sudoers.ldap.$(mantype) sudoers.$(mantype) \ ++DOCS = sudo.$(mantype) visudo.$(mantype) sudo.conf.$(mantype) \ ++ sudoers.$(mantype) sudoers.ldap.$(mantype) sudoers.$(mantype) \ + sudoreplay.$(mantype) sudo_plugin.$(mantype) + + DEVDOCS = $(srcdir)/sudo.man.in $(srcdir)/sudo.cat \ + $(srcdir)/visudo.man.in $(srcdir)/visudo.cat \ ++ $(srcdir)/sudo.conf.man.in $(srcdir)/sudo.conf.cat \ + $(srcdir)/sudoers.man.in $(srcdir)/sudoers.cat \ + $(srcdir)/sudoers.ldap.man.in $(srcdir)/sudoers.ldap.cat \ + $(srcdir)/sudoers.man.in $(srcdir)/sudoers.cat \ +@@ -158,6 +159,34 @@ $(srcdir)/visudo.cat: varsub $(srcdir)/v + + visudo.cat: $(srcdir)/visudo.cat + ++$(srcdir)/sudo.conf.man.in: $(srcdir)/sudo.conf.mdoc.in ++ @if [ -n "$(DEVEL)" ]; then \ ++ echo "Generating $@"; \ ++ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \ ++ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \ ++ printf '.\\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER!\n' > $@; \ ++ printf '.\\" IT IS GENERATED AUTOMATICALLY FROM sudo.conf.mdoc.in\n' >> $@; \ ++ $(SED) -n -e '/^.Dd/q' -e '/^\.\\/p' $(srcdir)/sudo.conf.mdoc.in >> $@; \ ++ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo.conf.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "VISUDO" \)"8"\(.*"\)OpenBSD \(.*\)/\1"'$$mansectsu'"\2\3/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" >> $@; \ ++ fi ++ ++sudo.conf.man.sed: $(srcdir)/fixman.sh ++ $(SHELL) $(srcdir)/fixman.sh $@ ++ ++sudo.conf.man: $(srcdir)/sudo.conf.man.in sudo.conf.man.sed ++ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/$@.in | $(SED) -f $@.sed > $@ ++ ++sudo.conf.mdoc: $(srcdir)/sudo.conf.mdoc.in ++ (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) ++ ++$(srcdir)/sudo.conf.cat: varsub $(srcdir)/sudo.conf.mdoc.in ++ @if [ -n "$(DEVEL)" ]; then \ ++ echo "Generating $@"; \ ++ $(SED) -f varsub $(srcdir)/sudo.conf.mdoc.in | $(MANDOC) -mdoc | $(SED) -e 's/ OpenBSD \([^ ].* \)/ \1 /' -e 's/(5)/(4)/g' -e 's/(8)/(1m)/g' > $@; \ ++ fi ++ ++sudo.conf.cat: $(srcdir)/sudo.conf.cat ++ + $(srcdir)/sudoers.man.in: $(srcdir)/sudoers.mdoc.in + @if [ -n "$(DEVEL)" ]; then \ + echo "Generating $@"; \ +@@ -292,10 +321,11 @@ install-doc: install-dirs + $(INSTALL) -O $(install_uid) -G $(install_gid) -m 0644 @mansrcdir@/sudo_plugin.$(mantype) $(DESTDIR)$(mandirsu)/sudo_plugin.$(mansectsu) + $(INSTALL) -O $(install_uid) -G $(install_gid) -m 0644 @mansrcdir@/sudoreplay.$(mantype) $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) + $(INSTALL) -O $(install_uid) -G $(install_gid) -m 0644 @mansrcdir@/visudo.$(mantype) $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) ++ $(INSTALL) -O $(install_uid) -G $(install_gid) -m 0644 @mansrcdir@/sudo.conf.$(mantype) $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform) + $(INSTALL) -O $(install_uid) -G $(install_gid) -m 0644 @mansrcdir@/sudoers.$(mantype) $(DESTDIR)$(mandirform)/sudoers.$(mansectform) + @LDAP@$(INSTALL) -O $(install_uid) -G $(install_gid) -m 0644 @mansrcdir@/sudoers.ldap.$(mantype) $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) + @if test -n "$(MANCOMPRESS)"; then \ +- for f in $(mandirsu)/sudo.$(mansectsu) $(mandirsu)/sudo_plugin.$(mansectsu) $(mandirsu)/sudoreplay.$(mansectsu) $(mandirsu)/visudo.$(mansectsu) $(mandirform)/sudoers.$(mansectform) $(mandirform)/sudoers.ldap.$(mansectform); do \ ++ for f in $(mandirsu)/sudo.$(mansectsu) $(mandirsu)/sudo_plugin.$(mansectsu) $(mandirsu)/sudoreplay.$(mansectsu) $(mandirsu)/visudo.$(mansectsu) $(mandirform)/sudo.conf.$(mansectform) $(mandirform)/sudoers.$(mansectform) $(mandirform)/sudoers.ldap.$(mansectform); do \ + if test -f $(DESTDIR)$$f; then \ + echo $(MANCOMPRESS) -f $(DESTDIR)$$f; \ + $(MANCOMPRESS) -f $(DESTDIR)$$f; \ +@@ -319,6 +349,7 @@ uninstall: + $(DESTDIR)$(mandirsu)/sudo_plugin.$(mansectsu) \ + $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) \ + $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) \ ++ $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform) \ + $(DESTDIR)$(mandirform)/sudoers.$(mansectform) \ + $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) + +diff -up sudo-1.8.6p7/doc/sudo.conf.cat.sudoconfman sudo-1.8.6p7/doc/sudo.conf.cat +--- sudo-1.8.6p7/doc/sudo.conf.cat.sudoconfman 2013-07-30 13:58:15.401285217 +0200 ++++ sudo-1.8.6p7/doc/sudo.conf.cat 2013-07-30 13:58:25.733323538 +0200 +@@ -0,0 +1,263 @@ ++SUDO(4) Programmer's Manual SUDO(4) ++ ++NNAAMMEE ++ ssuuddoo..ccoonnff - configuration for sudo front end ++ ++DDEESSCCRRIIPPTTIIOONN ++ The ssuuddoo..ccoonnff file is used to configure the ssuuddoo front end. It specifies ++ the security policy and I/O logging plugins, debug flags as well as ++ plugin-agnostic path names and settings. ++ ++ The ssuuddoo..ccoonnff file supports the following directives, described in detail ++ below. ++ ++ Plugin a security policy or I/O logging plugin ++ ++ Path a plugin-agnostic path ++ ++ Set a front end setting, such as _d_i_s_a_b_l_e___c_o_r_e_d_u_m_p or _g_r_o_u_p___s_o_u_r_c_e ++ ++ Debug debug flags to aid in debugging ssuuddoo, ssuuddoorreeppllaayy, vviissuuddoo, and ++ the ssuuddooeerrss plugin. ++ ++ The pound sign (`#') is used to indicate a comment. Both the comment ++ character and any text after it, up to the end of the line, are ignored. ++ ++ Non-comment lines that don't begin with Plugin, Path, Debug, or Set are ++ silently ignored. ++ ++ The ssuuddoo..ccoonnff file is always parsed in the ``C'' locale. ++ ++ PPlluuggiinn ccoonnffiigguurraattiioonn ++ ssuuddoo supports a plugin architecture for security policies and ++ input/output logging. Third parties can develop and distribute their own ++ policy and I/O logging plugins to work seamlessly with the ssuuddoo front ++ end. Plugins are dynamically loaded based on the contents of ssuuddoo..ccoonnff. ++ ++ A Plugin line consists of the Plugin keyword, followed by the _s_y_m_b_o_l___n_a_m_e ++ and the _p_a_t_h to the shared object containing the plugin. The _s_y_m_b_o_l___n_a_m_e ++ is the name of the struct policy_plugin or struct io_plugin in the plugin ++ shared object. The _p_a_t_h may be fully qualified or relative. If not ++ fully qualified, it is relative to the _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c directory. In ++ other words: ++ ++ Plugin sudoers_policy sudoers.so ++ ++ is equivalent to: ++ ++ Plugin sudoers_policy /usr/local/libexec/sudoers.so ++ ++ Any additional parameters after the _p_a_t_h are passed as arguments to the ++ plugin's _o_p_e_n function. For example, to override the compile-time ++ default sudoers file mode: ++ ++ Plugin sudoers_policy sudoers.so sudoers_mode=0440 ++ ++ If no ssuuddoo..ccoonnff file is present, or if it contains no Plugin lines, the ++ ssuuddooeerrss plugin will be used as the default security policy and for I/O ++ logging (if enabled by the policy). This is equivalent to the following: ++ ++ Plugin policy_plugin sudoers.so ++ Plugin io_plugin sudoers.so ++ ++ For more information on the ssuuddoo plugin architecture, see the ++ sudo_plugin(1m) manual. ++ ++ PPaatthh sseettttiinnggss ++ A Path line consists of the Path keyword, followed by the name of the ++ path to set and its value. For example: ++ ++ Path noexec /usr/local/libexec/sudo_noexec.so ++ Path askpass /usr/X11R6/bin/ssh-askpass ++ ++ The following plugin-agnostic paths may be set in the _/_e_t_c_/_s_u_d_o_._c_o_n_f ++ file: ++ ++ askpass The fully qualified path to a helper program used to read the ++ user's password when no terminal is available. This may be the ++ case when ssuuddoo is executed from a graphical (as opposed to ++ text-based) application. The program specified by _a_s_k_p_a_s_s ++ should display the argument passed to it as the prompt and ++ write the user's password to the standard output. The value of ++ _a_s_k_p_a_s_s may be overridden by the SUDO_ASKPASS environment ++ variable. ++ ++ noexec The fully-qualified path to a shared library containing dummy ++ versions of the eexxeeccvv(), eexxeeccvvee() and ffeexxeeccvvee() library ++ functions that just return an error. This is used to implement ++ the _n_o_e_x_e_c functionality on systems that support LD_PRELOAD or ++ its equivalent. The default value is: ++ _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c_/_s_u_d_o___n_o_e_x_e_c_._s_o. ++ ++ OOtthheerr sseettttiinnggss ++ The ssuuddoo..ccoonnff file also supports the following front end settings: ++ ++ disable_coredump ++ Core dumps of ssuuddoo itself are disabled by default. To aid in ++ debugging ssuuddoo crashes, you may wish to re-enable core dumps by ++ setting ``disable_coredump'' to false in ssuuddoo..ccoonnff as follows: ++ ++ Set disable_coredump false ++ ++ Note that most operating systems disable core dumps from setuid ++ programs, including ssuuddoo. To actually get a ssuuddoo core file you ++ will likely need to enable core dumps for setuid processes. On ++ BSD and Linux systems this is accomplished via the sysctl ++ command. On Solaris, the coreadm command is used to configure ++ core dump behavior. ++ ++ This setting is only available in ssuuddoo version 1.8.4 and ++ higher. ++ ++ DDeebbuugg ffllaaggss ++ ssuuddoo versions 1.8.4 and higher support a flexible debugging framework ++ that can help track down what ssuuddoo is doing internally if there is a ++ problem. ++ ++ A Debug line consists of the Debug keyword, followed by the name of the ++ program (or plugin) to debug (ssuuddoo, vviissuuddoo, ssuuddoorreeppllaayy, ssuuddooeerrss), the ++ debug file name and a comma-separated list of debug flags. The debug ++ flag syntax used by ssuuddoo and the ssuuddooeerrss plugin is _s_u_b_s_y_s_t_e_m@_p_r_i_o_r_i_t_y but ++ a plugin is free to use a different format so long as it does not include ++ a comma (`,'). ++ ++ For example: ++ ++ Debug sudo /var/log/sudo_debug all@warn,plugin@info ++ ++ would log all debugging statements at the _w_a_r_n level and higher in ++ addition to those at the _i_n_f_o level for the plugin subsystem. ++ ++ Currently, only one Debug entry per program is supported. The ssuuddoo Debug ++ entry is shared by the ssuuddoo front end, ssuuddooeeddiitt and the plugins. A ++ future release may add support for per-plugin Debug lines and/or support ++ for multiple debugging files for a single program. ++ ++ The priorities used by the ssuuddoo front end, in order of decreasing ++ severity, are: _c_r_i_t, _e_r_r, _w_a_r_n, _n_o_t_i_c_e, _d_i_a_g, _i_n_f_o, _t_r_a_c_e and _d_e_b_u_g. ++ Each priority, when specified, also includes all priorities higher than ++ it. For example, a priority of _n_o_t_i_c_e would include debug messages ++ logged at _n_o_t_i_c_e and higher. ++ ++ The following subsystems are used by the ssuuddoo front-end: ++ ++ _a_l_l matches every subsystem ++ ++ _a_r_g_s command line argument processing ++ ++ _c_o_n_v user conversation ++ ++ _e_d_i_t sudoedit ++ ++ _e_x_e_c command execution ++ ++ _m_a_i_n ssuuddoo main function ++ ++ _n_e_t_i_f network interface handling ++ ++ _p_c_o_m_m communication with the plugin ++ ++ _p_l_u_g_i_n plugin configuration ++ ++ _p_t_y pseudo-tty related code ++ ++ _s_e_l_i_n_u_x SELinux-specific handling ++ ++ _u_t_i_l utility functions ++ ++ _u_t_m_p utmp handling ++ ++FFIILLEESS ++ _/_e_t_c_/_s_u_d_o_._c_o_n_f ssuuddoo front end configuration ++ ++EEXXAAMMPPLLEESS ++ # ++ # Default /etc/sudo.conf file ++ # ++ # Format: ++ # Plugin plugin_name plugin_path plugin_options ... ++ # Path askpass /path/to/askpass ++ # Path noexec /path/to/sudo_noexec.so ++ # Debug sudo /var/log/sudo_debug all@warn ++ # Set disable_coredump true ++ # ++ # The plugin_path is relative to /usr/local/libexec unless ++ # fully qualified. ++ # The plugin_name corresponds to a global symbol in the plugin ++ # that contains the plugin interface structure. ++ # The plugin_options are optional. ++ # ++ # The sudoers plugin is used by default if no Plugin lines are ++ # present. ++ Plugin policy_plugin sudoers.so ++ Plugin io_plugin sudoers.so ++ ++ # ++ # Sudo askpass: ++ # ++ # An askpass helper program may be specified to provide a graphical ++ # password prompt for "sudo -A" support. Sudo does not ship with ++ # its own askpass program but can use the OpenSSH askpass. ++ # ++ # Use the OpenSSH askpass ++ #Path askpass /usr/X11R6/bin/ssh-askpass ++ # ++ # Use the Gnome OpenSSH askpass ++ #Path askpass /usr/libexec/openssh/gnome-ssh-askpass ++ ++ # ++ # Sudo noexec: ++ # ++ # Path to a shared library containing dummy versions of the execv(), ++ # execve() and fexecve() library functions that just return an error. ++ # This is used to implement the "noexec" functionality on systems that ++ # support C or its equivalent. ++ # The compiled-in value is usually sufficient and should only be ++ # changed if you rename or move the sudo_noexec.so file. ++ # ++ #Path noexec /usr/local/libexec/sudo_noexec.so ++ ++ # ++ # Core dumps: ++ # ++ # By default, sudo disables core dumps while it is executing ++ # (they are re-enabled for the command that is run). ++ # To aid in debugging sudo problems, you may wish to enable core ++ # dumps by setting "disable_coredump" to false. ++ # ++ #Set disable_coredump false ++ ++SSEEEE AALLSSOO ++ sudoers(4), sudo(1m), sudo_plugin(1m), ++ ++HHIISSTTOORRYY ++ See the HISTORY file in the ssuuddoo distribution ++ (http://www.sudo.ws/sudo/history.html) for a brief history of sudo. ++ ++AAUUTTHHOORRSS ++ Many people have worked on ssuuddoo over the years; this version consists of ++ code written primarily by: ++ ++ Todd C. Miller ++ ++ See the CONTRIBUTORS file in the ssuuddoo distribution ++ (http://www.sudo.ws/sudo/contributors.html) for an exhaustive list of ++ people who have contributed to ssuuddoo. ++ ++BBUUGGSS ++ If you feel you have found a bug in ssuuddoo, please submit a bug report at ++ http://www.sudo.ws/sudo/bugs/ ++ ++SSUUPPPPOORRTT ++ Limited free support is available via the sudo-users mailing list, see ++ http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search the ++ archives. ++ ++DDIISSCCLLAAIIMMEERR ++ ssuuddoo is provided ``AS IS'' and any express or implied warranties, ++ including, but not limited to, the implied warranties of merchantability ++ and fitness for a particular purpose are disclaimed. See the LICENSE ++ file distributed with ssuuddoo or http://www.sudo.ws/sudo/license.html for ++ complete details. ++ ++Sudo 1.8.6p7 February 1, 2013 Sudo 1.8.6p7 +diff -up sudo-1.8.6p7/doc/sudo.conf.man.in.sudoconfman sudo-1.8.6p7/doc/sudo.conf.man.in +--- sudo-1.8.6p7/doc/sudo.conf.man.in.sudoconfman 2013-07-30 13:58:15.401285217 +0200 ++++ sudo-1.8.6p7/doc/sudo.conf.man.in 2013-07-30 13:58:25.733323538 +0200 +@@ -0,0 +1,470 @@ ++.\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER! ++.\" IT IS GENERATED AUTOMATICALLY FROM sudo.conf.mdoc.in ++.\" ++.\" Copyright (c) 2010-2013 Todd C. Miller ++.\" ++.\" Permission to use, copy, modify, and distribute this software for any ++.\" purpose with or without fee is hereby granted, provided that the above ++.\" copyright notice and this permission notice appear in all copies. ++.\" ++.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++.\" ++.TH "SUDO" "5" "February 1, 2013" "Sudo @PACKAGE_VERSION@" "OpenBSD Programmer's Manual" ++.nh ++.if n .ad l ++.SH "NAME" ++\fBsudo.conf\fR ++\- configuration for sudo front end ++.SH "DESCRIPTION" ++The ++\fBsudo.conf\fR ++file is used to configure the ++\fBsudo\fR ++front end. ++It specifies the security policy and I/O logging plugins, debug flags ++as well as plugin-agnostic path names and settings. ++.PP ++The ++\fBsudo.conf\fR ++file supports the following directives, described in detail below. ++.TP 10n ++Plugin ++a security policy or I/O logging plugin ++.TP 10n ++Path ++a plugin-agnostic path ++.TP 10n ++Set ++a front end setting, such as ++\fIdisable_coredump\fR ++or ++\fIgroup_source\fR ++.TP 10n ++Debug ++debug flags to aid in debugging ++\fBsudo\fR, ++\fBsudoreplay\fR, ++\fBvisudo\fR, ++and the ++\fBsudoers\fR ++plugin. ++.PP ++The pound sign ++(`#') ++is used to indicate a comment. ++Both the comment character and any text after it, up to the end of ++the line, are ignored. ++.PP ++Non-comment lines that don't begin with ++\fRPlugin\fR, ++\fRPath\fR, ++\fRDebug\fR, ++or ++\fRSet\fR ++are silently ignored. ++.PP ++The ++\fBsudo.conf\fR ++file is always parsed in the ++``\fRC\fR'' ++locale. ++.SS "Plugin configuration" ++\fBsudo\fR ++supports a plugin architecture for security policies and input/output ++logging. ++Third parties can develop and distribute their own policy and I/O ++logging plugins to work seamlessly with the ++\fBsudo\fR ++front end. ++Plugins are dynamically loaded based on the contents of ++\fBsudo.conf\fR. ++.PP ++A ++\fRPlugin\fR ++line consists of the ++\fRPlugin\fR ++keyword, followed by the ++\fIsymbol_name\fR ++and the ++\fIpath\fR ++to the shared object containing the plugin. ++The ++\fIsymbol_name\fR ++is the name of the ++\fRstruct policy_plugin\fR ++or ++\fRstruct io_plugin\fR ++in the plugin shared object. ++The ++\fIpath\fR ++may be fully qualified or relative. ++If not fully qualified, it is relative to the ++\fI@PLUGINDIR@\fR ++directory. ++In other words: ++.nf ++.sp ++.RS 6n ++Plugin sudoers_policy sudoers.so ++.RE ++.fi ++.PP ++is equivalent to: ++.nf ++.sp ++.RS 6n ++Plugin sudoers_policy @PLUGINDIR@/sudoers.so ++.RE ++.fi ++.PP ++Any additional parameters after the ++\fIpath\fR ++are passed as arguments to the plugin's ++\fIopen\fR ++function. ++For example, to override the compile-time default sudoers file mode: ++.nf ++.sp ++.RS 6n ++Plugin sudoers_policy sudoers.so sudoers_mode=0440 ++.RE ++.fi ++.PP ++If no ++\fBsudo.conf\fR ++file is present, or if it contains no ++\fRPlugin\fR ++lines, the ++\fBsudoers\fR ++plugin will be used as the default security policy and for I/O logging ++(if enabled by the policy). ++This is equivalent to the following: ++.nf ++.sp ++.RS 6n ++Plugin policy_plugin sudoers.so ++Plugin io_plugin sudoers.so ++.RE ++.fi ++.PP ++For more information on the ++\fBsudo\fR ++plugin architecture, see the ++sudo_plugin(@mansectsu@) ++manual. ++.SS "Path settings" ++A ++\fRPath\fR ++line consists of the ++\fRPath\fR ++keyword, followed by the name of the path to set and its value. ++For example: ++.nf ++.sp ++.RS 6n ++Path noexec @noexec_file@ ++Path askpass /usr/X11R6/bin/ssh-askpass ++.RE ++.fi ++.PP ++The following plugin-agnostic paths may be set in the ++\fI@sysconfdir@/sudo.conf\fR ++file: ++.TP 10n ++askpass ++The fully qualified path to a helper program used to read the user's ++password when no terminal is available. ++This may be the case when ++\fBsudo\fR ++is executed from a graphical (as opposed to text-based) application. ++The program specified by ++\fIaskpass\fR ++should display the argument passed to it as the prompt and write ++the user's password to the standard output. ++The value of ++\fIaskpass\fR ++may be overridden by the ++\fRSUDO_ASKPASS\fR ++environment variable. ++.TP 10n ++noexec ++The fully-qualified path to a shared library containing dummy ++versions of the ++\fBexecv\fR(), ++\fBexecve\fR() ++and ++\fBfexecve\fR() ++library functions that just return an error. ++This is used to implement the ++\fInoexec\fR ++functionality on systems that support ++\fRLD_PRELOAD\fR ++or its equivalent. ++The default value is: ++\fI@noexec_file@\fR. ++.SS "Other settings" ++The ++\fBsudo.conf\fR ++file also supports the following front end settings: ++.TP 10n ++disable_coredump ++Core dumps of ++\fBsudo\fR ++itself are disabled by default. ++To aid in debugging ++\fBsudo\fR ++crashes, you may wish to re-enable core dumps by setting ++``disable_coredump'' ++to false in ++\fBsudo.conf\fR ++as follows: ++.RS ++.nf ++.sp ++.RS 6n ++Set disable_coredump false ++.RE ++.fi ++.sp ++Note that most operating systems disable core dumps from setuid programs, ++including ++\fBsudo\fR. ++To actually get a ++\fBsudo\fR ++core file you will likely need to enable core dumps for setuid processes. ++On BSD and Linux systems this is accomplished via the ++sysctl ++command. ++On Solaris, the ++coreadm ++command is used to configure core dump behavior. ++.sp ++This setting is only available in ++\fBsudo\fR ++version 1.8.4 and higher. ++.PP ++.RE ++.SS "Debug flags" ++\fBsudo\fR ++versions 1.8.4 and higher support a flexible debugging framework ++that can help track down what ++\fBsudo\fR ++is doing internally if there is a problem. ++.PP ++A ++\fRDebug\fR ++line consists of the ++\fRDebug\fR ++keyword, followed by the name of the program (or plugin) to debug ++(\fBsudo\fR, \fBvisudo\fR, \fBsudoreplay\fR, \fBsudoers\fR), ++the debug file name and a comma-separated list of debug flags. ++The debug flag syntax used by ++\fBsudo\fR ++and the ++\fBsudoers\fR ++plugin is ++\fIsubsystem\fR@\fIpriority\fR ++but a plugin is free to use a different format so long as it does ++not include a comma ++(`\&,'). ++.PP ++For example: ++.nf ++.sp ++.RS 6n ++Debug sudo /var/log/sudo_debug all@warn,plugin@info ++.RE ++.fi ++.PP ++would log all debugging statements at the ++\fIwarn\fR ++level and higher in addition to those at the ++\fIinfo\fR ++level for the plugin subsystem. ++.PP ++Currently, only one ++\fRDebug\fR ++entry per program is supported. ++The ++\fBsudo\fR ++\fRDebug\fR ++entry is shared by the ++\fBsudo\fR ++front end, ++\fBsudoedit\fR ++and the plugins. ++A future release may add support for per-plugin ++\fRDebug\fR ++lines and/or support for multiple debugging files for a single ++program. ++.PP ++The priorities used by the ++\fBsudo\fR ++front end, in order of decreasing severity, are: ++\fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, \fIinfo\fR, \fItrace\fR ++and ++\fIdebug\fR. ++Each priority, when specified, also includes all priorities higher ++than it. ++For example, a priority of ++\fInotice\fR ++would include debug messages logged at ++\fInotice\fR ++and higher. ++.PP ++The following subsystems are used by the ++\fBsudo\fR ++front-end: ++.TP 12n ++\fIall\fR ++matches every subsystem ++.TP 12n ++\fIargs\fR ++command line argument processing ++.TP 12n ++\fIconv\fR ++user conversation ++.TP 12n ++\fIedit\fR ++sudoedit ++.TP 12n ++\fIexec\fR ++command execution ++.TP 12n ++\fImain\fR ++\fBsudo\fR ++main function ++.TP 12n ++\fInetif\fR ++network interface handling ++.TP 12n ++\fIpcomm\fR ++communication with the plugin ++.TP 12n ++\fIplugin\fR ++plugin configuration ++.TP 12n ++\fIpty\fR ++pseudo-tty related code ++.TP 12n ++\fIselinux\fR ++SELinux-specific handling ++.TP 12n ++\fIutil\fR ++utility functions ++.TP 12n ++\fIutmp\fR ++utmp handling ++.SH "FILES" ++.TP 26n ++\fI@sysconfdir@/sudo.conf\fR ++\fBsudo\fR ++front end configuration ++.SH "EXAMPLES" ++.nf ++.RS 0n ++# ++# Default @sysconfdir@/sudo.conf file ++# ++# Format: ++# Plugin plugin_name plugin_path plugin_options ... ++# Path askpass /path/to/askpass ++# Path noexec /path/to/sudo_noexec.so ++# Debug sudo /var/log/sudo_debug all@warn ++# Set disable_coredump true ++# ++# The plugin_path is relative to @PLUGINDIR@ unless ++# fully qualified. ++# The plugin_name corresponds to a global symbol in the plugin ++# that contains the plugin interface structure. ++# The plugin_options are optional. ++# ++# The sudoers plugin is used by default if no Plugin lines are ++# present. ++Plugin policy_plugin sudoers.so ++Plugin io_plugin sudoers.so ++ ++# ++# Sudo askpass: ++# ++# An askpass helper program may be specified to provide a graphical ++# password prompt for "sudo -A" support. Sudo does not ship with ++# its own askpass program but can use the OpenSSH askpass. ++# ++# Use the OpenSSH askpass ++#Path askpass /usr/X11R6/bin/ssh-askpass ++# ++# Use the Gnome OpenSSH askpass ++#Path askpass /usr/libexec/openssh/gnome-ssh-askpass ++ ++# ++# Sudo noexec: ++# ++# Path to a shared library containing dummy versions of the execv(), ++# execve() and fexecve() library functions that just return an error. ++# This is used to implement the "noexec" functionality on systems that ++# support C or its equivalent. ++# The compiled-in value is usually sufficient and should only be ++# changed if you rename or move the sudo_noexec.so file. ++# ++#Path noexec @noexec_file@ ++ ++# ++# Core dumps: ++# ++# By default, sudo disables core dumps while it is executing ++# (they are re-enabled for the command that is run). ++# To aid in debugging sudo problems, you may wish to enable core ++# dumps by setting "disable_coredump" to false. ++# ++#Set disable_coredump false ++.RE ++.fi ++.SH "SEE ALSO" ++sudoers(@mansectform@), ++sudo(@mansectsu@), ++sudo_plugin(@mansectsu@), ++.SH "HISTORY" ++See the HISTORY file in the ++\fBsudo\fR ++distribution (http://www.sudo.ws/sudo/history.html) for a brief ++history of sudo. ++.SH "AUTHORS" ++Many people have worked on ++\fBsudo\fR ++over the years; this version consists of code written primarily by: ++.sp ++.RS 6n ++Todd C. Miller ++.RE ++.PP ++See the CONTRIBUTORS file in the ++\fBsudo\fR ++distribution (http://www.sudo.ws/sudo/contributors.html) for an ++exhaustive list of people who have contributed to ++\fBsudo\fR. ++.SH "BUGS" ++If you feel you have found a bug in ++\fBsudo\fR, ++please submit a bug report at http://www.sudo.ws/sudo/bugs/ ++.SH "SUPPORT" ++Limited free support is available via the sudo-users mailing list, ++see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or ++search the archives. ++.SH "DISCLAIMER" ++\fBsudo\fR ++is provided ++``AS IS'' ++and any express or implied warranties, including, but not limited ++to, the implied warranties of merchantability and fitness for a ++particular purpose are disclaimed. ++See the LICENSE file distributed with ++\fBsudo\fR ++or http://www.sudo.ws/sudo/license.html for complete details. +diff -up sudo-1.8.6p7/doc/sudo.conf.mdoc.in.sudoconfman sudo-1.8.6p7/doc/sudo.conf.mdoc.in +--- sudo-1.8.6p7/doc/sudo.conf.mdoc.in.sudoconfman 2013-07-30 13:58:15.401285217 +0200 ++++ sudo-1.8.6p7/doc/sudo.conf.mdoc.in 2013-07-30 13:58:25.734323547 +0200 +@@ -0,0 +1,430 @@ ++.\" ++.\" Copyright (c) 2010-2013 Todd C. Miller ++.\" ++.\" Permission to use, copy, modify, and distribute this software for any ++.\" purpose with or without fee is hereby granted, provided that the above ++.\" copyright notice and this permission notice appear in all copies. ++.\" ++.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++.\" ++.Dd February 5, 2013 ++.Dt SUDO @mansectform@ ++.Os Sudo @PACKAGE_VERSION@ ++.Sh NAME ++.Nm sudo.conf ++.Nd configuration for sudo front end ++.Sh DESCRIPTION ++The ++.Nm sudo.conf ++file is used to configure the ++.Nm sudo ++front end. ++It specifies the security policy and I/O logging plugins, debug flags ++as well as plugin-agnostic path names and settings. ++.Pp ++The ++.Nm sudo.conf ++file supports the following directives, described in detail below. ++.Bl -tag -width 8n ++.It Plugin ++a security policy or I/O logging plugin ++.It Path ++a plugin-agnostic path ++.It Set ++a front end setting, such as ++.Em disable_coredump ++or ++.Em group_source ++.It Debug ++debug flags to aid in debugging ++.Nm sudo , ++.Nm sudoreplay , ++.Nm visudo , ++and the ++.Nm sudoers ++plugin. ++.El ++.Pp ++The pound sign ++.Pq Ql # ++is used to indicate a comment. ++Both the comment character and any text after it, up to the end of ++the line, are ignored. ++.Pp ++Non-comment lines that don't begin with ++.Li Plugin , ++.Li Path , ++.Li Debug , ++or ++.Li Set ++are silently ignored. ++.Pp ++The ++.Nm sudo.conf ++file is always parsed in the ++.Dq Li C ++locale. ++.Ss Plugin configuration ++.Nm sudo ++supports a plugin architecture for security policies and input/output ++logging. ++Third parties can develop and distribute their own policy and I/O ++logging plugins to work seamlessly with the ++.Nm sudo ++front end. ++Plugins are dynamically loaded based on the contents of ++.Nm sudo.conf . ++.Pp ++A ++.Li Plugin ++line consists of the ++.Li Plugin ++keyword, followed by the ++.Em symbol_name ++and the ++.Em path ++to the shared object containing the plugin. ++The ++.Em symbol_name ++is the name of the ++.Li struct policy_plugin ++or ++.Li struct io_plugin ++in the plugin shared object. ++The ++.Em path ++may be fully qualified or relative. ++If not fully qualified, it is relative to the ++.Pa @PLUGINDIR@ ++directory. ++In other words: ++.Bd -literal -offset indent ++Plugin sudoers_policy sudoers.so ++.Ed ++.Pp ++is equivalent to: ++.Bd -literal -offset indent ++Plugin sudoers_policy @PLUGINDIR@/sudoers.so ++.Ed ++.Pp ++Any additional parameters after the ++.Em path ++are passed as arguments to the plugin's ++.Em open ++function. ++For example, to override the compile-time default sudoers file mode: ++.Bd -literal -offset indent ++Plugin sudoers_policy sudoers.so sudoers_mode=0440 ++.Ed ++.Pp ++If no ++.Nm sudo.conf ++file is present, or if it contains no ++.Li Plugin ++lines, the ++.Nm sudoers ++plugin will be used as the default security policy and for I/O logging ++(if enabled by the policy). ++This is equivalent to the following: ++.Bd -literal -offset indent ++Plugin policy_plugin sudoers.so ++Plugin io_plugin sudoers.so ++.Ed ++.Pp ++For more information on the ++.Nm sudo ++plugin architecture, see the ++.Xr sudo_plugin @mansectsu@ ++manual. ++.Ss Path settings ++A ++.Li Path ++line consists of the ++.Li Path ++keyword, followed by the name of the path to set and its value. ++For example: ++.Bd -literal -offset indent ++Path noexec @noexec_file@ ++Path askpass /usr/X11R6/bin/ssh-askpass ++.Ed ++.Pp ++The following plugin-agnostic paths may be set in the ++.Pa @sysconfdir@/sudo.conf ++file: ++.Bl -tag -width 8n ++.It askpass ++The fully qualified path to a helper program used to read the user's ++password when no terminal is available. ++This may be the case when ++.Nm sudo ++is executed from a graphical (as opposed to text-based) application. ++The program specified by ++.Em askpass ++should display the argument passed to it as the prompt and write ++the user's password to the standard output. ++The value of ++.Em askpass ++may be overridden by the ++.Ev SUDO_ASKPASS ++environment variable. ++.It noexec ++The fully-qualified path to a shared library containing dummy ++versions of the ++.Fn execv , ++.Fn execve ++and ++.Fn fexecve ++library functions that just return an error. ++This is used to implement the ++.Em noexec ++functionality on systems that support ++.Ev LD_PRELOAD ++or its equivalent. ++The default value is: ++.Pa @noexec_file@ . ++.El ++.Ss Other settings ++The ++.Nm sudo.conf ++file also supports the following front end settings: ++.Bl -tag -width 8n ++.It disable_coredump ++Core dumps of ++.Nm sudo ++itself are disabled by default. ++To aid in debugging ++.Nm sudo ++crashes, you may wish to re-enable core dumps by setting ++.Dq disable_coredump ++to false in ++.Nm sudo.conf ++as follows: ++.Bd -literal -offset indent ++Set disable_coredump false ++.Ed ++.Pp ++Note that most operating systems disable core dumps from setuid programs, ++including ++.Nm sudo . ++To actually get a ++.Nm sudo ++core file you will likely need to enable core dumps for setuid processes. ++On BSD and Linux systems this is accomplished via the ++.Xr sysctl ++command. ++On Solaris, the ++.Xr coreadm ++command is used to configure core dump behavior. ++.Pp ++This setting is only available in ++.Nm sudo ++version 1.8.4 and higher. ++.El ++.Ss Debug flags ++.Nm sudo ++versions 1.8.4 and higher support a flexible debugging framework ++that can help track down what ++.Nm sudo ++is doing internally if there is a problem. ++.Pp ++A ++.Li Debug ++line consists of the ++.Li Debug ++keyword, followed by the name of the program (or plugin) to debug ++.Pq Nm sudo , Nm visudo , Nm sudoreplay , Nm sudoers , ++the debug file name and a comma-separated list of debug flags. ++The debug flag syntax used by ++.Nm sudo ++and the ++.Nm sudoers ++plugin is ++.Em subsystem Ns No @ Ns Em priority ++but a plugin is free to use a different format so long as it does ++not include a comma ++.Pq Ql \&, . ++.Pp ++For example: ++.Bd -literal -offset indent ++Debug sudo /var/log/sudo_debug all@warn,plugin@info ++.Ed ++.Pp ++would log all debugging statements at the ++.Em warn ++level and higher in addition to those at the ++.Em info ++level for the plugin subsystem. ++.Pp ++Currently, only one ++.Li Debug ++entry per program is supported. ++The ++.Nm sudo ++.Li Debug ++entry is shared by the ++.Nm sudo ++front end, ++.Nm sudoedit ++and the plugins. ++A future release may add support for per-plugin ++.Li Debug ++lines and/or support for multiple debugging files for a single ++program. ++.Pp ++The priorities used by the ++.Nm sudo ++front end, in order of decreasing severity, are: ++.Em crit , err , warn , notice , diag , info , trace ++and ++.Em debug . ++Each priority, when specified, also includes all priorities higher ++than it. ++For example, a priority of ++.Em notice ++would include debug messages logged at ++.Em notice ++and higher. ++.Pp ++The following subsystems are used by the ++.Nm sudo ++front-end: ++.Bl -tag -width Fl ++.It Em all ++matches every subsystem ++.It Em args ++command line argument processing ++.It Em conv ++user conversation ++.It Em edit ++sudoedit ++.It Em exec ++command execution ++.It Em main ++.Nm sudo ++main function ++.It Em netif ++network interface handling ++.It Em pcomm ++communication with the plugin ++.It Em plugin ++plugin configuration ++.It Em pty ++pseudo-tty related code ++.It Em selinux ++SELinux-specific handling ++.It Em util ++utility functions ++.It Em utmp ++utmp handling ++.El ++.Sh FILES ++.Bl -tag -width 24n ++.It Pa @sysconfdir@/sudo.conf ++.Nm sudo ++front end configuration ++.El ++.Sh EXAMPLES ++.Bd -literal ++# ++# Default @sysconfdir@/sudo.conf file ++# ++# Format: ++# Plugin plugin_name plugin_path plugin_options ... ++# Path askpass /path/to/askpass ++# Path noexec /path/to/sudo_noexec.so ++# Debug sudo /var/log/sudo_debug all@warn ++# Set disable_coredump true ++# ++# The plugin_path is relative to @PLUGINDIR@ unless ++# fully qualified. ++# The plugin_name corresponds to a global symbol in the plugin ++# that contains the plugin interface structure. ++# The plugin_options are optional. ++# ++# The sudoers plugin is used by default if no Plugin lines are ++# present. ++Plugin policy_plugin sudoers.so ++Plugin io_plugin sudoers.so ++ ++# ++# Sudo askpass: ++# ++# An askpass helper program may be specified to provide a graphical ++# password prompt for "sudo -A" support. Sudo does not ship with ++# its own askpass program but can use the OpenSSH askpass. ++# ++# Use the OpenSSH askpass ++#Path askpass /usr/X11R6/bin/ssh-askpass ++# ++# Use the Gnome OpenSSH askpass ++#Path askpass /usr/libexec/openssh/gnome-ssh-askpass ++ ++# ++# Sudo noexec: ++# ++# Path to a shared library containing dummy versions of the execv(), ++# execve() and fexecve() library functions that just return an error. ++# This is used to implement the "noexec" functionality on systems that ++# support C or its equivalent. ++# The compiled-in value is usually sufficient and should only be ++# changed if you rename or move the sudo_noexec.so file. ++# ++#Path noexec @noexec_file@ ++ ++# ++# Core dumps: ++# ++# By default, sudo disables core dumps while it is executing ++# (they are re-enabled for the command that is run). ++# To aid in debugging sudo problems, you may wish to enable core ++# dumps by setting "disable_coredump" to false. ++# ++#Set disable_coredump false ++.Ed ++.Sh SEE ALSO ++.Xr sudoers @mansectform@ , ++.Xr sudo @mansectsu@ , ++.Xr sudo_plugin @mansectsu@ ++.Sh HISTORY ++See the HISTORY file in the ++.Nm sudo ++distribution (http://www.sudo.ws/sudo/history.html) for a brief ++history of sudo. ++.Sh AUTHORS ++Many people have worked on ++.Nm sudo ++over the years; this version consists of code written primarily by: ++.Bd -ragged -offset indent ++Todd C. Miller ++.Ed ++.Pp ++See the CONTRIBUTORS file in the ++.Nm sudo ++distribution (http://www.sudo.ws/sudo/contributors.html) for an ++exhaustive list of people who have contributed to ++.Nm sudo . ++.Sh BUGS ++If you feel you have found a bug in ++.Nm sudo , ++please submit a bug report at http://www.sudo.ws/sudo/bugs/ ++.Sh SUPPORT ++Limited free support is available via the sudo-users mailing list, ++see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or ++search the archives. ++.Sh DISCLAIMER ++.Nm sudo ++is provided ++.Dq AS IS ++and any express or implied warranties, including, but not limited ++to, the implied warranties of merchantability and fitness for a ++particular purpose are disclaimed. ++See the LICENSE file distributed with ++.Nm sudo ++or http://www.sudo.ws/sudo/license.html for complete details. +diff -up sudo-1.8.6p7/MANIFEST.sudoconfman sudo-1.8.6p7/MANIFEST +--- sudo-1.8.6p7/MANIFEST.sudoconfman 2013-07-30 13:56:49.585965170 +0200 ++++ sudo-1.8.6p7/MANIFEST 2013-07-30 13:58:25.731323515 +0200 +@@ -348,6 +348,9 @@ src/tgetpass.c + src/ttyname.c + src/utmp.c + sudo.pp ++sudo/sudo.conf.cat ++sudo/sudo.conf.man.in ++sudo/sudo.conf.mdoc.in + zlib/Makefile.in + zlib/adler32.c + zlib/compress.c diff --git a/SOURCES/sudo-1.8.6p7-sudoldapconfman.patch b/SOURCES/sudo-1.8.6p7-sudoldapconfman.patch new file mode 100644 index 00000000..8d46dbe6 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-sudoldapconfman.patch @@ -0,0 +1,50 @@ +From 447b3f0c91f019c1d30b5703c61316b583f5bce1 Mon Sep 17 00:00:00 2001 +From: Tomas Sykora +Date: Mon, 15 Aug 2016 15:15:40 +0200 +Subject: [PATCH] RHEL7 failed RPMdiff testing + +Package sudo-1.8.3p1-7.el7 failed RHEL7 RPMdiff testing + +Rebased from: +Patch16: sudo-1.8.6p7-sudoldapconfman.patch + +Resolves: +rhbz#881258 +--- + doc/Makefile.in | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/doc/Makefile.in b/doc/Makefile.in +index a6f2ea2..e27c6e0 100644 +--- a/doc/Makefile.in ++++ b/doc/Makefile.in +@@ -319,10 +319,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: +@@ -336,7 +342,8 @@ uninstall: + $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) \ + $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform) \ + $(DESTDIR)$(mandirform)/sudoers.$(mansectform) \ +- $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) ++ $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) \ ++ $(DESTDIR)$(mandirform)/sudo-ldap.conf.$(mansectform) + + splint: + +-- +2.7.4 + diff --git a/SOURCES/sudo-1.8.6p7-tty-name-parsing.patch b/SOURCES/sudo-1.8.6p7-tty-name-parsing.patch new file mode 100644 index 00000000..fb852a4f --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-tty-name-parsing.patch @@ -0,0 +1,29 @@ +diff -up sudo-1.8.6p7/src/ttyname.c.get_process_ttyname sudo-1.8.6p7/src/ttyname.c +--- sudo-1.8.6p7/src/ttyname.c.get_process_ttyname 2013-02-25 20:46:09.000000000 +0100 ++++ sudo-1.8.6p7/src/ttyname.c 2017-05-25 10:23:28.720850944 +0200 +@@ -171,6 +171,8 @@ static char *search_devs[] = { + + static char *ignore_devs[] = { + "/dev/fd/", ++ "/dev/mqueue/", ++ "/dev/shm/", + "/dev/stdin", + "/dev/stdout", + "/dev/stderr", +@@ -437,9 +439,13 @@ get_process_ttyname(void) + len = getline(&line, &linesize, fp); + fclose(fp); + if (len != -1) { +- /* Field 7 is the tty dev (0 if no tty) */ +- char *cp = line; +- int field = 1; ++ /* ++ * Field 7 is the tty dev (0 if no tty). ++ * Since the process name at field 2 "(comm)" may include spaces, ++ * start at the last ')' found. ++ */ ++ char *cp = strrchr(line, ')'); ++ int field = 2; + while (*cp != '\0') { + if (*cp++ == ' ') { + if (++field == 7) { diff --git a/SOURCES/sudo-1.8.6p7-unprivileged-list-fix.patch b/SOURCES/sudo-1.8.6p7-unprivileged-list-fix.patch new file mode 100644 index 00000000..231ac8f6 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-unprivileged-list-fix.patch @@ -0,0 +1,37 @@ +diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.unprivileged-list-fix sudo-1.8.6p7/plugins/sudoers/ldap.c +--- sudo-1.8.6p7/plugins/sudoers/ldap.c.unprivileged-list-fix 2016-05-09 15:58:36.581120998 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2016-05-09 15:58:36.588120900 +0200 +@@ -2494,12 +2494,12 @@ sudo_ldap_lookup(struct sudo_nss *nss, i + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || +- sudo_ldap_check_command(ld, entry, NULL)) { ++ sudo_ldap_check_command(ld, entry, NULL) == true) { + matched = true; + break; + } + } +- if (matched || user_uid == 0) { ++ if (matched == true || user_uid == 0) { + SET(ret, VALIDATE_OK); + CLR(ret, VALIDATE_NOT_OK); + if (def_authenticate) { +diff -up sudo-1.8.6p7/plugins/sudoers/sssd.c.unprivileged-list-fix sudo-1.8.6p7/plugins/sudoers/sssd.c +--- sudo-1.8.6p7/plugins/sudoers/sssd.c.unprivileged-list-fix 2016-05-09 15:58:36.581120998 +0200 ++++ sudo-1.8.6p7/plugins/sudoers/sssd.c 2016-05-09 15:58:36.589120886 +0200 +@@ -1062,13 +1062,13 @@ sudo_sss_lookup(struct sudo_nss *nss, in + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || +- sudo_sss_check_command(handle, rule, NULL)) { ++ sudo_sss_check_command(handle, rule, NULL) == true) { + matched = true; + break; + } + } + } +- if (matched || user_uid == 0) { ++ if (matched == true || user_uid == 0) { + SET(ret, VALIDATE_OK); + CLR(ret, VALIDATE_NOT_OK); + if (def_authenticate) { diff --git a/SOURCES/sudo-1.8.6p7-visudocontent.patch b/SOURCES/sudo-1.8.6p7-visudocontent.patch new file mode 100644 index 00000000..11777976 --- /dev/null +++ b/SOURCES/sudo-1.8.6p7-visudocontent.patch @@ -0,0 +1,20 @@ +diff -up ./plugins/sudoers/visudo.c.fix ./plugins/sudoers/visudo.c +--- ./plugins/sudoers/visudo.c.fix 2015-09-15 10:00:25.957642667 +0200 ++++ ./plugins/sudoers/visudo.c 2015-09-15 12:37:43.478306234 +0200 +@@ -479,6 +479,7 @@ reparse_sudoers(char *editor, char *args + * Parse the edited sudoers files and do sanity checking + */ + do { ++ parse_error = NULL; + sp = tq_first(&sudoerslist); + last = tq_last(&sudoerslist); + fp = fopen(sp->tpath, "r+"); +@@ -544,7 +545,7 @@ reparse_sudoers(char *editor, char *args + continue; + edit_sudoers(sp, editor, args, errorlineno); + } +- } while (parse_error && sp != NULL); ++ } while (parse_error); + + debug_return; + } diff --git a/SOURCES/sudo-ldap.conf b/SOURCES/sudo-ldap.conf new file mode 100644 index 00000000..d8f8e4de --- /dev/null +++ b/SOURCES/sudo-ldap.conf @@ -0,0 +1,86 @@ +## BINDDN DN +## The BINDDN parameter specifies the identity, in the form of a Dis‐ +## tinguished Name (DN), to use when performing LDAP operations. If +## not specified, LDAP operations are performed with an anonymous +## identity. By default, most LDAP servers will allow anonymous +## access. +## +#binddn uid=sudo,cn=sysaccounts,cn=etc,dc=example,dc=com + +## BINDPW secret +## The BINDPW parameter specifies the password to use when performing +## LDAP operations. This is typically used in conjunction with the +## BINDDN parameter. +## +#bindpw secret + +## SSL start_tls +## If the SSL parameter is set to start_tls, the LDAP server connec‐ +## tion is initiated normally and TLS encryption is begun before the +## bind credentials are sent. This has the advantage of not requiring +## a dedicated port for encrypted communications. This parameter is +## only supported by LDAP servers that honor the start_tls extension, +## such as the OpenLDAP and Tivoli Directory servers. +## +#ssl start_tls + +## TLS_CACERTFILE file name +## The path to a certificate authority bundle which contains the cer‐ +## tificates for all the Certificate Authorities the client knows to +## be valid, e.g. /etc/ssl/ca-bundle.pem. This option is only sup‐ +## ported by the OpenLDAP libraries. Netscape-derived LDAP libraries +## use the same certificate database for CA and client certificates +## (see TLS_CERT). +## +#tls_cacertfile /path/to/CA.crt + +## TLS_CHECKPEER on/true/yes/off/false/no +## If enabled, TLS_CHECKPEER will cause the LDAP server's TLS certifi‐ +## cated to be verified. If the server's TLS certificate cannot be +## verified (usually because it is signed by an unknown certificate +## authority), sudo will be unable to connect to it. If TLS_CHECKPEER +## is disabled, no check is made. Note that disabling the check cre‐ +## ates an opportunity for man-in-the-middle attacks since the +## server's identity will not be authenticated. If possible, the CA's +## certificate should be installed locally so it can be verified. +## This option is not supported by the Tivoli Directory Server LDAP +## libraries. +#tls_checkpeer yes + +## +## URI ldap[s]://[hostname[:port]] ... +## Specifies a whitespace-delimited list of one or more +## URIs describing the LDAP server(s) to connect to. +## +#uri ldap://ldapserver + +## +## SUDOERS_BASE base +## The base DN to use when performing sudo LDAP queries. +## Multiple SUDOERS_BASE lines may be specified, in which +## case they are queried in the order specified. +## +#sudoers_base ou=SUDOers,dc=example,dc=com + +## +## BIND_TIMELIMIT seconds +## The BIND_TIMELIMIT parameter specifies the amount of +## time to wait while trying to connect to an LDAP server. +## +#bind_timelimit 30 + +## +## TIMELIMIT seconds +## The TIMELIMIT parameter specifies the amount of time +## to wait for a response to an LDAP query. +## +#timelimit 30 + +## +## SUDOERS_DEBUG debug_level +## This sets the debug level for sudo LDAP queries. Debugging +## information is printed to the standard error. A value of 1 +## results in a moderate amount of debugging information. +## A value of 2 shows the results of the matches themselves. +## +#sudoers_debug 1 diff --git a/SOURCES/sudo.conf b/SOURCES/sudo.conf new file mode 100644 index 00000000..3047842c --- /dev/null +++ b/SOURCES/sudo.conf @@ -0,0 +1,57 @@ +# +# Default /etc/sudo.conf file +# +# Format: +# Plugin plugin_name plugin_path plugin_options ... +# Path askpass /path/to/askpass +# Path noexec /path/to/sudo_noexec.so +# Debug sudo /var/log/sudo_debug all@warn +# Set disable_coredump true +# +# Sudo plugins: +# +# The plugin_path is relative to ${prefix}/libexec unless fully qualified. +# The plugin_name corresponds to a global symbol in the plugin +# that contains the plugin interface structure. +# The plugin_options are optional. +# +# The sudoers plugin is used by default if no Plugin lines are present. +Plugin sudoers_policy sudoers.so +Plugin sudoers_io sudoers.so + +# +# Sudo askpass: +# +# An askpass helper program may be specified to provide a graphical +# password prompt for "sudo -A" support. Sudo does not ship with its +# own passpass program but can use the OpenSSH askpass. +# +# Use the OpenSSH askpass +#Path askpass /usr/X11R6/bin/ssh-askpass +# +# Use the Gnome OpenSSH askpass +#Path askpass /usr/libexec/openssh/gnome-ssh-askpass + +# +# Sudo noexec: +# +# Path to a shared library containing dummy versions of the execv(), +# execve() and fexecve() library functions that just return an error. +# This is used to implement the "noexec" functionality on systems that +# support C or its equivalent. +# The compiled-in value is usually sufficient and should only be changed +# if you rename or move the sudo_noexec.so file. +# +#Path noexec /usr/libexec/sudo_noexec.so + +# +# Core dumps: +# +# By default, sudo disables core dumps while it is executing (they +# are re-enabled for the command that is run). +# To aid in debugging sudo problems, you may wish to enable core +# dumps by setting "disable_coredump" to false. +# +# Set to false here so as not to interfere with /proc/sys/fs/suid_dumpable +# +Set disable_coredump false diff --git a/SOURCES/sudoers b/SOURCES/sudoers new file mode 100644 index 00000000..2fdc62f1 --- /dev/null +++ b/SOURCES/sudoers @@ -0,0 +1,112 @@ +## Sudoers allows particular users to run various commands as +## the root user, without needing the root password. +## +## Examples are provided at the bottom of the file for collections +## of related commands, which can then be delegated out to particular +## users or groups. +## +## This file must be edited with the 'visudo' command. + +## Host Aliases +## Groups of machines. You may prefer to use hostnames (perhaps using +## wildcards for entire domains) or IP addresses instead. +# Host_Alias FILESERVERS = fs1, fs2 +# Host_Alias MAILSERVERS = smtp, smtp2 + +## User Aliases +## These aren't often necessary, as you can use regular groups +## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname +## rather than USERALIAS +# User_Alias ADMINS = jsmith, mikem + + +## Command Aliases +## These are groups of related commands... + +## Networking +# Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool + +## Installation and management of software +# Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum + +## Services +# Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start, /usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart, /usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/bin/systemctl disable + +## Updating the locate database +# Cmnd_Alias LOCATE = /usr/bin/updatedb + +## Storage +# Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount + +## Delegating permissions +# Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp + +## Processes +# Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall + +## Drivers +# Cmnd_Alias DRIVERS = /sbin/modprobe + +# Defaults specification + +# +# Refuse to run if unable to disable echo on the tty. +# +Defaults !visiblepw + +# +# Preserving HOME has security implications since many programs +# use it when searching for configuration files. Note that HOME +# is already set when the the env_reset option is enabled, so +# this option is only effective for configurations where either +# env_reset is disabled or HOME is present in the env_keep list. +# +Defaults always_set_home +Defaults match_group_by_gid + +Defaults env_reset +Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" +Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" +Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES" +Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" +Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" + +# +# Adding HOME to env_keep may enable a user to run unrestricted +# commands via sudo. +# +# Defaults env_keep += "HOME" + +Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin + +## Next comes the main part: which users can run what software on +## which machines (the sudoers file can be shared between multiple +## systems). +## Syntax: +## +## user MACHINE=COMMANDS +## +## The COMMANDS section may have other options added to it. +## +## Allow root to run any commands anywhere +root ALL=(ALL) ALL + +## Allows members of the 'sys' group to run networking, software, +## service management apps and more. +# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS + +## Allows people in group wheel to run all commands +%wheel ALL=(ALL) ALL + +## Same thing without a password +# %wheel ALL=(ALL) NOPASSWD: ALL + +## Allows members of the users group to mount and unmount the +## cdrom as root +# %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom + +## Allows members of the users group to shutdown this system +# %users localhost=/sbin/shutdown -h now + +## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment) +#includedir /etc/sudoers.d