diff options
-rw-r--r-- | src/db/sysdb.h | 2 | ||||
-rw-r--r-- | src/db/sysdb_search.c | 54 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 302 | ||||
-rw-r--r-- | src/tests/sysdb-tests.c | 65 |
4 files changed, 160 insertions, 263 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 65b57bdfc..7b5166fea 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -277,7 +277,7 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx, struct sysdb_ctx *ctx, struct sss_domain_info *domain, gid_t gid, - sysdb_callback_t fn, void *ptr); + struct ldb_result **res); int sysdb_enumgrent(TALLOC_CTX *mem_ctx, struct sysdb_ctx *ctx, diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c index 144f6da51..cabf19f45 100644 --- a/src/db/sysdb_search.c +++ b/src/db/sysdb_search.c @@ -477,44 +477,56 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx, struct sysdb_ctx *ctx, struct sss_domain_info *domain, gid_t gid, - sysdb_callback_t fn, void *ptr) + struct ldb_result **_res) { - struct sysdb_search_ctx *sctx; - struct tevent_req *req; + TALLOC_CTX *tmpctx; + unsigned long int ul_gid = gid; + static const char *attrs[] = SYSDB_GRSRC_ATTRS; + const char *fmt_filter; + struct ldb_dn *base_dn; + struct ldb_result *res; + int ret; if (!domain) { return EINVAL; } - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { + tmpctx = talloc_new(mem_ctx); + if (!tmpctx) { return ENOMEM; } if (ctx->mpg) { - sctx->gen_conv_mpg_users = true; - sctx->expression = talloc_asprintf(sctx, - SYSDB_GRGID_MPG_FILTER, - (unsigned long int)gid); + fmt_filter = SYSDB_GRGID_MPG_FILTER; + base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb, + SYSDB_DOM_BASE, domain->name); } else { - sctx->expression = talloc_asprintf(sctx, - SYSDB_GRGID_FILTER, - (unsigned long int)gid); + fmt_filter = SYSDB_GRGID_FILTER; + base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb, + SYSDB_TMPL_GROUP_BASE, domain->name); } - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; + if (!base_dn) { + ret = ENOMEM; + goto done; } - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; + ret = ldb_search(ctx->ldb, tmpctx, &res, base_dn, + LDB_SCOPE_SUBTREE, attrs, fmt_filter, ul_gid); + if (ret) { + ret = sysdb_error_to_errno(ret); + goto done; } - tevent_req_set_callback(req, grp_search, sctx); + ret = mpg_res_convert(res); + if (ret) { + goto done; + } - return EOK; + *_res = talloc_steal(mem_ctx, res); + +done: + talloc_zfree(tmpctx); + return ret; } int sysdb_enumgrent(TALLOC_CTX *mem_ctx, diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 18f8d3995..508f33459 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -1841,136 +1841,108 @@ done: static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, const char *err_msg, void *ptr); -static void nss_cmd_getgrgid_callback(void *ptr, int status, - struct ldb_result *res) +/* search for a gid. + * Returns: + * ENOENT, if gid is definitely not found + * EAGAIN, if gid is beeing fetched from backend via async operations + * EOK, if found + * anything else on a fatal error + */ + +static int nss_cmd_getgrgid_search(struct nss_dom_ctx *dctx) { - struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; + struct sss_domain_info *dom = dctx->domain; struct cli_ctx *cctx = cmdctx->cctx; - struct sss_domain_info *dom; struct sysdb_ctx *sysdb; struct nss_ctx *nctx; - uint8_t *body; - size_t blen; - bool neghit = false; - int i, ret; - int ncret; + int ret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); - if (status != LDB_SUCCESS) { - ret = nss_cmd_send_error(cmdctx, status); - if (ret != EOK) { - NSS_CMD_FATAL_ERROR(cctx); - } - sss_cmd_done(cctx, cmdctx); - return; - } + while (dom) { - if (dctx->check_provider) { - ret = check_cache(dctx, nctx, res, - SSS_DP_GROUP, NULL, cmdctx->id, - nss_cmd_getgrgid_dp_callback); - if (ret != EOK) { - /* Anything but EOK means we should reenter the mainloop - * because we may be refreshing the cache - */ - return; + /* check that the gid is valid for this domain */ + if ((dom->id_min && (cmdctx->id < dom->id_min)) || + (dom->id_max && (cmdctx->id > dom->id_max))) { + DEBUG(4, ("Gid [%lu] does not exist in domain [%s]! " + "(id out of range)\n", + (unsigned long)cmdctx->id, dom->name)); + if (cmdctx->check_next) { + dom = dom->next; + continue; + } + return ENOENT; } - } - switch (res->count) { - case 0: - if (cmdctx->check_next) { + if (dom != dctx->domain) { + /* make sure we reset the check_provider flag when we check + * a new domain */ + dctx->check_provider = NEED_CHECK_PROVIDER(dom->provider); + } - ret = EOK; + /* make sure to update the dctx if we changed domain */ + dctx->domain = dom; - dom = dctx->domain->next; + DEBUG(4, ("Requesting info for [%d@%s]\n", cmdctx->id, dom->name)); - ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, - cmdctx->id); - if (ncret == EEXIST) { - DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n", - (unsigned long)cmdctx->id)); - ret = ENOENT; - } - if (dom == NULL) { - DEBUG(0, ("No matching domain found for [%lu], fail!\n", - (unsigned long)cmdctx->id)); - ret = ENOENT; - } + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, dom, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + return EIO; + } - if (ret == EOK) { - dctx->domain = dom; - dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); - if (dctx->res) talloc_free(res); - dctx->res = NULL; + ret = sysdb_getgrgid(cmdctx, sysdb, dom, cmdctx->id, &dctx->res); + if (ret != EOK) { + DEBUG(1, ("Failed to make request to our cache!\n")); + return EIO; + } - DEBUG(4, ("Requesting info for [%s@%s]\n", - cmdctx->name, dctx->domain->name)); + if (dctx->res->count > 1) { + DEBUG(0, ("getgrgid call returned more than one result !?!\n")); + return ENOENT; + } - ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, - dctx->domain, &sysdb); - if (ret != EOK) { - DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); - NSS_CMD_FATAL_ERROR(cctx); - } - ret = sysdb_getgrgid(cmdctx, sysdb, - dctx->domain, cmdctx->id, - nss_cmd_getgrgid_callback, dctx); - if (ret != EOK) { - DEBUG(1, ("Failed to make request to our cache!\n")); - } + if (dctx->res->count == 0 && !dctx->check_provider) { + /* if a multidomain search, try with next */ + if (cmdctx->check_next) { + dom = dom->next; + continue; } - /* we made another call, end here */ - if (ret == EOK) return; - } + DEBUG(2, ("No results for getgrgid call\n")); - DEBUG(2, ("No results for getgrgid call\n")); - - /* set negative cache only if not result of cache check */ - if (!neghit) { + /* set negative cache only if not result of cache check */ ret = nss_ncache_set_gid(nctx->ncache, false, cmdctx->id); if (ret != EOK) { - NSS_CMD_FATAL_ERROR(cctx); + return ret; } - } - ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t), - sss_packet_get_cmd(cctx->creq->in), - &cctx->creq->out); - if (ret != EOK) { - NSS_CMD_FATAL_ERROR(cctx); + return ENOENT; } - sss_packet_get_body(cctx->creq->out, &body, &blen); - ((uint32_t *)body)[0] = 0; /* 0 results */ - ((uint32_t *)body)[1] = 0; /* reserved */ - break; - default: + /* if this is a caching provider (or if we haven't checked the cache + * yet) then verify that the cache is uptodate */ + if (dctx->check_provider) { + ret = check_cache(dctx, nctx, dctx->res, + SSS_DP_GROUP, NULL, cmdctx->id, + nss_cmd_getgrgid_dp_callback); + if (ret != EOK) { + /* Anything but EOK means we should reenter the mainloop + * because we may be refreshing the cache + */ + return ret; + } + } - DEBUG(6, ("Returning info for group [%u]\n", (unsigned)cmdctx->id)); + /* One result found */ + DEBUG(6, ("Returning info for gid [%d@%s]\n", cmdctx->id, dom->name)); - /* create response packet */ - ret = sss_packet_new(cctx->creq, 0, - sss_packet_get_cmd(cctx->creq->in), - &cctx->creq->out); - if (ret != EOK) { - NSS_CMD_FATAL_ERROR(cctx); - } - i = res->count; - ret = fill_grent(cctx->creq->out, - dctx->domain, - nctx, true, - res->msgs, 1, &i); - if (ret == ENOENT) { - ret = fill_empty(cctx->creq->out); - } - sss_packet_set_error(cctx->creq->out, ret); + return EOK; } - sss_cmd_done(cctx, cmdctx); + DEBUG(2, ("No matching domain found for [%d], fail!\n", cmdctx->id)); + return ENOENT; } static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -1979,7 +1951,6 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; - struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -1988,38 +1959,33 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, "Will try to return what we have in cache\n", (unsigned int)err_maj, (unsigned int)err_min, err_msg)); - if (!dctx->res) { - /* return 0 results */ - dctx->res = talloc_zero(dctx, struct ldb_result); - if (!dctx->res) { - ret = ENOMEM; - goto done; - } + if (dctx->res && dctx->res->count == 1) { + ret = nss_cmd_getgr_send_reply(dctx, true); + goto done; } - nss_cmd_getgrgid_callback(dctx, LDB_SUCCESS, dctx->res); - return; + /* no previous results, just loop to next domain if possible */ + if (dctx->domain->next && cmdctx->check_next) { + dctx->domain = dctx->domain->next; + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + } else { + /* nothing vailable */ + ret = ENOENT; + goto done; + } } - ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, - dctx->domain, &sysdb); - if (ret != EOK) { - DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); - NSS_CMD_FATAL_ERROR(cctx); + /* ok the backend returned, search to see if we have updated results */ + ret = nss_cmd_getgrgid_search(dctx); + if (ret == EOK) { + /* we have results to return */ + ret = nss_cmd_getgr_send_reply(dctx, true); } - ret = sysdb_getgrgid(cmdctx, sysdb, - dctx->domain, cmdctx->id, - nss_cmd_getgrgid_callback, dctx); done: - if (ret != EOK) { - DEBUG(1, ("Failed to make request to our cache!\n")); - - ret = nss_cmd_send_error(cmdctx, ret); - if (ret != EOK) { - NSS_CMD_FATAL_ERROR(cctx); - } - sss_cmd_done(cctx, cmdctx); + ret = nss_cmd_done(cmdctx, ret); + if (ret) { + NSS_CMD_FATAL_ERROR(cctx); } } @@ -2027,15 +1993,11 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) { struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; - struct sss_domain_info *dom; - struct sysdb_ctx *sysdb; struct nss_ctx *nctx; uint8_t *body; size_t blen; int ret; - int ncret; - ret = ENOENT; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); cmdctx = talloc_zero(cctx, struct nss_cmd_ctx); @@ -2060,75 +2022,29 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) } cmdctx->id = *((uint32_t *)body); - /* this is a multidomain search */ - cmdctx->check_next = true; - - for (dom = cctx->rctx->domains; dom; dom = dom->next) { - /* verify this user has not yet been negatively cached, - * or has been permanently filtered */ - ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, - cmdctx->id); - if (ncret == EEXIST) { - DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n", - (unsigned long)cmdctx->id)); - continue; - } - - /* check that the uid is valid for this domain */ - if ((dom->id_min && (cmdctx->id < dom->id_min)) || - (dom->id_max && (cmdctx->id > dom->id_max))) { - DEBUG(4, ("Gid [%lu] does not exist in domain [%s]! " - "(id out of range)\n", - (unsigned long)cmdctx->id, dom->name)); - continue; - } - - dctx->domain = dom; - dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + ret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, cmdctx->id); + if (ret == EEXIST) { + DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n", + (unsigned long)cmdctx->id)); + ret = ENOENT; + goto done; + } - DEBUG(4, ("Requesting info for [%lu@%s]\n", - cmdctx->id, dctx->domain->name)); + /* gid searches are always multidomain */ + dctx->domain = cctx->rctx->domains; + cmdctx->check_next = true; - ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, - dctx->domain, &sysdb); - if (ret != EOK) { - DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); - ret = EFAULT; - goto done; - } - ret = sysdb_getgrgid(cmdctx, sysdb, - dctx->domain, cmdctx->id, - nss_cmd_getgrgid_callback, dctx); - if (ret != EOK) { - DEBUG(1, ("Failed to make request to our cache!\n")); - } + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); - break; + /* ok, find it ! */ + ret = nss_cmd_getgrgid_search(dctx); + if (ret == EOK) { + /* we have results to return */ + ret = nss_cmd_getgr_send_reply(dctx, true); } done: - if (ret != EOK) { - if (ret == ENOENT) { - /* we do not have any entry to return */ - ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t), - sss_packet_get_cmd(cctx->creq->in), - &cctx->creq->out); - if (ret == EOK) { - sss_packet_get_body(cctx->creq->out, &body, &blen); - ((uint32_t *)body)[0] = 0; /* 0 results */ - ((uint32_t *)body)[1] = 0; /* reserved */ - } - } - if (ret != EOK) { - ret = nss_cmd_send_error(cmdctx, ret); - } - if (ret == EOK) { - sss_cmd_done(cctx, cmdctx); - } - return ret; - } - - return EOK; + return nss_cmd_done(cmdctx, ret); } /* to keep it simple at this stage we are retrieving the diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c index d700f0b50..162d174b0 100644 --- a/src/tests/sysdb-tests.c +++ b/src/tests/sysdb-tests.c @@ -306,31 +306,6 @@ static int test_remove_group_by_gid(struct test_data *data) return ret; } -static void test_getgrgid(void *pvt, int error, struct ldb_result *res) -{ - struct test_data *data = talloc_get_type(pvt, struct test_data); - data->finished = true; - - if (error != EOK) { - data->error = error; - return; - } - - switch (res->count) { - case 0: - data->error = ENOENT; - break; - - case 1: - data->groupname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, 0); - break; - - default: - data->error = EFAULT; - break; - } -} - static void test_enumgrent(void *pvt, int error, struct ldb_result *res) { struct test_data *data = talloc_get_type(pvt, struct test_data); @@ -879,9 +854,10 @@ END_TEST START_TEST (test_sysdb_getgrgid) { struct sysdb_test_ctx *test_ctx; - struct test_data *data; + struct ldb_result *res; + const char *e_groupname; + const char *groupname; int ret; - const char *groupname = NULL; /* Setup */ ret = setup_sysdb_tests(&test_ctx); @@ -890,34 +866,27 @@ START_TEST (test_sysdb_getgrgid) return; } - groupname = talloc_asprintf(test_ctx, "testgroup%d", _i); - if (groupname == NULL) { - fail("Cannot allocate memory"); - return; - } - - data = talloc_zero(test_ctx, struct test_data); - data->ctx = test_ctx; - data->gid = _i; - ret = sysdb_getgrgid(test_ctx, test_ctx->sysdb, - data->ctx->domain, - data->gid, - test_getgrgid, - data); - if (ret == EOK) { - ret = test_loop(data); - } - + test_ctx->domain, + _i, &res); if (ret) { fail("sysdb_getgrgid failed for gid %d (%d: %s)", - data->gid, ret, strerror(ret)); + _i, ret, strerror(ret)); goto done; } - fail_unless(strcmp(data->groupname, groupname) == 0, + + groupname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, 0); + + e_groupname = talloc_asprintf(test_ctx, "testgroup%d", _i); + if (e_groupname == NULL) { + fail("Cannot allocate memory"); + goto done; + } + + fail_unless(strcmp(groupname, e_groupname) == 0, "Did not find the expected groupname (found %s expected %s)", - data->groupname, groupname); + groupname, e_groupname); done: talloc_free(test_ctx); } |