From f2d943ee47bb313e0bb7276122587989a3c54fb4 Mon Sep 17 00:00:00 2001 From: Jan Zeleny Date: Thu, 15 Dec 2011 05:16:10 -0500 Subject: Retrieve subdomains if there is a request for fully qualified user --- src/responder/nss/nsssrv_cmd.c | 135 +++++++++++++++++++++++++++++++++++- src/responder/nss/nsssrv_netgroup.c | 85 +++++++++++++++-------- src/responder/nss/nsssrv_private.h | 3 + 3 files changed, 192 insertions(+), 31 deletions(-) diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 2c9a08330..d4ce66569 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -833,8 +833,10 @@ done: } } +static void nss_cmd_getpwnam_cb(struct tevent_req *req); static int nss_cmd_getpwnam(struct cli_ctx *cctx) { + struct tevent_req *req; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; const char *rawname; @@ -888,7 +890,14 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) if (domname) { dctx->domain = responder_get_domain(dctx, cctx->rctx, domname); if (!dctx->domain) { - ret = ENOENT; + req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname); + if (req == NULL) { + ret = ENOMEM; + } else { + dctx->domname = domname; + tevent_req_set_callback(req, nss_cmd_getpwnam_cb, dctx); + ret = EAGAIN; + } goto done; } } else { @@ -910,6 +919,40 @@ done: return nss_cmd_done(cmdctx, ret); } +static void nss_cmd_getpwnam_cb(struct tevent_req *req) +{ + struct nss_dom_ctx *dctx = tevent_req_callback_data(req, struct nss_dom_ctx); + struct nss_cmd_ctx *cmdctx = dctx->cmdctx; + struct cli_ctx *cctx = cmdctx->cctx; + errno_t ret; + + ret = sss_dp_get_domains_recv(req); + talloc_free(req); + if (ret != EOK) { + goto done; + } + + if (dctx->domname) { + dctx->domain = responder_get_domain(dctx, cctx->rctx, dctx->domname); + if (dctx->domain == NULL) { + ret = ENOENT; + goto done; + } + } + + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + + /* ok, find it ! */ + ret = nss_cmd_getpwnam_search(dctx); + if (ret == EOK) { + /* we have results to return */ + ret = nss_cmd_getpw_send_reply(dctx, false); + } + +done: + nss_cmd_done(cmdctx, ret); +} + static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min, const char *err_msg, void *ptr); @@ -2150,8 +2193,10 @@ done: } } +static void nss_cmd_getgrnam_cb(struct tevent_req *req); static int nss_cmd_getgrnam(struct cli_ctx *cctx) { + struct tevent_req *req; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; const char *rawname; @@ -2205,7 +2250,14 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) if (domname) { dctx->domain = responder_get_domain(dctx, cctx->rctx, domname); if (!dctx->domain) { - ret = ENOENT; + req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname); + if (req == NULL) { + ret = ENOMEM; + } else { + dctx->domname = domname; + tevent_req_set_callback(req, nss_cmd_getgrnam_cb, dctx); + ret = EAGAIN; + } goto done; } } else { @@ -2227,6 +2279,40 @@ done: return nss_cmd_done(cmdctx, ret); } +static void nss_cmd_getgrnam_cb(struct tevent_req *req) +{ + struct nss_dom_ctx *dctx = tevent_req_callback_data(req, struct nss_dom_ctx); + struct nss_cmd_ctx *cmdctx = dctx->cmdctx; + struct cli_ctx *cctx = cmdctx->cctx; + errno_t ret; + + ret = sss_dp_get_domains_recv(req); + talloc_free(req); + if (ret != EOK) { + goto done; + } + + if (dctx->domname) { + dctx->domain = responder_get_domain(dctx, cctx->rctx, dctx->domname); + if (dctx->domain == NULL) { + ret = ENOENT; + goto done; + } + } + + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + + /* ok, find it ! */ + ret = nss_cmd_getgrnam_search(dctx); + if (ret == EOK) { + /* we have results to return */ + ret = nss_cmd_getpw_send_reply(dctx, false); + } + +done: + nss_cmd_done(cmdctx, ret); +} + static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, const char *err_msg, void *ptr); @@ -3204,8 +3290,10 @@ done: } /* for now, if we are online, try to always query the backend */ +static void nss_cmd_initgroups_cb(struct tevent_req *req); static int nss_cmd_initgroups(struct cli_ctx *cctx) { + struct tevent_req *req; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; const char *rawname; @@ -3259,7 +3347,14 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) if (domname) { dctx->domain = responder_get_domain(dctx, cctx->rctx, domname); if (!dctx->domain) { - ret = ENOENT; + req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname); + if (req == NULL) { + ret = ENOMEM; + } else { + dctx->domname = domname; + tevent_req_set_callback(req, nss_cmd_initgroups_cb, dctx); + ret = EAGAIN; + } goto done; } } else { @@ -3277,6 +3372,40 @@ done: return nss_cmd_done(cmdctx, ret); } +static void nss_cmd_initgroups_cb(struct tevent_req *req) +{ + struct nss_dom_ctx *dctx = tevent_req_callback_data(req, struct nss_dom_ctx); + struct nss_cmd_ctx *cmdctx = dctx->cmdctx; + struct cli_ctx *cctx = cmdctx->cctx; + errno_t ret; + + ret = sss_dp_get_domains_recv(req); + talloc_free(req); + if (ret != EOK) { + goto done; + } + + if (dctx->domname) { + dctx->domain = responder_get_domain(dctx, cctx->rctx, dctx->domname); + if (dctx->domain == NULL) { + ret = ENOENT; + goto done; + } + } + + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + + /* ok, find it ! */ + ret = nss_cmd_initgroups_search(dctx); + if (ret == EOK) { + /* we have results to return */ + ret = nss_cmd_getpw_send_reply(dctx, false); + } + +done: + nss_cmd_done(cmdctx, ret); +} + struct cli_protocol_version *register_cli_protocol_version(void) { static struct cli_protocol_version nss_cli_protocol_version[] = { diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c index 87b105719..83e79a2fa 100644 --- a/src/responder/nss/nsssrv_netgroup.c +++ b/src/responder/nss/nsssrv_netgroup.c @@ -161,7 +161,9 @@ struct setnetgrent_ctx { struct nss_dom_ctx *dctx; char *netgr_shortname; struct getent_ctx *netgr; + const char *rawname; }; +static errno_t setnetgrent_retry(struct tevent_req *req); static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx); static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, const char *rawname, @@ -172,7 +174,6 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct setnetgrent_ctx *state; struct nss_dom_ctx *dctx; - struct setent_step_ctx *step_ctx; struct cli_ctx *client = cmdctx->cctx; struct nss_ctx *nctx = @@ -186,6 +187,7 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, state->nctx = nctx; state->cmdctx = cmdctx; + state->rawname = rawname; state->dctx = talloc_zero(state, struct nss_dom_ctx); if (!state->dctx) { @@ -231,6 +233,42 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, } } + ret = setnetgrent_retry(req); + if (ret != EOK) { + if (ret == EAGAIN) { + /* We need to reenter the mainloop + * We may be refreshing the cache + */ + return req; + } + + goto error; + } + + return req; + +error: + tevent_req_error(req, ret); + tevent_req_post(req, cmdctx->cctx->ev); + return req; +} + +static errno_t setnetgrent_retry(struct tevent_req *req) +{ + errno_t ret; + struct setent_step_ctx *step_ctx; + struct setnetgrent_ctx *state; + struct cli_ctx *client; + struct nss_ctx *nctx; + struct nss_cmd_ctx *cmdctx; + struct nss_dom_ctx *dctx; + + state = tevent_req_data(req, struct setnetgrent_ctx); + dctx = state->dctx; + cmdctx = state->cmdctx; + client = cmdctx->cctx; + nctx = talloc_get_type(client->rctx->pvt_ctx, struct nss_ctx); + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); /* Is the result context already available? @@ -245,13 +283,15 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, if (state->netgr->found) { /* Ready to process results */ tevent_req_done(req); - tevent_req_post(req, nctx->rctx->ev); - return req; } else { tevent_req_error(req, ENOENT); - tevent_req_post(req, nctx->rctx->ev); - return req; } + + tevent_req_post(req, nctx->rctx->ev); + /* Return EOK, otherwise this will be treated as + * an error + */ + return EOK; } /* Result object is still being constructed @@ -259,7 +299,7 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, */ ret = nss_setent_add_ref(state, state->netgr, req); if (ret != EOK) { - goto error; + goto done; } /* Will return control below */ } else if (ret == ENOENT) { @@ -268,7 +308,7 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, state->netgr = talloc_zero(nctx, struct getent_ctx); if (!state->netgr) { ret = ENOMEM; - goto error; + goto done; } dctx->netgr = state->netgr; @@ -280,7 +320,7 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, if (!state->netgr->name) { talloc_free(state->netgr); ret = ENOMEM; - goto error; + goto done; } state->netgr->lookup_table = nctx->netgroups; @@ -289,21 +329,21 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, ret = nss_setent_add_ref(state, state->netgr, req); if (ret != EOK) { talloc_free(state->netgr); - goto error; + goto done; } ret = set_netgroup_entry(nctx, state->netgr); if (ret != EOK) { DEBUG(1, ("set_netgroup_entry failed.\n")); talloc_free(state->netgr); - goto error; + goto done; } /* Perform lookup */ step_ctx = talloc_zero(state->netgr, struct setent_step_ctx); if (!step_ctx) { ret = ENOMEM; - goto error; + goto done; } /* Steal the dom_ctx onto the step_ctx so it doesn't go out of scope if @@ -318,36 +358,25 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx, talloc_strdup(step_ctx, state->netgr->name); if (!step_ctx->name) { ret = ENOMEM; - goto error; + goto done; } ret = lookup_netgr_step(step_ctx); if (ret != EOK) { - if (ret == EAGAIN) { - /* We need to reenter the mainloop - * We may be refreshing the cache - */ - return req; - } - - /* An unexpected error occurred or no domains - * were eligible for the search */ - goto error; + goto done; } tevent_req_done(req); tevent_req_post(req, cmdctx->cctx->ev); /* Will return control below */ } else { /* Unexpected error from hash_lookup */ - goto error; + goto done; } - return req; + ret = EOK; -error: - tevent_req_error(req, ret); - tevent_req_post(req, cmdctx->cctx->ev); - return req; +done: + return ret; } static void lookup_netgr_dp_callback(uint16_t err_maj, uint32_t err_min, diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h index c9fb0d0a0..57975943b 100644 --- a/src/responder/nss/nsssrv_private.h +++ b/src/responder/nss/nsssrv_private.h @@ -63,6 +63,9 @@ struct nss_dom_ctx { struct nss_cmd_ctx *cmdctx; struct sss_domain_info *domain; + /* For a case when we are discovering subdomains */ + const char *domname; + bool check_provider; /* cache results */ -- cgit