summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/nss/nss_ldb.h4
-rw-r--r--server/nss/nsssrv_cmd.c82
-rw-r--r--server/nss/nsssrv_ldb.c114
-rw-r--r--server/nss/nsssrv_ldb.h6
4 files changed, 206 insertions, 0 deletions
diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h
index fe135683f..aa820168b 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 c69598bc7..0e1cd8ceb 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 62268042b..3e6d877a5 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 8cc7ebcae..eb3e8fca0 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);
+