diff options
author | Simo Sorce <idra@samba.org> | 2008-10-14 05:42:43 -0400 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2008-10-14 05:42:43 -0400 |
commit | 1170303766a4962cbb3253b8404a258bcfac8bf3 (patch) | |
tree | e87a31111ff18e5150b6b015b9ee89c689038998 /server | |
parent | e33930a92ec392cd4a36d24114f2ab1946d9ad4b (diff) | |
download | sssd-1170303766a4962cbb3253b8404a258bcfac8bf3.tar.gz sssd-1170303766a4962cbb3253b8404a258bcfac8bf3.tar.xz sssd-1170303766a4962cbb3253b8404a258bcfac8bf3.zip |
Fix error in parsing multiple groups
Revert to use 'cn' for group names
Implement getgrent()
Diffstat (limited to 'server')
-rw-r--r-- | server/nss/nss_ldb.h | 2 | ||||
-rw-r--r-- | server/nss/nsssrv_cmd.c | 221 | ||||
-rw-r--r-- | server/nss/nsssrv_ldb.c | 145 | ||||
-rw-r--r-- | server/nss/nsssrv_ldb.h | 7 |
4 files changed, 346 insertions, 29 deletions
diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h index 13e5a672a..fe135683f 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 6252ab4a0..c69598bc7 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 dce8d48bb..62268042b 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 ebb972550..8cc7ebcae 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); + |