>From c8639456822f471a05d9ca8032932116a35c9fc0 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 16 Dec 2013 02:51:43 +0100 Subject: [PATCH 4/6] AD: Enumerate users from GC, other entities from LDAP https://fedorahosted.org/sssd/ticket/2142 When performing regular lookups, we connect to GC for users from all domains, but defer to LDAP to read group memberships. However, the enumeration task could only connect to LDAP. When different attributes are present in GC and LDAP, this could have lead to very confusing results. This patch switches to using GC for users and LDAP for groups as is the case for normal lookups. Services, if present, are downloaded using the LDAP connection. --- src/providers/ad/ad_id.c | 134 ++++++++++++++++++++++++++++++++++++++- src/providers/ad/ad_subdomains.c | 11 ---- 2 files changed, 131 insertions(+), 14 deletions(-) diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 324431e1f9b77981229a8458237183478d9d83f2..def906ca1e3640ef941500a6dcd3d12fee1a1b3a 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -526,6 +526,7 @@ 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); @@ -544,8 +545,21 @@ ad_enumeration_master_done(struct tevent_req *subreq) return; } - subreq = sdap_dom_enum_send(state, state->ev, state->id_ctx->sdap_id_ctx, - state->sdom, state->id_ctx->ldap_ctx); + 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->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 */ if (subreq == NULL) { /* The ptask API will reschedule the enumeration on its own on * failure */ @@ -566,7 +580,7 @@ ad_enumeration_done(struct tevent_req *subreq) struct ad_enumeration_state *state = tevent_req_data(req, struct ad_enumeration_state); - ret = sdap_dom_enum_recv(subreq); + ret = sdap_dom_enum_ex_recv(subreq); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, @@ -584,3 +598,117 @@ 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) +{ + 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) { + 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_enum_subdom_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index e7871cc32407893948fe1b2803258d68c70889c1..0d9652b5c615add47958cfdc61eba862a332ae4d 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -177,17 +177,6 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, return EFAULT; } - ret = sdap_id_setup_tasks(be_ctx, - ad_id_ctx->sdap_id_ctx, - sdom, - ldap_enumeration_send, - ldap_enumeration_recv, - ad_id_ctx->sdap_id_ctx); - if (ret != EOK) { - talloc_free(ad_options); - return ret; - } - /* Set up the ID mapping object */ ad_id_ctx->sdap_id_ctx->opts->idmap_ctx = id_ctx->sdap_id_ctx->opts->idmap_ctx; -- 1.8.4.2