>From e62c5ca39ec9d7d850199e811708f739781f8df0 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 25 May 2015 19:44:05 +0200 Subject: [PATCH 14/29] IPA: Make constructing an IPA server mode context async Refactoring in preparation for requesting the keytab in future patches. Currently it's a fake async that just marks the request as done. --- src/providers/ipa/ipa_subdomains.c | 32 ++++- src/providers/ipa/ipa_subdomains.h | 7 +- src/providers/ipa/ipa_subdomains_server.c | 227 +++++++++++++++++++++++++++--- 3 files changed, 240 insertions(+), 26 deletions(-) diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 1867cd311a724e8e220f1b582d326e0330f4ea60..6a12fa8f50ff7d2ca5570282d59eea90683ec606 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -769,6 +769,7 @@ ipa_subdomains_handler_get_cont(struct ipa_subdomains_req_ctx *ctx, } static void ipa_get_view_name_done(struct tevent_req *req); +static void ipa_server_create_trusts_done(struct tevent_req *trust_req); static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx); static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx) @@ -1003,6 +1004,7 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) struct sss_domain_info *domain; bool refresh_has_changes = false; int dp_error = DP_ERR_FATAL; + struct tevent_req *trust_req; ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx); domain = ctx->sd_ctx->be_ctx->domain; @@ -1048,13 +1050,16 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) } if (ctx->sd_ctx->id_ctx->server_mode != NULL) { - ret = ipa_ad_subdom_refresh(ctx->sd_ctx->be_ctx, - ctx->sd_ctx->id_ctx, - domain); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_ad_subdom_refresh failed.\n"); + trust_req = ipa_server_create_trusts_send(ctx, ctx->sd_ctx->be_ctx->ev, + ctx->sd_ctx->be_ctx, + ctx->sd_ctx->id_ctx, + domain); + if (trust_req == NULL) { + ret = ENOMEM; goto done; } + tevent_req_set_callback(trust_req, ipa_server_create_trusts_done, ctx); + return; } } @@ -1090,6 +1095,23 @@ done: ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL); } +static void ipa_server_create_trusts_done(struct tevent_req *trust_req) +{ + errno_t ret; + int dp_error = DP_ERR_FATAL; + struct ipa_subdomains_req_ctx *ctx; + + ctx = tevent_req_callback_data(trust_req, struct ipa_subdomains_req_ctx); + + ret = ipa_server_create_trusts_recv(trust_req); + talloc_zfree(trust_req); + if (ret == EOK) { + dp_error = DP_ERR_OK; + } + + ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL); +} + static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx) { int ret; diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h index 76e4b3802284719cd4fb6f731f7f92fa877d8ba3..a2acb7887cf4156fd20944fcc82df320ae588e98 100644 --- a/src/providers/ipa/ipa_subdomains.h +++ b/src/providers/ipa/ipa_subdomains.h @@ -48,10 +48,15 @@ struct ipa_ad_server_ctx { }; /* To be used by ipa_subdomains.c only */ -errno_t ipa_ad_subdom_refresh(struct be_ctx *be_ctx, +struct tevent_req * +ipa_server_create_trusts_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, struct sss_domain_info *parent); +errno_t ipa_server_create_trusts_recv(struct tevent_req *req); + void ipa_ad_subdom_remove(struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, struct sss_domain_info *subdom); diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c index 9594735dfabd5165ed1fb514d7fa028df5748670..e9d1184a32000a0b8f411ad5fc77ef952c601ddd 100644 --- a/src/providers/ipa/ipa_subdomains_server.c +++ b/src/providers/ipa/ipa_subdomains_server.c @@ -253,66 +253,178 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, return EOK; } -static errno_t ipa_server_trust_add(struct be_ctx *be_ctx, - struct ipa_id_ctx *id_ctx, - struct sss_domain_info *subdom) +struct ipa_server_trust_add_state { +}; + +static struct tevent_req * +ipa_server_trust_add_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct ipa_id_ctx *id_ctx, + struct sss_domain_info *subdom) { + struct tevent_req *req = NULL; + struct ipa_server_trust_add_state *state = NULL; struct ipa_ad_server_ctx *trust_ctx; struct ad_id_ctx *ad_id_ctx; errno_t ret; + req = tevent_req_create(mem_ctx, &state, struct ipa_server_trust_add_state); + if (req == NULL) { + return NULL; + } + ret = ipa_ad_ctx_new(be_ctx, id_ctx, subdom, &ad_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Cannot create ad_id_ctx for subdomain %s\n", subdom->name); - return ret; + goto immediate; } trust_ctx = talloc(id_ctx->server_mode, struct ipa_ad_server_ctx); if (trust_ctx == NULL) { - return ENOMEM; + ret = ENOMEM; + goto immediate; } trust_ctx->dom = subdom; trust_ctx->ad_id_ctx = ad_id_ctx; DLIST_ADD(id_ctx->server_mode->trusts, trust_ctx); + ret = EOK; + goto immediate; + + return req; + +immediate: + if (ret != EOK) { + tevent_req_error(req, ret); + } else { + tevent_req_done(req); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ipa_server_trust_add_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } -errno_t ipa_ad_subdom_refresh(struct be_ctx *be_ctx, +struct ipa_server_create_trusts_state { + struct tevent_context *ev; + struct be_ctx *be_ctx; + struct ipa_id_ctx *id_ctx; + struct sss_domain_info *domiter; +}; + +static errno_t ipa_server_create_trusts_step(struct tevent_req *req); +static void ipa_server_create_trusts_done(struct tevent_req *subreq); + +struct tevent_req * +ipa_server_create_trusts_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, struct sss_domain_info *parent) { - struct sss_domain_info *dom; + struct tevent_req *req = NULL; + struct ipa_server_create_trusts_state *state = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct ipa_server_create_trusts_state); + if (req == NULL) { + return NULL; + } + + state->ev = ev; + state->be_ctx = be_ctx; + state->id_ctx = id_ctx; + state->domiter = parent; + + ret = ipa_server_create_trusts_step(req); + if (ret != EAGAIN) { + goto immediate; + } + + return req; + +immediate: + if (ret != EOK) { + tevent_req_error(req, ret); + } else { + tevent_req_done(req); + } + tevent_req_post(req, ev); + return req; +} + +static errno_t ipa_server_create_trusts_step(struct tevent_req *req) +{ + struct tevent_req *subreq = NULL; struct ipa_ad_server_ctx *trust_iter; - errno_t ret; + struct ipa_server_create_trusts_state *state = NULL; - for (dom = get_next_domain(parent, true); - dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ - dom = get_next_domain(dom, false)) { + state = tevent_req_data(req, struct ipa_server_create_trusts_state); + + for (state->domiter = get_next_domain(state->domiter, true); + state->domiter && IS_SUBDOMAIN(state->domiter); + state->domiter = get_next_domain(state->domiter, false)) { /* Check if we already have an ID context for this subdomain */ - DLIST_FOR_EACH(trust_iter, id_ctx->server_mode->trusts) { - if (trust_iter->dom == dom) { + DLIST_FOR_EACH(trust_iter, state->id_ctx->server_mode->trusts) { + if (trust_iter->dom == state->domiter) { break; } } /* Newly detected trust */ if (trust_iter == NULL) { - ret = ipa_server_trust_add(be_ctx, id_ctx, dom); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Cannot create ad_id_ctx for subdomain %s\n", - dom->name); - continue; + subreq = ipa_server_trust_add_send(state, state->ev, state->be_ctx, + state->id_ctx, state->domiter); + if (subreq == NULL) { + return ENOMEM; } + tevent_req_set_callback(subreq, ipa_server_create_trusts_done, req); + return EAGAIN; } } return EOK; } +static void ipa_server_create_trusts_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + + ret = ipa_server_trust_add_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + ret = ipa_server_create_trusts_step(req); + if (ret == EOK) { + tevent_req_done(req); + return; + } else if (ret != EAGAIN) { + tevent_req_error(req, ret); + return; + } + + /* Will cycle back */ +} + +errno_t ipa_server_create_trusts_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + void ipa_ad_subdom_remove(struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, struct sss_domain_info *subdom) @@ -343,6 +455,80 @@ void ipa_ad_subdom_remove(struct be_ctx *be_ctx, talloc_zfree(sdom); } +struct ipa_ad_subdom_reinit_state { + struct tevent_context *ev; + struct be_ctx *be_ctx; + struct ipa_id_ctx *id_ctx; + struct sss_domain_info *parent; +}; + +static void create_trusts_at_startup_done(struct tevent_req *req) +{ + errno_t ret; + + ret = ipa_server_create_trusts_recv(req); + talloc_free(req); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "ipa_server_create_trusts_send request failed.\n"); + } +} + +static void create_trusts_at_startup(struct tevent_context *ev, + struct tevent_immediate *imm, + void *pvt) +{ + struct tevent_req *req; + struct ipa_ad_subdom_reinit_state *state; + + state = talloc_get_type(pvt, struct ipa_ad_subdom_reinit_state); + + req = ipa_server_create_trusts_send(state, state->ev, state->be_ctx, + state->id_ctx, state->parent); + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_server_create_trusts_send failed.\n"); + talloc_free(state); + return; + } + + tevent_req_set_callback(req, create_trusts_at_startup_done, state); + return; +} + +static errno_t ipa_ad_subdom_reinit(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct ipa_id_ctx *id_ctx, + struct sss_domain_info *parent) +{ + struct tevent_immediate *imm; + struct ipa_ad_subdom_reinit_state *state; + + state = talloc(mem_ctx, struct ipa_ad_subdom_reinit_state); + if (state == NULL) { + return ENOMEM; + } + state->ev = ev; + state->be_ctx = be_ctx; + state->id_ctx = id_ctx; + state->parent = parent; + + if (dp_opt_get_bool(id_ctx->ipa_options->basic, + IPA_SERVER_MODE) == false) { + return EOK; + } + + imm = tevent_create_immediate(mem_ctx); + if (imm == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "tevent_create_immediate failed.\n"); + talloc_free(state); + return ENOMEM; + } + + tevent_schedule_immediate(imm, ev, create_trusts_at_startup, state); + return EOK; +} + int ipa_ad_subdom_init(struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx) { @@ -388,7 +574,8 @@ int ipa_ad_subdom_init(struct be_ctx *be_ctx, id_ctx->server_mode->trusts = NULL; id_ctx->server_mode->ext_groups = NULL; - ret = ipa_ad_subdom_refresh(be_ctx, id_ctx, be_ctx->domain); + ret = ipa_ad_subdom_reinit(be_ctx, be_ctx->ev, + be_ctx, id_ctx, be_ctx->domain); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ipa_ad_subdom_refresh failed.\n"); return ret; -- 2.1.0