On Fri, Jan 24, 2014 at 08:31:00PM +0100, Jakub Hrozek wrote: > On Wed, Jan 22, 2014 at 03:26:07PM +0100, Jakub Hrozek wrote: > > On Wed, Jan 22, 2014 at 12:02:34AM +0100, Jakub Hrozek wrote: > > > On Fri, Jan 10, 2014 at 02:54:46PM +0100, Sumit Bose wrote: > > > > On Fri, Jan 10, 2014 at 02:35:12PM +0100, Jakub Hrozek wrote: > > > > > On Fri, Jan 10, 2014 at 12:59:05PM +0100, Sumit Bose wrote: > > > > > > On Tue, Dec 17, 2013 at 09:00:25PM +0100, Jakub Hrozek wrote: > > > > > > > Hi, > > > > > > > > > > > > > > the attached patches address ticket > > > > > > > https://fedorahosted.org/sssd/ticket/2142 > > > > > > > > > > > > > > There are some things I'm still not satisfied with and one of > > > > > > > them is > > > > > > > refreshing subdomains. Currently the subdomain refresh happens > > > > > > > after > > > > > > > startup and then only if a direct lookup for a user or group > > > > > > > happens and > > > > > > > the timeout for subdomain refresh is over. So in theory it's > > > > > > > possible > > > > > > > that the user and group objects will be refreshed by the > > > > > > > enumeration > > > > > > > task only and there would be no lookup to trigger the subdomain > > > > > > > refresh. > > > > > > > > > > > > > > With master domain enumeration we've solved this problem by > > > > > > > re-downloading master domain info before the enumeration request. > > > > > > > We > > > > > > > could do something similar with subdomains (although a little more > > > > > > > involved becase there is always precisely one subdomain), but I > > > > > > > didn't > > > > > > > like doing all the changes in 1.11.3. I can code up additional > > > > > > > patch > > > > > > > only for master, though. > > > > > > > > > > > > > > Something similar is with fallback from GC to LDAP. Although here > > > > > > > I'm > > > > > > > not convinced we need to perform the fallback at all, since there > > > > > > > are > > > > > > > already patches on the list that implement the option to disable > > > > > > > GC > > > > > > > lookups and there will also be a patch to autodetect POSIX > > > > > > > attributes in > > > > > > > GC. > > > > > > > > > > > > > > These patches must be applied on top of my previous patches. > > > > > > > > > > > > Can you rebase these patches and their prerequisites? They do not > > > > > > apply > > > > > > to master anymore. I also cloud not apply "AD: Retry and terminate > > > > > > sdap_id_op if possible". > > > > > > Hi, > > > > > > the "AD: Retry and terminate sdap_id_op if possible" patch is not > > > strictly required, so I haven't rebased and resent it yet. > > > > > > > > > > > > > Sure, will do. > > > > > > > > > > > > > > > > > Based on the experience with AD group-memberships and the recent > > > > > > changes where we switch back from GC to LDAP to determine > > > > > > group-memberships I would suggest to use the LDAP connect for the > > > > > > group > > > > > > enumeration as well. > > > > > > > > > > The last word in a private mini-thread with Simo was to use LDAP for > > > > > the > > > > > parent domain by default and GC elsewhere, right? I would also like to > > > > > check all code is consistent when changing these patches. > > > > > > > > I think in the general only universal group can be retrieve correctly > > > > form the GC. If we read LDAP for the parent domain there are still the > > > > global groups from the other domains which might be incomplete in the > > > > GC. > > > > > > I've been testing the enumeration quite a bit and unfortunately I > > > found a defect that is not so easily fixed with the current enumeration > > > architecture. Because the original patches enumerated the primary domain > > > and > > > subdomain separately, cross-domain memberships were hard, if not > > > impossible > > > to maintain, at least because there was no guarantee on the order or > > > completeness of enumeration. > > > > > > So attached are rebased the original patches with the connections fixed > > > as you liked. But cross-domain memberships don't work. > > > > > > I have two additional patches, one finished and one WIP in my ad_enum > > > branch: > > > http://fedorapeople.org/cgit/jhrozek/public_git/sssd.git/log/?h=ad_enum > > > > > > The first makes sure the original_member contains the original DN and > > > not sysdb DN :-) The other is not finished but my intent was to > > > 1) check if any subdomains were enumerated. If not, do nothing > > > 2) if any of the groups saved had more original members than sysdb > > > members, check if members of these groups can be linked now that all > > > users and groups are saved. > > > > > > I hope this would be acceptable, because the cost is only incurred if > > > subdomains are enumerated and there are cross-domain memberships at the > > > same time.. Any other solution I could think of would require bigger > > > changes, but I'd welcome other ideas. > > > > Hi, > > > > all patches are attached now. With the attached patches, even > > cross-domain memberships are established in my testing if enumeration is > > on. > > Hi, > > Sumit found a rather embarrasing bug in the code, where a tevent_req was > terminated even if it shouldn't. I guess my testing only went fine > because the server and client are really close to one another and thus > the request completed quickly. > > Thank you for the review. A new set of patches is attached.
Patches 1, 2, 3 and 5 are looking good. In patch 4 you add ad_enum_subdom_send() and ad_enum_subdom_done() (without calling them) and in patch 6 you remove them again. Other comments for patch 6 are inline. bye, Sumit > From 066ce9945b6af3748f0ead06213f0180a742c542 Mon Sep 17 00:00:00 2001 > From: Jakub Hrozek <jhro...@redhat.com> > Date: Wed, 22 Jan 2014 15:21:24 +0100 > Subject: [PATCH 6/6] AD: Establish cross-domain memberships after enumeration > finishes > > Because domain enumeration currently works for each domain separately, > the code has to establish cross-domain memberships after all domains are > enumerated. The code works as follows: > > 1) check if any *sub*domains were enumerated. If not, do nothing > 2) if any of the groups saved had more original members than > sysdb members, check if members of these groups can be linked now > that all users and groups are saved using the orig_member > attribute of the group matched against originalDN member of the > user. > > Related: > https://fedorahosted.org/sssd/ticket/2142 > --- > src/providers/ad/ad_id.c | 515 > +++++++++++++++++++++++++++++++++++------------ > 1 file changed, 390 insertions(+), 125 deletions(-) > > diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c > index > 1bdacf74f0e6de2120603401bcf115549a03ac4f..8818869f73be4afa8b36c0da0341391b569aafd2 > 100644 > --- a/src/providers/ad/ad_id.c > +++ b/src/providers/ad/ad_id.c > @@ -420,10 +420,13 @@ struct ad_enumeration_state { > struct tevent_context *ev; > > struct sdap_domain *sdom; > + struct sdap_domain *sditer; > }; > > static void ad_enumeration_conn_done(struct tevent_req *subreq); > static void ad_enumeration_master_done(struct tevent_req *subreq); > +static errno_t ad_enum_sdom(struct tevent_req *req, struct sdap_domain *sd, > + struct ad_id_ctx *id_ctx); > static void ad_enumeration_done(struct tevent_req *subreq); > > struct tevent_req * > @@ -452,6 +455,7 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx, > state->ectx = ectx; > state->ev = ev; > state->sdom = ectx->sdom; > + state->sditer = state->sdom; > state->id_ctx = talloc_get_type(ectx->pvt, struct ad_id_ctx); > > state->sdap_op = sdap_id_op_create(state, > @@ -526,7 +530,6 @@ ad_enumeration_master_done(struct tevent_req *subreq) > char *flat_name; > char *master_sid; > char *forest; > - struct sdap_id_conn_ctx *user_conn; > > ret = ad_master_domain_recv(subreq, state, > &flat_name, &master_sid, &forest); > @@ -545,32 +548,57 @@ ad_enumeration_master_done(struct tevent_req *subreq) > return; > } > > - if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC)) { > - user_conn = state->id_ctx->gc_ctx; > + ret = ad_enum_sdom(req, state->sdom, state->id_ctx); > + if (ret != EOK) { > + DEBUG(SSSDBG_OP_FAILURE, > + ("Could not enumerate domain %s\n", state->sdom->dom->name)); > + tevent_req_error(req, ret); > + return; > + } > + > + /* Execution will resume in ad_enumeration_done */ > +} > + > +static errno_t > +ad_enum_sdom(struct tevent_req *req, > + struct sdap_domain *sd, > + struct ad_id_ctx *id_ctx) > +{ > + struct sdap_id_conn_ctx *user_conn; > + struct tevent_req *subreq; > + struct ad_enumeration_state *state = tevent_req_data(req, > + struct ad_enumeration_state); > + > + if (dp_opt_get_bool(id_ctx->ad_options->basic, AD_ENABLE_GC)) { > + user_conn = id_ctx->gc_ctx; > } else { > - user_conn = state->id_ctx->ldap_ctx; > + user_conn = id_ctx->ldap_ctx; > } > > /* Groups are searched for in LDAP, users in GC. Services (if present, > * which is unlikely in AD) from LDAP as well > */ > subreq = sdap_dom_enum_ex_send(state, state->ev, > - state->id_ctx->sdap_id_ctx, > - state->sdom, > - user_conn, /* Users */ > - state->id_ctx->ldap_ctx, /* Groups */ > - state->id_ctx->ldap_ctx); /* Services */ > + id_ctx->sdap_id_ctx, > + sd, > + user_conn, /* Users */ > + id_ctx->ldap_ctx, /* Groups */ > + id_ctx->ldap_ctx); /* Services */ > if (subreq == NULL) { > /* The ptask API will reschedule the enumeration on its own on > * failure */ > DEBUG(SSSDBG_OP_FAILURE, > ("Failed to schedule enumeration, retrying later!\n")); > - tevent_req_error(req, ENOMEM); > - return; > + return ENOMEM; > } > tevent_req_set_callback(subreq, ad_enumeration_done, req); > + > + return EOK; > } > > +static errno_t ad_enum_cross_dom_members(struct sdap_options *opts, > + struct sss_domain_info *dom); > + > static void > ad_enumeration_done(struct tevent_req *subreq) > { > @@ -579,121 +607,8 @@ ad_enumeration_done(struct tevent_req *subreq) > struct tevent_req); > struct ad_enumeration_state *state = tevent_req_data(req, > struct ad_enumeration_state); > - > - ret = sdap_dom_enum_ex_recv(subreq); > - talloc_zfree(subreq); > - if (ret != EOK) { > - DEBUG(SSSDBG_OP_FAILURE, > - ("Could not enumerate domain %s\n", state->sdom->dom->name)); > - tevent_req_error(req, ret); > - return; > - } > - > - tevent_req_done(req); > -} > - > -errno_t > -ad_enumeration_recv(struct tevent_req *req) > -{ > - TEVENT_REQ_RETURN_ON_ERROR(req); > - return EOK; > -} > - > -/* Enumerate a subdomain */ > -struct ad_enum_subdom_state { > - struct ad_id_ctx *id_ctx; > struct ad_id_ctx *subdom_id_ctx; > > - struct ldap_enum_ctx *ectx; > - struct tevent_context *ev; > - > - struct sdap_domain *sdom; > -}; > - > -static void ad_enum_subdom_done(struct tevent_req *subreq); > - > -struct tevent_req * > -ad_enum_subdom_send(TALLOC_CTX *mem_ctx, > - struct tevent_context *ev, > - struct be_ctx *be_ctx, > - struct be_ptask *be_ptask, > - void *pvt) > -{ see above. > - struct tevent_req *req; > - struct tevent_req *subreq; > - struct ad_enum_subdom_state *state; > - struct ldap_enum_ctx *ectx; > - errno_t ret; > - struct sdap_id_conn_ctx *user_conn; > - > - req = tevent_req_create(mem_ctx, &state, struct ad_enum_subdom_state); > - if (req == NULL) return NULL; > - > - ectx = talloc_get_type(pvt, struct ldap_enum_ctx); > - if (ectx == NULL) { > - DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve ldap_enum_ctx!\n")); > - ret = EFAULT; > - goto fail; > - } > - > - state->ectx = ectx; > - state->ev = ev; > - state->sdom = ectx->sdom; > - state->id_ctx = talloc_get_type(ectx->pvt, struct ad_id_ctx); > - if (state->id_ctx == NULL) { > - DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve ad_id_ctx!\n")); > - ret = EFAULT; > - goto fail; > - } > - > - state->subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct > ad_id_ctx); > - if (state->subdom_id_ctx == NULL) { > - DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve subdomain > ad_id_ctx!\n")); > - ret = EFAULT; > - goto fail; > - } > - > - if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC)) { > - user_conn = state->id_ctx->gc_ctx; > - } else { > - user_conn = state->subdom_id_ctx->ldap_ctx; > - } > - > - /* Groups are searched for in LDAP, users in GC. Services (if present, > - * which is unlikely in AD) from LDAP as well > - */ > - subreq = sdap_dom_enum_ex_send(state, state->ev, > state->id_ctx->sdap_id_ctx, > - state->sdom, > - user_conn, /* Users > */ > - state->subdom_id_ctx->ldap_ctx, /* Groups > */ > - state->subdom_id_ctx->ldap_ctx);/* svcs */ > - if (subreq == NULL) { > - /* The ptask API will reschedule the enumeration on its own on > - * failure */ > - DEBUG(SSSDBG_OP_FAILURE, > - ("Failed to schedule enumeration, retrying later!\n")); > - ret = ENOMEM; > - goto fail; > - } > - tevent_req_set_callback(subreq, ad_enum_subdom_done, req); > - > - return req; > - > -fail: > - tevent_req_error(req, ret); > - tevent_req_post(req, ev); > - return req; > -} > - > -static void > -ad_enum_subdom_done(struct tevent_req *subreq) > -{ > - errno_t ret; > - struct tevent_req *req = tevent_req_callback_data(subreq, > - struct tevent_req); > - struct ad_enum_subdom_state *state = tevent_req_data(req, > - struct ad_enum_subdom_state); > - > ret = sdap_dom_enum_ex_recv(subreq); > talloc_zfree(subreq); > if (ret != EOK) { > @@ -703,11 +618,361 @@ ad_enum_subdom_done(struct tevent_req *subreq) > return; > } > > + state->sditer = state->sditer->next; > + if (state->sditer != NULL) { > + subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx); > + if (subdom_id_ctx == NULL) { > + DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve subdomain > ad_id_ctx!\n")); > + tevent_req_error(req, EFAULT); > + return; > + } > + > + ret = ad_enum_sdom(req, state->sditer, state->sditer->pvt); ret is not checked here as well. > + DEBUG(SSSDBG_OP_FAILURE, > + ("Could not enumerate domain %s\n", state->sditer->dom->name)); > + tevent_req_error(req, ret); > + return; > + } > + > + /* No more subdomains to enumerate. Check if we need to fixup > + * cross-domain membership > + */ > + if (state->sditer != state->sdom) { > + /* We did enumerate at least one subdomain. Walk the subdomains > + * and fixup members for each of them > + */ > + for (state->sditer = state->sdom; > + state->sditer; > + state->sditer = state->sditer->next) { > + ret = ad_enum_cross_dom_members(state->id_ctx->ad_options->id, > + state->sditer->dom); > + if (ret != EOK) { > + DEBUG(SSSDBG_MINOR_FAILURE, ("Could not check cross-domain " > + "memberships for %s, group memberships might be " > + "incomplete!\n", state->sdom->dom->name)); > + continue; > + } > + } > + } > + > tevent_req_done(req); > } > > +static errno_t ad_group_extra_members(TALLOC_CTX *mem_ctx, > + const struct ldb_message *group, > + struct sss_domain_info *dom, > + char ***_group_only); > +static errno_t ad_group_add_member(struct sdap_options *opts, > + struct sss_domain_info *group_domain, > + struct ldb_dn *group_dn, > + const char *member); > + > +static errno_t > +ad_enum_cross_dom_members(struct sdap_options *opts, > + struct sss_domain_info *dom) > +{ > + errno_t ret; > + errno_t sret; > + char *filter; > + TALLOC_CTX *tmp_ctx; > + const char *attrs[] = { > + SYSDB_NAME, > + SYSDB_MEMBER, > + SYSDB_ORIG_MEMBER, > + NULL > + }; > + size_t count, i, mi; > + struct ldb_message **msgs; > + bool in_transaction = false; > + char **group_only; > + > + tmp_ctx = talloc_new(NULL); > + if (tmp_ctx == NULL) return ENOMEM; > + > + ret = sysdb_transaction_start(dom->sysdb); > + if (ret != EOK) { > + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); > + goto done; > + } > + in_transaction = true; > + > + filter = talloc_asprintf(tmp_ctx, "(%s=*)", SYSDB_NAME); > + if (filter == NULL) { > + ret = ENOMEM; > + goto done; > + } > + > + ret = sysdb_search_groups(tmp_ctx, dom, filter, attrs, &count, &msgs); > + if (ret != EOK) { > + goto done; > + } You try to process all groups in a domain in a single batch. We might run into performance/memory issues if there are a lot of groups. But I think we can keep it as it is for the time being since the easy workaround is to disable enumeration :-) > + > + for (i = 0; i < count; i++) { > + ret = ad_group_extra_members(tmp_ctx, msgs[i], dom, &group_only); > + if (ret != EOK) { > + DEBUG(SSSDBG_OP_FAILURE, ("Failed to check extra members\n")); > + } else if (group_only == NULL) { > + DEBUG(SSSDBG_TRACE_INTERNAL, ("No extra members\n")); > + continue; > + } > + > + /* Group has extra members */ > + for (mi = 0; group_only[mi]; mi++) { > + ret = ad_group_add_member(opts, dom, msgs[i]->dn, > group_only[mi]); > + if (ret != EOK) { > + DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add [%s]: %s\n", > + group_only[mi], strerror(ret))); > + continue; > + } > + } > + } > + > + ret = sysdb_transaction_commit(dom->sysdb); > + if (ret != EOK) { > + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); > + goto done; > + } > + in_transaction = false; > + > + ret = EOK; > +done: > + if (in_transaction) { > + sret = sysdb_transaction_cancel(dom->sysdb); > + if (sret != EOK) { > + DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); > + } > + } > + talloc_free(tmp_ctx); > + return ret; > +} > + > +static char ** > +ad_group_orig_members(TALLOC_CTX *mem_ctx, struct ldb_message_element *om); > +static errno_t > +ad_group_stored_orig_members(TALLOC_CTX *mem_ctx, struct sss_domain_info > *dom, > + struct ldb_dn *dn, char ***_odn_list); > + > +static errno_t > +ad_group_extra_members(TALLOC_CTX *mem_ctx, const struct ldb_message *group, > + struct sss_domain_info *dom, char ***_group_only) > +{ > + TALLOC_CTX *tmp_ctx; > + struct ldb_message_element *m, *om; > + const char *name; > + errno_t ret; > + char **sysdb_odn_list; > + char **group_odn_list; > + char **group_only = NULL; > + > + if (_group_only == NULL) return EINVAL; > + *_group_only = NULL; > + > + tmp_ctx = talloc_new(NULL); > + if (tmp_ctx == NULL) return ENOMEM; > + > + om = ldb_msg_find_element(group, SYSDB_ORIG_MEMBER); > + m = ldb_msg_find_element(group, SYSDB_MEMBER); > + name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL); > + if (name == NULL) { > + DEBUG(SSSDBG_OP_FAILURE, ("A group with no name!\n")); > + ret = EFAULT; > + goto done; > + } > + > + if (om == NULL || om->num_values == 0) { > + DEBUG(SSSDBG_TRACE_FUNC, ("Group %s has no original members\n", > name)); > + ret = EOK; > + goto done; > + } > + > + if (m == NULL || (m->num_values < om->num_values)) { > + DEBUG(SSSDBG_TRACE_FUNC, > + ("Group %s has %d members but %d original members\n", > + name, m ? m->num_values : 0, om->num_values)); > + > + /* Get the list of originalDN attributes that are already > + * linked to the group > + */ > + ret = ad_group_stored_orig_members(tmp_ctx, dom, group->dn, > + &sysdb_odn_list); > + if (ret != EOK) { > + DEBUG(SSSDBG_OP_FAILURE, > + ("Could not retrieve list of original members for %s\n", > + name)); > + goto done; > + } > + > + /* Get the list of original DN attributes the group had in AD */ > + group_odn_list = ad_group_orig_members(tmp_ctx, om); > + if (group_odn_list == NULL) { > + ret = EFAULT; > + goto done; > + } > + > + /* Compare the two lists */ > + ret = diff_string_lists(tmp_ctx, group_odn_list, sysdb_odn_list, > + &group_only, NULL, NULL); > + if (ret != EOK) { > + DEBUG(SSSDBG_OP_FAILURE, > + ("Could not compare lists of members for %s\n", name)); > + goto done; > + } > + } > + > + ret = EOK; > + *_group_only = talloc_steal(mem_ctx, group_only); > +done: > + talloc_free(tmp_ctx); > + return ret; > +} > + > +static char ** > +ad_group_orig_members(TALLOC_CTX *mem_ctx, struct ldb_message_element *om) this looks like a generic ldb_message_element_to_string_list call. I would recommend to rename it and maybe move it to utils/ or db/ ebcause it might be useful for others as well? > +{ > + char **odn_list; > + size_t i; > + > + /* Get the list of original DN attributes the group had in AD */ > + odn_list = talloc_zero_array(mem_ctx, char *, om->num_values + 1); > + if (odn_list == NULL) { > + return NULL; > + } > + > + for (i=0; i < om->num_values; i++) { > + odn_list[i] = (char *) om->values[i].data; > + } > + > + return odn_list; > +} > + > +static errno_t > +ad_group_stored_orig_members(TALLOC_CTX *mem_ctx, struct sss_domain_info > *dom, > + struct ldb_dn *dn, char ***_odn_list) > +{ > + errno_t ret; > + TALLOC_CTX *tmp_ctx; > + size_t m_count, i; > + struct ldb_message **members; > + const char *attrs[] = { > + SYSDB_NAME, > + SYSDB_ORIG_DN, > + NULL > + }; > + char **odn_list; > + const char *odn; > + size_t oi; > + > + tmp_ctx = talloc_new(NULL); > + if (tmp_ctx == NULL) return ENOMEM; > + > + /* Get all entries member element points to */ > + ret = sysdb_asq_search(tmp_ctx, dom, dn, NULL, SYSDB_MEMBER, > + attrs, &m_count, &members); > + if (ret != EOK) { > + goto done; > + } > + > + odn_list = talloc_zero_array(tmp_ctx, char *, m_count + 1); > + if (odn_list == NULL) { > + ret = ENOMEM; > + goto done; > + } > + > + /* Get a list of their original DNs */ > + oi = 0; > + for (i = 0; i < m_count; i++) { > + odn = ldb_msg_find_attr_as_string(members[i], SYSDB_ORIG_DN, NULL); > + if (odn == NULL) { > + continue; > + } > + > + odn_list[oi] = talloc_strdup(odn_list, odn); > + if (odn_list[oi] == NULL) { > + continue; do you really want to continue if talloc_strdup() fails? > + } > + oi++; > + DEBUG(SSSDBG_TRACE_INTERNAL, ("Member %s already in sysdb\n", odn)); > + } > + > + ret = EOK; > + *_odn_list = talloc_steal(mem_ctx, odn_list); > +done: > + talloc_free(tmp_ctx); > + return ret; > +} > + > +static errno_t > +ad_group_add_member(struct sdap_options *opts, > + struct sss_domain_info *group_domain, > + struct ldb_dn *group_dn, > + const char *member) > +{ > + struct sdap_domain *sd; > + struct ldb_dn *base_dn; > + TALLOC_CTX *tmp_ctx; > + errno_t ret; > + const char *mem_filter; > + size_t msgs_count; > + struct ldb_message **msgs; > + > + /* This member would be from a different domain */ > + sd = sdap_domain_get_by_dn(opts, member); > + if (sd == NULL) { > + DEBUG(SSSDBG_MINOR_FAILURE, ("No matching domain for %s\n", member)); > + return ENOENT; > + } > + > + tmp_ctx = talloc_new(NULL); > + if (tmp_ctx == NULL) return ENOMEM; > + > + mem_filter = talloc_asprintf(tmp_ctx, "(%s=%s)", > + SYSDB_ORIG_DN, member); > + if (mem_filter == NULL) { > + ret = ENOMEM; > + goto done; > + } > + > + base_dn = sysdb_domain_dn(tmp_ctx, sd->dom); > + if (base_dn == NULL) { > + ret = ENOMEM; > + goto done; > + } > + > + ret = sysdb_search_entry(tmp_ctx, sd->dom->sysdb, base_dn, > + LDB_SCOPE_SUBTREE, mem_filter, NULL, > + &msgs_count, &msgs); > + if (ret == ENOENT) { > + DEBUG(SSSDBG_TRACE_FUNC, ("No member [%s] in sysdb\n", member)); > + ret = EOK; > + goto done; > + } else if (ret != EOK) { > + goto done; > + } > + DEBUG(SSSDBG_TRACE_INTERNAL, ("[%s] found in sysdb\n", member)); > + > + if (msgs_count != 1) { > + DEBUG(SSSDBG_CRIT_FAILURE, > + ("Search by orig DN returned %zd results!\n", msgs_count)); > + ret = EFAULT; > + goto done; > + } > + > + ret = sysdb_mod_group_member(group_domain, msgs[0]->dn, group_dn, > SYSDB_MOD_ADD); > + if (ret != EOK) { > + DEBUG(SSSDBG_OP_FAILURE, ("Could not add [%s] as a member of [%s]\n", > + ldb_dn_get_linearized(msgs[0]->dn), > + ldb_dn_get_linearized(group_dn))); > + goto done; > + } > + > + ret = EOK; > +done: > + talloc_free(tmp_ctx); > + return ret; > +} > + > errno_t > -ad_enum_subdom_recv(struct tevent_req *req) > +ad_enumeration_recv(struct tevent_req *req) > { > TEVENT_REQ_RETURN_ON_ERROR(req); > return EOK; > -- > 1.8.4.2 > > _______________________________________________ > sssd-devel mailing list > sssd-devel@lists.fedorahosted.org > https://lists.fedorahosted.org/mailman/listinfo/sssd-devel _______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel