summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 5a779018..d49fe2eb 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()