Browse Source

sudo package update

Signed-off-by: basebuilder_pel7ppc64bebuilder0 <basebuilder@powerel.org>
master
basebuilder_pel7ppc64bebuilder0 6 years ago
parent
commit
36f654311f
  1. 27
      SOURCES/sudo-1.6.7p5-strip.patch
  2. 27
      SOURCES/sudo-1.7.2p1-envdebug.patch
  3. 189
      SOURCES/sudo-1.8.18-testsuitefix.patch
  4. 66
      SOURCES/sudo-1.8.19p2-CVE-2017-1000368.patch
  5. 16
      SOURCES/sudo-1.8.19p2-display-privs.patch
  6. 53
      SOURCES/sudo-1.8.19p2-error-warning-visudo-message.patch
  7. 124
      SOURCES/sudo-1.8.19p2-fqdn-use-after-free.patch
  8. 76
      SOURCES/sudo-1.8.19p2-get_process_ttyname.patch
  9. 142
      SOURCES/sudo-1.8.19p2-ignore-unknown-defaults.patch
  10. 317
      SOURCES/sudo-1.8.19p2-iologflush.patch
  11. 171
      SOURCES/sudo-1.8.19p2-iologtruncate.patch
  12. 54
      SOURCES/sudo-1.8.19p2-lecture-boolean.patch
  13. 164
      SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch
  14. 206
      SOURCES/sudo-1.8.19p2-manpage-use_pty.patch
  15. 44
      SOURCES/sudo-1.8.19p2-sssd-double-free.patch
  16. 113
      SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch
  17. 14
      SOURCES/sudo-1.8.19p2-upstream-testsuitefix.patch
  18. 19
      SOURCES/sudo-1.8.21-ldap-pass2-filter.patch
  19. 113
      SOURCES/sudo-1.8.6p3-ALL-with-negation-manupdate.patch
  20. 12
      SOURCES/sudo-1.8.6p3-aliaswarnonly.patch
  21. 29
      SOURCES/sudo-1.8.6p3-auditeditor.patch
  22. 45
      SOURCES/sudo-1.8.6p3-auditrolechange.patch
  23. 26
      SOURCES/sudo-1.8.6p3-authinterrupt.patch
  24. 477
      SOURCES/sudo-1.8.6p3-cycledetect.patch
  25. 46
      SOURCES/sudo-1.8.6p3-doublequotefix.patch
  26. 17
      SOURCES/sudo-1.8.6p3-emallocfail.patch
  27. 138
      SOURCES/sudo-1.8.6p3-lbufexpandcode.patch
  28. 24
      SOURCES/sudo-1.8.6p3-ldap-sssd-usermatch.patch
  29. 45
      SOURCES/sudo-1.8.6p3-ldapconfparse.patch
  30. 12
      SOURCES/sudo-1.8.6p3-mantypo.patch
  31. 74
      SOURCES/sudo-1.8.6p3-mantypos-ldap.patch
  32. 92
      SOURCES/sudo-1.8.6p3-netgrfilterfix.patch
  33. 56
      SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch
  34. 13
      SOURCES/sudo-1.8.6p3-nonehostname.patch
  35. 161
      SOURCES/sudo-1.8.6p3-nowaitopt.patch
  36. 117
      SOURCES/sudo-1.8.6p3-nprocfix.patch
  37. 12
      SOURCES/sudo-1.8.6p3-sigpipefix.patch
  38. 12
      SOURCES/sudo-1.8.6p3-sssd-noise.patch
  39. 119
      SOURCES/sudo-1.8.6p3-sssdfixes.patch
  40. 22
      SOURCES/sudo-1.8.6p3-sssdrulenames.patch
  41. 53
      SOURCES/sudo-1.8.6p3-strictuidgid.patch
  42. 747
      SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch
  43. 12
      SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch
  44. 333
      SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch
  45. 117
      SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch
  46. 38
      SOURCES/sudo-1.8.6p7-authlogicfix.patch
  47. 46
      SOURCES/sudo-1.8.6p7-clangfixes.patch
  48. 38
      SOURCES/sudo-1.8.6p7-closefrom-override-fix.patch
  49. 104
      SOURCES/sudo-1.8.6p7-constwarnfix.patch
  50. 12
      SOURCES/sudo-1.8.6p7-digest-backport-checklinkfix.patch
  51. 260
      SOURCES/sudo-1.8.6p7-digest-backport-docs.patch
  52. 435
      SOURCES/sudo-1.8.6p7-digest-backport.patch
  53. 88
      SOURCES/sudo-1.8.6p7-digest_race_doc.patch
  54. 43
      SOURCES/sudo-1.8.6p7-digestmessagesfix.patch
  55. 47
      SOURCES/sudo-1.8.6p7-duplicatenssfix.patch
  56. 192
      SOURCES/sudo-1.8.6p7-ipahostname.patch
  57. 91
      SOURCES/sudo-1.8.6p7-ldap_sssd_parse_whitespaces.patch
  58. 119
      SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch
  59. 47
      SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch
  60. 224
      SOURCES/sudo-1.8.6p7-legacy-group-processing.patch
  61. 90
      SOURCES/sudo-1.8.6p7-logsudouser.patch
  62. 107
      SOURCES/sudo-1.8.6p7-manfix-usepty.patch
  63. 194
      SOURCES/sudo-1.8.6p7-netgroup_tuple.patch
  64. 104
      SOURCES/sudo-1.8.6p7-newbase64decoder.patch
  65. 422
      SOURCES/sudo-1.8.6p7-noexec-update.patch
  66. 48
      SOURCES/sudo-1.8.6p7-nproc-nowait.patch
  67. 13
      SOURCES/sudo-1.8.6p7-null_exception.patch
  68. 221
      SOURCES/sudo-1.8.6p7-pam_servicebackport.patch
  69. 13
      SOURCES/sudo-1.8.6p7-segfault-null-group-list.patch
  70. 12
      SOURCES/sudo-1.8.6p7-sesh_loginshell.patch
  71. 137
      SOURCES/sudo-1.8.6p7-strunquote.patch
  72. 1263
      SOURCES/sudo-1.8.6p7-sudoconfman.patch
  73. 50
      SOURCES/sudo-1.8.6p7-sudoldapconfman.patch
  74. 29
      SOURCES/sudo-1.8.6p7-tty-name-parsing.patch
  75. 37
      SOURCES/sudo-1.8.6p7-unprivileged-list-fix.patch
  76. 20
      SOURCES/sudo-1.8.6p7-visudocontent.patch
  77. 86
      SOURCES/sudo-ldap.conf
  78. 57
      SOURCES/sudo.conf
  79. 112
      SOURCES/sudoers

27
SOURCES/sudo-1.6.7p5-strip.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
From 8a045c3880e06f5fcf69a73c4029d6725e17f7bc Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
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

27
SOURCES/sudo-1.7.2p1-envdebug.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
From 44a602b49365969e56c63c9f12eda197e951302f Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
Date: Fri, 19 Aug 2016 14:07:35 +0200
Subject: [PATCH 02/10] Added "Enviroment debugging" message

rebased from:
Patch2: sudo-1.7.2p1-envdebug.patch
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 9feddfd..39a2d86 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1390,7 +1390,7 @@ AC_ARG_ENABLE(env_debug,
[AS_HELP_STRING([--enable-env-debug], [Whether to enable environment debugging.])],
[ case "$enableval" in
yes) AC_MSG_RESULT(yes)
- AC_DEFINE(ENV_DEBUG)
+ AC_DEFINE(ENV_DEBUG, [], [Environment debugging.])
;;
no) AC_MSG_RESULT(no)
;;
--
2.7.4

189
SOURCES/sudo-1.8.18-testsuitefix.patch

@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
From ea44d916b9dffe0f33c3c62d1677567bf64a26b8 Mon Sep 17 00:00:00 2001
From: Radovan Sroka <rsroka@redhat.com>
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 <<EOF
-#includedir $TESTDIR/test3.d
-EOF
-
-exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test3.sh_ b/plugins/sudoers/regress/testsudoers/test3.sh_
new file mode 100755
index 0000000..c1251b9
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test3.sh_
@@ -0,0 +1,13 @@
+#!/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 <<EOF
+#includedir $TESTDIR/test3.d
+EOF
+
+exit 0
--
2.7.4

66
SOURCES/sudo-1.8.19p2-CVE-2017-1000368.patch

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
diff --git a/src/ttyname.c b/src/ttyname.c
index ff2cacc..013be95 100644
--- a/src/ttyname.c
+++ b/src/ttyname.c
@@ -477,26 +477,38 @@ done:
char *
get_process_ttyname(char *name, size_t namelen)
{
- char path[PATH_MAX], *line = NULL;
+ const char path[] = "/proc/self/stat";
+ char *cp, buf[1024];
char *ret = NULL;
- size_t linesize = 0;
int serrno = errno;
- ssize_t len;
- FILE *fp;
+ 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. */
- snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)getpid());
- if ((fp = fopen(path, "r")) != NULL) {
- 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, ')');
+ *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);

16
SOURCES/sudo-1.8.19p2-display-privs.patch

@ -0,0 +1,16 @@ @@ -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);

53
SOURCES/sudo-1.8.19p2-error-warning-visudo-message.patch

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
From daa728fd889680cf5294fbb0e836cade9fe1a6d8 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@courtesan.com>
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

124
SOURCES/sudo-1.8.19p2-fqdn-use-after-free.patch

@ -0,0 +1,124 @@ @@ -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;

76
SOURCES/sudo-1.8.19p2-get_process_ttyname.patch

@ -0,0 +1,76 @@ @@ -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 <Todd.Miller@courtesan.com>
+ * Copyright (c) 2012-2017 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -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;
}
}
}

142
SOURCES/sudo-1.8.19p2-ignore-unknown-defaults.patch

@ -0,0 +1,142 @@ @@ -0,0 +1,142 @@
From 93cef1efac4e2b4930c23cdc35c0b916365ccabc Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
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

317
SOURCES/sudo-1.8.19p2-iologflush.patch

@ -0,0 +1,317 @@ @@ -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);

171
SOURCES/sudo-1.8.19p2-iologtruncate.patch

@ -0,0 +1,171 @@ @@ -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);

54
SOURCES/sudo-1.8.19p2-lecture-boolean.patch

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
commit 631d458b6fc7341363a121c390e086cf676ecc83
Author: Todd C. Miller <Todd.Miller@courtesan.com>
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);
}
}

164
SOURCES/sudo-1.8.19p2-lookup-issue-doc.patch

@ -0,0 +1,164 @@ @@ -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

206
SOURCES/sudo-1.8.19p2-manpage-use_pty.patch

@ -0,0 +1,206 @@ @@ -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

44
SOURCES/sudo-1.8.19p2-sssd-double-free.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@

# HG changeset patch
# User Todd C. Miller <Todd.Miller@sudo.ws>
# 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;
}

113
SOURCES/sudo-1.8.19p2-sudo-l-sssd.patch

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
From 1f37620953699fe71b09760fe01e33eb6ada771c Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@courtesan.com>
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

14
SOURCES/sudo-1.8.19p2-upstream-testsuitefix.patch

@ -0,0 +1,14 @@ @@ -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"

19
SOURCES/sudo-1.8.21-ldap-pass2-filter.patch

@ -0,0 +1,19 @@ @@ -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"));

113
SOURCES/sudo-1.8.6p3-ALL-with-negation-manupdate.patch

@ -0,0 +1,113 @@ @@ -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

12
SOURCES/sudo-1.8.6p3-aliaswarnonly.patch

@ -0,0 +1,12 @@ @@ -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);
}

29
SOURCES/sudo-1.8.6p3-auditeditor.patch

@ -0,0 +1,29 @@ @@ -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;

45
SOURCES/sudo-1.8.6p3-auditrolechange.patch

@ -0,0 +1,45 @@ @@ -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;

26
SOURCES/sudo-1.8.6p3-authinterrupt.patch

@ -0,0 +1,26 @@ @@ -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

477
SOURCES/sudo-1.8.6p3-cycledetect.patch

@ -0,0 +1,477 @@ @@ -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 <Todd.Miller@courtesan.com>
*
* 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++;
}

46
SOURCES/sudo-1.8.6p3-doublequotefix.patch

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
From 1b16310c7ec5ba23fbe066c7d000016e534b4448 Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
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

17
SOURCES/sudo-1.8.6p3-emallocfail.patch

@ -0,0 +1,17 @@ @@ -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;

138
SOURCES/sudo-1.8.6p3-lbufexpandcode.patch

@ -0,0 +1,138 @@ @@ -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;

24
SOURCES/sudo-1.8.6p3-ldap-sssd-usermatch.patch

@ -0,0 +1,24 @@ @@ -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;

45
SOURCES/sudo-1.8.6p3-ldapconfparse.patch

@ -0,0 +1,45 @@ @@ -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 */

12
SOURCES/sudo-1.8.6p3-mantypo.patch

@ -0,0 +1,12 @@ @@ -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

74
SOURCES/sudo-1.8.6p3-mantypos-ldap.patch

@ -0,0 +1,74 @@ @@ -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.

92
SOURCES/sudo-1.8.6p3-netgrfilterfix.patch

@ -0,0 +1,92 @@ @@ -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);

56
SOURCES/sudo-1.8.6p3-netgrmatchtrace.patch

@ -0,0 +1,56 @@ @@ -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);

13
SOURCES/sudo-1.8.6p3-nonehostname.patch

@ -0,0 +1,13 @@ @@ -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;
}

161
SOURCES/sudo-1.8.6p3-nowaitopt.patch

@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
From 9b1f0f16bfe7552810b4adb6b17ac3674da660f9 Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
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

117
SOURCES/sudo-1.8.6p3-nprocfix.patch

@ -0,0 +1,117 @@ @@ -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);

12
SOURCES/sudo-1.8.6p3-sigpipefix.patch

@ -0,0 +1,12 @@ @@ -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);

12
SOURCES/sudo-1.8.6p3-sssd-noise.patch

@ -0,0 +1,12 @@ @@ -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);

119
SOURCES/sudo-1.8.6p3-sssdfixes.patch

@ -0,0 +1,119 @@ @@ -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);

22
SOURCES/sudo-1.8.6p3-sssdrulenames.patch

@ -0,0 +1,22 @@ @@ -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)) {

53
SOURCES/sudo-1.8.6p3-strictuidgid.patch

@ -0,0 +1,53 @@ @@ -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);
}
/*

747
SOURCES/sudo-1.8.6p3-sudoedit-selinux.patch

@ -0,0 +1,747 @@ @@ -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 <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
#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 <time.h>
#endif
+#ifdef HAVE_SELINUX
+# include <selinux/selinux.h>
+#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 <o1> <t1> ... <on> <tn> */
+ 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 <t1> <o1> ... <tn> <on> */
+ 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;

12
SOURCES/sudo-1.8.6p3-visudo-quiet-flag.patch

@ -0,0 +1,12 @@ @@ -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);

333
SOURCES/sudo-1.8.6p7-CVE-2014-9680.patch

@ -0,0 +1,333 @@ @@ -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);

117
SOURCES/sudo-1.8.6p7-CVE-2017-1000368.patch

@ -0,0 +1,117 @@ @@ -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
/*

38
SOURCES/sudo-1.8.6p7-authlogicfix.patch

@ -0,0 +1,38 @@ @@ -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 ||

46
SOURCES/sudo-1.8.6p7-clangfixes.patch

@ -0,0 +1,46 @@ @@ -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;
}

38
SOURCES/sudo-1.8.6p7-closefrom-override-fix.patch

@ -0,0 +1,38 @@ @@ -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)) {

104
SOURCES/sudo-1.8.6p7-constwarnfix.patch

@ -0,0 +1,104 @@ @@ -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 *);

12
SOURCES/sudo-1.8.6p7-digest-backport-checklinkfix.patch

@ -0,0 +1,12 @@ @@ -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

260
SOURCES/sudo-1.8.6p7-digest-backport-docs.patch

@ -0,0 +1,260 @@ @@ -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

435
SOURCES/sudo-1.8.6p7-digest-backport.patch

@ -0,0 +1,435 @@ @@ -0,0 +1,435 @@
From c8a6eecf768d8102a9a77f5fdb5b516e571d462e Mon Sep 17 00:00:00 2001
From: Radovan Sroka <rsroka@redhat.com>
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 <project.h> 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 <config.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "filedigest.h"
+#include "sudo_compat.h"
+#include "sudo_debug.h"
+
+#if defined(HAVE_LIBGCRYPT)
+#include <gcrypt.h>
+
+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 <stdio.h>
+
+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 <stddef.h>
+
+#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 <gram.h>
#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 "<INVALID>";
+}
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

88
SOURCES/sudo-1.8.6p7-digest_race_doc.patch

@ -0,0 +1,88 @@ @@ -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

43
SOURCES/sudo-1.8.6p7-digestmessagesfix.patch

@ -0,0 +1,43 @@ @@ -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 "<INVALID>";
+}
+
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)

47
SOURCES/sudo-1.8.6p7-duplicatenssfix.patch

@ -0,0 +1,47 @@ @@ -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 {

192
SOURCES/sudo-1.8.6p7-ipahostname.patch

@ -0,0 +1,192 @@ @@ -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 <dkopecek@redhat.com>
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+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 <dkopecek@redhat.com>
+ */
+#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 : "<none>", 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;

91
SOURCES/sudo-1.8.6p7-ldap_sssd_parse_whitespaces.patch

@ -0,0 +1,91 @@ @@ -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 <strings.h>
#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+
#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);

119
SOURCES/sudo-1.8.6p7-ldapsearchuidfix.patch

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
From b1f3fcf8d6e9a8e5326771a12fac8e08ed81f766 Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
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

47
SOURCES/sudo-1.8.6p7-ldapusermatchfix.patch

@ -0,0 +1,47 @@ @@ -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);
}

224
SOURCES/sudo-1.8.6p7-legacy-group-processing.patch

@ -0,0 +1,224 @@ @@ -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);

90
SOURCES/sudo-1.8.6p7-logsudouser.patch

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
From 06b46ae226fecd4188af372ac0ccd7aa582e21c8 Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
Date: Wed, 17 Aug 2016 10:12:11 +0200
Subject: [PATCH] Sudo logs username root instead of realuser

RHEL7 sudo logs username root instead of realuser in /var/log/secure

Rebased from:
Patch50: sudo-1.8.6p7-logsudouser.patch

Resolves:
rhbz#1312486
---
plugins/sudoers/logging.c | 14 +++++++-------
plugins/sudoers/sudoers.h | 1 +
2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c
index 45cae67..74b2220 100644
--- a/plugins/sudoers/logging.c
+++ b/plugins/sudoers/logging.c
@@ -104,7 +104,7 @@ do_syslog(int pri, char *msg)
* Log the full line, breaking into multiple syslog(3) calls if necessary
*/
fmt = _("%8s : %s");
- maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name));
+ maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(sudo_user_name));
for (p = msg; *p != '\0'; ) {
len = strlen(p);
if (len > maxlen) {
@@ -120,7 +120,7 @@ do_syslog(int pri, char *msg)
save = *tmp;
*tmp = '\0';
- mysyslog(pri, fmt, user_name, p);
+ mysyslog(pri, fmt, sudo_user_name, p);
*tmp = save; /* restore saved character */
@@ -128,11 +128,11 @@ do_syslog(int pri, char *msg)
for (p = tmp; *p == ' '; p++)
continue;
} else {
- mysyslog(pri, fmt, user_name, p);
+ mysyslog(pri, fmt, sudo_user_name, p);
p += len;
}
fmt = _("%8s : (command continued) %s");
- maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(user_name));
+ maxlen = def_syslog_maxlen - (strlen(fmt) - 5 + strlen(sudo_user_name));
}
sudoers_setlocale(oldlocale, NULL);
@@ -179,10 +179,10 @@ do_logfile(const char *msg)
timestr = "invalid date";
if (def_log_host) {
len = asprintf(&full_line, "%s : %s : HOST=%s : %s",
- timestr, user_name, user_srunhost, msg);
+ timestr, sudo_user_name, user_srunhost, msg);
} else {
len = asprintf(&full_line, "%s : %s : %s",
- timestr, user_name, msg);
+ timestr, sudo_user_name, msg);
}
if (len == -1) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
@@ -746,7 +746,7 @@ send_mail(const char *fmt, ...)
if ((timestr = get_timestr(time(NULL), def_log_year)) == NULL)
timestr = "invalid date";
- (void) fprintf(mail, "\n\n%s : %s : %s : ", user_host, timestr, user_name);
+ (void) fprintf(mail, "\n\n%s : %s : %s : ", user_host, timestr, sudo_user_name);
va_start(ap, fmt);
(void) vfprintf(mail, fmt, ap);
va_end(ap);
diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h
index cfd5abb..c69a043 100644
--- a/plugins/sudoers/sudoers.h
+++ b/plugins/sudoers/sudoers.h
@@ -180,6 +180,7 @@ struct sudo_user {
/*
* Shortcuts for sudo_user contents.
*/
+#define sudo_user_name (sudo_user.pw->pw_name)
#define user_name (sudo_user.name)
#define user_uid (sudo_user.uid)
#define user_gid (sudo_user.gid)
--
2.7.4

107
SOURCES/sudo-1.8.6p7-manfix-usepty.patch

@ -0,0 +1,107 @@ @@ -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 <Todd.Miller@courtesan.com>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
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
;;

194
SOURCES/sudo-1.8.6p7-netgroup_tuple.patch

@ -0,0 +1,194 @@ @@ -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);

104
SOURCES/sudo-1.8.6p7-newbase64decoder.patch

@ -0,0 +1,104 @@ @@ -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<in_len;ii++) {
+ unsigned char ch;
+ if(isspace(in[ii])) continue;
+ if(in[ii]=='=') break; /* stop at = */
+ ch=base64dec_tab[(size_t)in[ii]];
+ if(ch==255) break; /* stop at a parse error */
+ v=(v<<6)|ch;
+ rem+=6;
+ if(rem>=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

422
SOURCES/sudo-1.8.6p7-noexec-update.patch

@ -0,0 +1,422 @@ @@ -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 <wordexp.h> header file. */
+#undef HAVE_WORDEXP_H
+
/* Define to 1 if you have the <zlib.h> 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 <sys/types.h>
+#include <sys/prctl.h>
+#include <asm/unistd.h>
+#include <linux/seccomp.h>
+#include <linux/filter.h>
+ ])
;;
*-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 <procfs.h>
@@ -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 <Todd.Miller@courtesan.com>
+ * Copyright (c) 2004-2005, 2010-2016 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,20 +18,64 @@
#include <sys/types.h>
+#if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER
+# include <sys/prctl.h>
+# include <asm/unistd.h>
+# include <linux/filter.h>
+# include <linux/seccomp.h>
+#endif
+
#include <errno.h>
#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
#ifdef HAVE_SPAWN_H
#include <spawn.h>
#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#ifdef HAVE_WORDEXP_H
+#include <wordexp.h>
+#endif
+#if defined(HAVE_SHL_LOAD)
+# include <dl.h>
+#elif defined(HAVE_DLOPEN)
+# include <dlfcn.h>
+#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 */

48
SOURCES/sudo-1.8.6p7-nproc-nowait.patch

@ -0,0 +1,48 @@ @@ -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;

13
SOURCES/sudo-1.8.6p7-null_exception.patch

@ -0,0 +1,13 @@ @@ -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);

221
SOURCES/sudo-1.8.6p7-pam_servicebackport.patch

@ -0,0 +1,221 @@ @@ -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"
+

13
SOURCES/sudo-1.8.6p7-segfault-null-group-list.patch

@ -0,0 +1,13 @@ @@ -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 = &empty;
+ if (group_list == NULL)group_list = &empty;
+
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))

12
SOURCES/sudo-1.8.6p7-sesh_loginshell.patch

@ -0,0 +1,12 @@ @@ -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);

137
SOURCES/sudo-1.8.6p7-strunquote.patch

@ -0,0 +1,137 @@ @@ -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 <dkopecek@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <string.h>
+#include <ctype.h>
+
+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 <dkopecek@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+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 */

1263
SOURCES/sudo-1.8.6p7-sudoconfman.patch

File diff suppressed because it is too large Load Diff

50
SOURCES/sudo-1.8.6p7-sudoldapconfman.patch

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
From 447b3f0c91f019c1d30b5703c61316b583f5bce1 Mon Sep 17 00:00:00 2001
From: Tomas Sykora <tosykora@redhat.com>
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

29
SOURCES/sudo-1.8.6p7-tty-name-parsing.patch

@ -0,0 +1,29 @@ @@ -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) {

37
SOURCES/sudo-1.8.6p7-unprivileged-list-fix.patch

@ -0,0 +1,37 @@ @@ -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) {

20
SOURCES/sudo-1.8.6p7-visudocontent.patch

@ -0,0 +1,20 @@ @@ -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;
}

86
SOURCES/sudo-ldap.conf

@ -0,0 +1,86 @@ @@ -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

57
SOURCES/sudo.conf

@ -0,0 +1,57 @@ @@ -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<LD_PRELOAD> 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

112
SOURCES/sudoers

@ -0,0 +1,112 @@ @@ -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
Loading…
Cancel
Save