summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/db/sysdb.h2
-rw-r--r--src/db/sysdb_search.c40
-rw-r--r--src/responder/nss/nsssrv_cmd.c305
-rw-r--r--src/tests/sysdb-tests.c64
4 files changed, 146 insertions, 265 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 365e6adf6..cb5cbba11 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -259,7 +259,7 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
uid_t uid,
- sysdb_callback_t fn, void *ptr);
+ struct ldb_result **res);
int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 2403917b7..3d375214d 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -257,39 +257,43 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
struct sss_domain_info *domain,
uid_t uid,
- sysdb_callback_t fn, void *ptr)
+ struct ldb_result **_res)
{
+ TALLOC_CTX *tmpctx;
+ unsigned long int ul_uid = uid;
static const char *attrs[] = SYSDB_PW_ATTRS;
- struct sysdb_search_ctx *sctx;
- unsigned long int filter_uid = uid;
- struct tevent_req *req;
+ 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;
}
- sctx->expression = talloc_asprintf(sctx, SYSDB_PWUID_FILTER, filter_uid);
- if (!sctx->expression) {
- talloc_free(sctx);
- return ENOMEM;
+ base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb,
+ SYSDB_TMPL_USER_BASE, domain->name);
+ if (!base_dn) {
+ ret = ENOMEM;
+ goto done;
}
- sctx->attrs = attrs;
-
- 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, SYSDB_PWUID_FILTER, ul_uid);
+ if (ret) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
}
- tevent_req_set_callback(req, user_search, sctx);
+ *_res = talloc_steal(mem_ctx, res);
- return EOK;
+done:
+ talloc_zfree(tmpctx);
+ return ret;
}
int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index d25c467ae..c74969d10 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -711,143 +711,108 @@ done:
static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
const char *err_msg, void *ptr);
-static void nss_cmd_getpwuid_callback(void *ptr, int status,
- struct ldb_result *res)
+/* search for a uid.
+ * Returns:
+ * ENOENT, if uid is definitely not found
+ * EAGAIN, if uid is beeing fetched from backend via async operations
+ * EOK, if found
+ * anything else on a fatal error
+ */
+
+static int nss_cmd_getpwuid_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 ret;
- int ncret;
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);
+ while (dom) {
+
+ /* 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, ("Uid [%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;
}
- sss_cmd_done(cctx, cmdctx);
- return;
- }
- if (dctx->check_provider) {
- ret = check_cache(dctx, nctx, res,
- SSS_DP_USER, NULL, cmdctx->id,
- nss_cmd_getpwuid_dp_callback);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return;
+ 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);
}
- }
- switch (res->count) {
- case 0:
- if (cmdctx->check_next) {
+ /* make sure to update the dctx if we changed domain */
+ dctx->domain = dom;
- ret = EOK;
+ DEBUG(4, ("Requesting info for [%d@%s]\n", cmdctx->id, dom->name));
- dom = dctx->domain->next;
- ncret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout,
- cmdctx->id);
- if (ncret == EEXIST) {
- DEBUG(3, ("Uid [%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_getpwuid(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, ("getpwuid 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_getpwuid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getpwuid_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 getpwuid call\n"));
+ DEBUG(2, ("No results for getpwuid 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_uid(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);
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- break;
-
- case 1:
- DEBUG(6, ("Returning info for user [%u]\n", (unsigned)cmdctx->id));
- /* 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);
+ return ENOENT;
}
- ret = fill_pwent(cctx->creq->out,
- dctx->domain,
- nctx, true,
- res->msgs, res->count);
- if (ret == ENOENT) {
- ret = fill_empty(cctx->creq->out);
+ /* 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_USER, NULL, cmdctx->id,
+ nss_cmd_getpwuid_dp_callback);
+ if (ret != EOK) {
+ /* Anything but EOK means we should reenter the mainloop
+ * because we may be refreshing the cache
+ */
+ return ret;
+ }
}
- sss_packet_set_error(cctx->creq->out, ret);
- break;
+ /* One result found */
+ DEBUG(6, ("Returning info for uid [%d@%s]\n", cmdctx->id, dom->name));
- default:
- DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
+ 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_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
@@ -856,7 +821,6 @@ static void nss_cmd_getpwuid_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) {
@@ -865,38 +829,33 @@ static void nss_cmd_getpwuid_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_getpw_send_reply(dctx, true);
+ goto done;
}
- nss_cmd_getpwuid_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_getpwuid_search(dctx);
+ if (ret == EOK) {
+ /* we have results to return */
+ ret = nss_cmd_getpw_send_reply(dctx, true);
}
- ret = sysdb_getpwuid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getpwuid_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);
}
}
@@ -904,15 +863,11 @@ static int nss_cmd_getpwuid(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);
@@ -937,75 +892,29 @@ static int nss_cmd_getpwuid(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_uid(nctx->ncache, nctx->neg_timeout,
- cmdctx->id);
- if (ncret == EEXIST) {
- DEBUG(3, ("Uid [%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, ("Uid [%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_uid(nctx->ncache, nctx->neg_timeout, cmdctx->id);
+ if (ret == EEXIST) {
+ DEBUG(3, ("Uid [%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));
+ /* uid 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_getpwuid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getpwuid_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_getpwuid_search(dctx);
+ if (ret == EOK) {
+ /* we have results to return */
+ ret = nss_cmd_getpw_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 acb96b2e8..6633136d2 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -356,31 +356,6 @@ static void test_getgrgid(void *pvt, int error, struct ldb_result *res)
}
}
-static void test_getpwuid(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->username = 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);
@@ -976,9 +951,10 @@ END_TEST
START_TEST (test_sysdb_getpwuid)
{
struct sysdb_test_ctx *test_ctx;
- struct test_data *data;
+ struct ldb_result *res;
+ const char *e_username;
+ const char *username;
int ret;
- const char *username = NULL;
/* Setup */
ret = setup_sysdb_tests(&test_ctx);
@@ -987,35 +963,27 @@ START_TEST (test_sysdb_getpwuid)
return;
}
- username = talloc_asprintf(test_ctx, "testuser%d", _i);
- if (username == NULL) {
- fail("Cannot allocate memory");
- return;
- }
-
- data = talloc_zero(test_ctx, struct test_data);
- data->ctx = test_ctx;
- data->uid = _i;
-
ret = sysdb_getpwuid(test_ctx,
test_ctx->sysdb,
- data->ctx->domain,
- data->uid,
- test_getpwuid,
- data);
- if (ret == EOK) {
- ret = test_loop(data);
- }
-
+ test_ctx->domain,
+ _i, &res);
if (ret) {
fail("sysdb_getpwuid failed for uid %d (%d: %s)",
- data->uid, ret, strerror(ret));
+ _i, ret, strerror(ret));
+ goto done;
+ }
+
+ username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, 0);
+
+ e_username = talloc_asprintf(test_ctx, "testuser%d", _i);
+ if (username == NULL) {
+ fail("Cannot allocate memory");
goto done;
}
- fail_unless(strcmp(data->username, username) == 0,
+ fail_unless(strcmp(username, e_username) == 0,
"Did not find the expected username (found %s expected %s)",
- data->username, username);
+ username, e_username);
done:
talloc_free(test_ctx);
}