diff options
-rw-r--r-- | server/nss/nss_ldb.h | 4 | ||||
-rw-r--r-- | server/nss/nsssrv_cmd.c | 82 | ||||
-rw-r--r-- | server/nss/nsssrv_ldb.c | 114 | ||||
-rw-r--r-- | server/nss/nsssrv_ldb.h | 6 |
4 files changed, 206 insertions, 0 deletions
diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h index fe135683..aa820168 100644 --- a/server/nss/nss_ldb.h +++ b/server/nss/nss_ldb.h @@ -14,9 +14,13 @@ #define NSS_GRGID_FILTER "(&(objectclass=group)(gidNumber=%llu))" #define NSS_GRENT_FILTER "(objectclass=group)" +#define NSS_INITGR_FILTER "(&(objectclass=group)(gidNumber=*))" + #define NSS_PW_ATTRS {NSS_PW_NAME, NSS_PW_UIDNUM, NSS_PW_GIDNUM, \ NSS_PW_FULLNAME, NSS_PW_HOMEDIR, NSS_PW_SHELL, \ NULL} #define NSS_GRNAM_ATTRS {NSS_GR_NAME, NSS_GR_GIDNUM, NULL} #define NSS_GRPW_ATTRS {NSS_PW_NAME, NULL} +#define NSS_INITGR_SEARCH_ATTR "memberof" +#define NSS_INITGR_ATTRS {NSS_GR_GIDNUM, NULL} diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c index c69598bc..0e1cd8ce 100644 --- a/server/nss/nsssrv_cmd.c +++ b/server/nss/nsssrv_cmd.c @@ -882,6 +882,87 @@ done: return EOK; } +static int nss_cmd_initgr_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; + uint8_t *body; + size_t blen; + uint64_t gid; + uint32_t num; + int ret, i; + + /* 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; + } + + num = res->count; + /* the first 64 bit uint is really 2 32 units used to hold the number of + * results */ + ret = nss_packet_grow(cctx->creq->out, (1 + num) * sizeof(uint64_t)); + if (ret != EOK) { + nss_packet_set_error(cctx->creq->out, ret); + goto done; + } + nss_packet_get_body(cctx->creq->out, &body, &blen); + + for (i = 0; i < num; i++) { + gid = ldb_msg_find_attr_as_uint64(res->msgs[i], NSS_GR_GIDNUM, 0); + if (!gid) { + DEBUG(1, ("Incomplete group object for initgroups! Aborting\n")); + nss_packet_set_error(cctx->creq->out, EIO); + num = 0; + goto done; + } + ((uint64_t *)body)[i+1] = gid; + } + + ((uint32_t *)body)[0] = num; /* num results */ + ((uint32_t *)body)[1] = 0; /* reserved */ + +done: + nss_cmd_done(nctx); + return EOK; +} + +static int nss_cmd_initgroups(struct cli_ctx *cctx) +{ + struct nss_cmd_ctx *nctx; + uint8_t *body; + size_t blen; + int ret; + const char *name; + + /* get user name to query */ + nss_packet_get_body(cctx->creq->in, &body, &blen); + name = (const char *)body; + /* if not terminated fail */ + if (name[blen -1] != '\0') { + return EINVAL; + } + + nctx = talloc(cctx, struct nss_cmd_ctx); + if (!nctx) { + return ENOMEM; + } + nctx->cctx = cctx; + + ret = nss_ldb_initgroups(nctx, cctx->ev, cctx->ldb, name, + nss_cmd_initgr_callback, nctx); + + return ret; +} + struct nss_cmd_table nss_cmds[] = { {SSS_NSS_GET_VERSION, nss_cmd_get_version}, {SSS_NSS_GETPWNAM, nss_cmd_getpwnam}, @@ -894,6 +975,7 @@ struct nss_cmd_table nss_cmds[] = { {SSS_NSS_SETGRENT, nss_cmd_setgrent}, {SSS_NSS_GETGRENT, nss_cmd_getgrent}, {SSS_NSS_ENDGRENT, nss_cmd_endgrent}, + {SSS_NSS_INITGR, nss_cmd_initgroups}, {SSS_NSS_NULL, NULL} }; diff --git a/server/nss/nsssrv_ldb.c b/server/nss/nsssrv_ldb.c index 62268042..3e6d877a 100644 --- a/server/nss/nsssrv_ldb.c +++ b/server/nss/nsssrv_ldb.c @@ -484,6 +484,120 @@ int nss_ldb_enumgrent(TALLOC_CTX *mem_ctx, return grp_search(sctx, ldb, NSS_GRENT_FILTER); } +static int nss_ldb_initgr_search(void *ptr, int status, + struct ldb_result *res) +{ + struct nss_ldb_search_ctx *sctx; + static const char *attrs[] = NSS_INITGR_ATTRS; + char *expression; + struct ldb_request *req; + struct ldb_control **ctrl; + struct ldb_asq_control *control; + int ret; + + sctx = talloc_get_type(ptr, struct nss_ldb_search_ctx); + + if (res->count == 0) { + return request_done(sctx); + } + if (res->count > 1) { + return request_error(sctx, LDB_ERR_OPERATIONS_ERROR); + } + + expression = talloc_asprintf(sctx, NSS_INITGR_FILTER); + if (!expression) { + return request_error(sctx, LDB_ERR_OPERATIONS_ERROR); + } + + ctrl = talloc_array(sctx, struct ldb_control *, 2); + if (!ctrl) { + return request_error(sctx, LDB_ERR_OPERATIONS_ERROR); + } + ctrl[1] = NULL; + ctrl[0] = talloc(ctrl, struct ldb_control); + if (!ctrl[0]) { + return request_error(sctx, LDB_ERR_OPERATIONS_ERROR); + } + ctrl[0]->oid = LDB_CONTROL_ASQ_OID; + ctrl[0]->critical = 1; + control = talloc(ctrl[0], struct ldb_asq_control); + if (!control) { + return request_error(sctx, LDB_ERR_OPERATIONS_ERROR); + } + control->request = 1; + control->source_attribute = talloc_strdup(control, NSS_INITGR_SEARCH_ATTR); + if (!control->source_attribute) { + return request_error(sctx, LDB_ERR_OPERATIONS_ERROR); + } + control->src_attr_len = strlen(control->source_attribute); + ctrl[0]->data = control; + + ret = ldb_build_search_req(&req, sctx->ldb, sctx, + res->msgs[0]->dn, + LDB_SCOPE_BASE, + expression, attrs, ctrl, + sctx, get_gen_callback, + NULL); + if (ret != LDB_SUCCESS) { + return request_error(sctx, ret); + } + + ret = ldb_request(sctx->ldb, req); + if (ret != LDB_SUCCESS) { + return request_error(sctx, ret); + } + + return LDB_SUCCESS; +} + +int nss_ldb_initgroups(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct ldb_context *ldb, + const char *name, + nss_ldb_callback_t fn, void *ptr) +{ + struct nss_ldb_search_ctx *ret_sctx; + struct nss_ldb_search_ctx *sctx; + static const char *attrs[] = NSS_PW_ATTRS; + char *expression; + struct ldb_request *req; + int ret; + + ret_sctx = init_sctx(mem_ctx, ldb, fn, ptr); + if (!ret_sctx) { + return ENOMEM; + } + sctx = init_sctx(ret_sctx, ldb, nss_ldb_initgr_search, ret_sctx); + if (!sctx) { + talloc_free(sctx); + return ENOMEM; + } + + expression = talloc_asprintf(sctx, NSS_PWNAM_FILTER, name); + if (!expression) { + talloc_free(sctx); + return ENOMEM; + } + + ret = ldb_build_search_req(&req, ldb, sctx, + ldb_dn_new(sctx, ldb, NSS_USER_BASE), + LDB_SCOPE_SUBTREE, + expression, attrs, NULL, + sctx, get_gen_callback, + NULL); + if (ret != LDB_SUCCESS) { + return nss_ldb_error_to_errno(ret); + } + + ret = ldb_request(ldb, req); + if (ret != LDB_SUCCESS) { + return nss_ldb_error_to_errno(ret); + } + + return LDB_SUCCESS; +} + + int nss_ldb_init(TALLOC_CTX *mem_ctx, struct event_context *ev, struct ldb_context **ldbp) diff --git a/server/nss/nsssrv_ldb.h b/server/nss/nsssrv_ldb.h index 8cc7ebca..eb3e8fca 100644 --- a/server/nss/nsssrv_ldb.h +++ b/server/nss/nsssrv_ldb.h @@ -50,3 +50,9 @@ int nss_ldb_enumgrent(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, nss_ldb_callback_t fn, void *ptr); +int nss_ldb_initgroups(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct ldb_context *ldb, + const char *name, + nss_ldb_callback_t fn, void *ptr); + |