]> granicus.if.org Git - sudo/commitdiff
Let the main sudoers lookup code check the host name. We still
authorTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 14 May 2018 15:05:04 +0000 (09:05 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Mon, 14 May 2018 15:05:04 +0000 (09:05 -0600)
check the user name so it is possible to use a single userspec
but this may change in the future.

plugins/sudoers/ldap.c
plugins/sudoers/sssd.c

index 912b6db526ba33296fa9ebcbdca70d2841df2b01..244bf628dff5f5475cf11c148b25221e614c7747 100644 (file)
@@ -123,8 +123,6 @@ struct ldap_result {
     struct ldap_entry_wrapper *entries;
     unsigned int allocated_entries;
     unsigned int nentries;
-    bool user_matches;
-    bool host_matches;
 };
 #define        ALLOCATION_INCREMENT    100
 
@@ -339,49 +337,6 @@ sudo_ldap_check_non_unix_group(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
     debug_return_bool(ret);
 }
 
-/*
-* Walk through search results and return true if we have a
-* host match, else false.
-*/
-static bool
-sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry, struct passwd *pw)
-{
-    struct berval **bv, **p;
-    char *val;
-    bool negated;
-    int matched = UNSPEC;
-    debug_decl(sudo_ldap_check_host, SUDOERS_DEBUG_LDAP)
-
-    if (!entry)
-       debug_return_bool(false);
-
-    /* get the values from the entry */
-    bv = ldap_get_values_len(ld, entry, "sudoHost");
-    if (bv == NULL)
-       debug_return_bool(false);
-
-    /* walk through values */
-    for (p = bv; *p != NULL && matched != false; p++) {
-       val = (*p)->bv_val;
-       negated = sudo_ldap_is_negated(&val);
-
-       /* match any or address or netgroup or hostname */
-       if (strcmp(val, "ALL") == 0 || addr_matches(val) ||
-           netgr_matches(val, user_runhost, user_srunhost,
-           def_netgroup_tuple ? pw->pw_name : NULL) ||
-           hostname_matches(user_srunhost, user_runhost, val)) {
-
-           matched = negated ? false : true;
-       }
-       DPRINTF2("ldap sudoHost '%s' ... %s",
-           val, matched == true ? "MATCH!" : "not");
-    }
-
-    ldap_value_free_len(bv);   /* cleanup */
-
-    debug_return_bool(matched == true);
-}
-
 /*
  * Read sudoOption and fill in the defaults list.
  * This is used to parse the cn=defaults entry.
@@ -1175,11 +1130,13 @@ ldap_to_sudoers(LDAP *ld, struct ldap_result *lres,
     /* Treat each sudoRole as a separate privilege. */
     for (i = 0; i < lres->nentries; i++) {
        LDAPMessage *entry = lres->entries[i].entry;
-       struct berval **cmnds, **runasusers, **runasgroups;
+       struct berval **cmnds, **runasusers, **runasgroups, **hosts;
        struct berval **opts, **notbefore, **notafter;
        struct privilege *priv;
        char *cn;
 
+       /* XXX - check for errors, e.g. ld->ld_errno == LDAP_NO_MEMORY */
+
        /* Ignore sudoRole without sudoCommand. */
        cmnds = ldap_get_values_len(ld, entry, "sudoCommand");
        if (cmnds == NULL)
@@ -1188,6 +1145,9 @@ ldap_to_sudoers(LDAP *ld, struct ldap_result *lres,
        /* Get the entry's dn for long format printing. */
        cn = sudo_ldap_get_first_rdn(ld, entry);
 
+       /* Get sudoHost */
+       hosts = ldap_get_values_len(ld, entry, "sudoHost");
+
        /* Get sudoRunAsUser / sudoRunAsGroup */
        runasusers = ldap_get_values_len(ld, entry, "sudoRunAsUser");
        if (runasusers == NULL)
@@ -1201,7 +1161,7 @@ ldap_to_sudoers(LDAP *ld, struct ldap_result *lres,
        /* Parse sudoOptions. */
        opts = ldap_get_values_len(ld, entry, "sudoOption");
 
-       priv = sudo_ldap_role_to_priv(cn, NULL, runasusers, runasgroups,
+       priv = sudo_ldap_role_to_priv(cn, hosts, runasusers, runasgroups,
            cmnds, opts, notbefore ? notbefore[0]->bv_val : NULL,
            notafter ? notafter[0]->bv_val : NULL, false, long_list,
            berval_iter);
@@ -1211,6 +1171,8 @@ ldap_to_sudoers(LDAP *ld, struct ldap_result *lres,
            ldap_memfree(cn);
        if (cmnds != NULL)
            ldap_value_free_len(cmnds);
+       if (hosts != NULL)
+           ldap_value_free_len(hosts);
        if (runasusers != NULL)
            ldap_value_free_len(runasusers);
        if (runasgroups != NULL)
@@ -1877,14 +1839,9 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
                    debug_return_ptr(NULL);
                }
                LDAP_FOREACH(entry, ld, result) {
-                   /* Check user or non-unix group. */
+                   /* Check non-unix group in 2nd pass. */
                    if (pass && !sudo_ldap_check_non_unix_group(ld, entry, pw))
                        continue;
-                   lres->user_matches = true;
-                   /* Check host. */
-                   if (!sudo_ldap_check_host(ld, entry, pw))
-                       continue;
-                   lres->host_matches = true;
                    if (sudo_ldap_result_add_entry(lres, entry) == NULL) {
                        sudo_warnx(U_("%s: %s"), __func__,
                            U_("unable to allocate memory"));
index 5cd3d30421ad22da8ba8d5c3b517ef0a3fd48887..92a68c365448ec52264fce481d413273351ad929 100644 (file)
@@ -94,12 +94,13 @@ struct sudo_sss_handle {
 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 int sudo_sss_getdefs(struct sudo_nss *nss);
 
 static struct sss_sudo_result *sudo_sss_result_get(struct sudo_nss *nss,
                                                   struct passwd *pw);
@@ -108,186 +109,6 @@ static bool sss_to_sudoers(struct sudo_sss_handle *handle,
                           struct sss_sudo_result *sss_result,
                           struct userspec_list *sss_userspecs);
 
-static void
-sudo_sss_attrfree(struct sss_sudo_attr *attr)
-{
-    unsigned int i;
-    debug_decl(sudo_sss_attrfree, SUDOERS_DEBUG_SSSD)
-
-    free(attr->name);
-    attr->name = NULL;
-    if (attr->values != NULL) {
-       for (i = 0; i < attr->num_values; ++i)
-           free(attr->values[i]);
-       free(attr->values);
-       attr->values = NULL;
-    }
-    attr->num_values = 0;
-
-    debug_return;
-}
-
-static bool
-sudo_sss_attrcpy(struct sss_sudo_attr *dst, const struct sss_sudo_attr *src)
-{
-    unsigned int i = 0;
-    debug_decl(sudo_sss_attrcpy, SUDOERS_DEBUG_SSSD)
-
-    sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
-    sudo_debug_printf(SUDO_DEBUG_INFO, "malloc: cnt=%d", src->num_values);
-
-    dst->name = strdup(src->name);
-    dst->values = reallocarray(NULL, src->num_values, sizeof(char *));
-    if (dst->name == NULL || dst->values == NULL)
-       goto oom;
-    dst->num_values = src->num_values;
-
-    for (i = 0; i < dst->num_values; ++i) {
-       dst->values[i] = strdup(src->values[i]);
-       if (dst->values[i] == NULL) {
-           dst->num_values = i;
-           goto oom;
-       }
-    }
-
-    debug_return_bool(true);
-oom:
-    sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-    sudo_sss_attrfree(dst);
-    debug_return_bool(false);
-}
-
-static void
-sudo_sss_rulefree(struct sss_sudo_rule *rule)
-{
-    unsigned int i;
-    debug_decl(sudo_sss_rulefree, SUDOERS_DEBUG_SSSD)
-
-    for (i = 0; i < rule->num_attrs; ++i)
-       sudo_sss_attrfree(rule->attrs + i);
-    free(rule->attrs);
-    rule->attrs = NULL;
-    rule->num_attrs = 0;
-
-    debug_return;
-}
-
-static bool
-sudo_sss_rulecpy(struct sss_sudo_rule *dst, const struct sss_sudo_rule *src)
-{
-    unsigned int i;
-    debug_decl(sudo_sss_rulecpy, SUDOERS_DEBUG_SSSD)
-
-    sudo_debug_printf(SUDO_DEBUG_DEBUG, "dst=%p, src=%p", dst, src);
-    sudo_debug_printf(SUDO_DEBUG_INFO, "malloc: cnt=%d", src->num_attrs);
-
-    dst->num_attrs = 0;
-    dst->attrs = reallocarray(NULL, src->num_attrs, sizeof(struct sss_sudo_attr));
-    if (dst->attrs == NULL) {
-       sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-       debug_return_bool(false);
-    }
-
-    for (i = 0; i < src->num_attrs; ++i) {
-       if (!sudo_sss_attrcpy(dst->attrs + i, src->attrs + i)) {
-           dst->num_attrs = i;
-           sudo_sss_rulefree(dst);
-           debug_return_bool(false);
-       }
-    }
-    dst->num_attrs = i;
-
-    debug_return_bool(true);
-}
-
-#define SUDO_SSS_FILTER_INCLUDE 0
-#define SUDO_SSS_FILTER_EXCLUDE 1
-
-/* XXX - insted of filtering result, include user and host in sudoers parse tree */
-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;
-    unsigned int i, l;
-    int r;
-    debug_decl(sudo_sss_filter_result, SUDOERS_DEBUG_SSSD)
-
-    sudo_debug_printf(SUDO_DEBUG_DEBUG, "in_res=%p, count=%u, act=%s",
-       in_res, in_res ? in_res->num_rules : 0,
-       act == SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE");
-
-    if (in_res == NULL)
-       debug_return_ptr(NULL);
-
-    sudo_debug_printf(SUDO_DEBUG_DEBUG, "malloc: cnt=%d", in_res->num_rules);
-
-    if ((out_res = calloc(1, sizeof(struct sss_sudo_result))) == NULL) {
-       sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-       debug_return_ptr(NULL);
-    }
-    if (in_res->num_rules > 0) {
-       out_res->rules =
-           reallocarray(NULL, in_res->num_rules, sizeof(struct sss_sudo_rule));
-       if (out_res->rules == NULL) {
-           sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-           free(out_res);
-           debug_return_ptr(NULL);
-       }
-    }
-
-    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);
-
-           if (!sudo_sss_rulecpy(out_res->rules + l, in_res->rules + i)) {
-               while (l--) {
-                   sudo_sss_rulefree(out_res->rules + l);
-               }
-               free(out_res->rules);
-               free(out_res);
-               debug_return_ptr(NULL);
-           }
-           ++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);
-       if (l > 0) {
-           struct sss_sudo_rule *rules =
-               reallocarray(out_res->rules, l, sizeof(struct sss_sudo_rule));
-           if (out_res->rules == NULL) {
-               sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
-               while (l--) {
-                   sudo_sss_rulefree(out_res->rules + l);
-               }
-               free(out_res->rules);
-               free(out_res);
-               debug_return_ptr(NULL);
-           }
-           out_res->rules = rules;
-       } else {
-           free(out_res->rules);
-           out_res->rules = NULL;
-       }
-    }
-
-    out_res->num_rules = l;
-
-    debug_return_ptr(out_res);
-}
-
 static int
 get_ipa_hostname(char **shostp, char **lhostp)
 {
@@ -614,57 +435,6 @@ bad:
     debug_return_int(-1);
 }
 
-static bool
-sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
-{
-    const char *host = handle->ipa_host ? handle->ipa_host : user_runhost;
-    const char *shost = handle->ipa_shost ? handle->ipa_shost : user_srunhost;
-    char *val, **val_array;
-    int matched = UNSPEC;
-    bool negated;
-    int i;
-    debug_decl(sudo_sss_check_host, SUDOERS_DEBUG_SSSD);
-
-    if (rule == NULL)
-       debug_return_bool(false);
-
-    /* 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.");
-       debug_return_bool(false);
-    default:
-       sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0");
-       debug_return_bool(false);
-    }
-
-    /* walk through values */
-    for (i = 0; val_array[i] != NULL && matched != false; ++i) {
-       val = val_array[i];
-       sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
-
-       negated = sudo_ldap_is_negated(&val);
-
-       /* match any or address or netgroup or hostname */
-       if (strcmp(val, "ALL") == 0 || addr_matches(val) ||
-           netgr_matches(val, host, shost,
-           def_netgroup_tuple ? handle->pw->pw_name : NULL) ||
-           hostname_matches(shost, host, val)) {
-
-           matched = negated ? false : true;
-       }
-
-       sudo_debug_printf(SUDO_DEBUG_INFO, "sssd/ldap sudoHost '%s' ... %s",
-           val, matched == true ? "MATCH!" : "not");
-    }
-
-    handle->fn_free_values(val_array);
-
-    debug_return_bool(matched == true);
-}
-
 /*
  * 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
@@ -729,26 +499,11 @@ sudo_sss_check_user(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
     debug_return_bool(ret);
 }
 
-/* XXX - insted of filtering result, include user and host in sudoers parse tree */
-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, SUDOERS_DEBUG_SSSD);
-
-    if (sudo_sss_check_host(handle, rule) &&
-        sudo_sss_check_user(handle, rule))
-       debug_return_int(1);
-    else
-       debug_return_int(0);
-}
-
 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 *u_sss_result, *f_sss_result;
+    struct sss_sudo_result *sss_result = NULL;
     uint32_t sss_error = 0, ret;
     debug_decl(sudo_sss_result_get, SUDOERS_DEBUG_SSSD);
 
@@ -756,21 +511,19 @@ sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw)
     sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s",
        handle->domainname ? handle->domainname : "NULL");
 
-    u_sss_result = f_sss_result = NULL;
-
     ret = handle->fn_send_recv(pw->pw_uid, pw->pw_name,
-       handle->domainname, &sss_error, &u_sss_result);
+       handle->domainname, &sss_error, &sss_result);
 
     switch (ret) {
     case 0:
        switch (sss_error) {
        case 0:
-           if (u_sss_result != NULL) {
+           if (sss_result != NULL) {
                sudo_debug_printf(SUDO_DEBUG_INFO, "Received %u rule(s)",
-                   u_sss_result->num_rules);
+                   sss_result->num_rules);
            } else {
                sudo_debug_printf(SUDO_DEBUG_INFO,
-                   "Internal error: u_sss_result == NULL && sss_error == 0");
+                   "Internal error: sss_result == NULL && sss_error == 0");
                debug_return_ptr(NULL);
            }
            break;
@@ -788,23 +541,7 @@ sudo_sss_result_get(struct sudo_nss *nss, struct passwd *pw)
        debug_return_ptr(NULL);
     }
 
-    /* XXX - insted of filtering result, include user and host in sudoers parse tree */
-    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) {
-       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);
-    } else {
-       sudo_debug_printf(SUDO_DEBUG_DEBUG,
-           "u_sss_result=(%p, %u) => f_sss_result=NULL", u_sss_result,
-           u_sss_result->num_rules);
-    }
-
-    handle->fn_free_result(u_sss_result);
-
-    debug_return_ptr(f_sss_result);
+    debug_return_ptr(sss_result);
 }
 
 static bool
@@ -903,8 +640,7 @@ sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_resul
     STAILQ_INIT(&us->comments);
     TAILQ_INSERT_TAIL(sss_userspecs, us, entries);
 
-    /* The user has already matched, use ALL as wildcard. */
-    /* XXX - remove filtering and include sudoUser and host in userspec */
+    /* We only include rules where the user matches. */
     if ((m = calloc(1, sizeof(*m))) == NULL)
        goto oom;
     m->type = ALL;
@@ -915,12 +651,16 @@ sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_resul
        struct sss_sudo_rule *rule = sss_result->rules + i;
        char **cmnds, **runasusers = NULL, **runasgroups = NULL;
        char **opts = NULL, **notbefore = NULL, **notafter = NULL;
-       char **cn_array = NULL;
+       char **hosts = NULL, **cn_array = NULL;
        char *cn = NULL;
        struct privilege *priv;
 
        /* XXX - check for error vs. ENOENT */
 
+       /* Only include matching user roles (XXX). */
+       if (!sudo_sss_check_user(handle, rule))
+           continue;
+
        /* Ignore sudoRole without sudoCommand. */
        if (handle->fn_get_values(rule, "sudoCommand", &cmnds) != 0)
            continue;
@@ -929,6 +669,9 @@ sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_resul
        if (handle->fn_get_values(rule, "cn", &cn_array) == 0)
            cn = cn_array[0];
 
+       /* Get sudoHost */
+       handle->fn_get_values(rule, "sudoHost", &hosts);
+
        /* Get sudoRunAsUser / sudoRunAsGroup */
        if (handle->fn_get_values(rule, "sudoRunAsUser", &runasusers) != 0) {
            handle->fn_get_values(rule, "sudoRunAs", &runasusers);
@@ -942,7 +685,7 @@ sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_resul
        /* Parse sudoOptions. */
        handle->fn_get_values(rule, "sudoOption", &opts);
 
-       priv = sudo_ldap_role_to_priv(cn, NULL, runasusers, runasgroups,
+       priv = sudo_ldap_role_to_priv(cn, hosts, runasusers, runasgroups,
            cmnds, opts, notbefore ? notbefore[0] : NULL,
            notafter ? notafter[0] : NULL, false, long_list, val_array_iter);
 
@@ -951,6 +694,8 @@ sss_to_sudoers(struct sudo_sss_handle *handle, struct sss_sudo_result *sss_resul
            handle->fn_free_values(cn_array);
        if (cmnds != NULL)
            handle->fn_free_values(cmnds);
+       if (hosts != NULL)
+           handle->fn_free_values(hosts);
        if (runasusers != NULL)
            handle->fn_free_values(runasusers);
        if (runasgroups != NULL)