]> granicus.if.org Git - sudo/commitdiff
Move cached userspecs and defaults into the handle object.
authorTodd C. Miller <Todd.Miller@sudo.ws>
Tue, 29 May 2018 15:39:40 +0000 (09:39 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Tue, 29 May 2018 15:39:40 +0000 (09:39 -0600)
plugins/sudoers/file.c
plugins/sudoers/ldap.c
plugins/sudoers/parse.c
plugins/sudoers/sssd.c
plugins/sudoers/sudo_nss.c
plugins/sudoers/sudo_nss.h
plugins/sudoers/sudoers.c

index 71e498392d058a9288aac0c7dab28d3b7c7abb4d..c83e91605818ff3e6c373bb1f4db511c679bd921 100644 (file)
 #include "sudo_lbuf.h"
 #include <gram.h>
 
-static int
-sudo_file_open(struct sudo_nss *nss)
-{
-    debug_decl(sudo_file_open, SUDOERS_DEBUG_NSS)
-
-    if (def_ignore_local_sudoers)
-       debug_return_int(-1);
-    nss->handle = open_sudoers(sudoers_file, false, NULL);
-    debug_return_int(nss->handle ? 0 : -1);
-}
+struct sudo_file_handle {
+    FILE *fp;
+    struct defaults_list defaults;
+    struct userspec_list userspecs;
+};
 
 static int
 sudo_file_close(struct sudo_nss *nss)
 {
     debug_decl(sudo_file_close, SUDOERS_DEBUG_NSS)
+    struct sudo_file_handle *handle = nss->handle;
 
-    if (nss->handle != NULL) {
-       fclose(nss->handle);
-       nss->handle = NULL;
+    if (handle != NULL) {
+       fclose(handle->fp);
        sudoersin = NULL;
 
-       /* XXX - do in main module? */
-       free_userspecs(&nss->userspecs);
-       free_defaults(&nss->defaults);
+       free_userspecs(&handle->userspecs);
+       free_defaults(&handle->defaults);
+
+       nss->handle = NULL;
     }
 
     debug_return_int(0);
 }
 
+static int
+sudo_file_open(struct sudo_nss *nss)
+{
+    debug_decl(sudo_file_open, SUDOERS_DEBUG_NSS)
+    struct sudo_file_handle *handle;
+
+    if (def_ignore_local_sudoers)
+       debug_return_int(-1);
+
+    if (nss->handle != NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with non-NULL handle %p", __func__, nss->handle);
+       sudo_file_close(nss);
+    }
+
+    handle = malloc(sizeof(*handle));
+    if (handle != NULL) {
+       handle->fp = open_sudoers(sudoers_file, false, NULL);
+       if (handle->fp != NULL) {
+           TAILQ_INIT(&handle->userspecs);
+           TAILQ_INIT(&handle->defaults);
+       } else {
+           free(handle);
+           handle = NULL;
+       }
+    }
+    nss->handle = handle;
+    debug_return_int(nss->handle ? 0 : -1);
+}
+
 /*
  * Parse the specified sudoers file.
  */
@@ -74,11 +100,15 @@ static int
 sudo_file_parse(struct sudo_nss *nss)
 {
     debug_decl(sudo_file_close, SUDOERS_DEBUG_NSS)
+    struct sudo_file_handle *handle = nss->handle;
 
-    if (nss->handle == NULL)
+    if (handle == NULL || handle->fp == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: called with NULL %s",
+           __func__, handle ? "file pointer" : "handle");
        debug_return_int(-1);
+    }
 
-    sudoersin = nss->handle;
+    sudoersin = handle->fp;
     if (sudoersparse() != 0 || parse_error) {
        if (errorlineno != -1) {
            log_warningx(SLOG_SEND_MAIL, N_("parse error in %s near line %d"),
@@ -90,30 +120,45 @@ sudo_file_parse(struct sudo_nss *nss)
     }
 
     /* Move parsed userspecs and defaults to nss structure. */
-    TAILQ_CONCAT(&nss->userspecs, &userspecs, entries);
-    TAILQ_CONCAT(&nss->defaults, &defaults, entries);
+    TAILQ_CONCAT(&handle->userspecs, &userspecs, entries);
+    TAILQ_CONCAT(&handle->defaults, &defaults, entries);
 
     debug_return_int(0);
 }
 
 /*
- * No need for explicit queries for sudoers file, we have it all in memory.
+ * We return all cached userspecs, the parse functions will
+ * perform matching against pw for us.
  */
-static int
+static struct userspec_list *
 sudo_file_query(struct sudo_nss *nss, struct passwd *pw)
 {
+    struct sudo_file_handle *handle = nss->handle;
     debug_decl(sudo_file_query, SUDOERS_DEBUG_NSS)
-    debug_return_int(0);
+
+    if (handle == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with NULL handle", __func__);
+       debug_return_ptr(NULL);
+    }
+    debug_return_ptr(&handle->userspecs);
 }
 
 /*
- * No need to get defaults for sudoers file, the parse function handled it.
+ * Return cached defaults entries.
  */
-static int
+static struct defaults_list *
 sudo_file_getdefs(struct sudo_nss *nss)
 {
     debug_decl(sudo_file_getdefs, SUDOERS_DEBUG_NSS)
-    debug_return_int(0);
+    struct sudo_file_handle *handle = nss->handle;
+
+    if (handle == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with NULL handle", __func__);
+       debug_return_ptr(NULL);
+    }
+    debug_return_ptr(&handle->defaults);
 }
 
 /* sudo_nss implementation */
index c3f34f401b57a43d43a59ce6024c787622531f57..da15a1e3ab822edccc85fa1963e54a8b91854f1b 100644 (file)
@@ -152,6 +152,8 @@ STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
 struct sudo_ldap_handle {
     LDAP *ld;
     struct passwd *pw;
+    struct userspec_list userspecs;
+    struct defaults_list defaults;
 };
 
 #ifdef HAVE_LDAP_INITIALIZE
@@ -1540,6 +1542,33 @@ done:
     debug_return_int(ret);
 }
 
+/*
+ * Shut down the LDAP connection.
+ */
+static int
+sudo_ldap_close(struct sudo_nss *nss)
+{
+    struct sudo_ldap_handle *handle = nss->handle;
+    debug_decl(sudo_ldap_close, SUDOERS_DEBUG_LDAP)
+
+    if (handle != NULL) {
+       /* Unbind and close the LDAP connection. */
+       if (handle->ld != NULL) {
+           ldap_unbind_ext_s(handle->ld, NULL, NULL);
+           handle->ld = NULL;
+       }
+
+       /* Free the handle container. */
+       if (handle->pw != NULL)
+           sudo_pw_delref(handle->pw);
+       free_userspecs(&handle->userspecs);
+       free_defaults(&handle->defaults);
+       free(handle);
+       nss->handle = NULL;
+    }
+    debug_return_int(0);
+}
+
 /*
  * Open a connection to the LDAP server.
  * Returns 0 on success and non-zero on failure.
@@ -1553,6 +1582,12 @@ sudo_ldap_open(struct sudo_nss *nss)
     struct sudo_ldap_handle *handle;
     debug_decl(sudo_ldap_open, SUDOERS_DEBUG_LDAP)
 
+    if (nss->handle != NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with non-NULL handle %p", __func__, nss->handle);
+       sudo_ldap_close(nss);
+    }
+
     if (!sudo_ldap_read_config())
        goto done;
 
@@ -1632,42 +1667,46 @@ sudo_ldap_open(struct sudo_nss *nss)
        goto done;
     }
     handle->ld = ld;
-    /* handle->result = NULL; */
-    /* handle->username = NULL; */
-    /* handle->gidlist = NULL; */
+    /* handle->pw = NULL; */
+    TAILQ_INIT(&handle->userspecs);
+    TAILQ_INIT(&handle->defaults);
     nss->handle = handle;
 
 done:
     debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
 }
 
-static int
+static struct defaults_list *
 sudo_ldap_getdefs(struct sudo_nss *nss)
 {
     struct ldap_config_str *base;
     struct sudo_ldap_handle *handle = nss->handle;
     struct timeval tv, *tvp = NULL;
-    LDAP *ld;
+    struct defaults_list *ret = NULL;
     LDAPMessage *entry, *result = NULL;
     char *filt;
-    int rc, ret = -1;
+    int rc;
     debug_decl(sudo_ldap_getdefs, SUDOERS_DEBUG_LDAP)
 
-    if (handle == NULL || handle->ld == NULL)
-       debug_return_int(-1);
-    ld = handle->ld;
+    if (handle == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with NULL handle", __func__);
+       debug_return_ptr(NULL);
+    }
 
     /* Free old defaults, if any. */
-    free_defaults(&nss->defaults);
+    free_defaults(&handle->defaults);
 
     filt = sudo_ldap_build_default_filter();
     if (filt == NULL) {
        sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-       debug_return_int(-1);
+       debug_return_ptr(NULL);
     }
     DPRINTF1("Looking for cn=defaults: %s", filt);
 
     STAILQ_FOREACH(base, &ldap_conf.base, entries) {
+       LDAP *ld = handle->ld;
+
        if (ldap_conf.timeout > 0) {
            tv.tv_sec = ldap_conf.timeout;
            tv.tv_usec = 0;
@@ -1679,19 +1718,19 @@ sudo_ldap_getdefs(struct sudo_nss *nss)
            filt, NULL, 0, NULL, NULL, tvp, 0, &result);
        if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
            DPRINTF1("found:%s", ldap_get_dn(ld, entry));
-           if (!sudo_ldap_parse_options(ld, entry, &nss->defaults))
+           if (!sudo_ldap_parse_options(ld, entry, &handle->defaults))
                goto done;
        } else {
            DPRINTF1("no default options found in %s", base->val);
        }
     }
-    ret = 0;
+    ret = &handle->defaults;
 
 done:
     ldap_msgfree(result);
     free(filt);
 
-    debug_return_int(ret);
+    debug_return_ptr(ret);
 }
 
 /*
@@ -1777,25 +1816,6 @@ sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
     debug_return_ptr(&lres->entries[lres->nentries - 1]);
 }
 
-/*
- * Free the cached results in the sudo_nss handle, if present.
- */
-static void
-sudo_ldap_result_free_nss(struct sudo_nss *nss)
-{
-    struct sudo_ldap_handle *handle = nss->handle;
-    debug_decl(sudo_ldap_result_free_nss, SUDOERS_DEBUG_LDAP)
-
-    if (handle->pw != NULL)
-       sudo_pw_delref(handle->pw);
-
-    /* XXX - do in main module? */
-    free_userspecs(&nss->userspecs);
-    free_defaults(&nss->defaults);
-
-    debug_return;
-}
-
 /*
  * Perform the LDAP query for the user.  The caller is responsible for
  * freeing the result with sudo_ldap_result_free().
@@ -1899,48 +1919,23 @@ oom:
     debug_return_ptr(NULL);
 }
 
-/*
- * Shut down the LDAP connection.
- */
-static int
-sudo_ldap_close(struct sudo_nss *nss)
-{
-    struct sudo_ldap_handle *handle = nss->handle;
-    debug_decl(sudo_ldap_close, SUDOERS_DEBUG_LDAP)
-
-    if (handle != NULL) {
-       /* Free the cached result. */
-       sudo_ldap_result_free_nss(nss);
-
-       /* Unbind and close the LDAP connection. */
-       if (handle->ld != NULL) {
-           ldap_unbind_ext_s(handle->ld, NULL, NULL);
-           handle->ld = NULL;
-       }
-
-       /* Free the handle container. */
-       free(nss->handle);
-       nss->handle = NULL;
-    }
-    debug_return_int(0);
-}
-
 /*
  * Perform LDAP query for user and host and convert to sudoers
  * parse tree.
  */
-static int
+static struct userspec_list *
 sudo_ldap_query(struct sudo_nss *nss, struct passwd *pw)
 {
     struct sudo_ldap_handle *handle = nss->handle;
     struct ldap_result *lres = NULL;
-    int ret = 0;
-    LDAP *ld;
+    struct userspec_list *ret = &handle->userspecs;
     debug_decl(sudo_ldap_query, SUDOERS_DEBUG_LDAP)
 
-    if (handle == NULL || handle->ld == NULL)
-       goto done;
-    ld = handle->ld;
+    if (handle == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with NULL handle", __func__);
+       debug_return_ptr(NULL);
+    }
 
     /* Use cached result if it matches pw. */
     if (handle->pw != NULL) {
@@ -1951,18 +1946,18 @@ sudo_ldap_query(struct sudo_nss *nss, struct passwd *pw)
     }
 
     /* Free old userspecs, if any. */
-    free_userspecs(&nss->userspecs);
+    free_userspecs(&handle->userspecs);
 
     DPRINTF1("%s: ldap search user %s, host %s", __func__, pw->pw_name,
        user_runhost);
     if ((lres = sudo_ldap_result_get(nss, pw)) == NULL) {
-       ret = -1;
+       ret = NULL;
        goto done;
     }
 
     /* Convert to sudoers parse tree. */
-    if (!ldap_to_sudoers(ld, lres, &nss->userspecs)) {
-       ret = -1;
+    if (!ldap_to_sudoers(handle->ld, lres, &handle->userspecs)) {
+       ret = NULL;
        goto done;
     }
 
@@ -1970,12 +1965,16 @@ sudo_ldap_query(struct sudo_nss *nss, struct passwd *pw)
     sudo_pw_addref(pw);
     handle->pw = pw;
 
+    ret = &handle->userspecs;
+
 done:
     /* Cleanup. */
     sudo_ldap_result_free(lres);
-    if (ret == -1)
-       free_userspecs(&nss->userspecs);
-    debug_return_int(ret);
+    if (ret == NULL) {
+       free_userspecs(&handle->userspecs);
+       debug_return_ptr(NULL);
+    }
+    debug_return_ptr(ret);
 }
 
 /*
index 4f669a306cf90981273e33c3e1ff45489dd5cfef..d7f3e7e21ff956f444d5d568bbd7ac969550eaab 100644 (file)
@@ -65,12 +65,13 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
     CLR(validated, FLAG_NO_HOST);
     match = DENY;
     TAILQ_FOREACH(nss, snl, entries) {
-       if (nss->query(nss, pw) == -1) {
+       struct userspec_list *usl = nss->query(nss, pw);
+       if (usl == NULL) {
            /* The query function should have printed an error message. */
            SET(validated, VALIDATE_ERROR);
            break;
        }
-       TAILQ_FOREACH(us, &nss->userspecs, entries) {
+       TAILQ_FOREACH(us, usl, entries) {
            if (userlist_matches(pw, &us->users) != ALLOW)
                continue;
            TAILQ_FOREACH(priv, &us->privileges, entries) {
@@ -114,8 +115,9 @@ sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct passwd *pw,
 }
 
 static int
-sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw, int *validated,
-    struct cmndspec **matching_cs, struct defaults_list **defs, time_t now)
+sudoers_lookup_check(struct userspec_list *usl, struct passwd *pw,
+    int *validated, struct cmndspec **matching_cs,
+    struct defaults_list **defs, time_t now)
 {
     int host_match, runas_match, cmnd_match;
     struct cmndspec *cs;
@@ -124,7 +126,7 @@ sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw, int *validated,
     struct member *matching_user;
     debug_decl(sudoers_lookup_check, SUDOERS_DEBUG_PARSER)
 
-    TAILQ_FOREACH_REVERSE(us, &nss->userspecs, userspec_list, entries) {
+    TAILQ_FOREACH_REVERSE(us, usl, userspec_list, entries) {
        if (userlist_matches(pw, &us->users) != ALLOW)
            continue;
        CLR(*validated, FLAG_NO_USER);
@@ -290,13 +292,14 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int validated,
     /* Query each sudoers source and check the user. */
     time(&now);
     TAILQ_FOREACH(nss, snl, entries) {
-       if (nss->query(nss, pw) == -1) {
+       struct userspec_list *usl = nss->query(nss, pw);
+       if (usl == NULL) {
            /* The query function should have printed an error message. */
            SET(validated, VALIDATE_ERROR);
            break;
        }
 
-       m = sudoers_lookup_check(nss, pw, &validated, &cs, &defs, now);
+       m = sudoers_lookup_check(usl, pw, &validated, &cs, &defs, now);
        if (m != UNSPEC)
            match = m;
 
@@ -690,14 +693,6 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
     int cols, count, olen, n;
     debug_decl(display_privs, SUDOERS_DEBUG_PARSER)
 
-    /* Query all sudoers sources first. */
-    TAILQ_FOREACH(nss, snl, entries) {
-       if (nss->query(nss, pw) == -1) {
-           /* The query function should have printed an error message. */
-           debug_return_int(-1);
-       }
-    }
-
     cols = sudo_user.cols;
     if (fstat(STDOUT_FILENO, &sb) == 0 && S_ISFIFO(sb.st_mode))
        cols = 0;
@@ -708,10 +703,13 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
        pw->pw_name, user_srunhost);
     count = 0;
     TAILQ_FOREACH(nss, snl, entries) {
-       n = display_defaults(&nss->defaults, pw, &def_buf);
-       if (n == -1)
-           goto bad;
-       count += n;
+       struct defaults_list *defs = nss->getdefs(nss);
+       if (defs != NULL) {
+           n = display_defaults(defs, pw, &def_buf);
+           if (n == -1)
+               goto bad;
+           count += n;
+       }
     }
     if (count != 0) {
        sudo_lbuf_append(&def_buf, "\n\n");
@@ -726,10 +724,13 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
        pw->pw_name);
     count = 0;
     TAILQ_FOREACH(nss, snl, entries) {
-       n = display_bound_defaults(&nss->defaults, pw, &def_buf);
-       if (n == -1)
-           goto bad;
-       count += n;
+       struct defaults_list *defs = nss->getdefs(nss);
+       if (defs != NULL) {
+           n = display_bound_defaults(defs, pw, &def_buf);
+           if (n == -1)
+               goto bad;
+           count += n;
+       }
     }
     if (count != 0) {
        sudo_lbuf_append(&def_buf, "\n\n");
@@ -744,10 +745,13 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw)
        pw->pw_name, user_srunhost);
     count = 0;
     TAILQ_FOREACH(nss, snl, entries) {
-       n = sudo_display_userspecs(&nss->userspecs, pw, &priv_buf);
-       if (n == -1)
-           goto bad;
-       count += n;
+       struct userspec_list *usl = nss->query(nss, pw);
+       if (usl != NULL) {
+           n = sudo_display_userspecs(usl, pw, &priv_buf);
+           if (n == -1)
+               goto bad;
+           count += n;
+       }
     }
     if (count == 0) {
        def_buf.len = 0;
@@ -774,7 +778,7 @@ bad:
 }
 
 static int
-display_cmnd_check(struct sudo_nss *nss, struct passwd *pw, time_t now)
+display_cmnd_check(struct userspec_list *usl, struct passwd *pw, time_t now)
 {
     int host_match, runas_match, cmnd_match;
     struct cmndspec *cs;
@@ -782,7 +786,7 @@ display_cmnd_check(struct sudo_nss *nss, struct passwd *pw, time_t now)
     struct userspec *us;
     debug_decl(display_cmnd_check, SUDOERS_DEBUG_PARSER)
 
-    TAILQ_FOREACH_REVERSE(us, &nss->userspecs, userspec_list, entries) {
+    TAILQ_FOREACH_REVERSE(us, usl, userspec_list, entries) {
        if (userlist_matches(pw, &us->users) != ALLOW)
            continue;
        TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
@@ -828,12 +832,13 @@ display_cmnd(struct sudo_nss_list *snl, struct passwd *pw)
     /* Iterate over each source, checking for the command. */
     time(&now);
     TAILQ_FOREACH(nss, snl, entries) {
-       if (nss->query(nss, pw) == -1) {
+       struct userspec_list *usl = nss->query(nss, pw);
+       if (usl == NULL) {
            /* The query function should have printed an error message. */
            debug_return_int(-1);
        }
 
-       m = display_cmnd_check(nss, pw, now);
+       m = display_cmnd_check(usl, pw, now);
        if (m != UNSPEC)
            match = m;
 
index da69f32ec99db63c912ef34eb413e5cb6ec030c9..0174622699c6d1dc958717d340f2a6674d450e47 100644 (file)
@@ -83,6 +83,8 @@ struct sudo_sss_handle {
     char *ipa_shost;
     struct passwd *pw;
     void *ssslib;
+    struct userspec_list userspecs;
+    struct defaults_list defaults;
     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;
@@ -508,7 +510,27 @@ sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw)
 }
 
 /* sudo_nss implementation */
-// ok
+static int
+sudo_sss_close(struct sudo_nss *nss)
+{
+    struct sudo_sss_handle *handle = nss->handle;
+    debug_decl(sudo_sss_close, SUDOERS_DEBUG_SSSD);
+
+    if (handle != NULL) {
+       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_userspecs(&handle->userspecs);
+       free_defaults(&handle->defaults);
+       free(handle);
+       nss->handle = NULL;
+    }
+    debug_return_int(0);
+}
+
 static int
 sudo_sss_open(struct sudo_nss *nss)
 {
@@ -516,6 +538,12 @@ sudo_sss_open(struct sudo_nss *nss)
     static const char path[] = _PATH_SSSD_LIB"/libsss_sudo.so";
     debug_decl(sudo_sss_open, SUDOERS_DEBUG_SSSD);
 
+    if (nss->handle != NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with non-NULL handle %p", __func__, nss->handle);
+       sudo_sss_close(nss);
+    }
+
     /* Create a handle container. */
     handle = calloc(1, sizeof(struct sudo_sss_handle));
     if (handle == NULL) {
@@ -523,6 +551,9 @@ sudo_sss_open(struct sudo_nss *nss)
        debug_return_int(ENOMEM);
     }
 
+    TAILQ_INIT(&handle->userspecs);
+    TAILQ_INIT(&handle->defaults);
+
     /* Load symbols */
     handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
     if (handle->ssslib == NULL) {
@@ -597,42 +628,23 @@ sudo_sss_open(struct sudo_nss *nss)
     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
+static struct userspec_list *
 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;
+    struct userspec_list *ret = &handle->userspecs;
     debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
 
+    if (handle == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with NULL handle", __func__);
+       debug_return_ptr(NULL);
+    }
+
     /* Use cached result if it matches pw. */
     if (handle->pw != NULL) {
        if (pw == handle->pw)
@@ -642,7 +654,7 @@ sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
     }
 
     /* Free old userspecs, if any. */
-    free_userspecs(&nss->userspecs);
+    free_userspecs(&handle->userspecs);
 
     /* Fetch list of sudoRole entries that match user and host. */
     sss_result = sudo_sss_result_get(nss, pw);
@@ -659,26 +671,25 @@ sudo_sss_query(struct sudo_nss *nss, struct passwd *pw)
     handle->pw = pw;
 
     /* Convert to sudoers parse tree. */
-    if (!sss_to_sudoers(handle, sss_result, &nss->userspecs)) {
-       ret = -1;
+    if (!sss_to_sudoers(handle, sss_result, &handle->userspecs)) {
+       ret = NULL;
        goto done;
     }
 
 done:
     /* Cleanup */
     handle->fn_free_result(sss_result);
-    if (ret == -1) {
-       free_userspecs(&nss->userspecs);
+    if (ret == NULL) {
+       free_userspecs(&handle->userspecs);
        sudo_pw_delref(handle->pw);
        handle->pw = NULL;
     }
 
     sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
 
-    debug_return_int(ret);
+    debug_return_ptr(ret);
 }
 
-// ok
 static int
 sudo_sss_parse(struct sudo_nss *nss)
 {
@@ -686,10 +697,11 @@ sudo_sss_parse(struct sudo_nss *nss)
     debug_return_int(0);
 }
 
-static int
+static struct defaults_list *
 sudo_sss_getdefs(struct sudo_nss *nss)
 {
     struct sudo_sss_handle *handle = nss->handle;
+    struct defaults_list *ret = NULL;
     struct sss_sudo_result *sss_result = NULL;
     struct sss_sudo_rule   *sss_rule;
     uint32_t sss_error;
@@ -697,11 +709,14 @@ sudo_sss_getdefs(struct sudo_nss *nss)
     int rc;
     debug_decl(sudo_sss_getdefs, SUDOERS_DEBUG_SSSD);
 
-    if (handle == NULL)
-       debug_return_int(-1);
+    if (handle == NULL) {
+       sudo_debug_printf(SUDO_DEBUG_ERROR,
+           "%s: called with NULL handle", __func__);
+       debug_return_ptr(NULL);
+    }
 
     /* Free old defaults, if any. */
-    free_defaults(&nss->defaults);
+    free_defaults(&handle->defaults);
 
     sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
 
@@ -717,7 +732,7 @@ sudo_sss_getdefs(struct sudo_nss *nss)
     default:
        sudo_debug_printf(SUDO_DEBUG_INFO,
            "handle->fn_send_recv_defaults: rc=%d, sss_error=%u", rc, sss_error);
-       debug_return_int(-1);
+       debug_return_ptr(NULL);
     }
     if (sss_error != 0) {
        if (sss_error == ENOENT) {
@@ -726,23 +741,21 @@ sudo_sss_getdefs(struct sudo_nss *nss)
            goto done;
        }
        sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
-       goto bad;
+       goto done;
     }
 
     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;
+        if (!sudo_sss_parse_options(handle, sss_rule, &handle->defaults))
+           goto done;
     }
+    ret = &handle->defaults;
 
 done:
     handle->fn_free_result(sss_result);
-    debug_return_int(0);
-bad:
-    handle->fn_free_result(sss_result);
-    debug_return_int(-1);
+    debug_return_ptr(ret);
 }
 
 /* sudo_nss implementation */
index 426434cb8b2236378bee3b13fdc3a9c33c38e10d..bdd9a502aa5fad330ff5f2d81601951077b2f21d 100644 (file)
@@ -43,18 +43,6 @@ extern struct sudo_nss sudo_nss_ldap;
 extern struct sudo_nss sudo_nss_sss;
 #endif
 
-static void
-sudo_nss_insert(struct sudo_nss_list *snl, struct sudo_nss *nss)
-{
-    debug_decl(sudo_nss_insert, SUDOERS_DEBUG_NSS)
-
-    TAILQ_INIT(&nss->userspecs);
-    TAILQ_INIT(&nss->defaults);
-    TAILQ_INSERT_TAIL(snl, nss, entries);
-
-    debug_return;
-}
-
 /* Make sure we have not already inserted the nss entry. */
 #define SUDO_NSS_CHECK_UNUSED(nss, tag)                                               \
     if (nss.entries.tqe_next != NULL || nss.entries.tqe_prev != NULL) {      \
@@ -103,18 +91,18 @@ sudo_read_nss(void)
        for ((cp = strtok_r(line + 8, " \t", &last)); cp != NULL; (cp = strtok_r(NULL, " \t", &last))) {
            if (strcasecmp(cp, "files") == 0 && !saw_files) {
                SUDO_NSS_CHECK_UNUSED(sudo_nss_file, "files");
-               sudo_nss_insert(&snl, &sudo_nss_file);
+               TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
                got_match = saw_files = true;
 #ifdef HAVE_LDAP
            } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) {
                SUDO_NSS_CHECK_UNUSED(sudo_nss_ldap, "ldap");
-               sudo_nss_insert(&snl, &sudo_nss_ldap);
+               TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries);
                got_match = saw_ldap = true;
 #endif
 #ifdef HAVE_SSSD
            } else if (strcasecmp(cp, "sss") == 0 && !saw_sss) {
                SUDO_NSS_CHECK_UNUSED(sudo_nss_sss, "sss");
-               sudo_nss_insert(&snl, &sudo_nss_sss);
+               TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries);
                got_match = saw_sss = true;
 #endif
            } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) {
@@ -137,7 +125,7 @@ sudo_read_nss(void)
 nomatch:
     /* Default to files only if no matches */
     if (TAILQ_EMPTY(&snl))
-       sudo_nss_insert(&snl, &sudo_nss_file);
+       TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
 
     debug_return_ptr(&snl);
 }
@@ -190,20 +178,20 @@ sudo_read_nss(void)
 
            if (!saw_files && strncasecmp(cp, "files", 5) == 0 &&
                (isspace((unsigned char)cp[5]) || cp[5] == '\0')) {
-               sudo_nss_insert(&snl, &sudo_nss_file);
+               TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
                got_match = saw_files = true;
                ep = &cp[5];
 #ifdef HAVE_LDAP
            } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 &&
                (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
-               sudo_nss_insert(&snl, &sudo_nss_ldap);
+               TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries);
                got_match = saw_ldap = true;
                ep = &cp[4];
 #endif
 #ifdef HAVE_SSSD
            } else if (!saw_sss && strncasecmp(cp, "sss", 3) == 0 &&
                (isspace((unsigned char)cp[3]) || cp[3] == '\0')) {
-               sudo_nss_insert(&snl, &sudo_nss_sss);
+               TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries);
                got_match = saw_sss = true;
                ep = &cp[3];
 #endif
@@ -230,7 +218,7 @@ sudo_read_nss(void)
 nomatch:
     /* Default to files only if no matches */
     if (TAILQ_EMPTY(&snl))
-       sudo_nss_insert(&snl, &sudo_nss_file);
+       TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
 
     debug_return_ptr(&snl);
 }
@@ -247,12 +235,12 @@ sudo_read_nss(void)
     debug_decl(sudo_read_nss, SUDOERS_DEBUG_NSS)
 
 #  ifdef HAVE_SSSD
-    sudo_nss_insert(&snl, &sudo_nss_sss);
+    TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries);
 #  endif
 #  ifdef HAVE_LDAP
-    sudo_nss_insert(&snl, &sudo_nss_ldap);
+    TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries);
 #  endif
-    sudo_nss_insert(&snl, &sudo_nss_file);
+    TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
 
     debug_return_ptr(&snl);
 }
index 20909f57717c205d7f80bd2852b8ab296a4b6b97..d6d3aa3c0533992bb4d5da3db7222a4781909617 100644 (file)
 #ifndef SUDOERS_NSS_H
 #define SUDOERS_NSS_H
 
-struct sudo_lbuf;
 struct passwd;
+struct userspec_list;
+struct defaults_list;
 
 struct sudo_nss {
     TAILQ_ENTRY(sudo_nss) entries;
     int (*open)(struct sudo_nss *nss);
     int (*close)(struct sudo_nss *nss);
     int (*parse)(struct sudo_nss *nss);
-    int (*query)(struct sudo_nss *nss, struct passwd *pw);
-    int (*getdefs)(struct sudo_nss *nss);
+    struct userspec_list *(*query)(struct sudo_nss *nss, struct passwd *pw);
+    struct defaults_list *(*getdefs)(struct sudo_nss *nss);
     void *handle;
     bool ret_if_found;
     bool ret_if_notfound;
-    struct defaults_list defaults;
-    struct userspec_list userspecs;
 };
 
 TAILQ_HEAD(sudo_nss_list, sudo_nss);
index 29ce411f5ad46128ebd57a9326a6729db4678ae4..6bbe165fe256f62506a981d8f97d0f7826b8970d 100644 (file)
@@ -193,8 +193,9 @@ sudoers_policy_init(void *info, char * const envp[])
     init_parser(sudoers_file, false);
     TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
         if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
+           struct defaults_list *defs = nss->getdefs(nss);
             sources++;
-           if (nss->getdefs(nss) != 0 || !update_defaults(&nss->defaults,
+           if (defs == NULL || !update_defaults(defs,
                SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, false)) {
                log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
                    N_("problem with defaults entries"));
@@ -853,7 +854,8 @@ set_cmnd(void)
        user_base = user_cmnd;
 
     TAILQ_FOREACH(nss, snl, entries) {
-       if (!update_defaults(&nss->defaults, SETDEF_CMND, false)) {
+       struct defaults_list *defs = nss->getdefs(nss);
+       if (!update_defaults(defs, SETDEF_CMND, false)) {
            log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
                N_("problem with defaults entries"));
        }