summaryrefslogtreecommitdiff
path: root/server/nss
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2008-10-14 05:42:43 -0400
committerSimo Sorce <idra@samba.org>2008-10-14 05:42:43 -0400
commit1170303766a4962cbb3253b8404a258bcfac8bf3 (patch)
treee87a31111ff18e5150b6b015b9ee89c689038998 /server/nss
parente33930a92ec392cd4a36d24114f2ab1946d9ad4b (diff)
downloadsssd-1170303766a4962cbb3253b8404a258bcfac8bf3.tar.gz
sssd-1170303766a4962cbb3253b8404a258bcfac8bf3.tar.bz2
sssd-1170303766a4962cbb3253b8404a258bcfac8bf3.zip
Fix error in parsing multiple groups
Revert to use 'cn' for group names Implement getgrent()
Diffstat (limited to 'server/nss')
-rw-r--r--server/nss/nss_ldb.h2
-rw-r--r--server/nss/nsssrv_cmd.c221
-rw-r--r--server/nss/nsssrv_ldb.c145
-rw-r--r--server/nss/nsssrv_ldb.h7
4 files changed, 346 insertions, 29 deletions
diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h
index 13e5a672..fe135683 100644
--- a/server/nss/nss_ldb.h
+++ b/server/nss/nss_ldb.h
@@ -9,7 +9,7 @@
#define NSS_PWUID_FILTER "(&(objectclass=user)(uidNumber=%llu))"
#define NSS_PWENT_FILTER "(objectclass=user)"
-#define NSS_GRNAM_FILTER "(&(objectclass=group)(gid=%s))"
+#define NSS_GRNAM_FILTER "(&(objectclass=group)(cn=%s))"
#define NSS_GRNA2_FILTER "(&(objectclass=user)(memberof=%s))"
#define NSS_GRGID_FILTER "(&(objectclass=group)(gidNumber=%llu))"
#define NSS_GRENT_FILTER "(objectclass=group)"
diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c
index 6252ab4a..c69598bc 100644
--- a/server/nss/nsssrv_cmd.c
+++ b/server/nss/nsssrv_cmd.c
@@ -494,6 +494,7 @@ static int fill_grent(struct nss_packet *packet,
rp = 2*sizeof(uint32_t);
num = 0;
+ mnump = 0;
for (i = 0; i < count; i++) {
msg = msgs[i];
@@ -535,6 +536,7 @@ static int fill_grent(struct nss_packet *packet,
* set next element to be a group, and eventually
* fail there if here start bogus entries */
get_group = true;
+ i--;
nss_packet_get_body(packet, &body, &blen);
((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
continue;
@@ -555,8 +557,10 @@ static int fill_grent(struct nss_packet *packet,
}
/* fill in the last group member count */
- nss_packet_get_body(packet, &body, &blen);
- ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
+ if (mnump != 0) {
+ nss_packet_get_body(packet, &body, &blen);
+ ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
+ }
done:
nss_packet_get_body(packet, &body, &blen);
@@ -668,6 +672,216 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx)
return ret;
}
+/* to keep it simple at this stage we are retrieving the
+ * full enumeration again for each request for each process
+ * and we also block on setpwent() for the full time needed
+ * to retrieve the data. And endpwent() frees all the data.
+ * Next steps are:
+ * - use and nsssrv wide cache with data already structured
+ * so that it can be immediately returned (see nscd way)
+ * - use mutexes so that setpwent() can return immediately
+ * even if the data is still being fetched
+ * - make getpwent() wait on the mutex
+ */
+static int nss_cmd_setgrent_callback(void *ptr, int status,
+ struct ldb_result *res)
+{
+ struct nss_cmd_ctx *nctx = talloc_get_type(ptr, struct nss_cmd_ctx);
+ struct cli_ctx *cctx = nctx->cctx;
+ struct getent_ctx *gctx = cctx->gctx;
+ int ret;
+
+ /* create response packet */
+ ret = nss_packet_new(cctx->creq, 0,
+ nss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (status != LDB_SUCCESS) {
+ nss_packet_set_error(cctx->creq->out, status);
+ goto done;
+ }
+
+ gctx->grps = talloc_steal(gctx, res);
+
+done:
+ nss_cmd_done(nctx);
+ return EOK;
+}
+
+static int nss_cmd_setgrent(struct cli_ctx *cctx)
+{
+ struct nss_cmd_ctx *nctx;
+ struct getent_ctx *gctx;
+ int ret;
+
+ nctx = talloc(cctx, struct nss_cmd_ctx);
+ if (!nctx) {
+ return ENOMEM;
+ }
+ nctx->cctx = cctx;
+
+ if (cctx->gctx == NULL) {
+ gctx = talloc_zero(cctx, struct getent_ctx);
+ if (!gctx) {
+ talloc_free(nctx);
+ return ENOMEM;
+ }
+ cctx->gctx = gctx;
+ }
+ if (cctx->gctx->grps) {
+ talloc_free(cctx->gctx->grps);
+ cctx->gctx->grps = NULL;
+ cctx->gctx->grp_cur = 0;
+ }
+
+ ret = nss_ldb_enumgrent(nctx, cctx->ev, cctx->ldb,
+ nss_cmd_setgrent_callback, nctx);
+
+ return ret;
+}
+
+static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
+{
+ struct getent_ctx *gctx = cctx->gctx;
+ int n, ret;
+
+ n = gctx->grps->count - gctx->grp_cur;
+ if (n > num) n = num;
+
+ ret = fill_grent(cctx->creq->out, &(gctx->grps->msgs[gctx->grp_cur]), n);
+ gctx->grp_cur += n;
+
+ return ret;
+}
+
+/* used only if a process calls getpwent() without first calling setpwent()
+ * in this case we basically trigger an implicit setpwent() */
+static int nss_cmd_getgrent_callback(void *ptr, int status,
+ struct ldb_result *res)
+{
+ struct nss_cmd_ctx *nctx = talloc_get_type(ptr, struct nss_cmd_ctx);
+ struct cli_ctx *cctx = nctx->cctx;
+ struct getent_ctx *gctx = cctx->gctx;
+ uint8_t *body;
+ size_t blen;
+ uint32_t num;
+ int ret;
+
+ /* get max num of entries to return in one call */
+ nss_packet_get_body(cctx->creq->in, &body, &blen);
+ if (blen != sizeof(uint32_t)) {
+ return EINVAL;
+ }
+ num = *((uint32_t *)body);
+
+ /* create response packet */
+ ret = nss_packet_new(cctx->creq, 0,
+ nss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (status != LDB_SUCCESS) {
+ nss_packet_set_error(cctx->creq->out, status);
+ goto done;
+ }
+
+ gctx->grps = talloc_steal(gctx, res);
+
+ ret = nss_cmd_retgrent(cctx, num);
+ nss_packet_set_error(cctx->creq->out, ret);
+
+done:
+ nss_cmd_done(nctx);
+ return EOK;
+}
+
+static int nss_cmd_getgrent(struct cli_ctx *cctx)
+{
+ struct nss_cmd_ctx *nctx;
+ struct getent_ctx *gctx;
+ uint8_t *body;
+ size_t blen;
+ uint32_t num;
+ int ret;
+
+ /* get max num of entries to return in one call */
+ nss_packet_get_body(cctx->creq->in, &body, &blen);
+ if (blen != sizeof(uint32_t)) {
+ return EINVAL;
+ }
+ num = *((uint32_t *)body);
+
+ nctx = talloc(cctx, struct nss_cmd_ctx);
+ if (!nctx) {
+ return ENOMEM;
+ }
+ nctx->cctx = cctx;
+
+ /* see if we need to trigger an implicit setpwent() */
+ if (cctx->gctx == NULL || cctx->gctx->grps == NULL) {
+ if (cctx->gctx == NULL) {
+ gctx = talloc_zero(cctx, struct getent_ctx);
+ if (!gctx) {
+ talloc_free(nctx);
+ return ENOMEM;
+ }
+ cctx->gctx = gctx;
+ }
+ if (cctx->gctx->grps == NULL) {
+ ret = nss_ldb_enumgrent(nctx, cctx->ev, cctx->ldb,
+ nss_cmd_getgrent_callback, nctx);
+ return ret;
+ }
+ }
+
+ /* create response packet */
+ ret = nss_packet_new(cctx->creq, 0,
+ nss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = nss_cmd_retgrent(cctx, num);
+ nss_packet_set_error(cctx->creq->out, ret);
+ nss_cmd_done(nctx);
+ return EOK;
+}
+
+static int nss_cmd_endgrent(struct cli_ctx *cctx)
+{
+ struct nss_cmd_ctx *nctx;
+ int ret;
+
+ nctx = talloc(cctx, struct nss_cmd_ctx);
+ if (!nctx) {
+ return ENOMEM;
+ }
+ nctx->cctx = cctx;
+
+ /* create response packet */
+ ret = nss_packet_new(cctx->creq, 0,
+ nss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+
+ if (cctx->gctx == NULL) goto done;
+ if (cctx->gctx->grps == NULL) goto done;
+
+ /* free results and reset */
+ talloc_free(cctx->gctx->grps);
+ cctx->gctx->grps = NULL;
+ cctx->gctx->grp_cur = 0;
+
+done:
+ nss_cmd_done(nctx);
+ return EOK;
+}
+
struct nss_cmd_table nss_cmds[] = {
{SSS_NSS_GET_VERSION, nss_cmd_get_version},
{SSS_NSS_GETPWNAM, nss_cmd_getpwnam},
@@ -677,6 +891,9 @@ struct nss_cmd_table nss_cmds[] = {
{SSS_NSS_ENDPWENT, nss_cmd_endpwent},
{SSS_NSS_GETGRNAM, nss_cmd_getgrnam},
{SSS_NSS_GETGRGID, nss_cmd_getgrgid},
+ {SSS_NSS_SETGRENT, nss_cmd_setgrent},
+ {SSS_NSS_GETGRENT, nss_cmd_getgrent},
+ {SSS_NSS_ENDGRENT, nss_cmd_endgrent},
{SSS_NSS_NULL, NULL}
};
diff --git a/server/nss/nsssrv_ldb.c b/server/nss/nsssrv_ldb.c
index dce8d48b..62268042 100644
--- a/server/nss/nsssrv_ldb.c
+++ b/server/nss/nsssrv_ldb.c
@@ -131,6 +131,8 @@ static struct nss_ldb_search_ctx *init_sctx(TALLOC_CTX *mem_ctx,
return sctx;
}
+/* users */
+
static int pwd_search(struct nss_ldb_search_ctx *sctx,
struct ldb_context *ldb,
const char *expression)
@@ -219,7 +221,97 @@ int nss_ldb_enumpwent(TALLOC_CTX *mem_ctx,
return pwd_search(sctx, ldb, NSS_PWENT_FILTER);
}
+/* groups */
+
+struct get_mem_ctx {
+ struct nss_ldb_search_ctx *ret_sctx;
+ struct ldb_message **grps;
+ int num_grps;
+};
+
+static int get_members(void *ptr, int status,
+ struct ldb_result *res)
+{
+ struct nss_ldb_search_ctx *sctx;
+ struct get_mem_ctx *gmctx;
+ struct nss_ldb_search_ctx *mem_sctx;
+ static const char *attrs[] = NSS_GRPW_ATTRS;
+ struct ldb_request *req;
+ struct ldb_message *msg;
+ struct ldb_result *ret_res;
+ const char *expression;
+ int ret, i;
+
+ sctx = talloc_get_type(ptr, struct nss_ldb_search_ctx);
+ gmctx = talloc_get_type(sctx->ptr, struct get_mem_ctx);
+
+ if (status != LDB_SUCCESS) {
+ return request_error(gmctx->ret_sctx, status);
+ }
+
+ ret_res = gmctx->ret_sctx->res;
+
+ /* append previous search results to final (if any) */
+ if (res && res->count != 0) {
+ ret_res->msgs = talloc_realloc(ret_res, ret_res->msgs,
+ struct ldb_message *,
+ ret_res->count + res->count + 1);
+ for(i = 0; i < res->count; i++) {
+ ret_res->msgs[ret_res->count] = talloc_steal(ret_res, res->msgs[i]);
+ ret_res->count++;
+ }
+ ret_res->msgs[ret_res->count] = NULL;
+ }
+
+ if (gmctx->grps[0] == NULL) {
+ return request_done(gmctx->ret_sctx);
+ }
+
+ mem_sctx = init_sctx(gmctx, sctx->ldb, get_members, sctx);
+ if (!mem_sctx) {
+ return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ /* fetch next group to search for members */
+ gmctx->num_grps--;
+ msg = gmctx->grps[gmctx->num_grps];
+ gmctx->grps[gmctx->num_grps] = NULL;
+
+ /* queue the group entry on the final result structure */
+ ret_res->msgs = talloc_realloc(ret_res, ret_res->msgs,
+ struct ldb_message *,
+ ret_res->count + 2);
+ if (!ret_res->msgs) {
+ return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+ ret_res->msgs[ret_res->count + 1] = NULL;
+ ret_res->msgs[ret_res->count] = talloc_steal(ret_res->msgs, msg);
+ ret_res->count++;
+
+ /* search for this group members */
+ expression = talloc_asprintf(mem_sctx, NSS_GRNA2_FILTER,
+ ldb_dn_get_linearized(msg->dn));
+ if (!expression) {
+ return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ret = ldb_build_search_req(&req, mem_sctx->ldb, mem_sctx,
+ ldb_dn_new(mem_sctx, mem_sctx->ldb, NSS_USER_BASE),
+ LDB_SCOPE_SUBTREE,
+ expression, attrs, NULL,
+ mem_sctx, get_gen_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ return request_error(gmctx->ret_sctx, ret);
+ }
+ ret = ldb_request(mem_sctx->ldb, req);
+ if (ret != LDB_SUCCESS) {
+ return request_error(gmctx->ret_sctx, ret);
+ }
+
+ return LDB_SUCCESS;
+}
static int get_grp_callback(struct ldb_request *req,
struct ldb_reply *ares)
@@ -276,35 +368,24 @@ static int get_grp_callback(struct ldb_request *req,
if (res->count == 0) {
return request_done(sctx);
}
- /* 1 result, let's search for members now and append results */
- if (res->count == 1) {
- static const char *attrs[] = NSS_GRPW_ATTRS;
- struct ldb_request *ureq;
- const char *expression;
- int ret;
-
- expression = talloc_asprintf(sctx, NSS_GRNA2_FILTER,
- ldb_dn_get_linearized(res->msgs[0]->dn));
- if (!expression) {
- return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
- }
+ if (res->count > 0) {
+ struct get_mem_ctx *gmctx;
- ret = ldb_build_search_req(&ureq, sctx->ldb, sctx,
- ldb_dn_new(sctx, sctx->ldb, NSS_USER_BASE),
- LDB_SCOPE_SUBTREE,
- expression, attrs, NULL,
- sctx, get_gen_callback,
- NULL);
- if (ret != LDB_SUCCESS) {
- return request_error(sctx, ret);
+ gmctx = talloc_zero(req, struct get_mem_ctx);
+ if (!gmctx) {
+ request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
}
+ gmctx->ret_sctx = sctx;
+ gmctx->grps = talloc_steal(gmctx, res->msgs);
+ gmctx->num_grps = res->count;
+ res->msgs = NULL;
+ res->count = 0;
- ret = ldb_request(sctx->ldb, ureq);
- if (ret != LDB_SUCCESS) {
- return request_error(sctx, ret);
- }
+ /* re-use sctx to create a fake handler for the first call to
+ * get_members() */
+ sctx = init_sctx(gmctx, sctx->ldb, get_members, gmctx);
- return LDB_SUCCESS;
+ return get_members(sctx, LDB_SUCCESS, NULL);
}
/* anything else is an error */
@@ -388,6 +469,20 @@ int nss_ldb_getgrgid(TALLOC_CTX *mem_ctx,
return grp_search(sctx, ldb, expression);
}
+int nss_ldb_enumgrent(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct ldb_context *ldb,
+ nss_ldb_callback_t fn, void *ptr)
+{
+ struct nss_ldb_search_ctx *sctx;
+
+ sctx = init_sctx(mem_ctx, ldb, fn, ptr);
+ if (!sctx) {
+ return ENOMEM;
+ }
+
+ return grp_search(sctx, ldb, NSS_GRENT_FILTER);
+}
int nss_ldb_init(TALLOC_CTX *mem_ctx,
struct event_context *ev,
diff --git a/server/nss/nsssrv_ldb.h b/server/nss/nsssrv_ldb.h
index ebb97255..8cc7ebca 100644
--- a/server/nss/nsssrv_ldb.h
+++ b/server/nss/nsssrv_ldb.h
@@ -6,7 +6,7 @@
#define NSS_PW_HOMEDIR "HomeDirectory"
#define NSS_PW_SHELL "loginShell"
-#define NSS_GR_NAME "gid"
+#define NSS_GR_NAME "cn"
#define NSS_GR_GIDNUM "gidNumber"
#define NSS_GR_MEMBER "member"
@@ -45,3 +45,8 @@ int nss_ldb_getgrgid(TALLOC_CTX *mem_ctx,
uint64_t gid,
nss_ldb_callback_t fn, void *ptr);
+int nss_ldb_enumgrent(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct ldb_context *ldb,
+ nss_ldb_callback_t fn, void *ptr);
+