typedef void (*sss_sudo_free_values_t)(char**);
-/* sudo_nss implementation */
-
+/* sudo_nss handle */
struct sudo_sss_handle {
char *domainname;
char *ipa_host;
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 int sudo_sss_getdefs(struct sudo_nss *nss);
-static int sudo_sss_query(struct sudo_nss *nss, struct passwd *pw);
-
-static bool sudo_sss_parse_options(struct sudo_sss_handle *handle,
- struct sss_sudo_rule *rule,
- struct defaults_list *defs);
-
-
-static struct sss_sudo_result *sudo_sss_result_get(struct sudo_nss *nss,
- struct passwd *pw);
-
-static bool sss_to_sudoers(struct sudo_sss_handle *handle,
- struct sss_sudo_result *sss_result,
- struct userspec_list *sss_userspecs);
-
static int
get_ipa_hostname(char **shostp, char **lhostp)
{
debug_return_int(ret);
}
-struct sudo_nss sudo_nss_sss = {
- { NULL, NULL },
- sudo_sss_open,
- sudo_sss_close,
- sudo_sss_parse,
- sudo_sss_query,
- sudo_sss_getdefs
-};
-
-/* 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, SUDOERS_DEBUG_SSSD);
-
- /* Create a handle container. */
- handle = calloc(1, sizeof(struct sudo_sss_handle));
- if (handle == NULL) {
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
- debug_return_int(ENOMEM);
- }
-
- /* Load symbols */
- handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
- if (handle->ssslib == NULL) {
- const char *errstr = sudo_dso_strerror();
- sudo_warnx(U_("unable to load %s: %s"), path,
- errstr ? errstr : "unknown error");
- sudo_warnx(U_("unable to initialize SSS source. Is SSSD installed on your machine?"));
- free(handle);
- debug_return_int(EFAULT);
- }
-
- handle->fn_send_recv =
- sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv");
- if (handle->fn_send_recv == NULL) {
- sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
- "sss_sudo_send_recv");
- free(handle);
- debug_return_int(EFAULT);
- }
-
- handle->fn_send_recv_defaults =
- sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults");
- if (handle->fn_send_recv_defaults == NULL) {
- sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
- "sss_sudo_send_recv_defaults");
- free(handle);
- debug_return_int(EFAULT);
- }
-
- handle->fn_free_result =
- sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result");
- if (handle->fn_free_result == NULL) {
- sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
- "sss_sudo_free_result");
- free(handle);
- debug_return_int(EFAULT);
- }
-
- handle->fn_get_values =
- sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values");
- if (handle->fn_get_values == NULL) {
- sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
- "sss_sudo_get_values");
- free(handle);
- debug_return_int(EFAULT);
- }
-
- handle->fn_free_values =
- sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values");
- if (handle->fn_free_values == NULL) {
- sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
- "sss_sudo_free_values");
- free(handle);
- debug_return_int(EFAULT);
- }
-
- nss->handle = handle;
-
- /*
- * If runhost is the same as the local host, check for ipa_hostname
- * in sssd.conf and use it in preference to user_runhost.
- */
- if (strcasecmp(user_runhost, user_host) == 0) {
- if (get_ipa_hostname(&handle->ipa_shost, &handle->ipa_host) == -1) {
- free(handle);
- debug_return_int(ENOMEM);
- }
- }
-
- sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
-
- debug_return_int(0);
-}
-
-// ok
-static int
-sudo_sss_close(struct sudo_nss *nss)
-{
- struct sudo_sss_handle *handle;
- debug_decl(sudo_sss_close, SUDOERS_DEBUG_SSSD);
-
- if (nss && nss->handle) {
- handle = nss->handle;
- sudo_dso_unload(handle->ssslib);
- if (handle->pw != NULL)
- sudo_pw_delref(handle->pw);
- free(handle->ipa_host);
- if (handle->ipa_host != handle->ipa_shost)
- free(handle->ipa_shost);
- free(handle);
- nss->handle = NULL;
-
- /* XXX - do in main module? */
- free_userspecs(&nss->userspecs);
- free_defaults(&nss->defaults);
- }
- debug_return_int(0);
-}
-
-/*
- * Perform query for user and host and convert to sudoers parse tree.
- */
-static int
-sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
-{
- struct sudo_sss_handle *handle = nss->handle;
- struct sss_sudo_result *sss_result = NULL;
- int ret = 0;
- debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
-
- /* Use cached result if it matches pw. */
- if (handle->pw != NULL) {
- if (pw == handle->pw)
- goto done;
- sudo_pw_delref(handle->pw);
- handle->pw = NULL;
- }
-
- /* Free old userspecs, if any. */
- free_userspecs(&nss->userspecs);
-
- /* Fetch list of sudoRole entries that match user and host. */
- sss_result = sudo_sss_result_get(nss, pw);
-
- sudo_debug_printf(SUDO_DEBUG_DIAG,
- "searching SSSD/LDAP for sudoers entries for user %s, host %s",
- pw->pw_name, user_runhost);
-
- if (sss_result == NULL)
- goto done;
-
- /* Stash a ref to the passwd struct in the handle. */
- sudo_pw_addref(pw);
- handle->pw = pw;
-
- /* Convert to sudoers parse tree. */
- if (!sss_to_sudoers(handle, sss_result, &nss->userspecs)) {
- ret = -1;
- goto done;
- }
-
-done:
- /* Cleanup */
- handle->fn_free_result(sss_result);
- if (ret == -1) {
- free_userspecs(&nss->userspecs);
- sudo_pw_delref(handle->pw);
- handle->pw = NULL;
- }
-
- sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
-
- debug_return_int(ret);
-}
-
-// ok
-static int
-sudo_sss_parse(struct sudo_nss *nss)
-{
- debug_decl(sudo_sss_parse, SUDOERS_DEBUG_SSSD);
- debug_return_int(0);
-}
-
-static int
-sudo_sss_getdefs(struct sudo_nss *nss)
-{
- struct sudo_sss_handle *handle = nss->handle;
- struct sss_sudo_result *sss_result = NULL;
- struct sss_sudo_rule *sss_rule;
- uint32_t sss_error;
- unsigned int i;
- int rc;
- debug_decl(sudo_sss_getdefs, SUDOERS_DEBUG_SSSD);
-
- if (handle == NULL)
- debug_return_int(-1);
-
- /* Free old defaults, if any. */
- free_defaults(&nss->defaults);
-
- sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
-
- /* NOTE: these are global defaults, user ID and name are not used. */
- rc = handle->fn_send_recv_defaults(sudo_user.pw->pw_uid,
- sudo_user.pw->pw_name, &sss_error, &handle->domainname, &sss_result);
- switch (rc) {
- case 0:
- break;
- case ENOMEM:
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
- /* FALLTHROUGH */
- default:
- sudo_debug_printf(SUDO_DEBUG_INFO,
- "handle->fn_send_recv_defaults: rc=%d, sss_error=%u", rc, sss_error);
- debug_return_int(-1);
- }
- if (sss_error != 0) {
- if (sss_error == ENOENT) {
- sudo_debug_printf(SUDO_DEBUG_INFO,
- "The user was not found in SSSD.");
- goto done;
- }
- sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
- goto bad;
- }
-
- 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;
- if (!sudo_sss_parse_options(handle, sss_rule, &nss->defaults))
- goto bad;
- }
-
-done:
- handle->fn_free_result(sss_result);
- debug_return_int(0);
-bad:
- handle->fn_free_result(sss_result);
- debug_return_int(-1);
-}
-
/*
* SSSD doesn't handle netgroups, we have to ensure they are correctly filtered
* in sudo. The rules may contain mixed sudoUser specification so we have to
debug_return_bool(ret);
}
-static struct sss_sudo_result *
-sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw)
-{
- struct sudo_sss_handle *handle = nss->handle;
- struct sss_sudo_result *sss_result = NULL;
- uint32_t sss_error = 0, rc;
- debug_decl(sudo_sss_result_get, SUDOERS_DEBUG_SSSD);
-
- sudo_debug_printf(SUDO_DEBUG_DIAG, " username=%s", pw->pw_name);
- sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s",
- handle->domainname ? handle->domainname : "NULL");
-
- rc = handle->fn_send_recv(pw->pw_uid, pw->pw_name,
- handle->domainname, &sss_error, &sss_result);
- switch (rc) {
- case 0:
- switch (sss_error) {
- case 0:
- if (sss_result != NULL) {
- sudo_debug_printf(SUDO_DEBUG_INFO, "Received %u rule(s)",
- sss_result->num_rules);
- } else {
- sudo_debug_printf(SUDO_DEBUG_INFO,
- "Internal error: sss_result == NULL && sss_error == 0");
- debug_return_ptr(NULL);
- }
- break;
- case ENOENT:
- sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
- debug_return_ptr(NULL);
- default:
- sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
- debug_return_ptr(NULL);
- }
- break;
- case ENOMEM:
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
- /* FALLTHROUGH */
- default:
- sudo_debug_printf(SUDO_DEBUG_INFO,
- "handle->fn_send_recv: rc=%d", rc);
- debug_return_ptr(NULL);
- }
-
- debug_return_ptr(sss_result);
-}
-
-static bool
-sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule, struct defaults_list *defs)
-{
- int i;
- char *source = NULL;
- bool ret = false;
- char **val_array = NULL;
- char **cn_array = NULL;
- debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD);
-
- if (rule == NULL)
- debug_return_bool(true);
-
- switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
- case 0:
- break;
- case ENOENT:
- sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
- debug_return_bool(true);
- case ENOMEM:
- goto oom;
- default:
- sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0");
- debug_return_bool(false);
- }
-
- /* Use sudoRole in place of file name in defaults. */
- if (handle->fn_get_values(rule, "cn", &cn_array) == 0) {
- if (cn_array[0] != NULL) {
- char *cp;
- if (asprintf(&cp, "sudoRole %s", cn_array[0]) == -1)
- goto oom;
- source = rcstr_dup(cp);
- free(cp);
- if (source == NULL)
- goto oom;
- }
- handle->fn_free_values(cn_array);
- cn_array = NULL;
- }
- if (source == NULL) {
- if ((source = rcstr_dup("sudoRole UNKNOWN")) == NULL)
- goto oom;
- }
-
- /* Walk through options, appending to defs. */
- for (i = 0; val_array[i] != NULL; i++) {
- char *copy, *var, *val;
- int op;
-
- /* XXX - should not need to copy */
- if ((copy = strdup(val_array[i])) == NULL)
- goto oom;
- op = sudo_ldap_parse_option(copy, &var, &val);
- if (!sudo_ldap_add_default(var, val, op, source, defs)) {
- free(copy);
- goto oom;
- }
- free(copy);
- }
- ret = true;
- goto done;
-
-oom:
- sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-
-done:
- rcstr_delref(source);
- handle->fn_free_values(val_array);
- debug_return_bool(ret);
-}
-
static char *
val_array_iter(void **vp)
{
}
static bool
-sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_result, struct userspec_list *sss_userspecs)
+sss_to_sudoers(struct sudo_sss_handle *handle,
+ struct sss_sudo_result *sss_result, struct userspec_list *sss_userspecs)
{
struct userspec *us;
struct member *m;
free_userspecs(sss_userspecs);
debug_return_bool(false);
}
+
+static bool
+sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule, struct defaults_list *defs)
+{
+ int i;
+ char *source = NULL;
+ bool ret = false;
+ char **val_array = NULL;
+ char **cn_array = NULL;
+ debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD);
+
+ if (rule == NULL)
+ debug_return_bool(true);
+
+ switch (handle->fn_get_values(rule, "sudoOption", &val_array)) {
+ case 0:
+ break;
+ case ENOENT:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+ debug_return_bool(true);
+ case ENOMEM:
+ goto oom;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoOption): != 0");
+ debug_return_bool(false);
+ }
+
+ /* Use sudoRole in place of file name in defaults. */
+ if (handle->fn_get_values(rule, "cn", &cn_array) == 0) {
+ if (cn_array[0] != NULL) {
+ char *cp;
+ if (asprintf(&cp, "sudoRole %s", cn_array[0]) == -1)
+ goto oom;
+ source = rcstr_dup(cp);
+ free(cp);
+ if (source == NULL)
+ goto oom;
+ }
+ handle->fn_free_values(cn_array);
+ cn_array = NULL;
+ }
+ if (source == NULL) {
+ if ((source = rcstr_dup("sudoRole UNKNOWN")) == NULL)
+ goto oom;
+ }
+
+ /* Walk through options, appending to defs. */
+ for (i = 0; val_array[i] != NULL; i++) {
+ char *copy, *var, *val;
+ int op;
+
+ /* XXX - should not need to copy */
+ if ((copy = strdup(val_array[i])) == NULL)
+ goto oom;
+ op = sudo_ldap_parse_option(copy, &var, &val);
+ if (!sudo_ldap_add_default(var, val, op, source, defs)) {
+ free(copy);
+ goto oom;
+ }
+ free(copy);
+ }
+ ret = true;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+done:
+ rcstr_delref(source);
+ handle->fn_free_values(val_array);
+ debug_return_bool(ret);
+}
+
+static struct sss_sudo_result *
+sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ struct sss_sudo_result *sss_result = NULL;
+ uint32_t sss_error = 0, rc;
+ debug_decl(sudo_sss_result_get, SUDOERS_DEBUG_SSSD);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, " username=%s", pw->pw_name);
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s",
+ handle->domainname ? handle->domainname : "NULL");
+
+ rc = handle->fn_send_recv(pw->pw_uid, pw->pw_name,
+ handle->domainname, &sss_error, &sss_result);
+ switch (rc) {
+ case 0:
+ switch (sss_error) {
+ case 0:
+ if (sss_result != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "Received %u rule(s)",
+ sss_result->num_rules);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "Internal error: sss_result == NULL && sss_error == 0");
+ debug_return_ptr(NULL);
+ }
+ break;
+ case ENOENT:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
+ debug_return_ptr(NULL);
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
+ debug_return_ptr(NULL);
+ }
+ break;
+ case ENOMEM:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ /* FALLTHROUGH */
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "handle->fn_send_recv: rc=%d", rc);
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(sss_result);
+}
+
+/* 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, SUDOERS_DEBUG_SSSD);
+
+ /* Create a handle container. */
+ handle = calloc(1, sizeof(struct sudo_sss_handle));
+ if (handle == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(ENOMEM);
+ }
+
+ /* Load symbols */
+ handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
+ if (handle->ssslib == NULL) {
+ const char *errstr = sudo_dso_strerror();
+ sudo_warnx(U_("unable to load %s: %s"), path,
+ errstr ? errstr : "unknown error");
+ sudo_warnx(U_("unable to initialize SSS source. Is SSSD installed on your machine?"));
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_send_recv =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv");
+ if (handle->fn_send_recv == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_send_recv");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_send_recv_defaults =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults");
+ if (handle->fn_send_recv_defaults == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_send_recv_defaults");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_free_result =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result");
+ if (handle->fn_free_result == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_free_result");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_get_values =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values");
+ if (handle->fn_get_values == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_get_values");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_free_values =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values");
+ if (handle->fn_free_values == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_free_values");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ nss->handle = handle;
+
+ /*
+ * If runhost is the same as the local host, check for ipa_hostname
+ * in sssd.conf and use it in preference to user_runhost.
+ */
+ if (strcasecmp(user_runhost, user_host) == 0) {
+ if (get_ipa_hostname(&handle->ipa_shost, &handle->ipa_host) == -1) {
+ free(handle);
+ debug_return_int(ENOMEM);
+ }
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
+
+ debug_return_int(0);
+}
+
+// ok
+static int
+sudo_sss_close(struct sudo_nss *nss)
+{
+ struct sudo_sss_handle *handle;
+ debug_decl(sudo_sss_close, SUDOERS_DEBUG_SSSD);
+
+ if (nss && nss->handle) {
+ handle = nss->handle;
+ sudo_dso_unload(handle->ssslib);
+ if (handle->pw != NULL)
+ sudo_pw_delref(handle->pw);
+ free(handle->ipa_host);
+ if (handle->ipa_host != handle->ipa_shost)
+ free(handle->ipa_shost);
+ free(handle);
+ nss->handle = NULL;
+
+ /* XXX - do in main module? */
+ free_userspecs(&nss->userspecs);
+ free_defaults(&nss->defaults);
+ }
+ debug_return_int(0);
+}
+
+/*
+ * Perform query for user and host and convert to sudoers parse tree.
+ */
+static int
+sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ struct sss_sudo_result *sss_result = NULL;
+ int ret = 0;
+ debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
+
+ /* Use cached result if it matches pw. */
+ if (handle->pw != NULL) {
+ if (pw == handle->pw)
+ goto done;
+ sudo_pw_delref(handle->pw);
+ handle->pw = NULL;
+ }
+
+ /* Free old userspecs, if any. */
+ free_userspecs(&nss->userspecs);
+
+ /* Fetch list of sudoRole entries that match user and host. */
+ sss_result = sudo_sss_result_get(nss, pw);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG,
+ "searching SSSD/LDAP for sudoers entries for user %s, host %s",
+ pw->pw_name, user_runhost);
+
+ if (sss_result == NULL)
+ goto done;
+
+ /* Stash a ref to the passwd struct in the handle. */
+ sudo_pw_addref(pw);
+ handle->pw = pw;
+
+ /* Convert to sudoers parse tree. */
+ if (!sss_to_sudoers(handle, sss_result, &nss->userspecs)) {
+ ret = -1;
+ goto done;
+ }
+
+done:
+ /* Cleanup */
+ handle->fn_free_result(sss_result);
+ if (ret == -1) {
+ free_userspecs(&nss->userspecs);
+ sudo_pw_delref(handle->pw);
+ handle->pw = NULL;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
+
+ debug_return_int(ret);
+}
+
+// ok
+static int
+sudo_sss_parse(struct sudo_nss *nss)
+{
+ debug_decl(sudo_sss_parse, SUDOERS_DEBUG_SSSD);
+ debug_return_int(0);
+}
+
+static int
+sudo_sss_getdefs(struct sudo_nss *nss)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ struct sss_sudo_result *sss_result = NULL;
+ struct sss_sudo_rule *sss_rule;
+ uint32_t sss_error;
+ unsigned int i;
+ int rc;
+ debug_decl(sudo_sss_getdefs, SUDOERS_DEBUG_SSSD);
+
+ if (handle == NULL)
+ debug_return_int(-1);
+
+ /* Free old defaults, if any. */
+ free_defaults(&nss->defaults);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
+
+ /* NOTE: these are global defaults, user ID and name are not used. */
+ rc = handle->fn_send_recv_defaults(sudo_user.pw->pw_uid,
+ sudo_user.pw->pw_name, &sss_error, &handle->domainname, &sss_result);
+ switch (rc) {
+ case 0:
+ break;
+ case ENOMEM:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ /* FALLTHROUGH */
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "handle->fn_send_recv_defaults: rc=%d, sss_error=%u", rc, sss_error);
+ debug_return_int(-1);
+ }
+ if (sss_error != 0) {
+ if (sss_error == ENOENT) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "The user was not found in SSSD.");
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
+ goto bad;
+ }
+
+ 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;
+ if (!sudo_sss_parse_options(handle, sss_rule, &nss->defaults))
+ goto bad;
+ }
+
+done:
+ handle->fn_free_result(sss_result);
+ debug_return_int(0);
+bad:
+ handle->fn_free_result(sss_result);
+ debug_return_int(-1);
+}
+
+/* sudo_nss implementation */
+struct sudo_nss sudo_nss_sss = {
+ { NULL, NULL },
+ sudo_sss_open,
+ sudo_sss_close,
+ sudo_sss_parse,
+ sudo_sss_query,
+ sudo_sss_getdefs
+};
+
#endif /* HAVE_SSSD */