summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/db/sysdb.h2
-rw-r--r--src/db/sysdb_search.c88
-rw-r--r--src/responder/nss/nsssrv_cmd.c267
-rw-r--r--src/tests/sysdb-tests.c39
4 files changed, 147 insertions, 249 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 7d4b25819..969413be4 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -281,7 +281,7 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
- sysdb_callback_t fn, void *ptr);
+ struct ldb_result **res);
int sysdb_initgroups(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 2ac794987..b874f0d07 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -346,47 +346,6 @@ static int mpg_res_convert(struct ldb_result *res)
return EOK;
}
-static void grp_search(struct tevent_req *treq)
-{
- struct sysdb_search_ctx *sctx;
- static const char *attrs[] = SYSDB_GRSRC_ATTRS;
- struct ldb_request *req;
- struct ldb_dn *base_dn;
- int ret;
-
- sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx);
-
- ret = sysdb_operation_recv(treq, sctx, &sctx->handle);
- if (ret) {
- return request_error(sctx, ret);
- }
-
- if (sctx->gen_conv_mpg_users) {
- base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
- SYSDB_DOM_BASE, sctx->domain->name);
- } else {
- base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
- SYSDB_TMPL_GROUP_BASE, sctx->domain->name);
- }
- if (!base_dn) {
- return request_error(sctx, ENOMEM);
- }
-
- ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx,
- base_dn, LDB_SCOPE_SUBTREE,
- sctx->expression, attrs, NULL,
- sctx, get_gen_callback,
- NULL);
- if (ret != LDB_SUCCESS) {
- return request_ldberror(sctx, ret);
- }
-
- ret = ldb_request(sctx->ctx->ldb, req);
- if (ret != LDB_SUCCESS) {
- return request_ldberror(sctx, ret);
- }
-}
-
int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
@@ -501,36 +460,55 @@ done:
int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
- sysdb_callback_t fn, void *ptr)
+ struct ldb_result **_res)
{
- struct sysdb_search_ctx *sctx;
- struct tevent_req *req;
+ TALLOC_CTX *tmpctx;
+ 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 = SYSDB_GRENT_MPG_FILTER;
+ fmt_filter = SYSDB_GRENT_MPG_FILTER;
+ base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb,
+ SYSDB_DOM_BASE, domain->name);
} else {
- sctx->expression = SYSDB_GRENT_FILTER;
+ fmt_filter = SYSDB_GRENT_FILTER;
+ base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb,
+ SYSDB_TMPL_GROUP_BASE, domain->name);
+ }
+ 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);
+ if (ret) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+
+ ret = mpg_res_convert(res);
+ if (ret) {
+ goto done;
}
- tevent_req_set_callback(req, grp_search, sctx);
+ *_res = talloc_steal(mem_ctx, res);
- return EOK;
+done:
+ talloc_zfree(tmpctx);
+ return ret;
}
static void initgr_mem_search(struct sysdb_search_ctx *sctx)
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 32ee29881..4bd08e4b6 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -2004,97 +2004,108 @@ done:
*/
static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx);
-static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
+static void nss_cmd_getgrent_dp_callback(uint16_t err_maj, uint32_t err_min,
+ const char *err_msg, void *ptr);
-static void nss_cmd_setgrent_callback(void *ptr, int status,
- struct ldb_result *res)
+static int nss_cmd_getgrent_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 ldb_result *res;
struct getent_ctx *gctx;
struct nss_ctx *nctx;
int timeout;
int ret;
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
gctx = nctx->gctx;
if (gctx == NULL) {
gctx = talloc_zero(nctx, struct getent_ctx);
if (!gctx) {
- ret = nss_cmd_send_error(cmdctx, ENOMEM);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
+ return ENOMEM;
}
nctx->gctx = gctx;
}
- gctx->doms = talloc_realloc(gctx, gctx->doms, struct dom_ctx, gctx->num +1);
- if (!gctx->doms) NSS_CMD_FATAL_ERROR(cctx);
+ while (dom) {
+ while (dom && dom->enumerate == 0) {
+ dom = dom->next;
+ }
- gctx->doms[gctx->num].domain = dctx->domain;
- gctx->doms[gctx->num].res = talloc_steal(gctx->doms, res);
- gctx->doms[gctx->num].cur = 0;
+ if (!dom) break;
- gctx->num++;
+ if (dom != dctx->domain) {
+ /* make sure we reset the check_provider flag when we check
+ * a new domain */
+ if (cmdctx->enum_cached) {
+ dctx->check_provider = false;
+ } else {
+ dctx->check_provider = NEED_CHECK_PROVIDER(dom->provider);
+ }
+ }
- /* do not reply until all domain searches are done */
- for (dom = dctx->domain->next; dom; dom = dom->next) {
- if (dom->enumerate != 0) break;
- }
- dctx->domain = dom;
+ /* make sure to update the dctx if we changed domain */
+ dctx->domain = dom;
- if (dctx->domain != NULL) {
- if (cmdctx->enum_cached) {
- dctx->check_provider = false;
- } else {
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
+ DEBUG(4, ("Requesting info for domain [%s]\n", dom->name));
+
+ 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 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) {
+ dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT;
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_setgr_dp_callback, dctx,
+ nss_cmd_getgrent_dp_callback, dctx,
timeout, dom->name, true,
SSS_DP_GROUP, NULL, 0);
- } else {
- 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);
+ if (ret == EOK) {
+ return ret;
+ } else {
+ DEBUG(2, ("Enum Cache refresh for domain [%s] failed."
+ " Trying to return what we have in cache!\n",
+ dom->name));
}
- ret = sysdb_enumgrent(dctx, sysdb,
- dctx->domain,
- nss_cmd_setgrent_callback, dctx);
}
+
+ ret = sysdb_enumgrent(dctx, sysdb, dctx->domain, &res);
if (ret != EOK) {
- /* FIXME: shutdown ? */
- DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
+ DEBUG(1, ("Enum from cache failed, skipping domain [%s]\n",
dom->name));
+ dom = dom->next;
+ continue;
+ }
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
+ if (res->count == 0) {
+ DEBUG(4, ("Domain [%s] has no groups, skipping.\n", dom->name));
+ dom = dom->next;
+ continue;
}
- return;
+
+
+ gctx->doms = talloc_realloc(gctx, gctx->doms,
+ struct dom_ctx, gctx->num +1);
+ if (!gctx->doms) {
+ talloc_free(gctx);
+ nctx->gctx = NULL;
+ return ENOMEM;
+ }
+
+ gctx->doms[gctx->num].domain = dctx->domain;
+ gctx->doms[gctx->num].res = talloc_steal(gctx->doms, res);
+ gctx->doms[gctx->num].cur = 0;
+
+ gctx->num++;
+
+ /* do not reply until all domain searches are done */
+ dom = dom->next;
}
/* set cache mark */
@@ -2103,28 +2114,25 @@ static void nss_cmd_setgrent_callback(void *ptr, int status,
if (cmdctx->immediate) {
/* this was a getgrent call w/o setgrent,
* return immediately one result */
- ret = nss_cmd_getgrent_immediate(cmdctx);
- if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
- return;
+ return nss_cmd_getgrent_immediate(cmdctx);
}
/* 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);
+ if (ret == EOK) {
+ sss_cmd_done(cctx, cmdctx);
}
- sss_cmd_done(cctx, cmdctx);
+ return ret;
}
-static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
+static void nss_cmd_getgrent_dp_callback(uint16_t err_maj, uint32_t err_min,
+ const char *err_msg, void *ptr)
{
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) {
@@ -2134,37 +2142,20 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
}
- 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_enumgrent(dctx, sysdb,
- dctx->domain,
- nss_cmd_setgrent_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
+ ret = nss_cmd_getgrent_search(dctx);
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
+ if (ret) {
+ NSS_CMD_FATAL_ERROR(cctx);
}
}
static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
{
struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
struct nss_cmd_ctx *cmdctx;
struct nss_dom_ctx *dctx;
struct nss_ctx *nctx;
time_t now = time(NULL);
- int timeout;
- uint8_t *body;
- size_t blen;
int ret;
DEBUG(4, ("Requesting info for all groups\n"));
@@ -2189,8 +2180,7 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
/* do not query backends if we have a recent enumeration */
if (nctx->enum_cache_timeout) {
- if (nctx->last_group_enum +
- nctx->enum_cache_timeout > now) {
+ if (nctx->last_group_enum + nctx->enum_cache_timeout > now) {
cmdctx->enum_cached = true;
}
}
@@ -2203,71 +2193,25 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
if (dctx->domain == NULL) {
DEBUG(2, ("Enumeration disabled on all domains!\n"));
- ret = ENOENT;
+ if (cmdctx->immediate) {
+ ret = ENOENT;
+ } else {
+ ret = sss_packet_new(cctx->creq, 0,
+ sss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret == EOK) {
+ sss_cmd_done(cctx, cmdctx);
+ }
+ }
goto done;
}
- if (cmdctx->enum_cached) {
- dctx->check_provider = false;
- } else {
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- }
-
- if (dctx->check_provider) {
- timeout = SSS_CLI_SOCKET_TIMEOUT;
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_setgr_dp_callback, dctx,
- timeout, dom->name, true,
- SSS_DP_GROUP, NULL, 0);
- } else {
- 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_enumgrent(dctx, sysdb,
- dctx->domain,
- nss_cmd_setgrent_callback, dctx);
- }
- if (ret != EOK) {
- /* FIXME: shutdown ? */
- DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
- dom->name));
- }
+ dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
+ /* ok, start the searches */
+ ret = nss_cmd_getgrent_search(dctx);
done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- if (cmdctx->immediate) {
- /* 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 */
- }
- }
- else {
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- }
- }
- 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);
}
static int nss_cmd_setgrent(struct cli_ctx *cctx)
@@ -2282,13 +2226,15 @@ static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
struct ldb_message **msgs = NULL;
struct dom_ctx *gdom = NULL;
int n = 0;
- int ret;
+ int ret = ENOENT;
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
+ if (!nctx->gctx) goto none;
+
gctx = nctx->gctx;
- do {
- if (gctx->cur >= gctx->num) goto none;
+ while (ret == ENOENT) {
+ if (gctx->cur >= gctx->num) break;
gdom = &gctx->doms[gctx->cur];
@@ -2299,24 +2245,26 @@ static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
n = gdom->res->count - gdom->cur;
}
- if (!n) goto none;
+ if (!n) break;
+
+ if (n > num) n = num;
msgs = &(gdom->res->msgs[gdom->cur]);
- ret = fill_grent(cctx->creq->out, gdom->domain, nctx, true, msgs, num, &n);
+ ret = fill_grent(cctx->creq->out,
+ gdom->domain,
+ nctx, true, msgs, n, &n);
gdom->cur += n;
-
- } while(ret == ENOENT);
-
- return ret;
+ }
none:
- return fill_empty(cctx->creq->out);
+ if (ret == ENOENT) {
+ ret = fill_empty(cctx->creq->out);
+ }
+ return ret;
}
-/* used only if a process calls getpwent() without first calling setpwent()
- */
static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx)
{
struct cli_ctx *cctx = cmdctx->cctx;
@@ -2359,9 +2307,6 @@ static int nss_cmd_getgrent(struct cli_ctx *cctx)
/* see if we need to trigger an implicit setpwent() */
if (nctx->gctx == NULL) {
- nctx->gctx = talloc_zero(nctx, struct getent_ctx);
- if (!nctx->gctx) return ENOMEM;
-
return nss_cmd_setgrent_ext(cctx, true);
}
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index bfd640bcd..2a84da94b 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -305,26 +305,6 @@ static int test_remove_group_by_gid(struct test_data *data)
return ret;
}
-static void test_enumgrent(void *pvt, int error, struct ldb_result *res)
-{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- const int expected = 20; /* 10 groups + 10 users (we're MPG) */
-
- data->finished = true;
-
- if (error != EOK) {
- data->error = error;
- return;
- }
-
- if (res->count != expected) {
- data->error = EINVAL;
- return;
- }
-
- data->error = EOK;
-}
-
static int test_set_user_attr(struct test_data *data)
{
int ret;
@@ -890,7 +870,7 @@ END_TEST
START_TEST (test_sysdb_enumgrent)
{
struct sysdb_test_ctx *test_ctx;
- struct test_data *data;
+ struct ldb_result *res;
int ret;
/* Setup */
@@ -900,22 +880,17 @@ START_TEST (test_sysdb_enumgrent)
return;
}
- data = talloc_zero(test_ctx, struct test_data);
- data->ctx = test_ctx;
-
ret = sysdb_enumgrent(test_ctx,
- test_ctx->sysdb,
- data->ctx->domain,
- test_enumgrent,
- data);
- if (ret == EOK) {
- ret = test_loop(data);
- }
-
+ test_ctx->sysdb,
+ test_ctx->domain,
+ &res);
fail_unless(ret == EOK,
"sysdb_enumgrent failed (%d: %s)",
ret, strerror(ret));
+ /* 10 groups + 10 users (we're MPG) */
+ fail_if(res->count != 20, "Expected 20 users, got %d", res->count);
+
talloc_free(test_ctx);
}
END_TEST