Index: sudo-1.7.6p2/configure
===================================================================
--- sudo-1.7.6p2.orig/configure	2011-05-16 19:38:16.000000000 +0200
+++ sudo-1.7.6p2/configure	2013-03-27 11:27:54.090614900 +0100
@@ -787,6 +787,7 @@ editor
 secure_path
 netsvc_conf
 nsswitch_conf
+sssd_lib
 ldap_secret
 ldap_conf
 path_info
@@ -908,6 +909,8 @@ with_rpath
 with_blibpath
 with_bsm_audit
 with_linux_audit
+with_sssd
+with_sssd_lib
 with_incpath
 with_libpath
 with_libraries
@@ -1671,6 +1674,8 @@ Optional Packages:
   --with-blibpath=PATH    pass -blibpath flag to ld for additional lib paths
   --with-bsm-audit        enable BSM audit support
   --with-linux-audit      enable Linux audit support
+  --with-sssd             enable SSSD support
+  --with-sssd-lib         path to the SSSD library
   --with-incpath          additional places to look for include files
   --with-libpath          additional places to look for libraries
   --with-libraries        additional libraries to link with
@@ -3963,6 +3968,33 @@ esac
 fi
 
 
+# Check whether --with-sssd was given.
+if test "${with_sssd+set}" = set; then :
+  withval=$with_sssd; case $with_sssd in
+    yes)	SUDO_OBJS="${SUDO_OBJS} sssd.o"
+		$as_echo "#define HAVE_SSSD 1" >>confdefs.h
+
+		;;
+    no)		;;
+    *)		as_fn_error $? "\"--with-sssd does not take an argument.\"" "$LINENO" 5
+		;;
+esac
+fi
+
+
+
+# Check whether --with-sssd-lib was given.
+if test "${with_sssd_lib+set}" = set; then :
+  withval=$with_sssd_lib;
+fi
+
+sssd_lib="\"LIBDIR\""
+test -n "$with_sssd_lib" && sssd_lib="$with_sssd_lib"
+cat >>confdefs.h <<EOF
+#define _PATH_SSSD_LIB "$sssd_lib"
+EOF
+
+
 
 # Check whether --with-incpath was given.
 if test "${with_incpath+set}" = set; then :
@@ -8927,10 +8959,7 @@ done
 
 
 # Set options
-
-
-
-        enable_dlopen=no
+enable_dlopen=yes
 
 
   enable_win32_dll=no
@@ -18516,6 +18545,99 @@ $as_echo "$as_me: WARNING: Unable to loc
     LDFLAGS="$_LDFLAGS"
 fi
 
+#
+# How to do dynamic object loading.
+# We support dlopen() and sh_load(), else fall back to static loading.
+#
+case "$lt_cv_dlopen" in
+    dlopen)
+	$as_echo "#define HAVE_DLOPEN 1" >>confdefs.h
+
+	SUDOERS_OBJS="$SUDOERS_OBJS plugin_error.lo"
+	LT_STATIC="--tag=disable-static"
+	;;
+    shl_load)
+	$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h
+
+	SUDOERS_OBJS="$SUDOERS_OBJS plugin_error.lo"
+	LT_STATIC="--tag=disable-static"
+	case " $LIBOBJS " in
+  *" dlopen.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS dlopen.$ac_objext"
+ ;;
+esac
+
+	;;
+    *)
+	if test X"${ac_cv_func_dlopen}" = X"yes"; then
+	    as_fn_error $? "\"dlopen present but libtool doesn't appear to support your platform.\"" "$LINENO" 5
+	fi
+	# Preload sudoers module symbols
+	SUDO_OBJS="${SUDO_OBJS} preload.o"
+	SUDO_LIBS="${SUDO_LIBS} \$(top_builddir)/plugins/sudoers/sudoers.la"
+	LT_STATIC=""
+	case " $LIBOBJS " in
+  *" dlopen.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS dlopen.$ac_objext"
+ ;;
+esac
+
+	;;
+esac
+
+#
+# Add library needed for dynamic loading, if any.
+#
+LIBDL="$lt_cv_dlopen_libs"
+if test X"$LIBDL" != X""; then
+    SUDO_LIBS="${SUDO_LIBS} $LIBDL"
+    SUDOERS_LIBS="${SUDOERS_LIBS} $LIBDL"
+fi
+
+# On HP-UX, you cannot dlopen() a shared object that uses pthreads unless
+# the main program is linked against -lpthread.  We have no knowledge of
+# what libraries a plugin may depend on (e.g. HP-UX LDAP which uses pthreads)
+# so always link against -lpthread on HP-UX if it is available.
+# This check should go after all other libraries tests.
+case "$host" in
+    *-*-hpux*)
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
+$as_echo_n "checking for main in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthread_main=yes
+else
+  ac_cv_lib_pthread_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
+$as_echo "$ac_cv_lib_pthread_main" >&6; }
+if test "x$ac_cv_lib_pthread_main" = xyes; then :
+  SUDO_LIBS="${SUDO_LIBS} -lpthread"
+fi
+
+	;;
+esac
+
 if test X"$LIBVAS_RPATH" != X""; then
     if test -n "$blibpath"; then
 	blibpath_add="${blibpath_add}:$LIBVAS_RPATH"
Index: sudo-1.7.6p2/configure.in
===================================================================
--- sudo-1.7.6p2.orig/configure.in	2013-03-27 11:27:33.613006506 +0100
+++ sudo-1.7.6p2/configure.in	2013-03-27 11:27:54.090614900 +0100
@@ -89,6 +89,7 @@ AC_SUBST([root_sudo])
 AC_SUBST([path_info])
 AC_SUBST([ldap_conf])
 AC_SUBST([ldap_secret])
+AC_SUBST([sssd_lib])
 AC_SUBST([nsswitch_conf])
 AC_SUBST([netsvc_conf])
 AC_SUBST([secure_path])
@@ -263,6 +264,24 @@ 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)	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(sssd-lib, [AS_HELP_STRING([--with-sssd-lib], [path to the SSSD library])])
+sssd_lib="\"LIBDIR\""
+test -n "$with_sssd_lib" && sssd_lib="$with_sssd_lib"
+SUDO_DEFINE_UNQUOTED(_PATH_SSSD_LIB, "$sssd_lib", [Path to the SSSD library])
+
 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."])
@@ -2933,6 +2952,7 @@ AH_TEMPLATE(HAVE_KRB5_VERIFY_USER, [Defi
 AH_TEMPLATE(HAVE_LBER_H, [Define to 1 if your LDAP needs <lber.h>. (OpenLDAP does not)])
 AH_TEMPLATE(HAVE_LDAP, [Define to 1 if you use LDAP for sudoers.])
 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.])
Index: sudo-1.7.6p2/pathnames.h.in
===================================================================
--- sudo-1.7.6p2.orig/pathnames.h.in	2013-03-27 11:27:33.596006001 +0100
+++ sudo-1.7.6p2/pathnames.h.in	2013-03-27 11:27:33.727009893 +0100
@@ -142,6 +142,10 @@
 #undef	_PATH_LDAP_SECRET
 #endif /* _PATH_LDAP_SECRET */
 
+#ifndef _PATH_SSSD_LIB
+#undef  _PATH_SSSD_LIB
+#endif /* _PATH_SSSD_LIB */
+
 #ifndef _PATH_NSSWITCH_CONF
 #undef	_PATH_NSSWITCH_CONF
 #endif /* _PATH_NSSWITCH_CONF */
Index: sudo-1.7.6p2/sssd.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ sudo-1.7.6p2/sssd.c	2013-03-27 13:50:08.504488613 +0100
@@ -0,0 +1,1348 @@
+/*
+ * Copyright (c) 2003-2012 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
+#ifdef HAVE_DLOPEN
+# include <dlfcn.h>
+#else
+# include <dlfcn.h>
+#endif
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "sudo.h"
+#include "parse.h"
+#include "lbuf.h"
+
+/* TODO: wipe these entirely or define to something meaningful */
+/*
+ * Variadic macros are a C99 feature but GNU cpp has supported
+ * a (different) version of them for a long time.
+ */
+#if defined(__GNUC__) && __GNUC__ == 2
+# define sudo_debug_printf(pri, fmt...)
+# define _(fmt...) (fmt)
+#else
+# define sudo_debug_printf(pri, ...)
+# define _(...) (__VA_ARGS__)
+#endif
+# define debug_decl(a, b)
+
+
+/* SSSD <--> SUDO interface - do not change */
+struct sss_sudo_attr {
+    char *name;
+    char **values;
+    unsigned int num_values;
+};
+
+struct sss_sudo_rule {
+    unsigned int num_attrs;
+    struct sss_sudo_attr *attrs;
+};
+
+struct sss_sudo_result {
+    unsigned int num_rules;
+    struct sss_sudo_rule *rules;
+};
+
+typedef int  (*sss_sudo_send_recv_t)(uid_t, const char*, const char*,
+                                     uint32_t*, struct sss_sudo_result**);
+
+typedef int  (*sss_sudo_send_recv_defaults_t)(uid_t, const char*, uint32_t*,
+                                              char**, struct sss_sudo_result**);
+
+typedef void (*sss_sudo_free_result_t)(struct sss_sudo_result*);
+
+typedef int  (*sss_sudo_get_values_t)(struct sss_sudo_rule*, const char*,
+                                      char***);
+
+typedef void (*sss_sudo_free_values_t)(char**);
+
+/* sudo_nss implementation */
+
+struct sudo_sss_handle {
+    char *domainname;
+    struct passwd *pw;
+    void *ssslib;
+    sss_sudo_send_recv_t fn_send_recv;
+    sss_sudo_send_recv_defaults_t fn_send_recv_defaults;
+    sss_sudo_free_result_t fn_free_result;
+    sss_sudo_get_values_t fn_get_values;
+    sss_sudo_free_values_t fn_free_values;
+};
+
+static int sudo_sss_open(struct sudo_nss *nss);
+static int sudo_sss_close(struct sudo_nss *nss);
+static int sudo_sss_parse(struct sudo_nss *nss);
+static void sudo_sss_parse_options(struct sudo_sss_handle *handle,
+				   struct sss_sudo_rule *rule);
+static int sudo_sss_setdefs(struct sudo_nss *nss);
+static int sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag);
+static int sudo_sss_display_cmnd(struct sudo_nss *nss, struct passwd *pw);
+static int sudo_sss_display_defaults(struct sudo_nss *nss, struct passwd *pw,
+				     struct lbuf *lbuf);
+
+static int sudo_sss_display_bound_defaults(struct sudo_nss *nss,
+					   struct passwd *pw, struct lbuf *lbuf);
+
+static int sudo_sss_display_privs(struct sudo_nss *nss, struct passwd *pw,
+				  struct lbuf *lbuf);
+
+
+static struct sss_sudo_result *sudo_sss_result_get(struct sudo_nss *nss,
+						   struct passwd *pw,
+						   uint32_t *state);
+
+static void
+sudo_sss_attrcpy(struct sss_sudo_attr *dst, const struct sss_sudo_attr *src)
+{
+     int i;
+     debug_decl(sudo_sss_attrcpy, SUDO_DEBUG_SSSD)
+
+     sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
+     sudo_debug_printf(SUDO_DEBUG_INFO, "emalloc: cnt=%d", src->num_values);
+
+     dst->name = estrdup(src->name);
+     dst->num_values = src->num_values;
+     dst->values = emalloc2(dst->num_values, sizeof(char *));
+
+     for (i = 0; i < dst->num_values; ++i)
+	  dst->values[i] = estrdup(src->values[i]);
+
+     return;
+}
+
+static void
+sudo_sss_rulecpy(struct sss_sudo_rule *dst, const struct sss_sudo_rule *src)
+{
+     int i;
+     debug_decl(sudo_sss_rulecpy, SUDO_DEBUG_SSSD)
+
+     sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
+     sudo_debug_printf(SUDO_DEBUG_INFO, "emalloc: cnt=%d", src->num_attrs);
+
+     dst->num_attrs = src->num_attrs;
+     dst->attrs = emalloc2(dst->num_attrs, sizeof(struct sss_sudo_attr));
+
+     for (i = 0; i < dst->num_attrs; ++i)
+	  sudo_sss_attrcpy(dst->attrs + i, src->attrs + i);
+
+     return;
+}
+
+#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_sudo_result *
+sudo_sss_filter_result(struct sudo_sss_handle *handle,
+    struct sss_sudo_result *in_res,
+    int (*filterp)(struct sudo_sss_handle *, struct sss_sudo_rule *, void *),
+    int act, void *filterp_arg)
+{
+    struct sss_sudo_result *out_res;
+    int i, l, r;
+    debug_decl(sudo_sss_filter_result, SUDO_DEBUG_SSSD)
+
+    sudo_debug_printf(SUDO_DEBUG_DEBUG, "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);
+
+    sudo_debug_printf(SUDO_DEBUG_DEBUG, "emalloc: cnt=%d", in_res->num_rules);
+
+    out_res = emalloc(sizeof(struct sss_sudo_result));
+    out_res->rules = in_res->num_rules > 0 ?
+	emalloc2(in_res->num_rules, sizeof(struct sss_sudo_rule)) : NULL;
+    out_res->num_rules = 0;
+
+    for (i = l = 0; i < in_res->num_rules; ++i) {
+	 r = filterp(handle, in_res->rules + i, filterp_arg);
+
+	 if (( r && act == _SUDO_SSS_FILTER_INCLUDE) ||
+	     (!r && act == _SUDO_SSS_FILTER_EXCLUDE)) {
+	    sudo_debug_printf(SUDO_DEBUG_DEBUG,
+		"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_sss_rulecpy(out_res->rules + l, in_res->rules + i);
+	    ++l;
+	}
+    }
+
+    if (l < in_res->num_rules) {
+	sudo_debug_printf(SUDO_DEBUG_DEBUG,
+	    "reallocating result: %p (count: %u -> %u)", out_res->rules,
+	    in_res->num_rules, l);
+	out_res->rules = erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule));
+    }
+
+    out_res->num_rules = l;
+
+    return(out_res);
+}
+
+struct sudo_nss sudo_nss_sss = {
+    &sudo_nss_sss,
+    NULL,
+    sudo_sss_open,
+    sudo_sss_close,
+    sudo_sss_parse,
+    sudo_sss_setdefs,
+    sudo_sss_lookup,
+    sudo_sss_display_cmnd,
+    sudo_sss_display_defaults,
+    sudo_sss_display_bound_defaults,
+    sudo_sss_display_privs
+};
+
+/* sudo_nss implementation */
+// ok
+static int sudo_sss_open(struct sudo_nss *nss)
+{
+    struct sudo_sss_handle *handle;
+    static const char path[] = _PATH_SSSD_LIB"/libsss_sudo.so";
+    debug_decl(sudo_sss_open, SUDO_DEBUG_SSSD);
+
+    /* Create a handle container. */
+    handle = emalloc(sizeof(struct sudo_sss_handle));
+
+    /* Load symbols */
+    handle->ssslib = dlopen(path, RTLD_LAZY);
+    if (handle->ssslib == NULL) {
+	warningx(_("Unable to dlopen %s: %s"), path, dlerror());
+	warningx(_("Unable to initialize SSS source. Is SSSD installed on your machine?"));
+	return(EFAULT);
+    }
+
+    handle->fn_send_recv = dlsym(handle->ssslib, "sss_sudo_send_recv");
+    if (handle->fn_send_recv == NULL) {
+	warningx(_("unable to find symbol \"%s\" in %s"), path,
+	   "sss_sudo_send_recv");
+	return(EFAULT);
+    }
+
+    handle->fn_send_recv_defaults =
+	dlsym(handle->ssslib, "sss_sudo_send_recv_defaults");
+    if (handle->fn_send_recv_defaults == NULL) {
+	warningx(_("unable to find symbol \"%s\" in %s"), path,
+	   "sss_sudo_send_recv_defaults");
+	return(EFAULT);
+    }
+
+    handle->fn_free_result = dlsym(handle->ssslib, "sss_sudo_free_result");
+    if (handle->fn_free_result == NULL) {
+	warningx(_("unable to find symbol \"%s\" in %s"), path,
+	   "sss_sudo_free_result");
+	return(EFAULT);
+    }
+
+    handle->fn_get_values = dlsym(handle->ssslib, "sss_sudo_get_values");
+    if (handle->fn_get_values == NULL) {
+	warningx(_("unable to find symbol \"%s\" in %s"), path,
+	   "sss_sudo_get_values");
+	return(EFAULT);
+    }
+
+    handle->fn_free_values = dlsym(handle->ssslib, "sss_sudo_free_values");
+    if (handle->fn_free_values == NULL) {
+	warningx(_("unable to find symbol \"%s\" in %s"), path,
+	   "sss_sudo_free_values");
+	return(EFAULT);
+    }
+
+    handle->domainname = NULL;
+    handle->pw = sudo_user.pw;
+    nss->handle = handle;
+
+    sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
+
+    return(0);
+}
+
+// ok
+static int sudo_sss_close(struct sudo_nss *nss)
+{
+    struct sudo_sss_handle *handle;
+    debug_decl(sudo_sss_close, SUDO_DEBUG_SSSD);
+
+    if (nss && nss->handle) {
+	handle = nss->handle;
+	dlclose(handle->ssslib);
+    }
+
+    efree(nss->handle);
+    return(0);
+}
+
+// ok
+static int sudo_sss_parse(struct sudo_nss *nss)
+{
+    debug_decl(sudo_sss_parse, SUDO_DEBUG_SSSD);
+    return(0);
+}
+
+static int sudo_sss_setdefs(struct sudo_nss *nss)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+
+    struct sss_sudo_result *sss_result;
+    struct sss_sudo_rule   *sss_rule;
+    uint32_t sss_error;
+    int i;
+    debug_decl(sudo_sss_setdefs, SUDO_DEBUG_SSSD);
+
+    if (handle == NULL)
+	return(-1);
+
+    sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
+
+    if (handle->fn_send_recv_defaults(handle->pw->pw_uid, handle->pw->pw_name,
+				      &sss_error, &handle->domainname,
+				      &sss_result) != 0) {
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "handle->fn_send_recv_defaults: != 0, sss_error=%u", sss_error);
+	return(-1);
+    }
+
+    if (sss_error == ENOENT) {
+	sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
+	return(-1);
+    } else if(sss_error != 0) {
+	sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
+	return(-1);
+    }
+
+    for (i = 0; i < sss_result->num_rules; ++i) {
+	 sudo_debug_printf(SUDO_DEBUG_DIAG,
+	    "Parsing cn=defaults, %d/%d", i, sss_result->num_rules);
+	 sss_rule = sss_result->rules + i;
+	 sudo_sss_parse_options(handle, sss_rule);
+    }
+
+    handle->fn_free_result(sss_result);
+    return(0);
+}
+
+static int sudo_sss_checkpw(struct sudo_nss *nss, struct passwd *pw)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+    debug_decl(sudo_sss_checkpw, SUDO_DEBUG_SSSD);
+
+    if (pw->pw_name != handle->pw->pw_name ||
+	pw->pw_uid  != handle->pw->pw_uid) {
+	sudo_debug_printf(SUDO_DEBUG_DIAG,
+	    "Requested name or uid don't match the initial once, reinitializing...");
+	handle->pw = pw;
+
+	if (sudo_sss_setdefs(nss) != 0)
+	    return(-1);
+    }
+
+     return(0);
+}
+
+static int
+sudo_sss_check_runas_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *sss_rule)
+{
+    char **val_array = NULL;
+    char *val;
+    int ret = FALSE, i;
+    debug_decl(sudo_sss_check_runas_user, SUDO_DEBUG_SSSD);
+
+    if (!runas_pw)
+	return(UNSPEC);
+
+    /* get the runas user from the entry */
+    switch (handle->fn_get_values(sss_rule, "sudoRunAsUser", &val_array)) {
+    case 0:
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result. Trying old style (sudoRunAs)");
+
+	/* try old style */
+	switch (handle->fn_get_values(sss_rule, "sudoRunAs", &val_array)) {
+	case 0:
+	    break;
+	case ENOENT:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "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:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAs): != 0");
+	    return(UNSPEC);
+	}
+	break;
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_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; val_array[i] != NULL && !ret; ++i) {
+	val = val_array[i];
+
+	sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
+
+	switch (val[0]) {
+	case '+':
+	    sudo_debug_printf(SUDO_DEBUG_DEBUG, "netgr_");
+	    if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) {
+		sudo_debug_printf(SUDO_DEBUG_DEBUG, "=> match");
+		ret = TRUE;
+	    }
+	    break;
+	case '%':
+	    sudo_debug_printf(SUDO_DEBUG_DEBUG, "usergr_");
+	    if (usergr_matches(val, runas_pw->pw_name, runas_pw)) {
+		sudo_debug_printf(SUDO_DEBUG_DEBUG, "=> match");
+		ret = TRUE;
+	    }
+	    break;
+	case 'A':
+	    if (strcmp(val, "ALL") == 0) {
+		sudo_debug_printf(SUDO_DEBUG_DEBUG, "ALL => match");
+		ret = TRUE;
+		break;
+	    }
+	    /* FALLTHROUGH */
+	    sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH");
+	default:
+	    if (strcasecmp(val, runas_pw->pw_name) == 0) {
+		sudo_debug_printf(SUDO_DEBUG_DEBUG,
+		    "%s == %s (pw_name) => match", val, runas_pw->pw_name);
+		ret = TRUE;
+	    }
+	    break;
+	}
+
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "sssd/ldap sudoRunAsUser '%s' ... %s", val, ret ? "MATCH!" : "not");
+    }
+
+    handle->fn_free_values(val_array); /* cleanup */
+
+    return(ret);
+}
+
+static int
+sudo_sss_check_runas_group(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
+{
+    char **val_array = NULL;
+    char *val;
+    int ret = FALSE, i;
+    debug_decl(sudo_sss_check_runas_group, SUDO_DEBUG_SSSD);
+
+    /* runas_gr is only set if the user specified the -g flag */
+    if (!runas_gr)
+	return(UNSPEC);
+
+    /* get the values from the entry */
+    switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) {
+    case 0:
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	return(FALSE);
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "handle->fn_get_values(sudoRunAsGroup): != 0");
+	return(UNSPEC);
+    }
+
+    /* walk through values returned, looking for a match */
+    for (i = 0; val_array[i] != NULL; ++i) {
+	val = val_array[i];
+	sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
+
+	if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr))
+	    ret = TRUE;
+
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "sssd/ldap sudoRunAsGroup '%s' ... %s", val, ret ? "MATCH!" : "not");
+    }
+
+    handle->fn_free_values(val_array);
+
+    return(ret);
+}
+
+/*
+ * Walk through search results and return TRUE if we have a runas match,
+ * else FALSE.  RunAs info is optional.
+ */
+static int
+sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
+{
+    int ret;
+    debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD);
+
+    if (rule == NULL)
+	 return(FALSE);
+
+    ret = sudo_sss_check_runas_user(handle, rule) != FALSE &&
+	 sudo_sss_check_runas_group(handle, rule) != FALSE;
+
+    return(ret);
+}
+
+static int
+sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
+{
+    char **val_array, *val;
+    int ret = FALSE, i;
+    debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD);
+
+    if (rule == NULL)
+	return(ret);
+
+    /* get the values from the rule */
+    switch (handle->fn_get_values(rule, "sudoHost", &val_array))
+    {
+    case 0:
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	return(FALSE);
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0");
+	return(ret);
+    }
+
+    /* walk through values */
+    for (i = 0; val_array[i] != NULL; ++i) {
+	val = val_array[i];
+	sudo_debug_printf(SUDO_DEBUG_DEBUG, "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;
+
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "sssd/ldap sudoHost '%s' ... %s", val, ret ? "MATCH!" : "not");
+    }
+
+    handle->fn_free_values(val_array);
+
+    return(ret);
+}
+
+static int
+sudo_sss_result_filterp(struct sudo_sss_handle *handle,
+    struct sss_sudo_rule *rule, void *unused)
+{
+    (void)unused;
+    debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD);
+
+    if (sudo_sss_check_host(handle, rule))
+	return(1);
+    else
+	return(0);
+}
+
+static struct sss_sudo_result *
+sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw, uint32_t *state)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+    struct sss_sudo_result *u_sss_result, *f_sss_result;
+    uint32_t sss_error = 0, ret;
+    debug_decl(sudo_sss_result_get, SUDO_DEBUG_SSSD);
+
+    if (sudo_sss_checkpw(nss, pw) != 0)
+	return(NULL);
+
+    sudo_debug_printf(SUDO_DEBUG_DIAG, "  username=%s", handle->pw->pw_name);
+    sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s", handle->domainname);
+
+    u_sss_result = f_sss_result = NULL;
+
+    ret = handle->fn_send_recv(handle->pw->pw_uid, handle->pw->pw_name,
+	handle->domainname, &sss_error, &u_sss_result);
+
+    switch (ret) {
+    case 0:
+	switch (sss_error) {
+	case 0:
+	    if (u_sss_result != NULL) {
+		if (state != NULL) {
+		    sudo_debug_printf(SUDO_DEBUG_DEBUG, "state |= USERMATCH");
+		    *state |= _SUDO_SSS_STATE_USERMATCH;
+		}
+		sudo_debug_printf(SUDO_DEBUG_INFO, "Received %u rule(s)",
+		    u_sss_result->num_rules);
+	    } else {
+		sudo_debug_printf(SUDO_DEBUG_INFO,
+		    "Internal error: u_sss_result == NULL && sss_error == 0");
+		return(NULL);
+	    }
+	    break;
+	case ENOENT:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
+	default:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
+	    return(NULL);
+	}
+	break;
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "handle->fn_send_recv: != 0: ret=%d", ret);
+	return(NULL);
+    }
+
+    f_sss_result = sudo_sss_filter_result(handle, u_sss_result,
+	sudo_sss_result_filterp, _SUDO_SSS_FILTER_INCLUDE, NULL);
+
+    if (f_sss_result != NULL) {
+	if (f_sss_result->num_rules > 0) {
+	    if (state != NULL) {
+		sudo_debug_printf(SUDO_DEBUG_DEBUG, "state |= HOSTMATCH");
+		*state |= _SUDO_SSS_STATE_HOSTMATCH;
+	    }
+	}
+    }
+
+    sudo_debug_printf(SUDO_DEBUG_DEBUG,
+	"u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result,
+	u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules);
+
+    handle->fn_free_result(u_sss_result);
+
+    return(f_sss_result);
+}
+
+/*
+ * Search for boolean "option" in sudoOption.
+ * Returns TRUE if found and allowed, FALSE if negated, else UNSPEC.
+ */
+static int
+sudo_sss_check_bool(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule,
+    char *option)
+{
+    char ch, *var, **val_array = NULL;
+    int i, ret = UNSPEC;
+    debug_decl(sudo_sss_check_bool, SUDO_DEBUG_SSSD);
+
+    if (rule == NULL)
+	return(ret);
+
+    switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
+    case 0:
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	return(ret);
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values: != 0");
+	return(ret);
+    }
+
+    /* walk through options */
+    for (i = 0; val_array[i] != NULL; ++i) {
+	var = val_array[i];
+	sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'", var);
+
+	if ((ch = *var) == '!')
+	    var++;
+	if (strcmp(var, option) == 0)
+	    ret = (ch != '!');
+    }
+
+    handle->fn_free_values(val_array);
+
+    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_sss_check_command(struct sudo_sss_handle *handle,
+    struct sss_sudo_rule *rule, int *setenv_implied)
+{
+    char **val_array = NULL, *val;
+    char *allowed_cmnd, *allowed_args;
+    int i, foundbang, ret = UNSPEC;
+    debug_decl(sudo_sss_check_command, SUDO_DEBUG_SSSD);
+
+    if (rule == NULL)
+	return(ret);
+
+    switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) {
+    case 0:
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	return(ret);
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values: != 0");
+	return(ret);
+    }
+
+    for (i = 0; val_array[i] != NULL && ret != FALSE; ++i) {
+	val = val_array[i];
+
+	sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
+
+	/* Match against ALL ? */
+	if (!strcmp(val, "ALL")) {
+	    ret = TRUE;
+	    if (setenv_implied != NULL)
+		*setenv_implied = TRUE;
+	    sudo_debug_printf(SUDO_DEBUG_INFO,
+		"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;
+	}
+
+	sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoCommand '%s' ... %s",
+	    val, ret == TRUE ? "MATCH!" : "not");
+	efree(allowed_cmnd);	/* cleanup */
+    }
+
+    handle->fn_free_values(val_array); /* more cleanup */
+
+    return(ret);
+}
+
+static void
+sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
+{
+    int i;
+    char op, *v, *val;
+    char **val_array = NULL;
+    debug_decl(sudo_sss_parse_options, SUDO_DEBUG_SSSD);
+
+    if (rule == NULL)
+	return;
+
+    switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
+    case 0:
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	return;
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0");
+	return;
+    }
+
+    /* walk through options */
+    for (i = 0; val_array[i] != NULL; i++) {
+	sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoOption: '%s'",
+	 val_array[i]);
+	v = estrdup(val_array[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);
+    }
+
+    handle->fn_free_values(val_array);
+    return;
+}
+
+static int
+sudo_sss_lookup(struct sudo_nss *nss, int ret, int pwflag)
+{
+    int rc, setenv_implied;
+
+    struct sudo_sss_handle *handle = nss->handle;
+    struct sss_sudo_result *sss_result = NULL;
+    struct sss_sudo_rule   *rule;
+    uint32_t i, state = 0;
+    debug_decl(sudo_sss_lookup, SUDO_DEBUG_SSSD);
+
+    /* Fetch list of sudoRole entries that match user and host. */
+    sss_result = sudo_sss_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_tupple pwcheck =
+	    (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
+
+	sudo_debug_printf(SUDO_DEBUG_INFO, "perform search for pwflag %d", pwflag);
+	if (sss_result != NULL) {
+	    for (i = 0; i < sss_result->num_rules; i++) {
+		rule = sss_result->rules + i;
+		if ((pwcheck == any && doauth != FALSE) ||
+		    (pwcheck == all && doauth == FALSE)) {
+		    doauth = sudo_sss_check_bool(handle, rule, "authenticate");
+		}
+		/* Only check the command when listing another user. */
+		if (user_uid == 0 || list_pw == NULL ||
+		    user_uid == list_pw->pw_uid ||
+		    sudo_sss_check_command(handle, rule, NULL)) {
+		    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;
+    }
+
+    sudo_debug_printf(SUDO_DEBUG_DIAG,
+	"searching SSSD/LDAP for sudoers entries");
+
+    setenv_implied = FALSE;
+    if (sss_result != NULL) {
+	for (i = 0; i < sss_result->num_rules; i++) {
+	    rule = sss_result->rules + i;
+	    if (!sudo_sss_check_runas(handle, rule))
+		continue;
+	    rc = sudo_sss_check_command(handle, rule, &setenv_implied);
+	    if (rc != UNSPEC) {
+		/* We have a match. */
+		sudo_debug_printf(SUDO_DEBUG_DIAG, "Command %sallowed",
+		    rc == TRUE ? "" : "NOT ");
+		if (rc == TRUE) {
+		    sudo_debug_printf(SUDO_DEBUG_DEBUG, "SSSD rule: %p", rule);
+		    /* Apply entry-specific options. */
+		    if (setenv_implied)
+			def_setenv = TRUE;
+		    sudo_sss_parse_options(handle, 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:
+    sudo_debug_printf(SUDO_DEBUG_DIAG, "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);
+
+    sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_sss_lwwookup(%d)=0x%02x",
+     pwflag, ret);
+
+    return(ret);
+}
+
+static int
+sudo_sss_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+    struct sss_sudo_result *sss_result = NULL;
+    struct sss_sudo_rule *rule;
+    int i, found = FALSE;
+    debug_decl(sudo_sss_display_cmnd, SUDO_DEBUG_SSSD);
+
+    if (handle == NULL)
+	goto done;
+
+    if (sudo_sss_checkpw(nss, pw) != 0)
+	return(-1);
+
+    /*
+     * The sudo_sss_result_get() function returns all nodes that match
+     * the user and the host.
+     */
+    sudo_debug_printf(SUDO_DEBUG_DIAG, "sssd/ldap search for command list");
+    sss_result = sudo_sss_result_get(nss, pw, NULL);
+
+    if (sss_result == NULL)
+	goto done;
+
+    for (i = 0; i < sss_result->num_rules; i++) {
+	rule = sss_result->rules + i;
+	if (sudo_sss_check_command(handle, rule, NULL) &&
+	    sudo_sss_check_runas(handle, 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 (sss_result != NULL)
+	handle->fn_free_result(sss_result);
+
+    return(!found);
+}
+
+static int
+sudo_sss_display_defaults(struct sudo_nss *nss, struct passwd *pw,
+    struct lbuf *lbuf)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+
+    struct sss_sudo_rule *rule;
+    struct sss_sudo_result *sss_result = NULL;
+
+    uint32_t sss_error = 0;
+
+    char *prefix, *val, **val_array = NULL;
+    int count = 0, i, j;
+
+    debug_decl(sudo_sss_display_defaults, SUDO_DEBUG_SSSD);
+
+    if (handle == NULL)
+	goto done;
+
+    if (handle->fn_send_recv_defaults(pw->pw_uid, pw->pw_name,
+				    &sss_error, &handle->domainname,
+				    &sss_result) != 0) {
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_send_recv_defaults: !=0, sss_error=%u", sss_error);
+	goto done;
+    }
+
+    if (sss_error == ENOENT) {
+	sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
+	goto done;
+    } else if(sss_error != 0) {
+	sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
+	goto done;
+    }
+
+    handle->pw = pw;
+
+    for (i = 0; i < sss_result->num_rules; ++i) {
+	rule = sss_result->rules + i;
+
+	switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
+	case 0:
+	    break;
+	case ENOENT:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	    continue;
+	default:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values: != 0");
+	    continue;
+	}
+
+	if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
+	    prefix = "    ";
+	else
+	    prefix = ", ";
+
+	for (j = 0; val_array[j] != NULL; ++j) {
+	    val = val_array[j];
+	    lbuf_append(lbuf, prefix, val, NULL);
+	    prefix = ", ";
+	    count++;
+	}
+
+	handle->fn_free_values(val_array);
+	val_array = NULL;
+    }
+
+    handle->fn_free_result(sss_result);
+done:
+    return(count);
+}
+
+// ok
+static int
+sudo_sss_display_bound_defaults(struct sudo_nss *nss,
+    struct passwd *pw, struct lbuf *lbuf)
+{
+    debug_decl(sudo_sss_display_bound_defaults, SUDO_DEBUG_SSSD);
+    return(0);
+}
+
+static int
+sudo_sss_display_entry_long(struct sudo_sss_handle *handle,
+    struct sss_sudo_rule *rule, struct lbuf *lbuf)
+{
+    char **val_array = NULL;
+    int count = 0, i;
+    debug_decl(sudo_sss_display_entry_long, SUDO_DEBUG_SSSD);
+
+    /* get the RunAsUser Values from the entry */
+    lbuf_append(lbuf, "    RunAsUsers: ", NULL);
+    switch (handle->fn_get_values(rule, "sudoRunAsUser", &val_array)) {
+    case 0:
+	for (i = 0; val_array[i] != NULL; ++i)
+	    lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	handle->fn_free_values(val_array);
+	break;
+    case ENOENT:
+	switch (handle->fn_get_values(rule, "sudoRunAs", &val_array)) {
+	case 0:
+	    for (i = 0; val_array[i] != NULL; ++i)
+		 lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	    handle->fn_free_values(val_array);
+	    break;
+	case ENOENT:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	    lbuf_append(lbuf, def_runas_default, NULL);
+	    break;
+	default:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAs): != 0");
+	    return(count);
+	}
+	break;
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoRunAsUser): != 0");
+	return(count);
+    }
+    lbuf_append(lbuf, "\n", NULL);
+
+    /* get the RunAsGroup Values from the entry */
+    switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) {
+    case 0:
+	lbuf_append(lbuf, "    RunAsGroups: ", NULL);
+	for (i = 0; val_array[i] != NULL; ++i)
+	     lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	handle->fn_free_values(val_array);
+	lbuf_append(lbuf, "\n", NULL);
+	break;
+    case ENOENT:
+	sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	break;
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "handle->fn_get_values(sudoRunAsGroup): != 0");
+	return(count);
+    }
+
+    /* get the Option Values from the entry */
+    switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
+    case 0:
+	lbuf_append(lbuf, "    Options: ", NULL);
+	for (i = 0; val_array[i] != NULL; ++i)
+	     lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	handle->fn_free_values(val_array);
+	lbuf_append(lbuf, "\n", NULL);
+	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");
+	return(count);
+    }
+
+    /* Get the command values from the entry. */
+    switch (handle->fn_get_values(rule, "sudoCommand", &val_array)) {
+    case 0:
+	lbuf_append(lbuf, _("    Commands:\n"), NULL);
+	for (i = 0; val_array[i] != NULL; ++i) {
+	     lbuf_append(lbuf, "\t", val_array[i], "\n", NULL);
+	     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");
+	return(count);
+    }
+
+    return(count);
+}
+
+static int
+sudo_sss_display_entry_short(struct sudo_sss_handle *handle,
+    struct sss_sudo_rule *rule, struct lbuf *lbuf)
+{
+    char **val_array = NULL;
+    int count = 0, i;
+    debug_decl(sudo_sss_display_entry_short, SUDO_DEBUG_SSSD);
+
+    lbuf_append(lbuf, "    (", NULL);
+
+    /* 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)
+	     lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	handle->fn_free_values(val_array);
+	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)
+		 lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	    handle->fn_free_values(val_array);
+	    break;
+	case ENOENT:
+	    sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+	    lbuf_append(lbuf, def_runas_default, NULL);
+	    break;
+	default:
+	    sudo_debug_printf(SUDO_DEBUG_INFO,
+		"handle->fn_get_values(sudoRunAs): != 0");
+	    return(count);
+	}
+	break;
+    default:
+	sudo_debug_printf(SUDO_DEBUG_INFO,
+	    "handle->fn_get_values(sudoRunAsUser): != 0");
+	return(count);
+    }
+
+    /* get the RunAsGroup Values from the entry */
+    switch (handle->fn_get_values(rule, "sudoRunAsGroup", &val_array)) {
+    case 0:
+	lbuf_append(lbuf, " : ", NULL);
+	for (i = 0; val_array[i] != NULL; ++i)
+	     lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	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(sudoRunAsGroup): != 0");
+	return(count);
+    }
+
+    lbuf_append(lbuf, ") ", NULL);
+
+    /* 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 *cp = val_array[i];
+	    if (*cp == '!')
+		cp++;
+	    if (strcmp(cp, "authenticate") == 0)
+		lbuf_append(lbuf, val_array[i][0] == '!' ?
+			    "NOPASSWD: " : "PASSWD: ", NULL);
+	    else if (strcmp(cp, "noexec") == 0)
+		lbuf_append(lbuf, val_array[i][0] == '!' ?
+			    "EXEC: " : "NOEXEC: ", NULL);
+	    else if (strcmp(cp, "setenv") == 0)
+		lbuf_append(lbuf, val_array[i][0] == '!' ?
+			    "NOSETENV: " : "SETENV: ", NULL);
+	}
+	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");
+	return(count);
+    }
+
+    /* 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) {
+	    lbuf_append(lbuf, i != 0 ? ", " : "", val_array[i], NULL);
+	    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");
+	return(count);
+    }
+    lbuf_append(lbuf, "\n", NULL);
+
+    return(count);
+}
+
+static int
+sudo_sss_display_privs(struct sudo_nss *nss, struct passwd *pw,
+    struct lbuf *lbuf)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+
+    struct sss_sudo_result *sss_result = NULL;
+    struct sss_sudo_rule *rule;
+    unsigned int i, count = 0;
+    debug_decl(sudo_sss_display_privs, SUDO_DEBUG_SSSD);
+
+    if (handle == NULL)
+	return(-1);
+    if (sudo_sss_checkpw(nss, pw) != 0)
+	return(-1);
+
+    sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap search for command list");
+
+    sss_result = sudo_sss_result_get(nss, pw, NULL);
+
+    if (sss_result == NULL)
+	return(count);
+
+    /* 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, lbuf);
+	else
+	    count += sudo_sss_display_entry_short(handle, rule, lbuf);
+    }
+
+    if (sss_result != NULL)
+	handle->fn_free_result(sss_result);
+
+    return(count);
+}
Index: sudo-1.7.6p2/sudo_nss.c
===================================================================
--- sudo-1.7.6p2.orig/sudo_nss.c	2011-02-14 17:29:22.000000000 +0100
+++ sudo-1.7.6p2/sudo_nss.c	2013-03-27 11:27:33.729009953 +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_sss;
+#endif
 
-#if defined(HAVE_LDAP) && defined(_PATH_NSSWITCH_CONF)
+#if (defined(HAVE_LDAP) || defined(HAVE_SSSD)) && defined(_PATH_NSSWITCH_CONF)
 /*
  * Read in /etc/nsswitch.conf
  * Returns a tail queue of matches.
@@ -58,6 +61,9 @@ sudo_read_nss()
 {
     FILE *fp;
     char *cp;
+#ifdef HAVE_SSSD
+    int saw_sss = FALSE;
+#endif
     int saw_files = FALSE;
     int saw_ldap = FALSE;
     int got_match = FALSE;
@@ -83,6 +89,11 @@ sudo_read_nss()
 	    } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) {
 		tq_append(&snl, &sudo_nss_ldap);
 		got_match = TRUE;
+#ifdef HAVE_SSSD
+	    } else if (strcasecmp(cp, "sss") == 0 && !saw_sss) {
+		tq_append(&snl, &sudo_nss_sss);
+		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;
@@ -103,9 +114,9 @@ nomatch:
     return &snl;
 }
 
-#else /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
+#else /* (HAVE_LDAP || HAVE_SSSD) && _PATH_NSSWITCH_CONF */
 
-# if defined(HAVE_LDAP) && defined(_PATH_NETSVC_CONF)
+# if (defined(HAVE_LDAP) || defined(HAVE_SSSD)) && defined(_PATH_NETSVC_CONF)
 
 /*
  * Read in /etc/netsvc.conf (like nsswitch.conf on AIX)
@@ -116,6 +127,9 @@ sudo_read_nss()
 {
     FILE *fp;
     char *cp, *ep;
+#ifdef HAVE_SSSD
+    int saw_sss = FALSE;
+#endif
     int saw_files = FALSE;
     int saw_ldap = FALSE;
     int got_match = FALSE;
@@ -154,6 +168,13 @@ sudo_read_nss()
 		tq_append(&snl, &sudo_nss_ldap);
 		got_match = TRUE;
 		ep = &cp[4];
+#ifdef HAVE_SSSD
+	    } else if (!saw_sss && strncasecmp(cp, "sss", 3) == 0 &&
+		(isspace((unsigned char)cp[3]) || cp[3] == '\0')) {
+		tq_append(&snl, &sudo_nss_sss);
+		got_match = TRUE;
+		ep = &cp[3];
+#endif
 	    } else {
 		got_match = FALSE;
 	    }
@@ -192,6 +213,9 @@ sudo_read_nss()
 {
     static struct sudo_nss_list snl;
 
+#  ifdef HAVE_SSSD
+    tq_append(&snl, &sudo_nss_sss);
+#  endif
 #  ifdef HAVE_LDAP
     tq_append(&snl, &sudo_nss_ldap);
 #  endif
Index: sudo-1.7.6p2/sudo.c
===================================================================
--- sudo-1.7.6p2.orig/sudo.c	2011-03-16 21:01:00.000000000 +0100
+++ sudo-1.7.6p2/sudo.c	2013-03-27 11:27:54.090614900 +0100
@@ -167,6 +167,7 @@ main(argc, argv, envp)
     int fd, cmnd_status, pwflag, rc = 0;
     sigaction_t sa;
     struct sudo_nss *nss;
+    struct sudo_nss *nss_next;
 #if defined(SUDO_DEVEL) && defined(__OpenBSD__)
     extern char *malloc_options;
     malloc_options = "AFGJPR";
@@ -277,13 +278,16 @@ main(argc, argv, envp)
     snl = sudo_read_nss();
 
     /* Open and parse sudoers, set global defaults */
-    tq_foreach_fwd(snl, nss) {
-	if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
-	    sources++;
-	    if (nss->setdefs(nss) != 0)
+    for (nss = snl->first; nss != NULL; nss = nss_next) {
+        nss_next = nss->next;
+        if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
+            sources++;
+            if (nss->setdefs(nss) != 0)
 		log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
-	}
-    }
+        } else {
+            tq_remove(snl, nss);
+        }
+     }
     if (sources == 0)
 	log_error(0, "no valid sudoers sources found, quitting");
 
Index: sudo-1.7.6p2/Makefile.in
===================================================================
--- sudo-1.7.6p2.orig/Makefile.in	2011-03-29 21:25:56.000000000 +0200
+++ sudo-1.7.6p2/Makefile.in	2013-03-27 11:27:33.730009982 +0100
@@ -111,7 +111,7 @@ SRCS = aix.c alias.c alloc.c audit.c boo
        getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y interfaces.c \
        iolog.c isblank.c lbuf.c ldap.c linux_audit.c list.c logging.c match.c \
        mksiglist.c mkstemps.c memrchr.c nanosleep.c parse.c parse_args.c \
-       pwutil.c set_perms.c setsid.c sigaction.c snprintf.c strcasecmp.c \
+       pwutil.c set_perms.c setsid.c sigaction.c snprintf.c sssd.c strcasecmp.c \
        strerror.c strlcat.c strlcpy.c strsignal.c sudo.c sudo_noexec.c \
        sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l \
        toke_util.c tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \
@@ -361,6 +361,8 @@ siglist.o: siglist.c $(srcdir)/missing.h
 	$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/siglist.c
 snprintf.o: $(srcdir)/snprintf.c $(srcdir)/missing.h config.h
 	$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/snprintf.c
+sssd.o: $(srcdir)/sssd.c $(SUDODEP) $(srcdir)/lbuf.h $(srcdir)/list.h $(srcdir)/sudo.h
+	$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sssd.c
 strcasecmp.o: $(srcdir)/strcasecmp.c $(srcdir)/missing.h  config.h
 	$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strcasecmp.c
 strerror.o: $(srcdir)/strerror.c $(srcdir)/missing.h config.h
Index: sudo-1.7.6p2/config.h.in
===================================================================
--- sudo-1.7.6p2.orig/config.h.in	2011-02-19 14:18:06.000000000 +0100
+++ sudo-1.7.6p2/config.h.in	2013-03-27 11:27:54.090614900 +0100
@@ -262,6 +262,9 @@
 /* Define to 1 if you use LDAP for sudoers. */
 #undef HAVE_LDAP
 
+/* Define to 1 if you use SSSD for sudoers. */
+#undef HAVE_SSSD
+
 /* Define to 1 if you have the `ldapssl_init' function. */
 #undef HAVE_LDAPSSL_INIT
 
