>From 5351f0acf77b10c7a49a725be996b04d331432c9 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 99383c13bdadfe9eb2af9f9323ca19a9759d4620..1bdacf74f0e6de2120603401bcf115549a03ac4f 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