diff options
author | Simo Sorce <ssorce@redhat.com> | 2009-05-27 18:01:07 -0400 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2009-05-27 18:01:07 -0400 |
commit | 4fff9b914556f91f2caeca637fa8e76ceba91aed (patch) | |
tree | 77d0f5145f1abf75e5dd6ef667afdfc9681050b5 /server | |
parent | b4f46c6ecf529ed8115fb4d3664a80c4c98f8c52 (diff) | |
download | sssd-4fff9b914556f91f2caeca637fa8e76ceba91aed.tar.gz sssd-4fff9b914556f91f2caeca637fa8e76ceba91aed.tar.xz sssd-4fff9b914556f91f2caeca637fa8e76ceba91aed.zip |
Fix enumerations (bug #42)
If a backend had all its results filtered in fill_pwent or fill_grent
then we would return an empty result, which means "end of results" to
the client.
Now we return ENOENT and let callers decide what to do.
Also make sure we do not grow packets unless we are going to fill them
as that's a recipe for killing the client as the size passed to
sss_packet_grow is used to determine the size of the final packet.
Diffstat (limited to 'server')
-rw-r--r-- | server/responder/nss/nsssrv_cmd.c | 88 |
1 files changed, 76 insertions, 12 deletions
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c index 5a779018a..d49fe2ebb 100644 --- a/server/responder/nss/nsssrv_cmd.c +++ b/server/responder/nss/nsssrv_cmd.c @@ -93,6 +93,22 @@ static struct sss_domain_info *nss_get_dom(struct sss_domain_info *doms, return dom; } +static int fill_empty(struct sss_packet *packet) +{ + uint8_t *body; + size_t blen; + int ret; + + ret = sss_packet_grow(packet, 2*sizeof(uint32_t)); + if (ret != EOK) return ret; + + sss_packet_get_body(packet, &body, &blen); + ((uint32_t *)body)[0] = 0; /* num results */ + ((uint32_t *)body)[1] = 0; /* reserved */ + + return EOK; +} + /**************************************************************************** * PASSWD db related functions ***************************************************************************/ @@ -120,12 +136,15 @@ static int fill_pwent(struct sss_packet *packet, bool add_domain = dom->fqnames; const char *domain = dom->name; const char *namefmt = nctx->rctx->names->fq_fmt; + bool packet_initialized = false; int ncret; if (add_domain) dom_len = strlen(domain); /* first 2 fields (len and reserved), filled up later */ ret = sss_packet_grow(packet, 2*sizeof(uint32_t)); + if (ret != EOK) return ret; + rp = 2*sizeof(uint32_t); num = 0; @@ -161,6 +180,13 @@ static int fill_pwent(struct sss_packet *packet, continue; } + if (!packet_initialized) { + /* first 2 fields (len and reserved), filled up later */ + ret = sss_packet_grow(packet, 2*sizeof(uint32_t)); + if (ret != EOK) return ret; + packet_initialized = true; + } + gecos = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL); homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL); shell = ldb_msg_find_attr_as_string(msg, SYSDB_SHELL, NULL); @@ -229,6 +255,10 @@ static int fill_pwent(struct sss_packet *packet, } done: + /* if there are no results just return ENOENT, + * let the caller decide if this is the last packet or not */ + if (!packet_initialized) return ENOENT; + sss_packet_get_body(packet, &body, &blen); ((uint32_t *)body)[0] = num; /* num results */ ((uint32_t *)body)[1] = 0; /* reserved */ @@ -408,6 +438,9 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, dctx->domain, nctx, false, res->msgs, res->count); + if (ret == ENOENT) { + ret = fill_empty(cctx->creq->out); + } sss_packet_set_error(cctx->creq->out, ret); break; @@ -765,6 +798,9 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, dctx->domain, nctx, true, res->msgs, res->count); + if (ret == ENOENT) { + ret = fill_empty(cctx->creq->out); + } sss_packet_set_error(cctx->creq->out, ret); break; @@ -1195,13 +1231,15 @@ static int nss_cmd_retpwent(struct cli_ctx *cctx, int num) struct nss_ctx *nctx; struct getent_ctx *pctx; struct ldb_message **msgs = NULL; - struct dom_ctx *pdom; + struct dom_ctx *pdom = NULL; int n = 0; + int ret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); pctx = nctx->pctx; - if (pctx->cur >= pctx->num) goto done; +retry: + if (pctx->cur >= pctx->num) goto none; pdom = &pctx->doms[pctx->cur]; @@ -1212,15 +1250,19 @@ static int nss_cmd_retpwent(struct cli_ctx *cctx, int num) n = pdom->res->count - pdom->cur; } - if (!n) goto done; + if (!n) goto none; if (n > num) n = num; msgs = &(pdom->res->msgs[pdom->cur]); pdom->cur += n; -done: - return fill_pwent(cctx->creq->out, pdom->domain, nctx, true, msgs, n); + ret = fill_pwent(cctx->creq->out, pdom->domain, nctx, true, msgs, n); + if (ret == ENOENT) goto retry; + return ret; + +none: + return fill_empty(cctx->creq->out); } /* used only if a process calls getpwent() without first calling setpwent() @@ -1333,12 +1375,11 @@ static int fill_grent(struct sss_packet *packet, bool add_domain = dom->fqnames; const char *domain = dom->name; const char *namefmt = nctx->rctx->names->fq_fmt; + bool packet_initialized = false; int ncret; if (add_domain) dom_len = strlen(domain); - /* first 2 fields (len and reserved), filled up later */ - ret = sss_packet_grow(packet, 2*sizeof(uint32_t)); rp = 2*sizeof(uint32_t); num = 0; @@ -1391,6 +1432,13 @@ static int fill_grent(struct sss_packet *packet, continue; } + if (!packet_initialized) { + /* first 2 fields (len and reserved), filled up later */ + ret = sss_packet_grow(packet, 2*sizeof(uint32_t)); + if (ret != EOK) return ret; + packet_initialized = true; + } + /* fill in gid and name and set pointer for number of members */ name_len = strlen(name) + 1; if (add_domain) name_len += delim + dom_len; @@ -1614,6 +1662,10 @@ static int fill_grent(struct sss_packet *packet, } done: + /* if there are no results just return ENOENT, + * let the caller decide if this is the last packet or not */ + if (!packet_initialized) return ENOENT; + sss_packet_get_body(packet, &body, &blen); ((uint32_t *)body)[0] = num; /* num results */ ((uint32_t *)body)[1] = 0; /* reserved */ @@ -1787,6 +1839,9 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, dctx->domain, nctx, false, res->msgs, res->count); + if (ret == ENOENT) { + ret = fill_empty(cctx->creq->out); + } sss_packet_set_error(cctx->creq->out, ret); } @@ -2129,6 +2184,9 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, dctx->domain, nctx, true, res->msgs, res->count); + if (ret == ENOENT) { + ret = fill_empty(cctx->creq->out); + } sss_packet_set_error(cctx->creq->out, ret); } @@ -2545,13 +2603,15 @@ static int nss_cmd_retgrent(struct cli_ctx *cctx, int num) struct nss_ctx *nctx; struct getent_ctx *gctx; struct ldb_message **msgs = NULL; - struct dom_ctx *gdom; + struct dom_ctx *gdom = NULL; int n = 0; + int ret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); gctx = nctx->gctx; - if (gctx->cur >= gctx->num) goto done; +retry: + if (gctx->cur >= gctx->num) goto none; gdom = &gctx->doms[gctx->cur]; @@ -2562,15 +2622,19 @@ static int nss_cmd_retgrent(struct cli_ctx *cctx, int num) n = gdom->res->count - gdom->cur; } - if (!n) goto done; + if (!n) goto none; if (n > num) n = num; msgs = &(gdom->res->msgs[gdom->cur]); gdom->cur += n; -done: - return fill_grent(cctx->creq->out, gdom->domain, nctx, true, msgs, n); + ret = fill_grent(cctx->creq->out, gdom->domain, nctx, true, msgs, n); + if (ret == ENOENT) goto retry; + return ret; + +none: + return fill_empty(cctx->creq->out); } /* used only if a process calls getpwent() without first calling setpwent() |