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