summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-05-27 18:01:07 -0400
committerSimo Sorce <ssorce@redhat.com>2009-05-27 18:01:07 -0400
commit4fff9b914556f91f2caeca637fa8e76ceba91aed (patch)
tree77d0f5145f1abf75e5dd6ef667afdfc9681050b5 /server
parentb4f46c6ecf529ed8115fb4d3664a80c4c98f8c52 (diff)
downloadsssd-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.c88
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()