https://fedorahosted.org/sssd/ticket/960
From 5078bef5727419791a776c6892515fc58e588aa8 Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzel...@redhat.com>
Date: Wed, 16 Nov 2011 04:24:53 -0500
Subject: [PATCH 1/3] Multiple search bases helper function

---
 src/util/sss_ldap.c |  137 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/sss_ldap.h |    8 +++
 2 files changed, 145 insertions(+), 0 deletions(-)

diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c
index afff22f..c7070e7 100644
--- a/src/util/sss_ldap.c
+++ b/src/util/sss_ldap.c
@@ -26,6 +26,7 @@
 
 #include "config.h"
 
+#include "providers/ldap/sdap.h"
 #include "util/sss_ldap.h"
 #include "util/util.h"
 
@@ -477,3 +478,139 @@ int sss_ldap_init_recv(struct tevent_req *req, LDAP 
**ldap, int *sd)
 
     return EOK;
 }
+
+/*
+ * _filter will contain combined filters from all possible search bases
+ * or NULL if it should be empty
+ */
+bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx,
+                                 const char *dn,
+                                 struct sdap_search_base **search_bases,
+                                 char **_filter)
+{
+    struct sdap_search_base *base;
+    int basedn_len, dn_len;
+    int len_diff;
+    int i, j;
+    bool base_confirmed;
+    bool comma_found;
+    bool backslash_found;
+    char *filter = NULL;
+    bool ret = false;
+
+    if (dn == NULL) {
+        DEBUG(SSSDBG_FUNC_DATA, ("dn is NULL\n"));
+        ret = false;
+        goto done;
+    }
+
+    if (search_bases == NULL) {
+        DEBUG(SSSDBG_FUNC_DATA, ("search_bases is NULL\n"));
+        ret = false;
+        goto done;
+    }
+
+    if (_filter != NULL) {
+        *_filter = NULL;
+    }
+
+    dn_len = strlen(dn);
+    for (i = 0; search_bases[i] != NULL; i++) {
+        base = search_bases[i];
+        basedn_len = strlen(base->basedn);
+
+        if (basedn_len > dn_len) {
+            continue;
+        }
+
+        len_diff = dn_len - basedn_len;
+        base_confirmed = (strncasecmp(&dn[len_diff], base->basedn, basedn_len) 
== 0);
+        if (!base_confirmed) {
+            continue;
+        }
+
+        /*
+         * base:     dc=example,dc=com
+         * dn:   somedc=example,dc=com
+         * dn: some\,dc=example,dc=com
+         */
+        if (len_diff != 0) {
+            if (len_diff >= 1 && dn[len_diff - 1] != ',') {
+                if (len_diff >= 2 && dn[len_diff - 2] == '\\') {
+                    continue;
+                }
+            }
+        }
+
+        switch (base->scope) {
+        case LDAP_SCOPE_BASE:
+            /* dn > base? */
+            if (len_diff != 0) {
+                continue;
+            }
+            break;
+        case LDAP_SCOPE_ONELEVEL:
+            if (len_diff == 0) {
+                /* Base object doesn't belong to scope=one
+                 * search */
+                continue;
+            }
+
+            comma_found = false;
+            for (j = 0; j < len_diff - 1; j++) { /* ignore comma before base */
+                if (dn[j] == '\\') {
+                    backslash_found = true;
+                } else if (dn[j] == ',' && !backslash_found) {
+                    comma_found = true;
+                    break;
+                } else {
+                    backslash_found = false;
+                }
+            }
+
+            /* it has at least one more level */
+            if (comma_found) {
+                continue;
+            }
+
+            break;
+        case LDAP_SCOPE_SUBTREE:
+            /* dn length >= base dn length && base_confirmed == true */
+            break;
+        default:
+            DEBUG(SSSDBG_FUNC_DATA, ("Unsupported scope: %d\n", base->scope));
+            continue;
+        }
+
+        /*
+         *  If we get here, the dn is valid.
+         *  If no filter is set, than return true immediately.
+         *  Append filter otherwise.
+         */
+        ret = true;
+
+        if (base->filter == NULL || _filter == NULL) {
+            goto done;
+        } else {
+            filter = talloc_strdup_append(filter, base->filter);
+            if (filter == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup_append() 
failed\n"));
+                ret = false;
+                goto done;
+            }
+        }
+    }
+
+    if (_filter != NULL && filter != NULL) {
+        *_filter = talloc_asprintf(mem_ctx, "(|%s)", filter);
+        if (*_filter == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf_append() failed\n"));
+            ret = false;
+            goto done;
+        }
+    }
+
+done:
+    talloc_free(filter);
+    return ret;
+}
diff --git a/src/util/sss_ldap.h b/src/util/sss_ldap.h
index 38785b5..8a69b83 100644
--- a/src/util/sss_ldap.h
+++ b/src/util/sss_ldap.h
@@ -60,4 +60,12 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
                                       int addr_len, int timeout);
 
 int sss_ldap_init_recv(struct tevent_req *req, LDAP **ldap, int *sd);
+
+struct sdap_options;
+struct sdap_search_base;
+bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx,
+                                 const char *dn,
+                                 struct sdap_search_base **search_bases,
+                                 char **_filter);
+
 #endif /* __SSS_LDAP_H__ */
-- 
1.7.6.4

From 84e09cf84b26d65e1725737ce5c384ce2538a706 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Fri, 14 Oct 2011 14:11:30 +0200
Subject: [PATCH 2/3] Support search bases in RFC2307bis enumeration

https://fedorahosted.org/sssd/ticket/960
---
 src/providers/ldap/sdap_async_groups.c |  155 +++++++++++++++++++++++++++++--
 1 files changed, 145 insertions(+), 10 deletions(-)

diff --git a/src/providers/ldap/sdap_async_groups.c 
b/src/providers/ldap/sdap_async_groups.c
index 25a3e0a..0099e87 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -1297,7 +1297,7 @@ static struct tevent_req *sdap_nested_group_process_send(
         struct sysdb_ctx *sysdb, struct sysdb_attrs *group,
         hash_table_t *users, hash_table_t *groups,
         struct sdap_options *opts, struct sdap_handle *sh,
-        uint32_t nesting);
+        bool enable_deref, uint32_t nesting);
 static void sdap_nested_done(struct tevent_req *req);
 static errno_t sdap_nested_group_process_recv(struct tevent_req *req);
 static void sdap_get_groups_process(struct tevent_req *subreq)
@@ -1311,6 +1311,7 @@ static void sdap_get_groups_process(struct tevent_req 
*subreq)
     bool next_base = false;
     size_t count;
     struct sysdb_attrs **groups;
+    bool enable_deref = true;
 
     ret = sdap_get_generic_recv(subreq, state,
                                 &count, &groups);
@@ -1409,6 +1410,32 @@ static void sdap_get_groups_process(struct tevent_req 
*subreq)
                 return;
             }
 
+            /*
+             * If any search base contains filter, disable dereference.
+             */
+            enable_deref = true;
+            for (i = 0; state->opts->user_search_bases[i] != NULL; i++) {
+                if (state->opts->user_search_bases[i]->filter != NULL) {
+                    DEBUG(SSSDBG_TRACE_FUNC,
+                          ("User search base contains filter, "
+                           "dereference will be disabled\n"));
+                    enable_deref = false;
+                    break;
+                }
+            }
+
+            if (enable_deref) {
+                for (i = 0; state->opts->group_search_bases[i] != NULL; i++) {
+                    if (state->opts->group_search_bases[i]->filter != NULL) {
+                        DEBUG(SSSDBG_TRACE_FUNC,
+                              ("Group search base contains filter, "
+                               "dereference will be disabled\n"));
+                        enable_deref = false;
+                        break;
+                    }
+                }
+            }
+
             subreq = sdap_nested_group_process_send(state,
                                                     state->ev,
                                                     state->dom,
@@ -1418,6 +1445,7 @@ static void sdap_get_groups_process(struct tevent_req 
*subreq)
                                                     state->group_hash,
                                                     state->opts,
                                                     state->sh,
+                                                    enable_deref,
                                                     0);
             if (!subreq) {
                 tevent_req_error(req, EIO);
@@ -1814,6 +1842,7 @@ struct sdap_nested_group_ctx {
     uint32_t member_index;
     char *member_dn;
 
+    bool enable_deref;
     struct sdap_deref_ctx *derefctx;
 };
 
@@ -1826,7 +1855,7 @@ static struct tevent_req *sdap_nested_group_process_send(
         struct sysdb_ctx *sysdb, struct sysdb_attrs *group,
         hash_table_t *users, hash_table_t *groups,
         struct sdap_options *opts, struct sdap_handle *sh,
-        uint32_t nesting)
+        bool enable_deref, uint32_t nesting)
 {
     errno_t ret;
     int hret;
@@ -1849,6 +1878,7 @@ static struct tevent_req *sdap_nested_group_process_send(
     state->groups = groups;
     state->opts = opts;
     state->sh = sh;
+    state->enable_deref = enable_deref;
     state->nesting_level = nesting;
 
     /* If this is too many levels deep, just return success */
@@ -1940,7 +1970,7 @@ static struct tevent_req *sdap_nested_group_process_send(
 
     state->member_index = 0;
 
-    if (sdap_has_deref_support(state->sh, state->opts)) {
+    if (enable_deref && sdap_has_deref_support(state->sh, state->opts)) {
         state->derefctx = talloc_zero(state, struct sdap_deref_ctx);
         if (!state->derefctx) goto immediate;
 
@@ -2463,10 +2493,45 @@ static errno_t sdap_nested_group_lookup_user(struct 
tevent_req *req,
 {
     const char **sdap_attrs;
     char *filter;
+    char *search_bases_filter = NULL;
     struct tevent_req *subreq;
     struct sdap_nested_group_ctx *state =
             tevent_req_data(req, struct sdap_nested_group_ctx);
+    errno_t ret;
+
+    /*
+     * If dn is not in user search base and object may be group
+     * continue with group lookup. If it can't be group, skip it.
+     */
+    if (!sss_ldap_dn_in_search_bases(state, state->member_dn,
+                                     state->opts->user_search_bases,
+                                     &search_bases_filter)) {
+        if (fn == sdap_nested_group_process_ldap_user) {
+            return sdap_nested_group_lookup_group(req);
+        } else if (fn == sdap_nested_group_process_user) {
+            if (state->derefctx) {
+                state->derefctx->expired_users_index++;
+                ret = sdap_nested_group_process_noderef(req);
+            } else {
+                state->member_index++;
+                talloc_zfree(state->member_dn);
+                ret = sdap_nested_group_process_step(req);
+            }
 
+            if (ret == EOK) {
+                /* EOK means it's complete */
+                tevent_req_done(req);
+                tevent_req_post(req, state->ev);
+            } else if (ret != EAGAIN) {
+                tevent_req_error(req, ret);
+            }
+
+            return EOK;
+        }
+        /*
+         * Something else? Continue.
+         */
+    }
 
     /* Only pull down username and originalDN */
     sdap_attrs = talloc_array(state, const char *, 3);
@@ -2475,9 +2540,14 @@ static errno_t sdap_nested_group_lookup_user(struct 
tevent_req *req,
     sdap_attrs[1] = state->opts->user_map[SDAP_AT_USER_NAME].name;
     sdap_attrs[2] = NULL;
 
-    filter = talloc_asprintf(
-            sdap_attrs, "(objectclass=%s)",
-            state->opts->user_map[SDAP_OC_USER].name);
+    if (search_bases_filter != NULL) {
+        filter = talloc_asprintf(sdap_attrs, "(&%s(objectclass=%s))",
+                                 search_bases_filter,
+                                 state->opts->user_map[SDAP_OC_USER].name);
+    } else {
+        filter = talloc_asprintf(sdap_attrs, "(objectclass=%s)",
+                                 state->opts->user_map[SDAP_OC_USER].name);
+    }
     if (!filter) {
         talloc_free(sdap_attrs);
         return ENOMEM;
@@ -2507,20 +2577,58 @@ static errno_t sdap_nested_group_lookup_group(struct 
tevent_req *req)
     errno_t ret;
     const char **sdap_attrs;
     char *filter;
+    char *search_bases_filter = NULL;
     struct tevent_req *subreq;
     struct sdap_nested_group_ctx *state =
             tevent_req_data(req, struct sdap_nested_group_ctx);
 
+    /*
+     * If dn is not in group search base, skip it.
+     */
+    if (!sss_ldap_dn_in_search_bases(state, state->member_dn,
+                                     state->opts->group_search_bases,
+                                     &filter)) {
+        if (state->derefctx) {
+            if (state->derefctx->expired_groups_index <
+                state->derefctx->expired_groups_num) {
+                state->derefctx->expired_groups_index++;
+            } else {
+                state->derefctx->missing_dns_index++;
+            }
+            ret = sdap_nested_group_process_noderef(req);
+        } else {
+            state->member_index++;
+            talloc_zfree(state->member_dn);
+            ret = sdap_nested_group_process_step(req);
+        }
+
+        if (ret == EOK) {
+            /* EOK means it's complete */
+            tevent_req_done(req);
+            tevent_req_post(req, state->ev);
+        } else if (ret != EAGAIN) {
+            tevent_req_error(req, ret);
+        }
+
+        return EOK;
+    }
+
     ret = build_attrs_from_map(state, state->opts->group_map,
                                SDAP_OPTS_GROUP, &sdap_attrs);
     if (ret != EOK) {
         return ret;
     }
 
-    filter = talloc_asprintf(
-            sdap_attrs, "(&(objectclass=%s)(%s=*))",
-            state->opts->group_map[SDAP_OC_GROUP].name,
-            state->opts->group_map[SDAP_AT_GROUP_NAME].name);
+    if (search_bases_filter != NULL) {
+        filter = talloc_asprintf(sdap_attrs, "(&%s(objectclass=%s)(%s=*))",
+                                 search_bases_filter,
+                                 state->opts->group_map[SDAP_OC_GROUP].name,
+                                 
state->opts->group_map[SDAP_AT_GROUP_NAME].name);
+    } else {
+        filter = talloc_asprintf(sdap_attrs, "(&(objectclass=%s)(%s=*))",
+                                 state->opts->group_map[SDAP_OC_GROUP].name,
+                                 
state->opts->group_map[SDAP_AT_GROUP_NAME].name);
+    }
     if (!filter) {
         talloc_free(sdap_attrs);
         return ENOMEM;
@@ -2669,6 +2777,7 @@ static void sdap_nested_group_process_group(struct 
tevent_req *subreq)
                                             state->sysdb, replies[0],
                                             state->users, state->groups,
                                             state->opts, state->sh,
+                                            state->enable_deref,
                                             state->nesting_level + 1);
     if (!subreq) {
         tevent_req_error(req, EIO);
@@ -2895,6 +3004,7 @@ sdap_nested_group_process_deref_result(struct tevent_req 
*req)
     while (dctx->result_index < dctx->num_results) {
         if (dctx->deref_result[dctx->result_index]->map == \
             state->opts->user_map) {
+
             /* Add to appropriate hash table */
             ret = sysdb_attrs_get_string(
                     dctx->deref_result[dctx->result_index]->attrs,
@@ -2904,6 +3014,14 @@ sdap_nested_group_process_deref_result(struct tevent_req 
*req)
                 return ret;
             }
 
+            /* check if the user is in search base */
+            if (!sss_ldap_dn_in_search_bases(state, orig_dn,
+                                             state->opts->user_search_bases,
+                                             NULL)) {
+                dctx->result_index++;
+                continue;
+            }
+
             DEBUG(9, ("Found member user [%s]\n", orig_dn));
 
             key.type = HASH_KEY_STRING;
@@ -2929,12 +3047,29 @@ sdap_nested_group_process_deref_result(struct 
tevent_req *req)
                 return EIO;
             }
 
+            ret = sysdb_attrs_get_string(
+                    dctx->deref_result[dctx->result_index]->attrs,
+                    SYSDB_ORIG_DN, &orig_dn);
+            if (ret != EOK) {
+                DEBUG(2, ("The entry has no originalDN\n"));
+                return ret;
+            }
+
+            /* check if the group is in search base */
+            if (!sss_ldap_dn_in_search_bases(state, orig_dn,
+                                             state->opts->group_search_bases,
+                                             NULL)) {
+                dctx->result_index++;
+                continue;
+            }
+
             DEBUG(6, ("Recursing down a nested group\n"));
             subreq = sdap_nested_group_process_send(state, state->ev,
                                 state->domain, state->sysdb,
                                 dctx->deref_result[dctx->result_index]->attrs,
                                 state->users, state->groups,
                                 state->opts, state->sh,
+                                state->enable_deref,
                                 state->nesting_level + 1);
             if (!subreq) return EIO;
 
-- 
1.7.6.4

From b9fb39555e8eb86ac20f879f52539da3475e133c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Mon, 28 Nov 2011 18:47:19 +0100
Subject: [PATCH 3/3] Support search bases in netgroup members translation

---
 src/providers/ldap/sdap_async_netgroups.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/src/providers/ldap/sdap_async_netgroups.c 
b/src/providers/ldap/sdap_async_netgroups.c
index 1f0d1dd..6143a30 100644
--- a/src/providers/ldap/sdap_async_netgroups.c
+++ b/src/providers/ldap/sdap_async_netgroups.c
@@ -435,6 +435,7 @@ static errno_t netgr_translate_members_ldap_step(struct 
tevent_req *req)
     struct netgr_translate_members_state *state = tevent_req_data(req,
                                           struct 
netgr_translate_members_state);
     const char **cn_attr;
+    char *filter = NULL;
     struct tevent_req *subreq;
     int ret;
 
@@ -458,6 +459,15 @@ static errno_t netgr_translate_members_ldap_step(struct 
tevent_req *req)
         return EOK;
     }
 
+    if (!sss_ldap_dn_in_search_bases(state, state->dn_item->dn,
+                                     state->opts->netgroup_search_bases,
+                                     &filter)) {
+        /* not in search base, skip it */
+        state->dn_idx = state->dn_item->next;
+        DLIST_REMOVE(state->dn_list, state->dn_item);
+        return netgr_translate_members_ldap_step(req);
+    }
+
     cn_attr = talloc_array(state, const char *, 3);
     if (cn_attr == NULL) {
         DEBUG(1, ("talloc_array failed.\n"));
@@ -469,7 +479,7 @@ static errno_t netgr_translate_members_ldap_step(struct 
tevent_req *req)
 
     DEBUG(9, ("LDAP base search for [%s].\n", state->dn_item->dn));
     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
-                                   state->dn_item->dn, LDAP_SCOPE_BASE, NULL,
+                                   state->dn_item->dn, LDAP_SCOPE_BASE, filter,
                                    cn_attr, state->opts->netgroup_map,
                                    SDAP_OPTS_NETGROUP,
                                    dp_opt_get_int(state->opts->basic,
-- 
1.7.6.4

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to