1289 lines
35 KiB
Diff
1289 lines
35 KiB
Diff
diff -up sudo-1.8.3p1/configure.in.sssd-support sudo-1.8.3p1/configure.in
|
|
--- sudo-1.8.3p1/configure.in.sssd-support 2012-01-11 19:27:02.604019550 +0100
|
|
+++ sudo-1.8.3p1/configure.in 2012-01-12 16:28:48.031171923 +0100
|
|
@@ -275,6 +275,22 @@ AC_ARG_WITH(linux-audit, [AS_HELP_STRING
|
|
;;
|
|
esac])
|
|
|
|
+dnl
|
|
+dnl Handle SSSD support.
|
|
+dnl
|
|
+AC_ARG_WITH(sssd, [AS_HELP_STRING([--with-sssd], [enable SSSD support])],
|
|
+[case $with_sssd in
|
|
+ yes)
|
|
+ SUDO_LIBS="${SUDO_LIBS} `pkg-config libsss_sudo --libs`"
|
|
+ SUDOERS_LIBS="${SUDO_LIBS} `pkg-config libsss_sudo --libs`"
|
|
+ SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo"
|
|
+ AC_DEFINE(HAVE_SSSD)
|
|
+ ;;
|
|
+ no) ;;
|
|
+ *) AC_MSG_ERROR(["--with-sssd does not take an argument."])
|
|
+ ;;
|
|
+esac])
|
|
+
|
|
AC_ARG_WITH(incpath, [AS_HELP_STRING([--with-incpath], [additional places to look for include files])],
|
|
[case $with_incpath in
|
|
yes) AC_MSG_ERROR(["must give --with-incpath an argument."])
|
|
@@ -3157,6 +3173,7 @@ AH_TEMPLATE(HAVE_LBER_H, [Define to 1 if
|
|
AH_TEMPLATE(HAVE_LDAP, [Define to 1 if you use LDAP for sudoers.])
|
|
AH_TEMPLATE(HAVE_LIBINTL_H, [Define to 1 if you have the <libintl.h> header file.])
|
|
AH_TEMPLATE(HAVE_LINUX_AUDIT, [Define to 1 to enable Linux audit support.])
|
|
+AH_TEMPLATE(HAVE_SSSD, [Define to 1 to enable SSSD support.])
|
|
AH_TEMPLATE(HAVE_OPIE, [Define to 1 if you use NRL OPIE.])
|
|
AH_TEMPLATE(HAVE_PAM, [Define to 1 if you use PAM authentication.])
|
|
AH_TEMPLATE(HAVE_PAM_LOGIN, [Define to 1 if you use a specific PAM session for sudo -i.])
|
|
diff -up sudo-1.8.3p1/plugins/sudoers/Makefile.in.sssd-support sudo-1.8.3p1/plugins/sudoers/Makefile.in
|
|
--- sudo-1.8.3p1/plugins/sudoers/Makefile.in.sssd-support 2012-01-11 19:27:23.016032415 +0100
|
|
+++ sudo-1.8.3p1/plugins/sudoers/Makefile.in 2012-01-12 16:35:00.527406716 +0100
|
|
@@ -530,6 +530,10 @@ linux_audit.lo: $(srcdir)/linux_audit.c
|
|
$(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \
|
|
$(incdir)/gettext.h $(srcdir)/linux_audit.h
|
|
$(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/linux_audit.c
|
|
+sssd.lo: $(srcdir)/sssd.c $(top_builddir)/config.h \
|
|
+ $(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \
|
|
+ $(incdir)/gettext.h
|
|
+ $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sssd.c
|
|
logging.lo: $(srcdir)/logging.c $(top_builddir)/config.h $(srcdir)/sudoers.h \
|
|
$(top_builddir)/pathnames.h $(incdir)/missing.h $(incdir)/error.h \
|
|
$(incdir)/alloc.h $(incdir)/list.h $(incdir)/fileops.h \
|
|
diff -up sudo-1.8.3p1/plugins/sudoers/sssd.c.sssd-support sudo-1.8.3p1/plugins/sudoers/sssd.c
|
|
--- sudo-1.8.3p1/plugins/sudoers/sssd.c.sssd-support 2012-01-19 13:41:51.885154296 +0100
|
|
+++ sudo-1.8.3p1/plugins/sudoers/sssd.c 2012-02-07 12:22:37.641156963 +0100
|
|
@@ -0,0 +1,1157 @@
|
|
+/*
|
|
+ * Copyright (c) 2003-2011 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
+ * Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>
|
|
+ *
|
|
+ * 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 <config.h>
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <sys/time.h>
|
|
+#include <sys/param.h>
|
|
+#include <sys/stat.h>
|
|
+#include <stdio.h>
|
|
+#ifdef STDC_HEADERS
|
|
+# include <stdlib.h>
|
|
+# include <stddef.h>
|
|
+#else
|
|
+# ifdef HAVE_STDLIB_H
|
|
+# include <stdlib.h>
|
|
+# endif
|
|
+#endif /* STDC_HEADERS */
|
|
+#ifdef HAVE_STRING_H
|
|
+# include <string.h>
|
|
+#endif /* HAVE_STRING_H */
|
|
+#ifdef HAVE_STRINGS_H
|
|
+# include <strings.h>
|
|
+#endif /* HAVE_STRINGS_H */
|
|
+#ifdef HAVE_UNISTD_H
|
|
+# include <unistd.h>
|
|
+#endif /* HAVE_UNISTD_H */
|
|
+#if TIME_WITH_SYS_TIME
|
|
+# include <time.h>
|
|
+#endif
|
|
+#include <ctype.h>
|
|
+#include <pwd.h>
|
|
+#include <grp.h>
|
|
+
|
|
+#include <sss_sudo.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include "sudoers.h"
|
|
+#include "parse.h"
|
|
+#include "lbuf.h"
|
|
+
|
|
+extern int debug_level;
|
|
+#define __sssd_debug debug_level
|
|
+
|
|
+#define DPRINTF(level, fmt, ...) if (__sssd_debug >= (level)) warningx("%s:%d: "fmt, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
|
+
|
|
+/* sudo_nss implementation */
|
|
+static int sudo_sssd_open(struct sudo_nss *nss);
|
|
+static int sudo_sssd_close(struct sudo_nss *nss);
|
|
+static int sudo_sssd_parse(struct sudo_nss *nss);
|
|
+static void sudo_sssd_parse_options(struct sss_rule *rule);
|
|
+static int sudo_sssd_setdefs(struct sudo_nss *nss);
|
|
+static int sudo_sssd_lookup(struct sudo_nss *nss, int ret, int pwflag);
|
|
+static int sudo_sssd_display_cmnd(struct sudo_nss *nss, struct passwd *pw);
|
|
+static int sudo_sssd_display_defaults(struct sudo_nss *nss, struct passwd *pw,
|
|
+ struct lbuf *lbuf);
|
|
+
|
|
+static int sudo_sssd_display_bound_defaults(struct sudo_nss *nss,
|
|
+ struct passwd *pw, struct lbuf *lbuf);
|
|
+
|
|
+static int sudo_sssd_display_privs(struct sudo_nss *nss, struct passwd *pw,
|
|
+ struct lbuf *lbuf);
|
|
+
|
|
+
|
|
+static struct sss_result *sudo_sssd_result_get(struct sudo_nss *nss,
|
|
+ struct passwd *pw,
|
|
+ uint32_t *state);
|
|
+
|
|
+static void sudo_sssd_attrcpy(struct sss_attr *dst, const struct sss_attr *src)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ DPRINTF(3, "dst=%p, src=%p", dst, src);
|
|
+ DPRINTF(2, "emalloc: cnt=%d", src->num_values);
|
|
+
|
|
+ dst->name = strdup(src->name);
|
|
+ dst->num_values = src->num_values;
|
|
+ dst->values = emalloc(sizeof(char *) * dst->num_values);
|
|
+
|
|
+ for (i = 0; i < dst->num_values; ++i)
|
|
+ dst->values[i] = strdup(src->values[i]);
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void sudo_sssd_rulecpy(struct sss_rule *dst, const struct sss_rule *src)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ DPRINTF(3, "dst=%p, src=%p", dst, src);
|
|
+ DPRINTF(2, "emalloc: cnt=%d", src->num_attrs);
|
|
+
|
|
+ dst->num_attrs = src->num_attrs;
|
|
+ dst->attrs = emalloc(sizeof(struct sss_attr) * dst->num_attrs);
|
|
+
|
|
+ for (i = 0; i < dst->num_attrs; ++i) {
|
|
+ sudo_sssd_attrcpy(dst->attrs + i,
|
|
+ src->attrs + i);
|
|
+ }
|
|
+}
|
|
+
|
|
+#define _SUDO_SSS_FILTER_INCLUDE 0
|
|
+#define _SUDO_SSS_FILTER_EXCLUDE 1
|
|
+
|
|
+#define _SUDO_SSS_STATE_HOSTMATCH 0x01
|
|
+#define _SUDO_SSS_STATE_USERMATCH 0x02
|
|
+
|
|
+static struct sss_result *sudo_sssd_filter_result(struct sss_result *in_res, int (*filterp)(struct sss_rule *, void *), int act, void *filterp_arg)
|
|
+{
|
|
+ struct sss_result *out_res;
|
|
+ int i, l, r;
|
|
+
|
|
+ DPRINTF(3, "in_res=%p, count=%u, act=%s",
|
|
+ in_res, in_res->num_rules, act == _SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE");
|
|
+
|
|
+ if (in_res == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ DPRINTF(3, "emalloc: cnt=%d", in_res->num_rules);
|
|
+
|
|
+ out_res = emalloc(sizeof(struct sss_result));
|
|
+ out_res->rules = in_res->num_rules > 0 ? emalloc(sizeof(struct sss_rule) * in_res->num_rules) : NULL;
|
|
+ out_res->num_rules = 0;
|
|
+
|
|
+ for (i = l = 0; i < in_res->num_rules; ++i) {
|
|
+ r = filterp(in_res->rules + i, filterp_arg);
|
|
+
|
|
+ if (( r && act == _SUDO_SSS_FILTER_INCLUDE) ||
|
|
+ (!r && act == _SUDO_SSS_FILTER_EXCLUDE))
|
|
+ {
|
|
+ DPRINTF(3, "COPY (%s): %p[%u] => %p[%u] (= %p)",
|
|
+ act == _SUDO_SSS_FILTER_EXCLUDE ? "not excluded" : "included",
|
|
+ in_res->rules, i, out_res->rules, l, in_res->rules + i);
|
|
+
|
|
+ sudo_sssd_rulecpy(out_res->rules + l, in_res->rules + i);
|
|
+ ++l;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (l < in_res->num_rules) {
|
|
+ DPRINTF(3, "reallocating result: %p (count: %u -> %u)", out_res->rules, in_res->num_rules, l);
|
|
+ out_res->rules = realloc(out_res->rules, sizeof(struct sss_rule) * l);
|
|
+ }
|
|
+
|
|
+ out_res->num_rules = l;
|
|
+
|
|
+ return out_res;
|
|
+}
|
|
+
|
|
+struct sudo_sssd_handle {
|
|
+ char *username;
|
|
+ struct sss_result *result;
|
|
+ struct group_list *grlist;
|
|
+};
|
|
+
|
|
+struct sudo_nss sudo_nss_sssd = {
|
|
+ &sudo_nss_sssd,
|
|
+ NULL,
|
|
+ sudo_sssd_open,
|
|
+ sudo_sssd_close,
|
|
+ sudo_sssd_parse,
|
|
+ sudo_sssd_setdefs,
|
|
+ sudo_sssd_lookup,
|
|
+ sudo_sssd_display_cmnd,
|
|
+ sudo_sssd_display_defaults,
|
|
+ sudo_sssd_display_bound_defaults,
|
|
+ sudo_sssd_display_privs
|
|
+};
|
|
+
|
|
+
|
|
+/* sudo_nss implementation */
|
|
+// ok
|
|
+static int sudo_sssd_open(struct sudo_nss *nss)
|
|
+{
|
|
+ struct sudo_sssd_handle *handle;
|
|
+
|
|
+ /* Create a handle container. */
|
|
+ handle = emalloc(sizeof(struct sudo_sssd_handle));
|
|
+ handle->result = NULL;
|
|
+ handle->username = NULL;
|
|
+ handle->grlist = NULL;
|
|
+ nss->handle = handle;
|
|
+
|
|
+ DPRINTF(3, "handle=%p", handle);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+// ok
|
|
+static int sudo_sssd_close(struct sudo_nss *nss)
|
|
+{
|
|
+ efree(nss->handle);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+// ok
|
|
+static int sudo_sssd_parse(struct sudo_nss *nss)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_setdefs(struct sudo_nss *nss)
|
|
+{
|
|
+ struct sudo_sssd_handle *handle = nss->handle;
|
|
+
|
|
+ struct sss_result *sres;
|
|
+ struct sss_rule *rule;
|
|
+ uint32_t serr;
|
|
+ int i;
|
|
+
|
|
+ if (handle == NULL)
|
|
+ return -1;
|
|
+
|
|
+ DPRINTF(1, "Looking for cn=defaults");
|
|
+
|
|
+ if (sss_sudo_send_recv_defaults(&serr, &sres) != 0) {
|
|
+ DPRINTF(2, "sss_sudo_send_recv_defaults: != 0, serr=%u", serr);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < sres->num_rules; ++i) {
|
|
+ DPRINTF(1, "Parsing cn=defaults, %d/%d", i, sres->num_rules);
|
|
+ rule = sres->rules + i;
|
|
+ sudo_sssd_parse_options(rule);
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_result(sres);
|
|
+
|
|
+ DPRINTF(1, "Looking for cn=defaults... end");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+sudo_sssd_check_runas_user(struct sss_rule *rule)
|
|
+{
|
|
+ char **v_arr = NULL;
|
|
+ char *val;
|
|
+ int ret = FALSE, i;
|
|
+
|
|
+ if (!runas_pw)
|
|
+ return UNSPEC;
|
|
+
|
|
+
|
|
+ /* get the runas user from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAsUser", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result. Trying old style (sudoRunAs)");
|
|
+
|
|
+ /* try old style */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAs", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result. Matching against runas_default");
|
|
+ /*
|
|
+ * If there are no runas entries, match runas_default against
|
|
+ * what the user specified on the command line.
|
|
+ */
|
|
+ return !strcasecmp(runas_pw->pw_name, def_runas_default);
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAs): != 0");
|
|
+ return UNSPEC;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAsUser): != 0");
|
|
+ return UNSPEC;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * BUG:
|
|
+ *
|
|
+ * if runas is not specified on the command line, the only information
|
|
+ * as to which user to run as is in the runas_default option. We should
|
|
+ * check to see if we have the local option present. Unfortunately we
|
|
+ * don't parse these options until after this routine says yes or no.
|
|
+ * The query has already returned, so we could peek at the attribute
|
|
+ * values here though.
|
|
+ *
|
|
+ * For now just require users to always use -u option unless its set
|
|
+ * in the global defaults. This behaviour is no different than the global
|
|
+ * /etc/sudoers.
|
|
+ *
|
|
+ * Sigh - maybe add this feature later
|
|
+ */
|
|
+
|
|
+ /* walk through values returned, looking for a match */
|
|
+ for (i = 0; v_arr[i] != NULL && !ret; ++i) {
|
|
+ val = v_arr[i];
|
|
+
|
|
+ DPRINTF(3, "val[%d]=%s", i, val);
|
|
+
|
|
+ switch (val[0]) {
|
|
+ case '+':
|
|
+ DPRINTF(3, "netgr_");
|
|
+ if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) {
|
|
+ DPRINTF(3, "=> match");
|
|
+ ret = TRUE;
|
|
+ }
|
|
+ break;
|
|
+ case '%':
|
|
+ DPRINTF(3, "usergr_");
|
|
+ if (usergr_matches(val, runas_pw->pw_name, runas_pw)) {
|
|
+ DPRINTF(3, "=> match");
|
|
+ ret = TRUE;
|
|
+ }
|
|
+ break;
|
|
+ case 'A':
|
|
+ if (strcmp(val, "ALL") == 0) {
|
|
+ DPRINTF(3, "ALL => match");
|
|
+ ret = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ /* FALLTHROUGH */
|
|
+ DPRINTF(3, "FALLTHROUGH");
|
|
+ default:
|
|
+ if (strcasecmp(val, runas_pw->pw_name) == 0) {
|
|
+ DPRINTF(3, "%s == %s (pw_name) => match", val, runas_pw->pw_name);
|
|
+ ret = TRUE;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ DPRINTF(2, "sssd/ldap sudoRunAsUser '%s' ... %s", val, ret ? "MATCH!" : "not");
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr); /* cleanup */
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+sudo_sssd_check_runas_group(struct sss_rule *rule)
|
|
+{
|
|
+ char **v_arr = NULL;
|
|
+ char *val;
|
|
+ int ret = FALSE, i;
|
|
+
|
|
+ /* runas_gr is only set if the user specified the -g flag */
|
|
+ if (!runas_gr)
|
|
+ return UNSPEC;
|
|
+
|
|
+ /* get the values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAsGroup", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ return FALSE;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAsGroup): != 0");
|
|
+ return UNSPEC;
|
|
+ }
|
|
+
|
|
+ /* walk through values returned, looking for a match */
|
|
+ for (i = 0; v_arr[i] != NULL; ++i) {
|
|
+ val = v_arr[i];
|
|
+ DPRINTF(3, "val[%d]=%s", i, val);
|
|
+
|
|
+ if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr))
|
|
+ ret = TRUE;
|
|
+
|
|
+ DPRINTF(2, "sssd/ldap sudoRunAsGroup '%s' ... %s", val, ret ? "MATCH!" : "not");
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Walk through search results and return TRUE if we have a runas match,
|
|
+ * else FALSE. RunAs info is optional.
|
|
+ */
|
|
+static int
|
|
+sudo_sssd_check_runas(struct sss_rule *rule)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (rule == NULL)
|
|
+ return FALSE;
|
|
+
|
|
+ ret = sudo_sssd_check_runas_user(rule) != FALSE &&
|
|
+ sudo_sssd_check_runas_group(rule) != FALSE;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_check_host(struct sss_rule *rule)
|
|
+{
|
|
+ char **v_arr, *val;
|
|
+ int ret = FALSE, i;
|
|
+
|
|
+ if (rule == NULL)
|
|
+ return ret;
|
|
+
|
|
+ /* get the values from the rule */
|
|
+ switch (sss_sudo_get_values(rule, "sudoHost", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ return FALSE;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoHost): != 0");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* walk through values */
|
|
+ for (i = 0; v_arr[i] != NULL; ++i) {
|
|
+ val = v_arr[i];
|
|
+ DPRINTF(3, "val[%d]=%s", i, val);
|
|
+
|
|
+ /* match any or address or netgroup or hostname */
|
|
+ if (!strcmp(val, "ALL") || addr_matches(val) ||
|
|
+ netgr_matches(val, user_host, user_shost, NULL) ||
|
|
+ hostname_matches(user_shost, user_host, val))
|
|
+ ret = TRUE;
|
|
+
|
|
+ DPRINTF(2, "sssd/ldap sudoHost '%s' ... %s", val, ret ? "MATCH!" : "not");
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_result_filterp(struct sss_rule *rule, void *unused)
|
|
+{
|
|
+ (void)unused;
|
|
+
|
|
+ if (sudo_sssd_check_host(rule))
|
|
+ return 1;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct sss_result *sudo_sssd_result_get(struct sudo_nss *nss,
|
|
+ struct passwd *pw,
|
|
+ uint32_t *state)
|
|
+{
|
|
+ struct sudo_sssd_handle *handle = nss->handle;
|
|
+ struct sss_result *u_sres, *f_sres;
|
|
+ uint32_t serr = 0, ret;
|
|
+
|
|
+ DPRINTF(1, "pw_name=%s", pw->pw_name);
|
|
+
|
|
+ u_sres = f_sres = NULL;
|
|
+
|
|
+ switch (ret = sss_sudo_send_recv(pw->pw_name, &serr, &u_sres))
|
|
+ {
|
|
+ case 0:
|
|
+ switch (serr) {
|
|
+ case 0:
|
|
+ if (u_sres != NULL) {
|
|
+ if (state != NULL) {
|
|
+ DPRINTF(3, "state |= USERMATCH");
|
|
+ *state |= _SUDO_SSS_STATE_USERMATCH;
|
|
+ }
|
|
+ DPRINTF(2, "Received %u rule(s)", u_sres->num_rules);
|
|
+ } else {
|
|
+ DPRINTF(2, "Internal error: u_sres == NULL && serr == 0");
|
|
+ return NULL;
|
|
+ }
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ default:
|
|
+ DPRINTF(2, "serr=%u\n", serr);
|
|
+ return NULL;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_send_recv: != 0: ret=%d", ret);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ f_sres = sudo_sssd_filter_result(u_sres, sudo_sssd_result_filterp, _SUDO_SSS_FILTER_INCLUDE, NULL);
|
|
+
|
|
+ if (f_sres != NULL)
|
|
+ if (f_sres->num_rules > 0)
|
|
+ if (state != NULL) {
|
|
+ DPRINTF(3, "state |= HOSTMATCH");
|
|
+ *state |= _SUDO_SSS_STATE_HOSTMATCH;
|
|
+ }
|
|
+
|
|
+ DPRINTF(3, "u_sres=(%p, %u) => f_sres=(%p, %u)",
|
|
+ u_sres, u_sres->num_rules, f_sres, f_sres->num_rules);
|
|
+
|
|
+ sss_sudo_free_result(u_sres);
|
|
+
|
|
+ /* Store everything in the sudo_nss handle. */
|
|
+ handle->result = NULL;
|
|
+
|
|
+ if (handle->username != NULL) {
|
|
+ DPRINTF(3, "Freeing previously stored username");
|
|
+ efree(handle->username);
|
|
+ }
|
|
+
|
|
+ handle->username = estrdup(pw->pw_name);
|
|
+ handle->grlist = user_group_list;
|
|
+
|
|
+ return f_sres;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Search for boolean "option" in sudoOption.
|
|
+ * Returns TRUE if found and allowed, FALSE if negated, else UNSPEC.
|
|
+ */
|
|
+static int
|
|
+sudo_sssd_check_bool(struct sss_rule *rule, char *option)
|
|
+{
|
|
+ char ch, *var, **v_arr = NULL;
|
|
+ int i, ret = UNSPEC;
|
|
+
|
|
+ if (rule == NULL)
|
|
+ return ret;
|
|
+
|
|
+ switch (sss_sudo_get_values(rule, "sudoOption", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ return ret;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values: != 0");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* walk through options */
|
|
+ for (i = 0; v_arr[i] != NULL; ++i) {
|
|
+ var = v_arr[i];
|
|
+ DPRINTF(2, "sssd/ldap sudoOption: '%s'", var);
|
|
+
|
|
+ if ((ch = *var) == '!')
|
|
+ var++;
|
|
+ if (strcmp(var, option) == 0)
|
|
+ ret = (ch != '!');
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Walk through search results and return TRUE if we have a command match,
|
|
+ * FALSE if disallowed and UNSPEC if not matched.
|
|
+ */
|
|
+static int
|
|
+sudo_sssd_check_command(struct sss_rule *rule, int *setenv_implied)
|
|
+{
|
|
+ char **v_arr = NULL, *val;
|
|
+ char *allowed_cmnd, *allowed_args;
|
|
+ int i, foundbang, ret = UNSPEC;
|
|
+
|
|
+ if (rule == NULL)
|
|
+ return ret;
|
|
+
|
|
+ switch (sss_sudo_get_values(rule, "sudoCommand", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ return ret;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values: != 0");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ for (i = 0; v_arr[i] != NULL && ret != FALSE; ++i) {
|
|
+ val = v_arr[i];
|
|
+
|
|
+ DPRINTF(3, "val[%d]=%s", i, val);
|
|
+
|
|
+ /* Match against ALL ? */
|
|
+ if (!strcmp(val, "ALL")) {
|
|
+ ret = TRUE;
|
|
+ if (setenv_implied != NULL)
|
|
+ *setenv_implied = TRUE;
|
|
+ DPRINTF(2, "sssd/ldap sudoCommand '%s' ... MATCH!", val);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* check for !command */
|
|
+ if (*val == '!') {
|
|
+ foundbang = TRUE;
|
|
+ allowed_cmnd = estrdup(1 + val); /* !command */
|
|
+ } else {
|
|
+ foundbang = FALSE;
|
|
+ allowed_cmnd = estrdup(val); /* command */
|
|
+ }
|
|
+
|
|
+ /* split optional args away from command */
|
|
+ allowed_args = strchr(allowed_cmnd, ' ');
|
|
+ if (allowed_args)
|
|
+ *allowed_args++ = '\0';
|
|
+
|
|
+ /* check the command like normal */
|
|
+ if (command_matches(allowed_cmnd, allowed_args)) {
|
|
+ /*
|
|
+ * If allowed (no bang) set ret but keep on checking.
|
|
+ * If disallowed (bang), exit loop.
|
|
+ */
|
|
+ ret = foundbang ? FALSE : TRUE;
|
|
+ }
|
|
+
|
|
+ DPRINTF(2, "sssd/ldap sudoCommand '%s' ... %s", val, ret == TRUE ? "MATCH!" : "not");
|
|
+ efree(allowed_cmnd); /* cleanup */
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr); /* more cleanup */
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void
|
|
+sudo_sssd_parse_options(struct sss_rule *rule)
|
|
+{
|
|
+ int i;
|
|
+ char op, *v, *val;
|
|
+ char **v_arr = NULL;
|
|
+
|
|
+ if (rule == NULL)
|
|
+ return;
|
|
+
|
|
+ switch (sss_sudo_get_values(rule, "sudoOption", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ return;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoOption): != 0");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* walk through options */
|
|
+ for (i = 0; v_arr[i] != NULL; i++) {
|
|
+ DPRINTF(2, "sssd/ldap sudoOption: '%s'", v_arr[i]);
|
|
+ v = estrdup(v_arr[i]);
|
|
+
|
|
+ /* check for equals sign past first char */
|
|
+ val = strchr(v, '=');
|
|
+ if (val > v) {
|
|
+ *val++ = '\0'; /* split on = and truncate var */
|
|
+ op = *(val - 2); /* peek for += or -= cases */
|
|
+ if (op == '+' || op == '-') {
|
|
+ *(val - 2) = '\0'; /* found, remove extra char */
|
|
+ /* case var+=val or var-=val */
|
|
+ set_default(v, val, (int) op);
|
|
+ } else {
|
|
+ /* case var=val */
|
|
+ set_default(v, val, TRUE);
|
|
+ }
|
|
+ } else if (*v == '!') {
|
|
+ /* case !var Boolean False */
|
|
+ set_default(v + 1, NULL, FALSE);
|
|
+ } else {
|
|
+ /* case var Boolean True */
|
|
+ set_default(v, NULL, TRUE);
|
|
+ }
|
|
+ efree(v);
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr);
|
|
+}
|
|
+
|
|
+static int sudo_sssd_lookup(struct sudo_nss *nss, int ret, int pwflag)
|
|
+{
|
|
+ int rc, setenv_implied;
|
|
+
|
|
+ struct sss_result *sres = NULL;
|
|
+ struct sss_rule *rule;
|
|
+ uint32_t i, state = 0;
|
|
+
|
|
+ /* Fetch list of sudoRole entries that match user and host. */
|
|
+ sres = sudo_sssd_result_get(nss, sudo_user.pw, &state);
|
|
+
|
|
+ /*
|
|
+ * The following queries are only determine whether or not a
|
|
+ * password is required, so the order of the entries doesn't matter.
|
|
+ */
|
|
+ if (pwflag) {
|
|
+ int doauth = UNSPEC;
|
|
+ int matched = UNSPEC;
|
|
+ enum def_tuple pwcheck =
|
|
+ (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
|
|
+
|
|
+ DPRINTF(2, "perform search for pwflag %d", pwflag);
|
|
+ if (sres != NULL) {
|
|
+ for (i = 0; i < sres->num_rules; i++) {
|
|
+ rule = sres->rules + i;
|
|
+ if ((pwcheck == any && doauth != FALSE) ||
|
|
+ (pwcheck == all && doauth == FALSE)) {
|
|
+ doauth = sudo_sssd_check_bool(rule, "authenticate");
|
|
+ }
|
|
+ /* Only check the command when listing another user. */
|
|
+ if (user_uid == 0 || list_pw == NULL ||
|
|
+ user_uid == list_pw->pw_uid ||
|
|
+ sudo_sssd_check_command(rule, NULL)) {
|
|
+ matched = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (matched || user_uid == 0) {
|
|
+ SET(ret, VALIDATE_OK);
|
|
+ CLR(ret, VALIDATE_NOT_OK);
|
|
+ if (def_authenticate) {
|
|
+ switch (pwcheck) {
|
|
+ case always:
|
|
+ SET(ret, FLAG_CHECK_USER);
|
|
+ break;
|
|
+ case all:
|
|
+ case any:
|
|
+ if (doauth == FALSE)
|
|
+ def_authenticate = FALSE;
|
|
+ break;
|
|
+ case never:
|
|
+ def_authenticate = FALSE;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ DPRINTF(1, "searching SSSD/LDAP for sudoers entries");
|
|
+
|
|
+ setenv_implied = FALSE;
|
|
+ if (sres != NULL) {
|
|
+ for (i = 0; i < sres->num_rules; i++) {
|
|
+ rule = sres->rules + i;
|
|
+ if (!sudo_sssd_check_runas(rule))
|
|
+ continue;
|
|
+ rc = sudo_sssd_check_command(rule, &setenv_implied);
|
|
+ if (rc != UNSPEC) {
|
|
+ /* We have a match. */
|
|
+ DPRINTF(1, "Command %sallowed", rc == TRUE ? "" : "NOT ");
|
|
+ if (rc == TRUE) {
|
|
+ DPRINTF(3, "SSSD rule: %p", rule);
|
|
+ /* Apply entry-specific options. */
|
|
+ if (setenv_implied)
|
|
+ def_setenv = TRUE;
|
|
+ sudo_sssd_parse_options(rule);
|
|
+#ifdef HAVE_SELINUX
|
|
+ /* Set role and type if not specified on command line. */
|
|
+ if (user_role == NULL)
|
|
+ user_role = def_role;
|
|
+ if (user_type == NULL)
|
|
+ user_type = def_type;
|
|
+#endif /* HAVE_SELINUX */
|
|
+ SET(ret, VALIDATE_OK);
|
|
+ CLR(ret, VALIDATE_NOT_OK);
|
|
+ } else {
|
|
+ SET(ret, VALIDATE_NOT_OK);
|
|
+ CLR(ret, VALIDATE_OK);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+done:
|
|
+ DPRINTF(1, "Done with LDAP searches");
|
|
+
|
|
+ if (!ISSET(ret, VALIDATE_OK)) {
|
|
+ /* No matching entries. */
|
|
+ if (pwflag && list_pw == NULL)
|
|
+ SET(ret, FLAG_NO_CHECK);
|
|
+ }
|
|
+
|
|
+ if (state & _SUDO_SSS_STATE_USERMATCH)
|
|
+ CLR(ret, FLAG_NO_USER);
|
|
+ if (state & _SUDO_SSS_STATE_HOSTMATCH)
|
|
+ CLR(ret, FLAG_NO_HOST);
|
|
+
|
|
+ DPRINTF(3, "sudo_sssd_lookup(%d)=0x%02x", pwflag, ret);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
|
|
+{
|
|
+ struct sudo_sssd_handle *handle = nss->handle;
|
|
+ struct sss_result *sres = NULL;
|
|
+ struct sss_rule *rule;
|
|
+ int i, found = FALSE;
|
|
+
|
|
+ if (handle == NULL)
|
|
+ goto done;
|
|
+
|
|
+ /*
|
|
+ * The sudo_sssd_result_get() function returns all nodes that match
|
|
+ * the user and the host.
|
|
+ */
|
|
+ DPRINTF(1, "sssd/ldap search for command list");
|
|
+ sres = sudo_sssd_result_get(nss, pw, NULL);
|
|
+
|
|
+ if (sres == NULL)
|
|
+ goto done;
|
|
+
|
|
+ for (i = 0; i < sres->num_rules; i++) {
|
|
+ rule = sres->rules + i;
|
|
+ if (sudo_sssd_check_command(rule, NULL) &&
|
|
+ sudo_sssd_check_runas(rule)) {
|
|
+ found = TRUE;
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+
|
|
+done:
|
|
+ if (found)
|
|
+ printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd,
|
|
+ user_args ? " " : "", user_args ? user_args : "");
|
|
+
|
|
+ if (sres != NULL)
|
|
+ sss_sudo_free_result(sres);
|
|
+
|
|
+ return !found;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_display_defaults(struct sudo_nss *nss, struct passwd *pw,
|
|
+ struct lbuf *lbuf)
|
|
+{
|
|
+ struct sudo_sssd_handle *handle = nss->handle;
|
|
+
|
|
+ struct sss_rule *rule;
|
|
+ struct sss_result *sres = NULL;
|
|
+
|
|
+ uint32_t serr = 0;
|
|
+
|
|
+ char *prefix, *val, **v_arr = NULL;
|
|
+ int count = 0, i, j;
|
|
+
|
|
+ if (handle == NULL)
|
|
+ goto done;
|
|
+
|
|
+ if (sss_sudo_send_recv_defaults(&serr, &sres) != 0) {
|
|
+ DPRINTF(2, "sss_sudo_send_recv_defaults: !=0, serr=%u", serr);
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < sres->num_rules; ++i) {
|
|
+ rule = sres->rules + i;
|
|
+
|
|
+ switch (sss_sudo_get_values(rule, "sudoOption", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ continue;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values: != 0");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
|
|
+ prefix = " ";
|
|
+ else
|
|
+ prefix = ", ";
|
|
+
|
|
+ for (j = 0; v_arr[j] != NULL; ++j) {
|
|
+ val = v_arr[j];
|
|
+ lbuf_append(lbuf, "%s%s", prefix, val);
|
|
+ prefix = ", ";
|
|
+ count++;
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ v_arr = NULL;
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_result(sres);
|
|
+done:
|
|
+ return count;
|
|
+}
|
|
+
|
|
+// ok
|
|
+static int sudo_sssd_display_bound_defaults(struct sudo_nss *nss,
|
|
+ struct passwd *pw, struct lbuf *lbuf)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_display_entry_long(struct sss_rule *rule, struct lbuf *lbuf)
|
|
+{
|
|
+ char **v_arr = NULL;
|
|
+ int count = 0, i;
|
|
+
|
|
+#if 0 /* do we need this? */
|
|
+ char *rdn;
|
|
+ /* extract the dn, only show the first rdn */
|
|
+ rdn = sudo_ldap_get_first_rdn(ld, entry);
|
|
+ if (rdn != NULL)
|
|
+ lbuf_append(lbuf, _("\nLDAP Role: %s\n"), rdn);
|
|
+ else
|
|
+ lbuf_append(lbuf, _("\nLDAP Role: UNKNOWN\n"));
|
|
+ if (rdn)
|
|
+ ldap_memfree(rdn);
|
|
+#endif
|
|
+
|
|
+ /* get the RunAsUser Values from the entry */
|
|
+ lbuf_append(lbuf, " RunAsUsers: ");
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAsUser", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAs", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ lbuf_append(lbuf, "%s", def_runas_default);
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAs): != 0");
|
|
+ return count;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAsUser): != 0");
|
|
+ return count;
|
|
+ }
|
|
+ lbuf_append(lbuf, "\n");
|
|
+
|
|
+ /* get the RunAsGroup Values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAsGroup", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ lbuf_append(lbuf, " RunAsGroups: ");
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ lbuf_append(lbuf, "\n");
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAsGroup): != 0");
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+
|
|
+ /* get the Option Values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoOption", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ lbuf_append(lbuf, " Options: ");
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ lbuf_append(lbuf, "\n");
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoOption): != 0");
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ /* Get the command values from the entry. */
|
|
+ switch (sss_sudo_get_values(rule, "sudoCommand", &v_arr)) {
|
|
+ case 0:
|
|
+ lbuf_append(lbuf, _(" Commands:\n"));
|
|
+ for (i = 0; v_arr[i] != NULL; ++i) {
|
|
+ lbuf_append(lbuf, "\t%s\n", v_arr[i]);
|
|
+ count++;
|
|
+ }
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoCommand): != 0");
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_display_entry_short(struct sss_rule *rule, struct lbuf *lbuf)
|
|
+{
|
|
+ char **v_arr = NULL;
|
|
+ int count = 0, i;
|
|
+
|
|
+ lbuf_append(lbuf, " (");
|
|
+
|
|
+ /* get the RunAsUser Values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAsUser", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result. Trying old style (sudoRunAs).");
|
|
+ /* try old style */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAs", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ lbuf_append(lbuf, "%s", def_runas_default);
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAs): != 0");
|
|
+ return count;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAsUser): != 0");
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ /* get the RunAsGroup Values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoRunAsGroup", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ lbuf_append(lbuf, " : ");
|
|
+ for (i = 0; v_arr[i] != NULL; ++i)
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoRunAsGroup): != 0");
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ lbuf_append(lbuf, ") ");
|
|
+
|
|
+ /* get the Option Values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoOption", &v_arr))
|
|
+ {
|
|
+ case 0:
|
|
+ for (i = 0; v_arr[i] != NULL; ++i) {
|
|
+ char *cp = v_arr[i];
|
|
+ if (*cp == '!')
|
|
+ cp++;
|
|
+ if (strcmp(cp, "authenticate") == 0)
|
|
+ lbuf_append(lbuf, v_arr[i][0] == '!' ?
|
|
+ "NOPASSWD: " : "PASSWD: ");
|
|
+ else if (strcmp(cp, "noexec") == 0)
|
|
+ lbuf_append(lbuf, v_arr[i][0] == '!' ?
|
|
+ "EXEC: " : "NOEXEC: ");
|
|
+ else if (strcmp(cp, "setenv") == 0)
|
|
+ lbuf_append(lbuf, v_arr[i][0] == '!' ?
|
|
+ "NOSETENV: " : "SETENV: ");
|
|
+ }
|
|
+
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoOption): != 0");
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ /* get the Command Values from the entry */
|
|
+ switch (sss_sudo_get_values(rule, "sudoCommand", &v_arr)) {
|
|
+ case 0:
|
|
+ for (i = 0; v_arr[i] != NULL; ++i) {
|
|
+ lbuf_append(lbuf, "%s%s", i != 0 ? ", " : "", v_arr[i]);
|
|
+ count++;
|
|
+ }
|
|
+ sss_sudo_free_values(v_arr);
|
|
+ break;
|
|
+ case ENOENT:
|
|
+ DPRINTF(2, "No result.");
|
|
+ break;
|
|
+ default:
|
|
+ DPRINTF(2, "sss_sudo_get_values(sudoCommand): != 0");
|
|
+ return count;
|
|
+ }
|
|
+ lbuf_append(lbuf, "\n");
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static int sudo_sssd_display_privs(struct sudo_nss *nss, struct passwd *pw,
|
|
+ struct lbuf *lbuf)
|
|
+{
|
|
+ struct sss_result *sres = NULL;
|
|
+ struct sss_rule *rule;
|
|
+ unsigned int i, count = 0;
|
|
+
|
|
+ DPRINTF(2, "sssd/ldap search for command list");
|
|
+
|
|
+ sres = sudo_sssd_result_get(nss, pw, NULL);
|
|
+
|
|
+ if (sres == NULL)
|
|
+ return count;
|
|
+
|
|
+ /* Display all matching entries. */
|
|
+ for (i = 0; i < sres->num_rules; ++i) {
|
|
+ rule = sres->rules + i;
|
|
+ if (long_list)
|
|
+ count += sudo_sssd_display_entry_long(rule, lbuf);
|
|
+ else
|
|
+ count += sudo_sssd_display_entry_short(rule, lbuf);
|
|
+ }
|
|
+
|
|
+ if (sres != NULL)
|
|
+ sss_sudo_free_result(sres);
|
|
+
|
|
+ return count;
|
|
+}
|
|
diff -up sudo-1.8.3p1/plugins/sudoers/sudo_nss.c.sssd-support sudo-1.8.3p1/plugins/sudoers/sudo_nss.c
|
|
--- sudo-1.8.3p1/plugins/sudoers/sudo_nss.c.sssd-support 2012-01-18 18:21:10.155151843 +0100
|
|
+++ sudo-1.8.3p1/plugins/sudoers/sudo_nss.c 2012-01-18 18:29:40.366473444 +0100
|
|
@@ -47,8 +47,11 @@ extern struct sudo_nss sudo_nss_file;
|
|
#ifdef HAVE_LDAP
|
|
extern struct sudo_nss sudo_nss_ldap;
|
|
#endif
|
|
+#ifdef HAVE_SSSD
|
|
+extern struct sudo_nss sudo_nss_sssd;
|
|
+#endif
|
|
|
|
-#if defined(HAVE_LDAP) && defined(_PATH_NSSWITCH_CONF)
|
|
+#if (defined(HAVE_SSSD) || defined(HAVE_LDAP)) && defined(_PATH_NSSWITCH_CONF)
|
|
/*
|
|
* Read in /etc/nsswitch.conf
|
|
* Returns a tail queue of matches.
|
|
@@ -60,6 +63,7 @@ sudo_read_nss(void)
|
|
char *cp;
|
|
int saw_files = FALSE;
|
|
int saw_ldap = FALSE;
|
|
+ int saw_sssd = FALSE;
|
|
int got_match = FALSE;
|
|
static struct sudo_nss_list snl;
|
|
|
|
@@ -80,9 +84,16 @@ sudo_read_nss(void)
|
|
if (strcasecmp(cp, "files") == 0 && !saw_files) {
|
|
tq_append(&snl, &sudo_nss_file);
|
|
got_match = TRUE;
|
|
+#if defined(HAVE_LDAP)
|
|
} else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) {
|
|
tq_append(&snl, &sudo_nss_ldap);
|
|
got_match = TRUE;
|
|
+#endif
|
|
+#if defined(HAVE_SSSD)
|
|
+ } else if (strcasecmp(cp, "sss") == 0 && !saw_sssd) {
|
|
+ tq_append(&snl, &sudo_nss_sssd);
|
|
+ got_match = TRUE;
|
|
+#endif
|
|
} else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) {
|
|
/* NOTFOUND affects the most recent entry */
|
|
tq_last(&snl)->ret_if_notfound = TRUE;
|
|
@@ -105,7 +116,7 @@ nomatch:
|
|
|
|
#else /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
|
|
|
|
-# if defined(HAVE_LDAP) && defined(_PATH_NETSVC_CONF)
|
|
+# if (defined(HAVE_SSSD) || defined(HAVE_LDAP)) && defined(_PATH_NETSVC_CONF)
|
|
|
|
/*
|
|
* Read in /etc/netsvc.conf (like nsswitch.conf on AIX)
|
|
@@ -118,6 +129,7 @@ sudo_read_nss(void)
|
|
char *cp, *ep;
|
|
int saw_files = FALSE;
|
|
int saw_ldap = FALSE;
|
|
+ int saw_sssd = FALSE;
|
|
int got_match = FALSE;
|
|
static struct sudo_nss_list snl;
|
|
|
|
@@ -149,11 +161,20 @@ sudo_read_nss(void)
|
|
tq_append(&snl, &sudo_nss_file);
|
|
got_match = TRUE;
|
|
ep = &cp[5];
|
|
+#if defined(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;
|
|
ep = &cp[4];
|
|
+#endif
|
|
+#if defined(HAVE_SSSD)
|
|
+ } else if (!saw_sssd && strncasecmp(cp, "sss", 3) == 0 &&
|
|
+ (isspace((unsigned char)cp[3]) || cp[3] == '\0')) {
|
|
+ tq_append(&snl, &sudo_nss_sssd);
|
|
+ got_match = TRUE;
|
|
+ ep = &cp[3];
|
|
+#endif
|
|
} else {
|
|
got_match = FALSE;
|
|
}
|