From 3226f7e28b7000d3c9d32346a1265a562ca7fc1e Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 9 Feb 2018 18:21:40 -0700 Subject: [PATCH] Move common bits of ldap to sudoers conversion into ldap_common.c and use it in sssd.c. --- MANIFEST | 2 + configure | 8 + configure.ac | 8 + mkdep.pl | 2 +- plugins/sudoers/Makefile.in | 56 ++-- plugins/sudoers/gram.c | 114 ++++---- plugins/sudoers/gram.y | 110 ++++---- plugins/sudoers/ldap.c | 433 +++-------------------------- plugins/sudoers/ldap_common.c | 428 +++++++++++++++++++++++++++++ plugins/sudoers/parse.h | 1 + plugins/sudoers/sssd.c | 504 ++++++++-------------------------- plugins/sudoers/sudo_ldap.h | 25 ++ 12 files changed, 778 insertions(+), 913 deletions(-) create mode 100644 plugins/sudoers/ldap_common.c create mode 100644 plugins/sudoers/sudo_ldap.h diff --git a/MANIFEST b/MANIFEST index 1ce3f8091..d4ec2d6d7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -303,6 +303,7 @@ plugins/sudoers/iolog.c plugins/sudoers/iolog.h plugins/sudoers/iolog_path.c plugins/sudoers/ldap.c +plugins/sudoers/ldap_common.c plugins/sudoers/linux_audit.c plugins/sudoers/linux_audit.h plugins/sudoers/locale.c @@ -550,6 +551,7 @@ plugins/sudoers/solaris_audit.h plugins/sudoers/sssd.c plugins/sudoers/starttime.c plugins/sudoers/stubs.c +plugins/sudoers/sudo_ldap.h plugins/sudoers/sudo_nss.c plugins/sudoers/sudo_nss.h plugins/sudoers/sudo_printf.c diff --git a/configure b/configure index a368b0aeb..900203b2c 100755 --- a/configure +++ b/configure @@ -4617,6 +4617,10 @@ fi if test "${with_sssd+set}" = set; then : withval=$with_sssd; case $with_sssd in yes) SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo" + case "$SUDOERS_OBJS" in + *ldap_common.lo*) ;; + *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";; + esac $as_echo "#define HAVE_SSSD 1" >>confdefs.h ;; @@ -24489,6 +24493,10 @@ fi with_ldap=yes fi SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo" + case "$SUDOERS_OBJS" in + *ldap_common.lo*) ;; + *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";; + esac LDAP="" _LIBS="$LIBS" diff --git a/configure.ac b/configure.ac index a008d323a..4731be4e7 100644 --- a/configure.ac +++ b/configure.ac @@ -379,6 +379,10 @@ dnl AC_ARG_WITH(sssd, [AS_HELP_STRING([--with-sssd], [enable SSSD support])], [case $with_sssd in yes) SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo" + case "$SUDOERS_OBJS" in + *ldap_common.lo*) ;; + *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";; + esac AC_DEFINE(HAVE_SSSD) ;; no) ;; @@ -3727,6 +3731,10 @@ if test ${with_ldap-'no'} != "no"; then with_ldap=yes fi SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo" + case "$SUDOERS_OBJS" in + *ldap_common.lo*) ;; + *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_common.lo";; + esac LDAP="" _LIBS="$LIBS" diff --git a/mkdep.pl b/mkdep.pl index fd51d8f72..4b4d85fbd 100755 --- a/mkdep.pl +++ b/mkdep.pl @@ -79,7 +79,7 @@ sub mkdep { $makefile =~ s:\@DEV\@::g; $makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:; $makefile =~ s:\@SUDO_OBJS\@:openbsd.o preload.o selinux.o sesh.o solaris.o:; - $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo solaris_audit.lo sssd.lo:; + $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo ldap_common.lo solaris_audit.lo sssd.lo:; # XXX - fill in AUTH_OBJS from contents of the auth dir instead $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; $makefile =~ s:\@FILEDIGEST\@:filedigest.lo filedigest_openssl.lo filedigest_gcrypt.lo:; diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 232fa2754..f6ea6f40c 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -710,13 +710,12 @@ cvtsudoers.o: $(srcdir)/cvtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \ - $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \ - $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ - $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \ - $(srcdir)/parse.h $(srcdir)/redblack.h $(srcdir)/sudo_nss.h \ - $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ - $(srcdir)/sudoers_version.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h + $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \ + $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ + $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \ + $(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ + $(srcdir)/sudoers_debug.h $(srcdir)/sudoers_version.h \ + $(top_builddir)/config.h $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers.c cvtsudoers_json.o: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \ $(devdir)/gram.h $(incdir)/compat/stdbool.h \ @@ -736,9 +735,9 @@ cvtsudoers_ldif.o: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ - $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ - $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h + $(srcdir)/redblack.h $(srcdir)/sudo_nss.h \ + $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \ + $(top_builddir)/config.h $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/cvtsudoers_ldif.c dce.lo: $(authdir)/dce.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ @@ -955,15 +954,27 @@ kerb5.lo: $(authdir)/kerb5.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) $(authdir)/kerb5.c -ldap.lo: $(srcdir)/ldap.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ - $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ - $(incdir)/sudo_dso.h $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ - $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ - $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \ - $(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ +ldap.lo: $(srcdir)/ldap.c $(devdir)/def_data.h $(devdir)/gram.h \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \ + $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ + $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ + $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.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)/ldap.c +ldap_common.lo: $(srcdir)/ldap_common.c $(devdir)/def_data.h $(devdir)/gram.h \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ + $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \ + $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ + $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ + $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.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)/ldap_common.c linux_audit.lo: $(srcdir)/linux_audit.c $(devdir)/def_data.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ @@ -1181,12 +1192,13 @@ solaris_audit.lo: $(srcdir)/solaris_audit.c $(devdir)/def_data.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)/solaris_audit.c -sssd.lo: $(srcdir)/sssd.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ - $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ - $(incdir)/sudo_dso.h $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ - $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ - $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \ - $(srcdir)/parse.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ +sssd.lo: $(srcdir)/sssd.c $(devdir)/def_data.h $(devdir)/gram.h \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \ + $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ + $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \ + $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.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)/sssd.c diff --git a/plugins/sudoers/gram.c b/plugins/sudoers/gram.c index bb7c3ae45..dca7253ae 100644 --- a/plugins/sudoers/gram.c +++ b/plugins/sudoers/gram.c @@ -864,70 +864,76 @@ free_members(struct member_list *members) } void -free_userspec(struct userspec *us) +free_privilege(struct privilege *priv) { - struct privilege *priv; - - free_members(&us->users); - while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { - struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; - struct cmndspec *cs; - struct defaults *def; + struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; + struct cmndspec *cs; + struct defaults *def; #ifdef HAVE_SELINUX - char *role = NULL, *type = NULL; + char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET - char *privs = NULL, *limitprivs = NULL; + char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ - TAILQ_REMOVE(&us->privileges, priv, entries); - free(priv->ldap_role); - free_members(&priv->hostlist); - while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { - TAILQ_REMOVE(&priv->cmndlist, cs, entries); + free(priv->ldap_role); + free_members(&priv->hostlist); + while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { + TAILQ_REMOVE(&priv->cmndlist, cs, entries); #ifdef HAVE_SELINUX - /* Only free the first instance of a role/type. */ - if (cs->role != role) { - role = cs->role; - free(cs->role); - } - if (cs->type != type) { - type = cs->type; - free(cs->type); - } + /* Only free the first instance of a role/type. */ + if (cs->role != role) { + role = cs->role; + free(cs->role); + } + if (cs->type != type) { + type = cs->type; + free(cs->type); + } #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET - /* Only free the first instance of privs/limitprivs. */ - if (cs->privs != privs) { - privs = cs->privs; - free(cs->privs); - } - if (cs->limitprivs != limitprivs) { - limitprivs = cs->limitprivs; - free(cs->limitprivs); - } + /* Only free the first instance of privs/limitprivs. */ + if (cs->privs != privs) { + privs = cs->privs; + free(cs->privs); + } + if (cs->limitprivs != limitprivs) { + limitprivs = cs->limitprivs; + free(cs->limitprivs); + } #endif /* HAVE_PRIV_SET */ - /* Only free the first instance of runas user/group lists. */ - if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { - runasuserlist = cs->runasuserlist; - free_members(runasuserlist); - free(runasuserlist); - } - if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { - runasgrouplist = cs->runasgrouplist; - free_members(runasgrouplist); - free(runasgrouplist); - } - free_member(cs->cmnd); - free(cs); + /* Only free the first instance of runas user/group lists. */ + if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { + runasuserlist = cs->runasuserlist; + free_members(runasuserlist); + free(runasuserlist); } - while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { - TAILQ_REMOVE(&priv->defaults, def, entries); - free(def->var); - free(def->val); - free(def); + if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { + runasgrouplist = cs->runasgrouplist; + free_members(runasgrouplist); + free(runasgrouplist); } - free(priv); + free_member(cs->cmnd); + free(cs); + } + while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { + TAILQ_REMOVE(&priv->defaults, def, entries); + free(def->var); + free(def->val); + free(def); + } + free(priv); +} + +void +free_userspec(struct userspec *us) +{ + struct privilege *priv; + + free_members(&us->users); + while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { + TAILQ_REMOVE(&us->privileges, priv, entries); + free_privilege(priv); } rcstr_delref(us->file); free(us); @@ -1010,7 +1016,7 @@ init_options(struct command_options *opts) opts->limitprivs = NULL; #endif } -#line 961 "gram.c" +#line 967 "gram.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -2135,7 +2141,7 @@ case 116: } } break; -#line 2086 "gram.c" +#line 2092 "gram.c" } yyssp -= yym; yystate = *yyssp; diff --git a/plugins/sudoers/gram.y b/plugins/sudoers/gram.y index a85c3027b..5bc1003d3 100644 --- a/plugins/sudoers/gram.y +++ b/plugins/sudoers/gram.y @@ -1092,70 +1092,76 @@ free_members(struct member_list *members) } void -free_userspec(struct userspec *us) +free_privilege(struct privilege *priv) { - struct privilege *priv; - - free_members(&us->users); - while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { - struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; - struct cmndspec *cs; - struct defaults *def; + struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; + struct cmndspec *cs; + struct defaults *def; #ifdef HAVE_SELINUX - char *role = NULL, *type = NULL; + char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET - char *privs = NULL, *limitprivs = NULL; + char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ - TAILQ_REMOVE(&us->privileges, priv, entries); - free(priv->ldap_role); - free_members(&priv->hostlist); - while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { - TAILQ_REMOVE(&priv->cmndlist, cs, entries); + free(priv->ldap_role); + free_members(&priv->hostlist); + while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { + TAILQ_REMOVE(&priv->cmndlist, cs, entries); #ifdef HAVE_SELINUX - /* Only free the first instance of a role/type. */ - if (cs->role != role) { - role = cs->role; - free(cs->role); - } - if (cs->type != type) { - type = cs->type; - free(cs->type); - } + /* Only free the first instance of a role/type. */ + if (cs->role != role) { + role = cs->role; + free(cs->role); + } + if (cs->type != type) { + type = cs->type; + free(cs->type); + } #endif /* HAVE_SELINUX */ #ifdef HAVE_PRIV_SET - /* Only free the first instance of privs/limitprivs. */ - if (cs->privs != privs) { - privs = cs->privs; - free(cs->privs); - } - if (cs->limitprivs != limitprivs) { - limitprivs = cs->limitprivs; - free(cs->limitprivs); - } + /* Only free the first instance of privs/limitprivs. */ + if (cs->privs != privs) { + privs = cs->privs; + free(cs->privs); + } + if (cs->limitprivs != limitprivs) { + limitprivs = cs->limitprivs; + free(cs->limitprivs); + } #endif /* HAVE_PRIV_SET */ - /* Only free the first instance of runas user/group lists. */ - if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { - runasuserlist = cs->runasuserlist; - free_members(runasuserlist); - free(runasuserlist); - } - if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { - runasgrouplist = cs->runasgrouplist; - free_members(runasgrouplist); - free(runasgrouplist); - } - free_member(cs->cmnd); - free(cs); + /* Only free the first instance of runas user/group lists. */ + if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { + runasuserlist = cs->runasuserlist; + free_members(runasuserlist); + free(runasuserlist); } - while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { - TAILQ_REMOVE(&priv->defaults, def, entries); - free(def->var); - free(def->val); - free(def); + if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { + runasgrouplist = cs->runasgrouplist; + free_members(runasgrouplist); + free(runasgrouplist); } - free(priv); + free_member(cs->cmnd); + free(cs); + } + while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { + TAILQ_REMOVE(&priv->defaults, def, entries); + free(def->var); + free(def->val); + free(def); + } + free(priv); +} + +void +free_userspec(struct userspec *us) +{ + struct privilege *priv; + + free_members(&us->users); + while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { + TAILQ_REMOVE(&us->privileges, priv, entries); + free_privilege(priv); } rcstr_delref(us->file); free(us); diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 65e3eb46f..ed8520654 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -61,6 +61,7 @@ #include "parse.h" #include "gram.h" #include "sudo_lbuf.h" +#include "sudo_ldap.h" #include "sudo_dso.h" /* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */ @@ -715,28 +716,6 @@ sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw) debug_return_bool(ret); } -/* - * Returns true if the string pointed to by valp begins with an - * odd number of '!' characters. Intervening blanks are ignored. - * Stores the address of the string after '!' removal in valp. - */ -static bool -sudo_ldap_is_negated(char **valp) -{ - char *val = *valp; - bool ret = false; - debug_decl(sudo_ldap_is_negated, SUDOERS_DEBUG_LDAP) - - while (*val == '!') { - ret = !ret; - do { - val++; - } while (isblank((unsigned char)*val)); - } - *valp = val; - debug_return_bool(ret); -} - /* * Walk through search results and return true if we have a * host match, else false. @@ -933,67 +912,6 @@ sudo_ldap_check_runas(LDAP *ld, LDAPMessage *entry) debug_return_bool(group_matched != false && user_matched != false); } -static struct sudo_digest * -sudo_ldap_extract_digest(char **cmnd, struct sudo_digest *digest) -{ - char *ep, *cp = *cmnd; - int digest_type = SUDO_DIGEST_INVALID; - debug_decl(sudo_ldap_extract_digest, SUDOERS_DEBUG_LDAP) - - /* - * Check for and extract a digest prefix, e.g. - * sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls - */ - if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') { - switch (cp[3]) { - case '2': - if (cp[4] == '2' && cp[5] == '4') - digest_type = SUDO_DIGEST_SHA224; - else if (cp[4] == '5' && cp[5] == '6') - digest_type = SUDO_DIGEST_SHA256; - break; - case '3': - if (cp[4] == '8' && cp[5] == '4') - digest_type = SUDO_DIGEST_SHA384; - break; - case '5': - if (cp[4] == '1' && cp[5] == '2') - digest_type = SUDO_DIGEST_SHA512; - break; - } - if (digest_type != SUDO_DIGEST_INVALID) { - cp += 6; - while (isblank((unsigned char)*cp)) - cp++; - if (*cp == ':') { - cp++; - while (isblank((unsigned char)*cp)) - cp++; - ep = cp; - while (*ep != '\0' && !isblank((unsigned char)*ep)) - ep++; - if (*ep != '\0') { - digest->digest_type = digest_type; - digest->digest_str = strndup(cp, (size_t)(ep - cp)); - if (digest->digest_str == NULL) { - sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - debug_return_ptr(NULL); - } - cp = ep + 1; - while (isblank((unsigned char)*cp)) - cp++; - *cmnd = cp; - DPRINTF1("%s digest %s for %s", - digest_type_to_name(digest_type), - digest->digest_str, cp); - debug_return_ptr(digest); - } - } - } - } - debug_return_ptr(NULL); -} - /* * Walk through search results and return true if we have a command match, * false if disallowed and UNSPEC if not matched. @@ -1097,58 +1015,6 @@ sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option) debug_return_int(ret); } -/* - * Parse an option string into a defaults structure. - * The members of def are pointers into optstr (which is modified). - */ -static int -sudo_ldap_parse_option(char *optstr, char **varp, char **valp) -{ - char *cp, *val = NULL; - char *var = optstr; - int op; - debug_decl(sudo_ldap_parse_option, SUDOERS_DEBUG_LDAP) - - DPRINTF2("ldap sudoOption: '%s'", optstr); - - /* check for equals sign past first char */ - cp = strchr(var, '='); - if (cp > var) { - val = cp + 1; - op = cp[-1]; /* peek for += or -= cases */ - if (op == '+' || op == '-') { - /* case var+=val or var-=val */ - cp--; - } else { - /* case var=val */ - op = true; - } - /* Trim whitespace between var and operator. */ - while (cp > var && isblank((unsigned char)cp[-1])) - cp--; - /* Truncate variable name. */ - *cp = '\0'; - /* Trim leading whitespace from val. */ - while (isblank((unsigned char)*val)) - val++; - /* Strip double quotes if present. */ - if (*val == '"') { - char *ep = val + strlen(val); - if (ep != val && ep[-1] == '"') { - val++; - ep[-1] = '\0'; - } - } - } else { - /* Boolean value, either true or false. */ - op = sudo_ldap_is_negated(&var) ? false : true; - } - *varp = var; - *valp = val; - - debug_return_int(op); -} - /* * Read sudoOption and modify the defaults as we go. This is used once * from the cn=defaults entry and also once when a final sudoRole is matched. @@ -2467,73 +2333,14 @@ sudo_ldap_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw, debug_return_int(0); } -/* - * Convert an array of struct berval to a member list. - */ -static struct member_list * -bv_to_member_list(struct berval **bv) -{ - struct member_list *members; - struct berval **p; - struct member *m; - debug_decl(bv_to_member_list, SUDOERS_DEBUG_LDAP) - - if ((members = calloc(1, sizeof(*members))) == NULL) - return NULL; - TAILQ_INIT(members); - - for (p = bv; *p != NULL; p++) { - if ((m = calloc(1, sizeof(*m))) == NULL) - goto bad; - - char *val = (*p)->bv_val; - switch (val[0]) { - case '\0': - /* Empty RunAsUser means run as the invoking user. */ - m->type = MYSELF; - break; - case 'A': - if (strcmp(val, "ALL") == 0) { - m->type = ALL; - break; - } - /* FALLTHROUGH */ - default: - m->type = WORD; - m->name = strdup(val); - if (m->name == NULL) { - free(m); - goto bad; - } - break; - } - TAILQ_INSERT_TAIL(members, m, entries); - } - debug_return_ptr(members); -bad: - while ((m = TAILQ_FIRST(members)) != NULL) { - TAILQ_REMOVE(members, m, entries); - free(m->name); - free(m); - } - free(members); - debug_return_ptr(NULL); -} - static struct userspec_list * -ldap2sudoers(LDAP *ld, struct ldap_result *lres) +ldap_to_sudoers(LDAP *ld, struct ldap_result *lres) { struct userspec_list *ldap_userspecs; - struct cmndspec *cmndspec = NULL; - struct sudo_command *c; - struct privilege *priv; struct userspec *us; struct member *m; - struct berval **bv, **p; - struct berval **cmnd_bv, **cmnd; /* XXX - naming */ - char *cn; unsigned int i; - debug_decl(ldap2sudoers, SUDOERS_DEBUG_LDAP) + debug_decl(ldap_to_sudoers, SUDOERS_DEBUG_LDAP) if ((ldap_userspecs = calloc(1, sizeof(*ldap_userspecs))) == NULL) goto oom; @@ -2554,217 +2361,63 @@ ldap2sudoers(LDAP *ld, struct ldap_result *lres) /* Treat each sudoRole as a separate privilege. */ for (i = 0; i < lres->nentries; i++) { - struct cmndspec *prev_cmndspec = NULL; LDAPMessage *entry = lres->entries[i].entry; + struct berval **cmnds, **runasusers, **runasgroups; + struct berval **opts, **notbefore, **notafter; + struct privilege *priv; + char *cn; /* Ignore sudoRole without sudoCommand. */ - cmnd_bv = ldap_get_values_len(ld, entry, "sudoCommand"); - if (cmnd_bv == NULL) + cmnds = ldap_get_values_len(ld, entry, "sudoCommand"); + if (cmnds == NULL) continue; - if ((priv = calloc(1, sizeof(*priv))) == NULL) - goto oom; - TAILQ_INIT(&priv->hostlist); - TAILQ_INIT(&priv->cmndlist); - TAILQ_INIT(&priv->defaults); - TAILQ_INSERT_TAIL(&us->privileges, priv, entries); - /* Get the entry's dn for long format printing. */ cn = sudo_ldap_get_first_rdn(ld, entry); - priv->ldap_role = strdup(cn ? cn : "UNKNOWN"); - if (cn != NULL) - ldap_memfree(cn); - if (priv->ldap_role == NULL) - goto oom; - /* The host has already matched, use ALL as wildcard. */ - if ((m = calloc(1, sizeof(*m))) == NULL) - goto oom; - m->type = ALL; - TAILQ_INSERT_TAIL(&priv->hostlist, m, entries); - - /* Parse sudoCommands and add to cmndlist. */ - for (cmnd = cmnd_bv; *cmnd != NULL; cmnd++) { - char *args; - - /* Allocate storage upfront. */ - cmndspec = calloc(1, sizeof(*cmndspec)); - c = calloc(1, sizeof(*c)); - m = calloc(1, sizeof(*m)); - if (cmndspec == NULL || c == NULL || m == NULL) { - free(c); - free(m); - goto oom; - } - TAILQ_INSERT_TAIL(&priv->cmndlist, cmndspec, entries); - - /* Initialize cmndspec */ - TAGS_INIT(cmndspec->tags); - cmndspec->notbefore = UNSPEC; - cmndspec->notafter = UNSPEC; - cmndspec->timeout = UNSPEC; - - /* Fill in command. */ - if ((args = strpbrk((*cmnd)->bv_val, " \t")) != NULL) { - *args++ = '\0'; - if ((c->args = strdup(args)) == NULL) { - free(c); - free(m); - goto oom; - } - } - if ((c->cmnd = strdup((*cmnd)->bv_val)) == NULL) { - free(c->args); - free(c); - free(m); - goto oom; - } - m->type = COMMAND; - m->name = (char *)c; - cmndspec->cmnd = m; - - if (prev_cmndspec != NULL) { - /* Inherit values from prior cmndspec */ - cmndspec->runasuserlist = prev_cmndspec->runasuserlist; - cmndspec->runasgrouplist = prev_cmndspec->runasgrouplist; - cmndspec->notbefore = prev_cmndspec->notbefore; - cmndspec->notafter = prev_cmndspec->notafter; - cmndspec->tags = prev_cmndspec->tags; - } else { - /* Parse sudoRunAsUser / sudoRunAs */ - bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); - if (bv == NULL) - bv = ldap_get_values_len(ld, entry, "sudoRunAs"); /* old style */ - if (bv != NULL) { - cmndspec->runasuserlist = bv_to_member_list(bv); - if (cmndspec->runasuserlist == NULL) - goto oom; - ldap_value_free_len(bv); - bv = NULL; - } - - /* Parse sudoRunAsGroup */ - bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); - if (bv != NULL) { - cmndspec->runasgrouplist = bv_to_member_list(bv); - if (cmndspec->runasgrouplist == NULL) - goto oom; - ldap_value_free_len(bv); - bv = NULL; - } + /* Get sudoRunAsUser / sudoRunAsGroup */ + runasusers = ldap_get_values_len(ld, entry, "sudoRunAsUser"); + if (runasusers == NULL) + runasusers = ldap_get_values_len(ld, entry, "sudoRunAs"); + runasgroups = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); - /* Parse sudoNotBefore */ - bv = ldap_get_values_len(ld, entry, "sudoNotBefore"); - if (bv != NULL) { - /* Only takes the last entry. */ - for (p = bv; *p != NULL; p++) { - cmndspec->notbefore = parse_gentime((*p)->bv_val); - } - ldap_value_free_len(bv); - bv = NULL; - } + /* Get sudoNotBefore / sudoNotAfter */ + notbefore = ldap_get_values_len(ld, entry, "sudoNotBefore"); + notafter = ldap_get_values_len(ld, entry, "sudoNotAfter"); - /* Parse sudoNotAfter */ - bv = ldap_get_values_len(ld, entry, "sudoNotAfter"); - if (bv != NULL) { - /* Only takes the last entry. */ - for (p = bv; *p != NULL; p++) { - cmndspec->notafter = parse_gentime((*p)->bv_val); - } - ldap_value_free_len(bv); - bv = NULL; - } + /* Parse sudoOptions. */ + opts = ldap_get_values_len(ld, entry, "sudoOption"); - /* Parse sudoOptions. */ - bv = ldap_get_values_len(ld, entry, "sudoOption"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - char *var, *val; - int op; - - op = sudo_ldap_parse_option((*p)->bv_val, &var, &val); - if (strcmp(var, "command_timeout") == 0) { - if (op == '=') - cmndspec->timeout = parse_timeout(val); -#ifdef HAVE_SELINUX - } else if (strcmp(var, "role") == 0) { - if (op == '=') { - if ((cmndspec->role = strdup(val)) == NULL) - goto oom; - } - } else if (strcmp(var, "type") == 0) { - if (op == '=') { - if ((cmndspec->type = strdup(val)) == NULL) - goto oom; - } -#endif /* HAVE_SELINUX */ -#ifdef HAVE_PRIV_SET - } else if (strcmp(var, "privs") == 0) { - if (op == '=') { - if ((cmndspec->privs = strdup(val)) == NULL) - goto oom; - } - } else if (strcmp(val, "limitprivs") == 0) { - if (op == '=') { - if ((cmndspec->limitprivs = strdup(val)) == NULL) - goto oom; - } -#endif /* HAVE_PRIV_SET */ - } else if (long_list) { - struct defaults *def = calloc(1, sizeof(*def)); - if (def == NULL) - goto oom; - def->op = op; - if ((def->var = strdup(var)) == NULL) { - free(def); - goto oom; - } - if (val != NULL) { - if ((def->val = strdup(val)) == NULL) { - free(def->var); - free(def); - goto oom; - } - } - TAILQ_INSERT_TAIL(&priv->defaults, def, entries); - } else { - /* Convert to tags. */ - if (op != true && op != false) - continue; - if (strcmp(var, "authenticate") == 0) { - cmndspec->tags.nopasswd = op == false; - } else if (strcmp(var, "sudoedit_follow") == 0) { - cmndspec->tags.follow = op == true; - } else if (strcmp(var, "noexec") == 0) { - cmndspec->tags.noexec = op == true; - } else if (strcmp(var, "setenv") == 0) { - cmndspec->tags.setenv = op == true; - } else if (strcmp(var, "mail_all_cmnds") == 0 || - strcmp(var, "mail_always") == 0) { - cmndspec->tags.send_mail = op == true; - } - } - } - ldap_value_free_len(bv); - bv = NULL; - } + priv = sudo_ldap_role_to_priv(cn, runasusers, runasgroups, + cmnds, opts, notbefore ? notbefore[0]->bv_val : NULL, + notafter ? notafter[0]->bv_val : NULL, + sizeof(struct berval *), offsetof(struct berval, bv_val)); - /* So we can inherit previous values. */ - prev_cmndspec = cmndspec; - } - } - ldap_value_free_len(cmnd_bv); - cmnd_bv = NULL; + /* Cleanup */ + if (cn != NULL) + ldap_memfree(cn); + if (cmnds != NULL) + ldap_value_free_len(cmnds); + if (runasusers != NULL) + ldap_value_free_len(runasusers); + if (runasgroups != NULL) + ldap_value_free_len(runasgroups); + if (opts != NULL) + ldap_value_free_len(opts); + if (notbefore != NULL) + ldap_value_free_len(notbefore); + if (notafter != NULL) + ldap_value_free_len(notafter); + + if (priv == NULL) + goto oom; + TAILQ_INSERT_TAIL(&us->privileges, priv, entries); } debug_return_ptr(ldap_userspecs); oom: sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - if (cmnd_bv != NULL) - ldap_value_free_len(cmnd_bv); - if (bv != NULL) - ldap_value_free_len(bv); if (ldap_userspecs != NULL) { while ((us = TAILQ_FIRST(ldap_userspecs)) != NULL) { TAILQ_REMOVE(ldap_userspecs, us, entries); @@ -2799,7 +2452,7 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw, goto done; /* Convert to sudoers parse tree. */ - if ((ldap_userspecs = ldap2sudoers(ld, lres)) == NULL) { + if ((ldap_userspecs = ldap_to_sudoers(ld, lres)) == NULL) { ret = -1; goto done; } diff --git a/plugins/sudoers/ldap_common.c b/plugins/sudoers/ldap_common.c new file mode 100644 index 000000000..fa14308c8 --- /dev/null +++ b/plugins/sudoers/ldap_common.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2013, 2016, 2018 Todd C. Miller + * + * This code is derived from software contributed by Aaron Spangler. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#ifdef HAVE_LBER_H +# include +#endif +#include + +#include "sudoers.h" +#include "parse.h" +#include "gram.h" +#include "sudo_lbuf.h" +#include "sudo_ldap.h" + +/* + * Returns true if the string pointed to by valp begins with an + * odd number of '!' characters. Intervening blanks are ignored. + * Stores the address of the string after '!' removal in valp. + */ +bool +sudo_ldap_is_negated(char **valp) +{ + char *val = *valp; + bool ret = false; + debug_decl(sudo_ldap_is_negated, SUDOERS_DEBUG_LDAP) + + while (*val == '!') { + ret = !ret; + do { + val++; + } while (isblank((unsigned char)*val)); + } + *valp = val; + debug_return_bool(ret); +} + +/* + * Parse an option string into a defaults structure. + * The members of def are pointers into optstr (which is modified). + */ +int +sudo_ldap_parse_option(char *optstr, char **varp, char **valp) +{ + char *cp, *val = NULL; + char *var = optstr; + int op; + debug_decl(sudo_ldap_parse_option, SUDOERS_DEBUG_LDAP) + + /* check for equals sign past first char */ + cp = strchr(var, '='); + if (cp > var) { + val = cp + 1; + op = cp[-1]; /* peek for += or -= cases */ + if (op == '+' || op == '-') { + /* case var+=val or var-=val */ + cp--; + } else { + /* case var=val */ + op = true; + } + /* Trim whitespace between var and operator. */ + while (cp > var && isblank((unsigned char)cp[-1])) + cp--; + /* Truncate variable name. */ + *cp = '\0'; + /* Trim leading whitespace from val. */ + while (isblank((unsigned char)*val)) + val++; + /* Strip double quotes if present. */ + if (*val == '"') { + char *ep = val + strlen(val); + if (ep != val && ep[-1] == '"') { + val++; + ep[-1] = '\0'; + } + } + } else { + /* Boolean value, either true or false. */ + op = sudo_ldap_is_negated(&var) ? false : true; + } + *varp = var; + *valp = val; + + debug_return_int(op); +} + +/* + * Convert an array to a member list. + * The caller is responsible for freeing the returned struct member_list. + */ +static struct member_list * +array_to_member_list(void *a, size_t ele_size, size_t str_off) +{ + struct member_list *members; + struct member *m; + debug_decl(bv_to_member_list, SUDOERS_DEBUG_LDAP) + + if ((members = calloc(1, sizeof(*members))) == NULL) + return NULL; + TAILQ_INIT(members); + + for (;*((char **)a) != NULL; a = (char *)a + ele_size) { + char *val = *(char **)(*((char **)a) + str_off); + + if ((m = calloc(1, sizeof(*m))) == NULL) + goto bad; + + switch (val[0]) { + case '\0': + /* Empty RunAsUser means run as the invoking user. */ + m->type = MYSELF; + break; + case 'A': + if (strcmp(val, "ALL") == 0) { + m->type = ALL; + break; + } + /* FALLTHROUGH */ + default: + m->type = WORD; + m->name = strdup(val); + if (m->name == NULL) { + free(m); + goto bad; + } + break; + } + TAILQ_INSERT_TAIL(members, m, entries); + } + debug_return_ptr(members); +bad: + while ((m = TAILQ_FIRST(members)) != NULL) { + TAILQ_REMOVE(members, m, entries); + free(m->name); + free(m); + } + free(members); + debug_return_ptr(NULL); +} + +/* + * Convert an LDAP sudoRole to a sudoers privilege. + * Pass in struct berval ** for LDAP or char *** for SSSD. + */ +struct privilege * +sudo_ldap_role_to_priv(const char *cn, void *runasusers, void *runasgroups, + void *cmnds, void *opts, const char *notbefore, + const char *notafter, size_t ele_size, size_t str_off) +{ + struct cmndspec *cmndspec = NULL; + struct cmndspec *prev_cmndspec = NULL; + struct sudo_command *c; + struct privilege *priv; + struct member *m; + debug_decl(sudo_ldap_role_to_priv, SUDOERS_DEBUG_LDAP) + + if ((priv = calloc(1, sizeof(*priv))) == NULL) + goto oom; + TAILQ_INIT(&priv->hostlist); + TAILQ_INIT(&priv->cmndlist); + TAILQ_INIT(&priv->defaults); + + priv->ldap_role = strdup(cn ? cn : "UNKNOWN"); + if (priv->ldap_role == NULL) + goto oom; + + /* The host has already matched, use ALL as wildcard. */ + if ((m = calloc(1, sizeof(*m))) == NULL) + goto oom; + m->type = ALL; + TAILQ_INSERT_TAIL(&priv->hostlist, m, entries); + + /* + * Parse sudoCommands and add to cmndlist. + * The convoluted pointer arithmetic is to support passing in + * either a struct berval ** or a char ***. + * An interator would probably be better. + */ + for (;*((char **)cmnds) != NULL; cmnds = (char *)cmnds + ele_size) { + char *cmnd = *(char **)(*((char **)cmnds) + str_off); + char *args; + + /* Allocate storage upfront. */ + cmndspec = calloc(1, sizeof(*cmndspec)); + c = calloc(1, sizeof(*c)); + m = calloc(1, sizeof(*m)); + if (cmndspec == NULL || c == NULL || m == NULL) { + free(cmndspec); + free(c); + free(m); + goto oom; + } + TAILQ_INSERT_TAIL(&priv->cmndlist, cmndspec, entries); + + /* Initialize cmndspec */ + TAGS_INIT(cmndspec->tags); + cmndspec->notbefore = UNSPEC; + cmndspec->notafter = UNSPEC; + cmndspec->timeout = UNSPEC; + + /* Fill in command. */ + if ((args = strpbrk(cmnd, " \t")) != NULL) { + *args++ = '\0'; + if ((c->args = strdup(args)) == NULL) { + free(c); + free(m); + goto oom; + } + } + if ((c->cmnd = strdup(cmnd)) == NULL) { + free(c->args); + free(c); + free(m); + goto oom; + } + m->type = COMMAND; + m->name = (char *)c; + cmndspec->cmnd = m; + + if (prev_cmndspec != NULL) { + /* Inherit values from prior cmndspec */ + cmndspec->runasuserlist = prev_cmndspec->runasuserlist; + cmndspec->runasgrouplist = prev_cmndspec->runasgrouplist; + cmndspec->notbefore = prev_cmndspec->notbefore; + cmndspec->notafter = prev_cmndspec->notafter; + cmndspec->tags = prev_cmndspec->tags; + } else { + /* Parse sudoRunAsUser / sudoRunAs */ + if (runasusers != NULL) { + cmndspec->runasuserlist = + array_to_member_list(runasusers, ele_size, str_off); + if (cmndspec->runasuserlist == NULL) + goto oom; + } + + /* Parse sudoRunAsGroup */ + if (runasgroups != NULL) { + cmndspec->runasgrouplist = + array_to_member_list(runasgroups, ele_size, str_off); + if (cmndspec->runasgrouplist == NULL) + goto oom; + } + + /* Parse sudoNotBefore / sudoNotAfter */ + if (notbefore != NULL) + cmndspec->notbefore = parse_gentime(notbefore); + if (notafter != NULL) + cmndspec->notbefore = parse_gentime(notafter); + + /* Parse sudoOptions. */ + if (opts != NULL) { + for (; *((char **)opts) != NULL; opts = (char *)opts + ele_size) { + char *opt = *(char **)(*((char **)opts) + str_off); + char *var, *val; + int op; + + op = sudo_ldap_parse_option(opt, &var, &val); + if (strcmp(var, "command_timeout") == 0) { + if (op == '=') + cmndspec->timeout = parse_timeout(val); +#ifdef HAVE_SELINUX + } else if (strcmp(var, "role") == 0) { + if (op == '=') { + if ((cmndspec->role = strdup(val)) == NULL) + goto oom; + } + } else if (strcmp(var, "type") == 0) { + if (op == '=') { + if ((cmndspec->type = strdup(val)) == NULL) + goto oom; + } +#endif /* HAVE_SELINUX */ +#ifdef HAVE_PRIV_SET + } else if (strcmp(var, "privs") == 0) { + if (op == '=') { + if ((cmndspec->privs = strdup(val)) == NULL) + goto oom; + } + } else if (strcmp(val, "limitprivs") == 0) { + if (op == '=') { + if ((cmndspec->limitprivs = strdup(val)) == NULL) + goto oom; + } +#endif /* HAVE_PRIV_SET */ + } else if (long_list) { + struct defaults *def = calloc(1, sizeof(*def)); + if (def == NULL) + goto oom; + def->op = op; + if ((def->var = strdup(var)) == NULL) { + free(def); + goto oom; + } + if (val != NULL) { + if ((def->val = strdup(val)) == NULL) { + free(def->var); + free(def); + goto oom; + } + } + TAILQ_INSERT_TAIL(&priv->defaults, def, entries); + } else { + /* Convert to tags. */ + if (op != true && op != false) + continue; + if (strcmp(var, "authenticate") == 0) { + cmndspec->tags.nopasswd = op == false; + } else if (strcmp(var, "sudoedit_follow") == 0) { + cmndspec->tags.follow = op == true; + } else if (strcmp(var, "noexec") == 0) { + cmndspec->tags.noexec = op == true; + } else if (strcmp(var, "setenv") == 0) { + cmndspec->tags.setenv = op == true; + } else if (strcmp(var, "mail_all_cmnds") == 0 || + strcmp(var, "mail_always") == 0) { + cmndspec->tags.send_mail = op == true; + } + } + } + } + + /* So we can inherit previous values. */ + prev_cmndspec = cmndspec; + } + } + debug_return_ptr(priv); + +oom: + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + if (priv != NULL) + free_privilege(priv); + debug_return_ptr(NULL); +} + +/* + * If a digest prefix is present, fills in struct sudo_digest + * and returns a pointer to it, updating cmnd to point to the + * command after the digest. + */ +struct sudo_digest * +sudo_ldap_extract_digest(char **cmnd, struct sudo_digest *digest) +{ + char *ep, *cp = *cmnd; + int digest_type = SUDO_DIGEST_INVALID; + debug_decl(sudo_ldap_check_command, SUDOERS_DEBUG_LDAP) + + /* + * Check for and extract a digest prefix, e.g. + * sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls + */ + if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') { + switch (cp[3]) { + case '2': + if (cp[4] == '2' && cp[5] == '4') + digest_type = SUDO_DIGEST_SHA224; + else if (cp[4] == '5' && cp[5] == '6') + digest_type = SUDO_DIGEST_SHA256; + break; + case '3': + if (cp[4] == '8' && cp[5] == '4') + digest_type = SUDO_DIGEST_SHA384; + break; + case '5': + if (cp[4] == '1' && cp[5] == '2') + digest_type = SUDO_DIGEST_SHA512; + break; + } + if (digest_type != SUDO_DIGEST_INVALID) { + cp += 6; + while (isblank((unsigned char)*cp)) + cp++; + if (*cp == ':') { + cp++; + while (isblank((unsigned char)*cp)) + cp++; + ep = cp; + while (*ep != '\0' && !isblank((unsigned char)*ep)) + ep++; + if (*ep != '\0') { + digest->digest_type = digest_type; + digest->digest_str = strndup(cp, (size_t)(ep - cp)); + if (digest->digest_str == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_ptr(NULL); + } + cp = ep + 1; + while (isblank((unsigned char)*cp)) + cp++; + *cmnd = cp; + sudo_debug_printf(SUDO_DEBUG_INFO, + "%s digest %s for %s", + digest_type_to_name(digest_type), + digest->digest_str, cp); + debug_return_ptr(digest); + } + } + } + } + debug_return_ptr(NULL); +} diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 275071eaa..f37a838c1 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -259,6 +259,7 @@ bool init_aliases(void); bool init_parser(const char *path, bool quiet); void free_member(struct member *m); void free_members(struct member_list *members); +void free_privilege(struct privilege *priv); void free_userspec(struct userspec *us); /* match_addr.c */ diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c index 398f9a758..9278c7cd6 100644 --- a/plugins/sudoers/sssd.c +++ b/plugins/sudoers/sssd.c @@ -42,7 +42,9 @@ #include "sudoers.h" #include "parse.h" +#include "gram.h" #include "sudo_lbuf.h" +#include "sudo_ldap.h" #include "sudo_dso.h" /* SSSD <--> SUDO interface - do not change */ @@ -540,28 +542,6 @@ bad: debug_return_int(-1); } -/* - * Returns true if the string pointed to by valp begins with an - * odd number of '!' characters. Intervening blanks are ignored. - * Stores the address of the string after '!' removal in valp. - */ -static bool -sudo_sss_is_negated(char **valp) -{ - char *val = *valp; - bool ret = false; - debug_decl(sudo_sss_is_negated, SUDOERS_DEBUG_SSSD) - - while (*val == '!') { - ret = !ret; - do { - val++; - } while (isblank((unsigned char)*val)); - } - *valp = val; - debug_return_bool(ret); -} - static int sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw) { @@ -804,7 +784,7 @@ sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) val = val_array[i]; sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val); - negated = sudo_sss_is_negated(&val); + negated = sudo_ldap_is_negated(&val); /* match any or address or netgroup or hostname */ if (strcmp(val, "ALL") == 0 || addr_matches(val) || @@ -1009,7 +989,7 @@ sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule, var = val_array[i]; sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", var); - negated = sudo_sss_is_negated(&var); + negated = sudo_ldap_is_negated(&var); if (strcmp(var, option) == 0) ret = negated ? false : true; } @@ -1019,73 +999,6 @@ sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule, debug_return_int(ret); } -/* - * If a digest prefix is present, fills in struct sudo_digest - * and returns a pointer to it, updating cmnd to point to the - * command after the digest. - */ -static struct sudo_digest * -sudo_sss_extract_digest(char **cmnd, struct sudo_digest *digest) -{ - char *ep, *cp = *cmnd; - int digest_type = SUDO_DIGEST_INVALID; - debug_decl(sudo_sss_check_command, SUDOERS_DEBUG_LDAP) - - /* - * Check for and extract a digest prefix, e.g. - * sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls - */ - if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') { - switch (cp[3]) { - case '2': - if (cp[4] == '2' && cp[5] == '4') - digest_type = SUDO_DIGEST_SHA224; - else if (cp[4] == '5' && cp[5] == '6') - digest_type = SUDO_DIGEST_SHA256; - break; - case '3': - if (cp[4] == '8' && cp[5] == '4') - digest_type = SUDO_DIGEST_SHA384; - break; - case '5': - if (cp[4] == '1' && cp[5] == '2') - digest_type = SUDO_DIGEST_SHA512; - break; - } - if (digest_type != SUDO_DIGEST_INVALID) { - cp += 6; - while (isblank((unsigned char)*cp)) - cp++; - if (*cp == ':') { - cp++; - while (isblank((unsigned char)*cp)) - cp++; - ep = cp; - while (*ep != '\0' && !isblank((unsigned char)*ep)) - ep++; - if (*ep != '\0') { - digest->digest_type = digest_type; - digest->digest_str = strndup(cp, (size_t)(ep - cp)); - if (digest->digest_str == NULL) { - sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); - debug_return_ptr(NULL); - } - cp = ep + 1; - while (isblank((unsigned char)*cp)) - cp++; - *cmnd = cp; - sudo_debug_printf(SUDO_DEBUG_INFO, - "%s digest %s for %s", - digest_type_to_name(digest_type), - digest->digest_str, cp); - debug_return_ptr(digest); - } - } - } - } - debug_return_ptr(NULL); -} - /* * Walk through search results and return true if we have a command match, * false if disallowed and UNSPEC if not matched. @@ -1132,11 +1045,11 @@ sudo_sss_check_command(struct sudo_sss_handle *handle, } /* check for sha-2 digest */ - allowed_digest = sudo_sss_extract_digest(&val, &digest); + allowed_digest = sudo_ldap_extract_digest(&val, &digest); /* check for !command */ allowed_cmnd = val; - negated = sudo_sss_is_negated(&allowed_cmnd); + negated = sudo_ldap_is_negated(&allowed_cmnd); /* split optional args away from command */ allowed_args = strchr(allowed_cmnd, ' '); @@ -1165,58 +1078,6 @@ sudo_sss_check_command(struct sudo_sss_handle *handle, debug_return_int(ret); } -/* - * Parse an option string into a defaults structure. - * The members of def are pointers into optstr (which is modified). - */ -static int -sudo_sss_parse_option(char *optstr, char **varp, char **valp) -{ - char *cp, *val = NULL; - char *var = optstr; - int op; - debug_decl(sudo_sss_parse_option, SUDOERS_DEBUG_SSSD) - - sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", optstr); - - /* check for equals sign past first char */ - cp = strchr(var, '='); - if (cp > var) { - val = cp + 1; - op = cp[-1]; /* peek for += or -= cases */ - if (op == '+' || op == '-') { - /* case var+=val or var-=val */ - cp--; - } else { - /* case var=val */ - op = true; - } - /* Trim whitespace between var and operator. */ - while (cp > var && isblank((unsigned char)cp[-1])) - cp--; - /* Truncate variable name. */ - *cp = '\0'; - /* Trim leading whitespace from val. */ - while (isblank((unsigned char)*val)) - val++; - /* Strip double quotes if present. */ - if (*val == '"') { - char *ep = val + strlen(val); - if (ep != val && ep[-1] == '"') { - val++; - ep[-1] = '\0'; - } - } - } else { - /* Boolean value, either true or false. */ - op = sudo_sss_is_negated(&var) ? false : true; - } - *varp = var; - *valp = val; - - debug_return_int(op); -} - static bool sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule) { @@ -1263,7 +1124,7 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); goto done; } - op = sudo_sss_parse_option(copy, &var, &val); + op = sudo_ldap_parse_option(copy, &var, &val); early = is_early_default(var); if (early != NULL) { set_early_default(var, val, op, @@ -1279,7 +1140,7 @@ sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rul sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); goto done; } - op = sudo_sss_parse_option(copy, &var, &val); + op = sudo_ldap_parse_option(copy, &var, &val); if (is_early_default(var) == NULL) { set_default(var, val, op, source ? source : "sudoRole UNKNOWN", 0, false); @@ -1544,255 +1405,102 @@ sudo_sss_display_bound_defaults(struct sudo_nss *nss, debug_return_int(0); } -static int -sudo_sss_display_entry_long(struct sudo_sss_handle *handle, - struct sss_sudo_rule *rule, struct passwd *pw, struct sudo_lbuf *lbuf) +static struct userspec_list * +sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_result) { - char **val_array = NULL; - bool no_runas_user = true; - int count = 0, i; - debug_decl(sudo_sss_display_entry_long, SUDOERS_DEBUG_SSSD); - - switch (handle->fn_get_values(rule, "cn", &val_array)) { - case 0: - if (val_array[0] != NULL) - sudo_lbuf_append(lbuf, _("\nSSSD Role: %s\n"), val_array[0]); - handle->fn_free_values(val_array); - val_array = NULL; - break; - default: - sudo_lbuf_append(lbuf, _("\nSSSD Role: UNKNOWN\n")); - } - - /* get the RunAsUser Values from the entry */ - sudo_lbuf_append(lbuf, " RunAsUsers: "); - switch (handle->fn_get_values(rule, "sudoRunAsUser", &val_array)) { - case 0: - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - no_runas_user = false; - break; - case ENOENT: - switch (handle->fn_get_values(rule, "sudoRunAs", &val_array)) { - case 0: - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - no_runas_user = false; - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAs): != 0"); - debug_return_int(count); - } - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAsUser): != 0"); - debug_return_int(count); - } + struct userspec_list *sss_userspecs; + struct userspec *us; + struct member *m; + unsigned int i; + debug_decl(sss_to_sudoers, SUDOERS_DEBUG_SSSD) - /* get the RunAsGroup Values from the entry */ - switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) { - case 0: - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_lbuf_append(lbuf, "%s", pw->pw_name); - } - sudo_lbuf_append(lbuf, "\n RunAsGroups: "); - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - sudo_lbuf_append(lbuf, "\n"); - break; - case ENOENT: - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_lbuf_append(lbuf, "%s", pw->pw_name); - } - sudo_lbuf_append(lbuf, "\n"); - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, - "handle->fn_get_values(sudoRunAsGroup): != 0"); - debug_return_int(count); - } + if ((sss_userspecs = calloc(1, sizeof(*sss_userspecs))) == NULL) + goto oom; + TAILQ_INIT(sss_userspecs); - /* get the Option Values from the entry */ - switch (handle->fn_get_values(rule, "sudoOption", &val_array)) { - case 0: - sudo_lbuf_append(lbuf, " Options: "); - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - sudo_lbuf_append(lbuf, "\n"); - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0"); - debug_return_int(count); - } + /* We only have a single userspec */ + if ((us = calloc(1, sizeof(*us))) == NULL) + goto oom; + TAILQ_INIT(&us->users); + TAILQ_INIT(&us->privileges); + TAILQ_INSERT_TAIL(sss_userspecs, us, entries); - /* Get the command values from the entry. */ - switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) { - case 0: - sudo_lbuf_append(lbuf, _(" Commands:\n")); - for (i = 0; val_array[i] != NULL; ++i) { - sudo_lbuf_append(lbuf, "\t%s\n", val_array[i]); - count++; - } - handle->fn_free_values(val_array); - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, - "handle->fn_get_values(sudoCommand): != 0"); - debug_return_int(count); - } + /* The user has already matched, use ALL as wildcard. */ + if ((m = calloc(1, sizeof(*m))) == NULL) + goto oom; + m->type = ALL; + TAILQ_INSERT_TAIL(&us->users, m, entries); - debug_return_int(count); -} + /* Treat each sudoRole as a separate privilege. */ + for (i = 0; i < sss_result->num_rules; i++) { + struct sss_sudo_rule *rule = sss_result->rules + i; + char **cmnds, **runasusers = NULL, **runasgroups = NULL; + char **opts = NULL, **notbefore = NULL, **notafter = NULL; + char **cn_array = NULL; + char *cn = NULL; + struct privilege *priv; -static int -sudo_sss_display_entry_short(struct sudo_sss_handle *handle, - struct sss_sudo_rule *rule, struct passwd *pw, struct sudo_lbuf *lbuf) -{ - char **val_array = NULL; - bool no_runas_user = true; - int count = 0, i; - debug_decl(sudo_sss_display_entry_short, SUDOERS_DEBUG_SSSD); + /* XXX - check for error vs. ENOENT */ - sudo_lbuf_append(lbuf, " ("); + /* Ignore sudoRole without sudoCommand. */ + if (handle->fn_get_values(rule, "sudoCommand", &cmnds) != 0) + continue; - /* get the RunAsUser Values from the entry */ - switch (handle->fn_get_values(rule, "sudoRunAsUser", &val_array)) { - case 0: - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - no_runas_user = false; - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result. Trying old style (sudoRunAs)."); - /* try old style */ - switch (handle->fn_get_values(rule, "sudoRunAs", &val_array)) { - case 0: - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - no_runas_user = false; - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, - "handle->fn_get_values(sudoRunAs): != 0"); - debug_return_int(count); - } - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, - "handle->fn_get_values(sudoRunAsUser): != 0"); - debug_return_int(count); - } + /* Get the entry's dn for long format printing. */ + if (handle->fn_get_values(rule, "cn", &cn_array) == 0) + cn = cn_array[0]; - /* get the RunAsGroup Values from the entry */ - switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) { - case 0: - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_lbuf_append(lbuf, "%s", pw->pw_name); + /* Get sudoRunAsUser / sudoRunAsGroup */ + if (handle->fn_get_values(rule, "sudoRunAsUser", &runasusers) != 0) { + handle->fn_get_values(rule, "sudoRunAs", &runasusers); } - sudo_lbuf_append(lbuf, " : "); - for (i = 0; val_array[i] != NULL; ++i) - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", val_array[i]); - handle->fn_free_values(val_array); - break; - case ENOENT: - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_lbuf_append(lbuf, "%s", def_runas_default); - } - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAsGroup): != 0"); - debug_return_int(count); + handle->fn_get_values(rule, "sudoRunAsGroup", &runasgroups); + + /* Get sudoNotBefore / sudoNotAfter */ + handle->fn_get_values(rule, "sudoNotBefore", ¬before); + handle->fn_get_values(rule, "sudoNotAfter", ¬after); + + /* Parse sudoOptions. */ + handle->fn_get_values(rule, "sudoOption", &opts); + + priv = sudo_ldap_role_to_priv(cn, runasusers ? &runasusers : NULL, + runasgroups ? &runasgroups: NULL, &cmnds, opts ? &opts : NULL, + notbefore ? notbefore[0] : NULL, notafter ? notafter[0] : NULL, + sizeof(char **), 0); + + /* Cleanup */ + if (cn_array != NULL) + handle->fn_free_values(cn_array); + if (cmnds != NULL) + handle->fn_free_values(cmnds); + if (runasusers != NULL) + handle->fn_free_values(runasusers); + if (runasgroups != NULL) + handle->fn_free_values(runasgroups); + if (opts != NULL) + handle->fn_free_values(opts); + if (notbefore != NULL) + handle->fn_free_values(notbefore); + if (notafter != NULL) + handle->fn_free_values(notafter); + + if (priv == NULL) + goto oom; + TAILQ_INSERT_TAIL(&us->privileges, priv, entries); } - sudo_lbuf_append(lbuf, ") "); + debug_return_ptr(sss_userspecs); - /* get the Option Values from the entry */ - switch (handle->fn_get_values(rule, "sudoOption", &val_array)) { - case 0: - for (i = 0; val_array[i] != NULL; ++i) { - char *val = val_array[i]; - bool negated = sudo_sss_is_negated(&val); - if (strcmp(val, "authenticate") == 0) - sudo_lbuf_append(lbuf, negated ? "NOPASSWD: " : "PASSWD: "); - else if (strcmp(val, "sudoedit_follow") == 0) - sudo_lbuf_append(lbuf, negated ? "NOFOLLOW: " : "FOLLOW: "); - else if (strcmp(val, "noexec") == 0) - sudo_lbuf_append(lbuf, negated ? "EXEC: " : "NOEXEC: "); - else if (strcmp(val, "setenv") == 0) - sudo_lbuf_append(lbuf, negated ? "NOSETENV: " : "SETENV: "); - else if (strcmp(val, "mail_all_cmnds") == 0 || strcmp(val, "mail_always") == 0) - sudo_lbuf_append(lbuf, negated ? "NOMAIL: " : "MAIL: "); - else if (!negated && strncmp(val, "command_timeout=", 16) == 0) - sudo_lbuf_append(lbuf, "TIMEOUT=%s ", val + 16); -#ifdef HAVE_SELINUX - else if (!negated && strncmp(val, "role=", 5) == 0) - sudo_lbuf_append(lbuf, "ROLE=%s ", val + 5); - else if (!negated && strncmp(val, "type=", 5) == 0) - sudo_lbuf_append(lbuf, "TYPE=%s ", val + 5); -#endif /* HAVE_SELINUX */ -#ifdef HAVE_PRIV_SET - else if (!negated && strncmp(val, "privs=", 6) == 0) - sudo_lbuf_append(lbuf, "PRIVS=%s ", val + 6); - else if (!negated && strncmp(val, "limitprivs=", 11) == 0) - sudo_lbuf_append(lbuf, "LIMITPRIVS=%s ", val + 11); -#endif /* HAVE_PRIV_SET */ +oom: + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + if (sss_userspecs != NULL) { + while ((us = TAILQ_FIRST(sss_userspecs)) != NULL) { + TAILQ_REMOVE(sss_userspecs, us, entries); + free_userspec(us); } - handle->fn_free_values(val_array); - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, - "handle->fn_get_values(sudoOption): != 0"); - debug_return_int(count); + free(sss_userspecs); } - - /* get the Command Values from the entry */ - switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) { - case 0: - for (i = 0; val_array[i] != NULL; ++i) { - sudo_lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", - val_array[i][0] ? val_array[i] : user_name); - count++; - } - handle->fn_free_values(val_array); - break; - case ENOENT: - sudo_debug_printf(SUDO_DEBUG_INFO, "No result."); - break; - default: - sudo_debug_printf(SUDO_DEBUG_INFO, - "handle->fn_get_values(sudoCommand): != 0"); - debug_return_int(count); - } - sudo_lbuf_append(lbuf, "\n"); - - debug_return_int(count); + debug_return_ptr(NULL); } static int @@ -1800,9 +1508,9 @@ sudo_sss_display_privs(struct sudo_nss *nss, struct passwd *pw, struct sudo_lbuf *lbuf) { struct sudo_sss_handle *handle = nss->handle; + struct userspec_list *sss_userspecs = NULL; struct sss_sudo_result *sss_result = NULL; - struct sss_sudo_rule *rule; - unsigned int i, count = 0; + int ret = 0; debug_decl(sudo_sss_display_privs, SUDOERS_DEBUG_SSSD); if (handle == NULL) @@ -1815,22 +1523,30 @@ sudo_sss_display_privs(struct sudo_nss *nss, struct passwd *pw, sss_result = sudo_sss_result_get(nss, pw, NULL); if (sss_result == NULL) - debug_return_int(count); + debug_return_int(ret); - /* Display all matching entries. */ - for (i = 0; i < sss_result->num_rules; ++i) { - rule = sss_result->rules + i; - if (long_list) - count += sudo_sss_display_entry_long(handle, rule, pw, lbuf); - else - count += sudo_sss_display_entry_short(handle, rule, pw, lbuf); + /* Convert to sudoers parse tree. */ + if ((sss_userspecs = sss_to_sudoers(handle, sss_result)) == NULL) { + ret = -1; + goto done; } - handle->fn_free_result(sss_result); + /* Call common display code. */ + ret = sudo_display_userspecs(sss_userspecs, pw, lbuf); +done: + /* Cleanup */ + handle->fn_free_result(sss_result); + if (sss_userspecs != NULL) { + struct userspec *us; + while ((us = TAILQ_FIRST(sss_userspecs)) != NULL) { + TAILQ_REMOVE(sss_userspecs, us, entries); + free_userspec(us); + } + free(sss_userspecs); + } if (sudo_lbuf_error(lbuf)) debug_return_int(-1); - debug_return_int(count); + debug_return_int(ret); } - #endif /* HAVE_SSSD */ diff --git a/plugins/sudoers/sudo_ldap.h b/plugins/sudoers/sudo_ldap.h new file mode 100644 index 000000000..8904433f0 --- /dev/null +++ b/plugins/sudoers/sudo_ldap.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SUDOERS_LDAP_H +#define SUDOERS_LDAP_H + +bool sudo_ldap_is_negated(char **valp); +int sudo_ldap_parse_option(char *optstr, char **varp, char **valp); +struct privilege *sudo_ldap_role_to_priv(const char *cn, void *runasusers, void *runasgroups, void *cmnds, void *opts, const char *notbefore, const char *notafter, size_t ele_size, size_t str_off); +struct sudo_digest *sudo_ldap_extract_digest(char **cmnd, struct sudo_digest *digest); + +#endif /* SUDOERS_LDAP_H */ -- 2.40.0