>From 71156b46a10a08a9b011ae47bb3506b3e8c719af Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 16 Dec 2013 02:51:43 +0100 Subject: [PATCH 4/4] 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_id.h | 10 +++ src/providers/ad/ad_subdomains.c | 24 +++---- 3 files changed, 154 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_id.h b/src/providers/ad/ad_id.h index 74b85645c2d6458617a4064fe3fb3f99696c3741..20fe0b76350f1246fd0ad3f24b1138271a8a1521 100644 --- a/src/providers/ad/ad_id.h +++ b/src/providers/ad/ad_id.h @@ -47,6 +47,16 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx, errno_t ad_enumeration_recv(struct tevent_req *req); +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); + +errno_t +ad_enum_subdom_recv(struct tevent_req *req); + void ad_check_online(struct be_req *be_req); #endif /* AD_ID_H_ */ diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index e7871cc32407893948fe1b2803258d68c70889c1..e2c775ee643ef11dba140b13c5c49a30ab1f6aad 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -26,6 +26,7 @@ #include "providers/ad/ad_subdomains.h" #include "providers/ad/ad_domain_info.h" #include "providers/ad/ad_srv.h" +#include "providers/ad/ad_id.h" #include "providers/ldap/sdap_idmap.h" #include "util/util_sss_idmap.h" #include @@ -177,17 +178,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; @@ -218,6 +208,18 @@ ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx, DEBUG(SSSDBG_OP_FAILURE, ("ad_subdom_ad_ctx_new failed.\n")); } else { sditer->pvt = subdom_id_ctx; + + /* Set up enumeration/cleanup for the new subdomain */ + ret = sdap_id_setup_tasks(ctx->be_ctx, + ctx->ad_id_ctx->sdap_id_ctx, + sditer, + ad_enum_subdom_send, + ad_enum_subdom_recv, + subdom_id_ctx); + if (ret != EOK) { + return ret; + } + } } } -- 1.8.4.2