diff options
Diffstat (limited to 'src/providers/ipa/ipa_subdomains_server.c')
-rw-r--r-- | src/providers/ipa/ipa_subdomains_server.c | 236 |
1 files changed, 213 insertions, 23 deletions
diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c index 56cf0162a..6e43bbc2d 100644 --- a/src/providers/ipa/ipa_subdomains_server.c +++ b/src/providers/ipa/ipa_subdomains_server.c @@ -255,71 +255,185 @@ 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); + + /* In this particular patch, we just want to fake the async interface + * for an otherwise synchronous operation of creating two-way trusts, + * so currently the request is just marked as done and terminated. We + * will convert the request to fully async in a subsequent patch that + * adds support for one-way trusts. + */ + 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 ipa_ad_server_ctx *trust_iter; + struct tevent_req *req = NULL; + struct ipa_server_create_trusts_state *state = NULL; errno_t ret; - if (dp_opt_get_bool(id_ctx->ipa_options->basic, - IPA_SERVER_MODE) == false) { - return EOK; + 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; } - 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)) { + 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; + struct ipa_server_create_trusts_state *state = NULL; + + 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) @@ -355,6 +469,81 @@ 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 [%d]: %s\n", + ret, sss_strerror(ret)); + } +} + +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) { @@ -405,7 +594,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; |