summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-05-29 18:40:24 +0200
committerJakub Hrozek <jhrozek@redhat.com>2012-07-09 16:11:45 +0200
commitd87f787405ccd86e3dbc434aa12bb62dca80ae6d (patch)
tree6f280c82ef7eb6ad023dbd5011a17d56b71fe491
parent708cd09df21550ffd9fb5eefbf95720bc470356f (diff)
downloadsssd-d87f787405ccd86e3dbc434aa12bb62dca80ae6d.tar.gz
sssd-d87f787405ccd86e3dbc434aa12bb62dca80ae6d.tar.xz
sssd-d87f787405ccd86e3dbc434aa12bb62dca80ae6d.zip
Provide new search for getpwnam
FIXME - this removed the internal dp callback
-rw-r--r--src/responder/nss/nsssrv_cmd.c286
1 files changed, 140 insertions, 146 deletions
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 5c5f8060b..314d5fbe9 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -31,6 +31,8 @@
#include "db/sysdb.h"
#include <time.h>
+#define NSS_CASED_NAME(dom, pvt) (dom->case_sensitive ? pvt->name : pvt->cased_name)
+
static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
{
return sss_cmd_send_error(cmdctx->cctx, err);
@@ -581,176 +583,168 @@ static void nsssrv_dp_send_acct_req_done(struct tevent_req *req)
cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
}
-static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-/* search for a user.
- * Returns:
- * ENOENT, if user is definitely not found
- * EAGAIN, if user is beeing fetched from backend via async operations
- * EOK, if found
- * anything else on a fatal error
- */
-
-static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
-{
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct sss_domain_info *dom = dctx->domain;
- struct cli_ctx *cctx = cmdctx->cctx;
- char *name = NULL;
- struct sysdb_ctx *sysdb;
+/* FIXME - does this obsolete dctx? */
+struct getpwnam_search_ctx {
struct nss_ctx *nctx;
- int ret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- while (dom) {
- /* if it is a domainless search, skip domains that require fully
- * qualified names instead */
- while (dom && cmdctx->check_next && dom->fqnames) {
- dom = dom->next;
- }
-
- if (!dom) break;
-
- 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);
- }
-
- /* make sure to update the dctx if we changed domain */
- dctx->domain = dom;
+ struct cli_ctx *cctx;
+ const char *name;
+ const char *cased_name;
+};
- talloc_free(name);
- name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive);
- if (!name) return ENOMEM;
+static errno_t
+nss_cmd_getpwnam_check_ncache(struct sss_domain_info *dom, void *pvt)
+{
+ struct getpwnam_search_ctx *ctx =
+ talloc_get_type(pvt, struct getpwnam_search_ctx);
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ret = sss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- dom, name);
+ return sss_ncache_check_user(ctx->nctx->ncache, ctx->nctx->neg_timeout,
+ dom, ctx->name);
+}
- /* if neg cached, return we didn't find it */
- if (ret == EEXIST) {
- DEBUG(2, ("User [%s] does not exist in [%s]! (negative cache)\n",
- name, dom->name));
- /* if a multidomain search, try with next */
- if (cmdctx->check_next) {
- dom = dom->next;
- continue;
- }
- /* There are no further domains or this was a
- * fully-qualified user request.
- */
- return ENOENT;
- }
+static errno_t
+nss_cmd_getpwnam_set_ncache(struct sss_domain_info *dom, void *pvt)
+{
+ struct getpwnam_search_ctx *ctx =
+ talloc_get_type(pvt, struct getpwnam_search_ctx);
- DEBUG(4, ("Requesting info for [%s@%s]\n", name, dom->name));
+ return sss_ncache_set_user(ctx->nctx->ncache, false, dom, ctx->name);
+}
- sysdb = dom->sysdb;
- if (sysdb == NULL) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- return EIO;
- }
+static errno_t
+nss_cmd_getpwnam_check_cache(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
+ struct sss_domain_info *dom, void *pvt,
+ struct ldb_result **res)
+{
+ struct getpwnam_search_ctx *ctx =
+ talloc_get_type(pvt, struct getpwnam_search_ctx);
- ret = sysdb_getpwnam(cmdctx, sysdb, name, &dctx->res);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- return EIO;
- }
+ return sysdb_getpwnam(mem_ctx, sysdb, NSS_CASED_NAME(dom, ctx), res);
+}
- if (dctx->res->count > 1) {
- DEBUG(0, ("getpwnam call returned more than one result !?!\n"));
- return ENOENT;
- }
+static struct tevent_req *
+nss_cmd_getpwnam_update_cache(struct sss_domain_info *dom, void *pvt)
+{
+ struct getpwnam_search_ctx *ctx =
+ talloc_get_type(pvt, struct getpwnam_search_ctx);
- if (dctx->res->count == 0 && !dctx->check_provider) {
- /* set negative cache only if not result of cache check */
- ret = sss_ncache_set_user(nctx->ncache, false, dom, name);
- if (ret != EOK) {
- return ret;
- }
+ return sss_dp_get_account_send(ctx->cctx, ctx->cctx->rctx,
+ dom, true, SSS_DP_USER,
+ NSS_CASED_NAME(dom, ctx),
+ 0, NULL);
+}
- /* if a multidomain search, try with next */
- if (cmdctx->check_next) {
- dom = dom->next;
- if (dom) continue;
- }
+static errno_t
+nss_cmd_getpwnam_cache_updated(TALLOC_CTX *mem_ctx, struct tevent_req *req,
+ dbus_uint16_t *err_maj, dbus_uint32_t *err_min,
+ char **err_msg)
+{
+ return sss_dp_get_account_recv(mem_ctx, req, err_maj, err_min, err_msg);
+}
- DEBUG(2, ("No results for getpwnam call\n"));
+static const char *
+nss_cmd_getpwnam_get_name(struct sss_domain_info *dom, void *pvt)
+{
+ struct getpwnam_search_ctx *ctx =
+ talloc_get_type(pvt, struct getpwnam_search_ctx);
+ return NSS_CASED_NAME(dom, ctx);
+}
- return ENOENT;
- }
+static void nss_cmd_getpwnam_done(struct tevent_req *subreq);
- /* 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, name, 0,
- nss_cmd_getpwnam_dp_callback,
- dctx);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return ret;
- }
- }
+static errno_t
+nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
+{
+ struct tevent_req *req;
+ struct nss_ctx *nctx;
+ struct getpwnam_search_ctx *search_ctx;
+ static struct getent_ops getpwnam_ops = {
+ .check_ncache = nss_cmd_getpwnam_check_ncache,
+ .set_ncache = nss_cmd_getpwnam_set_ncache,
+ .check_sysdb = nss_cmd_getpwnam_check_cache,
+ .update_cache = nss_cmd_getpwnam_update_cache,
+ .cache_updated = nss_cmd_getpwnam_cache_updated,
+ .get_ent_name = nss_cmd_getpwnam_get_name
+ };
- /* One result found */
- DEBUG(6, ("Returning info for user [%s@%s]\n", name, dom->name));
+ nctx = talloc_get_type(dctx->cmdctx->cctx->rctx->pvt_ctx, struct nss_ctx);
- return EOK;
+ search_ctx = talloc_zero(dctx, struct getpwnam_search_ctx);
+ if (!search_ctx) {
+ return ENOMEM;
+ }
+ search_ctx->nctx = nctx;
+ search_ctx->cctx = dctx->cmdctx->cctx;
+ search_ctx->name = dctx->cmdctx->name;
+ search_ctx->cased_name = sss_get_cased_name(search_ctx, search_ctx->name,
+ false);
+ if (search_ctx->cased_name == NULL) {
+ talloc_free(search_ctx);
+ return ENOMEM;
}
- DEBUG(SSSDBG_MINOR_FAILURE,
- ("No matching domain found for [%s], fail!\n", cmdctx->name));
- return ENOENT;
+ req = getent_send(dctx, dctx->cmdctx->cctx->ev, dctx->cmdctx->cctx,
+ dctx->cmdctx->cctx, nctx->cache_refresh_percent,
+ &getpwnam_ops, "getpwnam", dctx);
+ if (!req) {
+ talloc_free(search_ctx);
+ return ENOMEM;
+ }
+ /* FIXME - what if the client disconnects at this point? A potential cache
+ * update must be allocated on rctx, so that it goes all the way, but will
+ * the callback be invoked?*/
+ tevent_req_set_callback(req, nss_cmd_getpwnam_done, dctx);
+ return EOK;
}
-static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
+static void
+nss_cmd_getpwnam_done(struct tevent_req *req)
{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
+ errno_t ret, reqret;
+ int i;
+ 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;
- int ret;
+ struct nss_ctx *nctx =
+ talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
-
- if (dctx->res && dctx->res->count == 1) {
- ret = nss_cmd_getpw_send_reply(dctx, false);
- goto done;
- }
+ reqret = getent_recv(dctx, req, NULL, &dctx->res);
+ talloc_zfree(req);
+ if (reqret != EOK && reqret != ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE, ("getpwnam failed\n"));
+ nss_cmd_done(cmdctx, reqret);
+ 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);
+ /* FIXME - split out to provide nss_cmd_getpw_send_reply */
+ /* Either we succeeded or no domains were eligible */
+ ret = sss_packet_new(cmdctx->cctx->creq, 0,
+ sss_packet_get_cmd(cmdctx->cctx->creq->in),
+ &cmdctx->cctx->creq->out);
+ if (ret == EOK) {
+ if (reqret == ENOENT) {
+ /* Notify the caller that this entry wasn't found */
+ ret = sss_cmd_empty_packet(cmdctx->cctx->creq->out);
} else {
- /* nothing available */
- ret = ENOENT;
- goto done;
+ i = dctx->res->count;
+ ret = fill_pwent(cmdctx->cctx->creq->out,
+ dctx->domain,
+ nctx,
+ false, true, /* getpwname sets filter to false, getpwuid to true */
+ dctx->res->msgs,
+ &i);
+ }
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not create response packet: [%s]\n",
+ strerror(ret)));
}
- }
- /* ok the backend returned, search to see if we have updated results */
- ret = nss_cmd_getpwnam_search(dctx);
- if (ret == EOK) {
- /* we have results to return */
- ret = nss_cmd_getpw_send_reply(dctx, false);
+ sss_cmd_done(cmdctx->cctx, cmdctx);
+ return;
}
-done:
- ret = nss_cmd_done(cmdctx, ret);
- if (ret) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
+ DEBUG(SSSDBG_OP_FAILURE, ("Error creating packet\n"));
}
static void nss_cmd_getpwnam_cb(struct tevent_req *req);
@@ -844,9 +838,9 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
/* 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);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not start search\n"));
+ goto done;
}
done:
@@ -896,8 +890,8 @@ static void nss_cmd_getpwnam_cb(struct tevent_req *req)
/* 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);
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not start search\n"));
+ goto done;
}
done: