The current code use some rough heuristics to determine if an object is a group or a user when calculating group memberships. That code easily breaks if you do not set a separate specific group base dn and is generally too tied to a specific DIT configuration.
The following patches instead actively lookup entries by their original DN so that group memberships can be translated correctly. The patch uses a dirty trick for now, it uses a synchronous[1] search (looping in place) to fetch the local entry. This was done to minimize the impact of the patch. 0001 talking with nalin it turns out that rfc2307bis is supposed to implement also nested groups, so I changed the code to do the same we do for ipa/ad servers in this case, and resolve nested groups. 0002 a patch that makes a couple of functions available to external callers 0003 the patch that actually fixes #264 Simo. [1] In general operations against the local ldb are "fake asynchronous" anyway when using the tdb backend. I am considering a future set of patches to make the sysdb code more synchronous like we did for the confdb code. The sysdb code was initially made asynchronous because we were considering using also the ldb_ldap backend, but it turned up we didn't. -- Simo Sorce * Red Hat, Inc * New York
>From 9f261eb0d4b18c09851231b86e2ff3ca949e656a Mon Sep 17 00:00:00 2001 From: Simo Sorce <[email protected]> Date: Mon, 30 Nov 2009 15:00:50 -0500 Subject: [PATCH 1/3] Resolve nested groups also when rfc2307bis is used --- server/providers/ldap/sdap_async_accounts.c | 70 +-------------------------- 1 files changed, 2 insertions(+), 68 deletions(-) diff --git a/server/providers/ldap/sdap_async_accounts.c b/server/providers/ldap/sdap_async_accounts.c index 07e165f..157ec3e 100644 --- a/server/providers/ldap/sdap_async_accounts.c +++ b/server/providers/ldap/sdap_async_accounts.c @@ -686,53 +686,6 @@ static int sdap_parse_memberships(TALLOC_CTX *memctx, break; case SDAP_SCHEMA_RFC2307BIS: - DEBUG(9, ("[RFC2307bis Schema]\n")); - - /* in this schema only users are members */ - mus = talloc_array(memctx, const char *, num_values +1); - if (!mus) { - ret = ENOMEM; - goto done; - } - - for (i = 0, u = 0; i < num_values; i++) { - struct ldb_dn *tmp_dn = NULL; - const struct ldb_val *v; - - /* parse out DN */ - tmp_dn = ldb_dn_new_fmt(mus, - sysdb_handle_get_ldb(handle), "%.*s", - (int)values[i].length, - (char *)values[i].data); - if (!tmp_dn) { - DEBUG(1, ("Unable to parse DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - v = ldb_dn_get_rdn_val(tmp_dn); - if (!v) { - DEBUG(1, ("Unable to parse DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - - mus[u] = talloc_asprintf(mus, "%.*s", - (int)v->length, - (char *)v->data); - if (!mus[u]) { - DEBUG(1, ("Out of memory?!\n")); - continue; - } - u++; - - DEBUG(9, ("Member DN [%.*s], RDN [%.*s]\n", - (int)values[i].length, (char *)values[i].data, - (int)v->length, (char *)v->data)); - } - break; - case SDAP_SCHEMA_IPA_V1: case SDAP_SCHEMA_AD: DEBUG(9, ("[IPA or AD Schema]\n")); @@ -1216,10 +1169,10 @@ struct tevent_req *sdap_save_groups_send(TALLOC_CTX *memctx, switch (opts->schema_type) { case SDAP_SCHEMA_RFC2307: - case SDAP_SCHEMA_RFC2307BIS: state->twopass = false; break; + case SDAP_SCHEMA_RFC2307BIS: case SDAP_SCHEMA_IPA_V1: case SDAP_SCHEMA_AD: state->twopass = true; @@ -2056,25 +2009,6 @@ static void sdap_get_initgr_process(struct tevent_req *subreq) break; case SDAP_SCHEMA_RFC2307BIS: - - ret = sysdb_attrs_get_string(state->orig_user, - SYSDB_ORIG_DN, &user_dn); - if (ret) { - tevent_req_error(req, EINVAL); - return; - } - - subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts, - state->sysdb, state->dom, - state->sh, user_dn, - state->name, state->grp_attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_done, req); - return; - case SDAP_SCHEMA_IPA_V1: case SDAP_SCHEMA_AD: /* TODO: AD uses a different member/memberof schema @@ -2109,11 +2043,11 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) switch (state->opts->schema_type) { case SDAP_SCHEMA_RFC2307: - case SDAP_SCHEMA_RFC2307BIS: ret = sdap_initgr_rfc2307_recv(subreq); break; + case SDAP_SCHEMA_RFC2307BIS: case SDAP_SCHEMA_IPA_V1: case SDAP_SCHEMA_AD: -- 1.6.2.5
>From b3a7d8ee6e8b18ae487a9bc66c21249fb3025556 Mon Sep 17 00:00:00 2001 From: Simo Sorce <[email protected]> Date: Mon, 30 Nov 2009 15:40:36 -0500 Subject: [PATCH 2/3] Make strdn build functions more available --- server/db/sysdb.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ server/db/sysdb.h | 4 ++++ server/db/sysdb_ops.c | 48 ++++++------------------------------------------ 3 files changed, 58 insertions(+), 42 deletions(-) diff --git a/server/db/sysdb.c b/server/db/sysdb.c index b59ffa4..c77c67c 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -254,6 +254,54 @@ int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, return ret; } +static char *build_dom_dn_str_escape(TALLOC_CTX *memctx, const char *template, + const char *domain, const char *name) +{ + char *ret; + int l; + + l = strcspn(name, ",=\n+<>#;\\\""); + if (name[l] != '\0') { + struct ldb_val v; + char *tmp; + + v.data = discard_const_p(uint8_t, name); + v.length = strlen(name); + + tmp = ldb_dn_escape_value(memctx, v); + if (!tmp) { + return NULL; + } + + ret = talloc_asprintf(memctx, template, tmp, domain); + talloc_zfree(tmp); + if (!ret) { + return NULL; + } + + return ret; + } + + ret = talloc_asprintf(memctx, template, name, domain); + if (!ret) { + return NULL; + } + + return ret; +} + +char *sysdb_user_strdn(TALLOC_CTX *memctx, + const char *domain, const char *name) +{ + return build_dom_dn_str_escape(memctx, SYSDB_TMPL_USER, domain, name); +} + +char *sysdb_group_strdn(TALLOC_CTX *memctx, + const char *domain, const char *name) +{ + return build_dom_dn_str_escape(memctx, SYSDB_TMPL_GROUP, domain, name); +} + /* TODO: make a more complete and precise mapping */ int sysdb_error_to_errno(int ldberr) { diff --git a/server/db/sysdb.h b/server/db/sysdb.h index bc2bf66..33e1728 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -192,6 +192,10 @@ struct ldb_dn *sysdb_custom_subtree_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain, const char *subtree_name); +char *sysdb_user_strdn(TALLOC_CTX *memctx, + const char *domain, const char *name); +char *sysdb_group_strdn(TALLOC_CTX *memctx, + const char *domain, const char *name); struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index da53fd3..93c24b1 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -2769,42 +2769,6 @@ int sysdb_store_user_recv(struct tevent_req *req) /* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */ -static char *build_dom_dn_str_escape(TALLOC_CTX *memctx, const char *template, - const char *domain, const char *name) -{ - char *ret; - int l; - - l = strcspn(name, ",=\n+<>#;\\\""); - if (name[l] != '\0') { - struct ldb_val v; - char *tmp; - - v.data = discard_const_p(uint8_t, name); - v.length = strlen(name); - - tmp = ldb_dn_escape_value(memctx, v); - if (!tmp) { - return NULL; - } - - ret = talloc_asprintf(memctx, template, tmp, domain); - talloc_zfree(tmp); - if (!ret) { - return NULL; - } - - return ret; - } - - ret = talloc_asprintf(memctx, template, name, domain); - if (!ret) { - return NULL; - } - - return ret; -} - /* this function does not check that all user members are actually present */ struct sysdb_store_group_state { @@ -2909,9 +2873,9 @@ static void sysdb_store_group_check(struct tevent_req *subreq) for (i = 0; state->member_users && state->member_users[i]; i++) { char *member; - member = build_dom_dn_str_escape(state, SYSDB_TMPL_USER, - state->domain->name, - state->member_users[i]); + member = sysdb_user_strdn(state, + state->domain->name, + state->member_users[i]); if (!member) { DEBUG(4, ("Error: Out of memory\n")); tevent_req_error(req, ENOMEM); @@ -2932,9 +2896,9 @@ static void sysdb_store_group_check(struct tevent_req *subreq) for (i = 0; state->member_groups && state->member_groups[i]; i++) { char *member; - member = build_dom_dn_str_escape(state, SYSDB_TMPL_GROUP, - state->domain->name, - state->member_groups[i]); + member = sysdb_group_strdn(state, + state->domain->name, + state->member_groups[i]); if (!member) { DEBUG(4, ("Error: Out of memory\n")); tevent_req_error(req, ENOMEM); -- 1.6.2.5
>From 0c50ee04780bd13a2a17064e9c9588762369931a Mon Sep 17 00:00:00 2001 From: Simo Sorce <[email protected]> Date: Mon, 30 Nov 2009 21:51:41 -0500 Subject: [PATCH 3/3] Fix nested group memberships Search the local db to find the local DN using the original DN as search key. This way we do not have to rely on weak and faulty heuristicts based on DN names. Add a few helper functions in the process and change the way we pass members to sysdb_store_group_send(), instead of passing users and groups list, just add member DNs to the other sysdb attrs. --- server/db/sysdb.c | 97 ++++++++++ server/db/sysdb.h | 13 +- server/db/sysdb_ops.c | 65 +------- server/providers/ldap/sdap_async_accounts.c | 272 +++++++++++++-------------- server/providers/proxy.c | 71 ++++++- server/tests/sysdb-tests.c | 2 +- 6 files changed, 299 insertions(+), 221 deletions(-) diff --git a/server/db/sysdb.c b/server/db/sysdb.c index c77c67c..7a23976 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -68,6 +68,11 @@ struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle) return handle->ctx->ldb; } +struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle) +{ + return handle->ctx; +} + struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx) { return talloc_zero(memctx, struct sysdb_attrs); @@ -254,6 +259,98 @@ int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, return ret; } +int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + const char **list) +{ + struct ldb_message_element *el = NULL; + struct ldb_val *vals; + int i, j, num; + char *member; + int ret; + + ret = sysdb_attrs_get_el(attrs, attr_name, &el); + if (!ret) { + return ret; + } + + for (num = 0; list[num]; num++) /* count */ ; + + vals = talloc_realloc(attrs->a, el->values, + struct ldb_val, el->num_values + num); + if (!vals) { + return ENOMEM; + } + el->values = vals; + + DEBUG(9, ("Adding %d members to existing %d ones\n", + num, el->num_values)); + + for (i = 0, j = el->num_values; i < num; i++) { + + member = sysdb_user_strdn(el->values, domain, list[i]); + if (!member) { + DEBUG(4, ("Failed to get user dn for [%s]\n", list[i])); + continue; + } + el->values[j].data = (uint8_t *)member; + el->values[j].length = strlen(member); + j++; + + DEBUG(7, (" member #%d: [%s]\n", i, member)); + } + el->num_values = j; + + return EOK; +} + +int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + struct ldb_val *values, + int num_values) +{ + struct ldb_message_element *el = NULL; + struct ldb_val *vals; + int i, j; + char *member; + int ret; + + ret = sysdb_attrs_get_el(attrs, attr_name, &el); + if (!ret) { + return ret; + } + + vals = talloc_realloc(el, el->values, struct ldb_val, + el->num_values + num_values); + if (!vals) { + return ENOMEM; + } + el->values = vals; + + DEBUG(9, ("Adding %d members to existing %d ones\n", + num_values, el->num_values)); + + for (i = 0, j = el->num_values; i < num_values; i++) { + member = sysdb_user_strdn(el->values, domain, + (char *)values[i].data); + if (!member) { + DEBUG(4, ("Failed to get user dn for [%s]\n", + (char *)values[i].data)); + return ENOMEM; + } + el->values[j].data = (uint8_t *)member; + el->values[j].length = strlen(member); + j++; + + DEBUG(7, (" member #%d: [%s]\n", i, member)); + } + el->num_values = j; + + return EOK; +} + static char *build_dom_dn_str_escape(TALLOC_CTX *memctx, const char *template, const char *domain, const char *name) { diff --git a/server/db/sysdb.h b/server/db/sysdb.h index 33e1728..a1851cd 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -175,6 +175,16 @@ int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname, const char *newname); +int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + const char **list); +int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs, + const char *attr_name, + const char *domain, + struct ldb_val *values, + int num_values); + /* convert an ldb error into an errno error */ int sysdb_error_to_errno(int ldberr); @@ -200,6 +210,7 @@ char *sysdb_group_strdn(TALLOC_CTX *memctx, struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle); +struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle); int compare_ldb_dn_comp_num(const void *m1, const void *m2); @@ -497,8 +508,6 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char **member_users, - const char **member_groups, struct sysdb_attrs *attrs, uint64_t cache_timeout); int sysdb_store_group_recv(struct tevent_req *req); diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index 93c24b1..8819919 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -2778,8 +2778,6 @@ struct sysdb_store_group_state { const char *name; gid_t gid; - const char **member_users; - const char **member_groups; struct sysdb_attrs *attrs; @@ -2796,8 +2794,6 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char **member_users, - const char **member_groups, struct sysdb_attrs *attrs, uint64_t cache_timeout) { @@ -2815,8 +2811,6 @@ struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, state->domain = domain; state->name = name; state->gid = gid; - state->member_users = member_users; - state->member_groups = member_groups; state->attrs = attrs; state->cache_timeout = cache_timeout; @@ -2845,7 +2839,7 @@ static void sysdb_store_group_check(struct tevent_req *subreq) struct ldb_message *msg; time_t now = time(NULL); bool new_group = false; - int ret, i; + int ret; ret = sysdb_search_group_recv(subreq, state, &msg); talloc_zfree(subreq); @@ -2860,63 +2854,6 @@ static void sysdb_store_group_check(struct tevent_req *subreq) /* FIXME: use the remote modification timestamp to know if the * group needs any update */ - if (state->member_users || state->member_groups) { - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - for (i = 0; state->member_users && state->member_users[i]; i++) { - char *member; - - member = sysdb_user_strdn(state, - state->domain->name, - state->member_users[i]); - if (!member) { - DEBUG(4, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - DEBUG(9, ("adding member: %s to group %s\n", - member, state->name)); - - ret = sysdb_attrs_steal_string(state->attrs, - SYSDB_MEMBER, member); - if (ret) { - DEBUG(4, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - for (i = 0; state->member_groups && state->member_groups[i]; i++) { - char *member; - - member = sysdb_group_strdn(state, - state->domain->name, - state->member_groups[i]); - if (!member) { - DEBUG(4, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - DEBUG(9, ("adding member: %s to group %s\n", - member, state->name)); - - ret = sysdb_attrs_steal_string(state->attrs, - SYSDB_MEMBER, member); - if (ret) { - DEBUG(4, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - } - if (new_group) { /* group doesn't exist, turn into adding a group */ subreq = sysdb_add_group_send(state, state->ev, state->handle, diff --git a/server/providers/ldap/sdap_async_accounts.c b/server/providers/ldap/sdap_async_accounts.c index 157ec3e..e4656cd 100644 --- a/server/providers/ldap/sdap_async_accounts.c +++ b/server/providers/ldap/sdap_async_accounts.c @@ -624,64 +624,110 @@ int sdap_get_users_recv(struct tevent_req *req, /* ==Group-Parsing Routines=============================================== */ -static int sdap_parse_memberships(TALLOC_CTX *memctx, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct ldb_val *values, - int num_values, - const char ***member_users, - const char ***member_groups) +struct sdap_orig_entry_state { + int done; +}; + +static void sdap_find_entry_by_origDN_done(struct tevent_req *req) +{ + struct sdap_orig_entry_state *state = tevent_req_callback_data(req, + struct sdap_orig_entry_state); + state->done = 1; +} + +/* WARNING: this is a sync routine for now */ +static int sdap_find_entry_by_origDN(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *orig_dn, + char **localdn) { - const char **mgs = NULL; - const char **mus = NULL; - int i, u, g; + struct tevent_req *req; + struct sdap_orig_entry_state *state; + static const char *attrs[] = { NULL }; + struct ldb_dn *base_dn; + char *filter; + struct ldb_message **msgs; + size_t num_msgs; int ret; - /* if this is the first time we are called, check if users and - * groups base DNs are set, if not do it */ - if (!opts->users_base) { - opts->users_base = ldb_dn_new_fmt(opts, - sysdb_handle_get_ldb(handle), "%s", - dp_opt_get_string(opts->basic, - SDAP_USER_SEARCH_BASE)); - if (!opts->users_base) { - DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", - dp_opt_get_string(opts->basic, - SDAP_USER_SEARCH_BASE))); - DEBUG(1, ("Out of memory?!\n")); - ret = ENOMEM; - goto done; - } + state = talloc_zero(memctx, struct sdap_orig_entry_state); + if (!state) { + ret = ENOMEM; + goto done; } - if (!opts->groups_base) { - opts->groups_base = ldb_dn_new_fmt(opts, - sysdb_handle_get_ldb(handle), "%s", - dp_opt_get_string(opts->basic, - SDAP_GROUP_SEARCH_BASE)); - if (!opts->users_base) { - DEBUG(1, ("Unable to get casefold Users Base DN from [%s]\n", - dp_opt_get_string(opts->basic, - SDAP_GROUP_SEARCH_BASE))); - DEBUG(1, ("Out of memory?!\n")); - ret = ENOMEM; - goto done; - } + + filter = talloc_asprintf(state, "%s=%s", SYSDB_ORIG_DN, orig_dn); + if (!filter) { + ret = ENOMEM; + goto done; + } + + base_dn = sysdb_domain_dn(sysdb_handle_get_ctx(handle), + state, domain->name); + if (!base_dn) { + ret = ENOMEM; + goto done; + } + + req = sysdb_search_entry_send(state, ev, handle, base_dn, + LDB_SCOPE_SUBTREE, filter, attrs); + if (!req) { + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(req, sdap_find_entry_by_origDN_done, state); + + /* WARNING: SYNC LOOP HERE */ + while (state->done == 0) { + tevent_loop_once(ev); + } + + ret = sysdb_search_entry_recv(req, state, &num_msgs, &msgs); + if (ret) { + goto done; + } + if (num_msgs != 1) { + ret = ENOENT; + goto done; + } + + *localdn = talloc_strdup(memctx, ldb_dn_get_linearized(msgs[0]->dn)); + if (!*localdn) { + ret = ENOENT; + goto done; } + ret = EOK; + +done: + talloc_zfree(state); + return ret; +} + +static int sdap_fill_memberships(struct sysdb_attrs *group_attrs, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sdap_options *opts, + struct sss_domain_info *domain, + struct ldb_val *values, + int num_values) +{ + struct ldb_message_element *el; + int i, j; + int ret; + switch (opts->schema_type) { case SDAP_SCHEMA_RFC2307: DEBUG(9, ("[RFC2307 Schema]\n")); - mus = talloc_array(memctx, const char *, num_values +1); - if (!mus) { - ret = ENOMEM; + ret = sysdb_attrs_users_from_ldb_vals(group_attrs, SYSDB_MEMBER, + domain->name, + values, num_values); + if (ret) { goto done; } - for (i = 0; i < num_values; i++) { - mus[i] = (char *)values[i].data; - DEBUG(7, (" member user %d: [%s]\n", i, mus[i])); - } - mus[i] = NULL; break; @@ -690,93 +736,43 @@ static int sdap_parse_memberships(TALLOC_CTX *memctx, case SDAP_SCHEMA_AD: DEBUG(9, ("[IPA or AD Schema]\n")); - /* Just allocate both big enough to contain all members for now */ - mus = talloc_array(memctx, const char *, num_values +1); - if (!mus) { - ret = ENOMEM; + ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el); + if (ret) { goto done; } - mgs = talloc_array(memctx, const char *, num_values +1); - if (!mgs) { + /* Just allocate both big enough to contain all members for now */ + el->values = talloc_realloc(el, el->values, struct ldb_val, + el->num_values + num_values); + if (!el->values) { ret = ENOMEM; goto done; } - u = 0; - g = 0; - - for (i = 0; i < num_values; i++) { - struct ldb_dn *tmp_dn = NULL; - const struct ldb_val *v; - - /* parse out DN */ - tmp_dn = ldb_dn_new_fmt(mus, - sysdb_handle_get_ldb(handle), - "%.*s", - (int)values[i].length, - (char *)values[i].data); - if (!tmp_dn) { - DEBUG(1, ("Unable to parse DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - v = ldb_dn_get_rdn_val(tmp_dn); - if (!v) { - DEBUG(1, ("Unable to parse DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - DEBUG(9, ("Member DN [%.*s], RDN [%.*s]\n", - (int)values[i].length, (char *)values[i].data, - (int)v->length, (char *)v->data)); - - if (ldb_dn_compare_base(opts->users_base, tmp_dn) == 0) { - mus[u] = talloc_asprintf(mus, "%.*s", - (int)v->length, - (char *)v->data); - if (!mus[u]) { - DEBUG(1, ("Out of memory?!\n")); - continue; - } - u++; - - DEBUG(7, (" member user %d: [%.*s]\n", i, - (int)v->length, (char *)v->data)); - } else - if (ldb_dn_compare_base(opts->groups_base, tmp_dn) == 0) { - mgs[g] = talloc_asprintf(mgs, "%.*s", - (int)v->length, - (char *)v->data); - if (!mgs[g]) { - DEBUG(1, ("Out of memory?!\n")); - continue; + for (i = 0, j = el->num_values; i < num_values; i++) { + + /* sync search entry with this as origDN */ + ret = sdap_find_entry_by_origDN(el->values, ev, + handle, domain, + (char *)values[i].data, + (char **)&el->values[j].data); + if (ret != EOK) { + if (ret != ENOENT) { + goto done; } - g++; - DEBUG(7, (" member group %d: [%.*s]\n", i, - (int)v->length, (char *)v->data)); + DEBUG(7, (" member #%d (%s): not found!\n", + i, (char *)values[i].data)); } else { - DEBUG(1, ("Unkown Member type for DN: [%.*s]\n", - (int)values[i].length, - (char *)values[i].data)); - continue; - } - } + DEBUG(7, (" member #%d (%s): [%s]\n", + i, (char *)values[i].data, + (char *)el->values[j].data)); - if (g) { - mgs[g] = NULL; - } else { - talloc_zfree(mgs); - } - - if (u) { - mus[u] = NULL; - } else { - talloc_zfree(mus); + el->values[j].length = strlen((char *)el->values[j].data); + j++; + } } + el->num_values = j; break; @@ -790,14 +786,6 @@ static int sdap_parse_memberships(TALLOC_CTX *memctx, ret = EOK; done: - if (ret != EOK) { - talloc_zfree(mus); - talloc_zfree(mgs); - } - - *member_users = mus; - *member_groups = mgs; - return ret; } @@ -830,8 +818,6 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, struct tevent_req *req, *subreq; struct sdap_save_group_state *state; struct ldb_message_element *el; - const char **member_groups = NULL; - const char **member_users = NULL; struct sysdb_attrs *group_attrs; long int l; gid_t gid; @@ -937,9 +923,8 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, } else { DEBUG(7, ("Adding member users to group [%s]\n", state->name)); - ret = sdap_parse_memberships(state, handle, opts, - el->values, el->num_values, - &member_users, &member_groups); + ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom, + el->values, el->num_values); if (ret) { goto fail; } @@ -951,7 +936,6 @@ static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, subreq = sysdb_store_group_send(state, state->ev, state->handle, state->dom, state->name, gid, - member_users, member_groups, group_attrs, dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT)); @@ -1031,8 +1015,7 @@ static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, struct tevent_req *req, *subreq; struct sdap_save_grpmem_state *state; struct ldb_message_element *el; - const char **member_groups = NULL; - const char **member_users = NULL; + struct sysdb_attrs *group_attrs = NULL; int ret; req = tevent_req_create(memctx, &state, struct sdap_save_grpmem_state); @@ -1061,9 +1044,14 @@ static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, } else { DEBUG(7, ("Adding member users to group [%s]\n", state->name)); - ret = sdap_parse_memberships(state, handle, opts, - el->values, el->num_values, - &member_users, &member_groups); + group_attrs = sysdb_new_attrs(state); + if (!group_attrs) { + ret = ENOMEM; + goto fail; + } + + ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom, + el->values, el->num_values); if (ret) { goto fail; } @@ -1074,8 +1062,7 @@ static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, subreq = sysdb_store_group_send(state, state->ev, state->handle, state->dom, state->name, 0, - member_users, member_groups, - NULL, + group_attrs, dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT)); if (!subreq) { @@ -1982,7 +1969,6 @@ static void sdap_get_initgr_process(struct tevent_req *subreq) struct tevent_req); struct sdap_get_initgr_state *state = tevent_req_data(req, struct sdap_get_initgr_state); - const char *user_dn; int ret; DEBUG(9, ("Process user's groups\n")); diff --git a/server/providers/proxy.c b/server/providers/proxy.c index f55b1c2..ef52ae9 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -956,7 +956,7 @@ static void get_gr_name_process(struct tevent_req *subreq) char *newbuf; size_t buflen; bool delete_group = false; - const char **members; + struct sysdb_attrs *members; int ret; DEBUG(7, ("Searching group by name (%s)\n", state->name)); @@ -1031,7 +1031,18 @@ again: DEBUG_GR_MEM(7, state); if (state->grp->gr_mem && state->grp->gr_mem[0]) { - members = (const char **)state->grp->gr_mem; + members = sysdb_new_attrs(state); + if (!members) { + tevent_req_error(req, ENOMEM); + return; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + tevent_req_error(req, ret); + return; + } } else { members = NULL; } @@ -1040,7 +1051,7 @@ again: state->domain, state->grp->gr_name, state->grp->gr_gid, - members, NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { tevent_req_error(req, ENOMEM); @@ -1178,7 +1189,7 @@ static void get_gr_gid_process(struct tevent_req *subreq) char *newbuf; size_t buflen; bool delete_group = false; - const char **members; + struct sysdb_attrs *members; int ret; DEBUG(7, ("Searching group by gid (%d)\n", state->gid)); @@ -1251,7 +1262,18 @@ again: DEBUG_GR_MEM(7, state); if (state->grp->gr_mem && state->grp->gr_mem[0]) { - members = (const char **)state->grp->gr_mem; + members = sysdb_new_attrs(state); + if (!members) { + tevent_req_error(req, ENOMEM); + return; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + tevent_req_error(req, ret); + return; + } } else { members = NULL; } @@ -1260,7 +1282,7 @@ again: state->domain, state->grp->gr_name, state->grp->gr_gid, - members, NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { tevent_req_error(req, ENOMEM); @@ -1405,7 +1427,7 @@ static void enum_groups_process(struct tevent_req *subreq) struct proxy_ctx *ctx = state->ctx; struct sss_domain_info *dom = ctx->be->domain; enum nss_status status; - const char **members; + struct sysdb_attrs *members; char *newbuf; int ret; @@ -1486,7 +1508,18 @@ again: DEBUG_GR_MEM(7, state); if (state->grp->gr_mem && state->grp->gr_mem[0]) { - members = (const char **)state->grp->gr_mem; + members = sysdb_new_attrs(state); + if (!members) { + tevent_req_error(req, ENOMEM); + return; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + tevent_req_error(req, ret); + return; + } } else { members = NULL; } @@ -1495,7 +1528,7 @@ again: state->domain, state->grp->gr_name, state->grp->gr_gid, - members, NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { tevent_req_error(req, ENOMEM); @@ -1881,6 +1914,7 @@ static struct tevent_req *get_group_from_gid_send(TALLOC_CTX *mem_ctx, char *newbuf; size_t buflen; bool delete_group = false; + struct sysdb_attrs *members; int ret; req = tevent_req_create(mem_ctx, &state, struct proxy_state); @@ -1948,12 +1982,27 @@ again: break; } + if (state->grp->gr_mem && state->grp->gr_mem[0]) { + members = sysdb_new_attrs(state); + if (!members) { + ret = ENOMEM; + goto fail; + } + ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER, + state->domain->name, + (const char **)state->grp->gr_mem); + if (ret) { + goto fail; + } + } else { + members = NULL; + } + subreq = sysdb_store_group_send(state, state->ev, state->handle, state->domain, state->grp->gr_name, state->grp->gr_gid, - (const char **)state->grp->gr_mem, - NULL, NULL, + members, ctx->entry_cache_timeout); if (!subreq) { ret = ENOMEM; diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index d4f0e2f..771f6a4 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -479,7 +479,7 @@ static void test_store_group(struct tevent_req *req) subreq = sysdb_store_group_send(data, data->ev, data->handle, data->ctx->domain, data->groupname, - data->gid, NULL, NULL, NULL, -1); + data->gid, NULL, -1); if (!subreq) { test_return(data, ret); } -- 1.6.2.5
_______________________________________________ sssd-devel mailing list [email protected] https://fedorahosted.org/mailman/listinfo/sssd-devel
