summaryrefslogtreecommitdiff
path: root/server/nss
diff options
context:
space:
mode:
Diffstat (limited to 'server/nss')
-rw-r--r--server/nss/nss_ldb.h8
-rw-r--r--server/nss/nsssrv_cmd.c180
-rw-r--r--server/nss/nsssrv_ldb.c169
-rw-r--r--server/nss/nsssrv_ldb.h11
4 files changed, 354 insertions, 14 deletions
diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h
index 64ac592b..3dbe70d9 100644
--- a/server/nss/nss_ldb.h
+++ b/server/nss/nss_ldb.h
@@ -3,12 +3,20 @@
#define NSS_LDB_PATH "/var/lib/sss/db/sssd.ldb"
#define NSS_USER_BASE "cn=users,cn=local"
+#define NSS_GROUP_BASE "cn=groups,cn=local"
#define NSS_PWNAM_FILTER "(&(objectclass=user)(uid=%s))"
#define NSS_PWUID_FILTER "(&(objectclass=user)(uidNumber=%llu))"
#define NSS_PWENT_FILTER "(objectclass=user)"
+#define NSS_GRNAM_FILTER "(&(objectclass=group)(gid=%s))"
+#define NSS_GRNA2_FILTER "(&(objectclass=user)(memberof=%s))"
+#define NSS_GRUID_FILTER "(&(objectclass=group)(gidNumber=%llu))"
+#define NSS_GRENT_FILTER "(objectclass=group)"
+
#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}
diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c
index 66676613..b8183e00 100644
--- a/server/nss/nsssrv_cmd.c
+++ b/server/nss/nsssrv_cmd.c
@@ -78,6 +78,10 @@ static int nss_cmd_get_version(struct cli_ctx *cctx)
return EOK;
}
+/****************************************************************************
+ * PASSWD db related functions
+ ***************************************************************************/
+
static int fill_pwent(struct nss_packet *packet,
struct ldb_message **msgs,
int count)
@@ -92,12 +96,13 @@ static int fill_pwent(struct nss_packet *packet,
uint64_t gid;
size_t rsize, rp, blen;
size_t s1, s2, s3, s4;
- int i, ret, num = 0;
+ int i, ret, num;
- /* first 2 fieldss (len and reserved), filled up later */
+ /* first 2 fields (len and reserved), filled up later */
ret = nss_packet_grow(packet, 2*sizeof(uint32_t));
rp = 2*sizeof(uint32_t);
+ num = 0;
for (i = 0; i < count; i++) {
msg = msgs[i];
@@ -109,7 +114,7 @@ static int fill_pwent(struct nss_packet *packet,
gid = ldb_msg_find_attr_as_uint64(msg, NSS_PW_GIDNUM, 0);
if (!name || !fullname || !homedir || !shell || !uid || !gid) {
- DEBUG(1, ("Incomplede user object for %s[%llu]! Skipping\n",
+ DEBUG(1, ("Incomplete user object for %s[%llu]! Skipping\n",
name?name:"<NULL>", (unsigned long long int)uid));
continue;
}
@@ -176,7 +181,7 @@ static int nss_cmd_getpw_callback(void *ptr, int status,
if (res->count != 1) {
if (res->count > 1) {
- DEBUG(1, ("getpwnam call returned more than oine result !?!\n"));
+ DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
}
if (res->count == 0) {
DEBUG(2, ("No results for getpwnam call"));
@@ -468,6 +473,172 @@ done:
return EOK;
}
+/****************************************************************************
+ * GROUP db related functions
+ ***************************************************************************/
+
+static int fill_grent(struct nss_packet *packet,
+ struct ldb_message **msgs,
+ int count)
+{
+ struct ldb_message *msg;
+ uint8_t *body;
+ const char *name;
+ uint64_t gid;
+ size_t rsize, rp, blen, mnump;
+ int i, ret, num, memnum;
+ bool get_group = true;
+
+ /* first 2 fields (len and reserved), filled up later */
+ ret = nss_packet_grow(packet, 2*sizeof(uint32_t));
+ rp = 2*sizeof(uint32_t);
+
+ num = 0;
+ for (i = 0; i < count; i++) {
+ msg = msgs[i];
+
+ if (get_group) {
+ /* find group name/gid */
+ name = ldb_msg_find_attr_as_string(msg, NSS_GR_NAME, NULL);
+ gid = ldb_msg_find_attr_as_uint64(msg, NSS_GR_GIDNUM, 0);
+ if (!name || !gid) {
+ DEBUG(1, ("Incomplete group object for %s[%llu]! Aborting\n",
+ name?name:"<NULL>", (unsigned long long int)gid));
+ num = 0;
+ goto done;
+ }
+
+ /* fill in gid and name and set pointer for number of members */
+ rsize = sizeof(uint64_t) + sizeof(uint32_t) + strlen(name)+1 +2;
+ ret = nss_packet_grow(packet, rsize);
+ nss_packet_get_body(packet, &body, &blen);
+ rp = blen - rsize;
+ ((uint64_t *)(&body[rp]))[0] = gid;
+ rp += sizeof(uint64_t);
+ ((uint32_t *)(&body[rp]))[0] = 0; /* init members num to 0 */
+ mnump = rp; /* keep around pointer to set members num later */
+ rp += sizeof(uint32_t);
+ memcpy(&body[rp], name, strlen(name)+1);
+ body[blen-2] = 'x'; /* group passwd field */
+ body[blen-1] = '\0';
+
+ get_group = false;
+ memnum = 0;
+ num++;
+ continue;
+ }
+
+ name = ldb_msg_find_attr_as_string(msg, NSS_PW_NAME, NULL);
+
+ if (!name) {
+ /* last member of previous group found, or error.
+ * set next element to be a group, and eventually
+ * fail there if here start bogus entries */
+ get_group = true;
+ nss_packet_get_body(packet, &body, &blen);
+ ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
+ continue;
+ }
+
+ rsize = strlen(name) + 1;
+
+ ret = nss_packet_grow(packet, rsize);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
+ nss_packet_get_body(packet, &body, &blen);
+ rp = blen - rsize;
+ memcpy(&body[rp], name, rsize);
+
+ memnum++;
+ }
+
+ /* fill in the last group member count */
+ nss_packet_get_body(packet, &body, &blen);
+ ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
+
+done:
+ nss_packet_get_body(packet, &body, &blen);
+ ((uint32_t *)body)[0] = num; /* num results */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+
+ return EOK;
+}
+
+static int nss_cmd_getgr_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;
+ 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;
+ }
+
+ if (res->count == 0) {
+ DEBUG(2, ("No results for getpwnam call"));
+
+ ret = nss_packet_new(cctx->creq, 2*sizeof(uint32_t),
+ nss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ return ret;
+ }
+ nss_packet_get_body(cctx->creq->out, &body, &blen);
+ ((uint32_t *)body)[0] = 0; /* 0 results */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+ goto done;
+ }
+
+ ret = fill_grent(cctx->creq->out, res->msgs, res->count);
+ nss_packet_set_error(cctx->creq->out, ret);
+
+done:
+ nss_cmd_done(nctx);
+ return EOK;
+}
+
+static int nss_cmd_getgrnam(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_getgrnam(nctx, cctx->ev, cctx->ldb, name,
+ nss_cmd_getgr_callback, nctx);
+
+ return ret;
+}
+
struct nss_cmd_table nss_cmds[] = {
{SSS_NSS_GET_VERSION, nss_cmd_get_version},
{SSS_NSS_GETPWNAM, nss_cmd_getpwnam},
@@ -475,6 +646,7 @@ struct nss_cmd_table nss_cmds[] = {
{SSS_NSS_SETPWENT, nss_cmd_setpwent},
{SSS_NSS_GETPWENT, nss_cmd_getpwent},
{SSS_NSS_ENDPWENT, nss_cmd_endpwent},
+ {SSS_NSS_GETGRNAM, nss_cmd_getgrnam},
{SSS_NSS_NULL, NULL}
};
diff --git a/server/nss/nsssrv_ldb.c b/server/nss/nsssrv_ldb.c
index a54bc6a5..04225e00 100644
--- a/server/nss/nsssrv_ldb.c
+++ b/server/nss/nsssrv_ldb.c
@@ -27,6 +27,7 @@
#include "nss/nss_ldb.h"
struct nss_ldb_search_ctx {
+ struct ldb_context *ldb;
nss_ldb_callback_t callback;
void *ptr;
struct ldb_result *res;
@@ -49,8 +50,8 @@ static int request_done(struct nss_ldb_search_ctx *sctx)
return sctx->callback(sctx->ptr, EOK, sctx->res);
}
-static int getpw_callback(struct ldb_request *req,
- struct ldb_reply *ares)
+static int get_gen_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
{
struct nss_ldb_search_ctx *sctx;
struct ldb_result *res;
@@ -109,6 +110,7 @@ static int getpw_callback(struct ldb_request *req,
}
static struct nss_ldb_search_ctx *init_sctx(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb,
nss_ldb_callback_t fn, void *ptr)
{
struct nss_ldb_search_ctx *sctx;
@@ -117,6 +119,7 @@ static struct nss_ldb_search_ctx *init_sctx(TALLOC_CTX *mem_ctx,
if (!sctx) {
return NULL;
}
+ sctx->ldb = ldb;
sctx->callback = fn;
sctx->ptr = ptr;
sctx->res = talloc_zero(sctx, struct ldb_result);
@@ -128,7 +131,7 @@ static struct nss_ldb_search_ctx *init_sctx(TALLOC_CTX *mem_ctx,
return sctx;
}
-static int do_search(struct nss_ldb_search_ctx *sctx,
+static int pwd_search(struct nss_ldb_search_ctx *sctx,
struct ldb_context *ldb,
const char *expression)
{
@@ -140,7 +143,7 @@ static int do_search(struct nss_ldb_search_ctx *sctx,
ldb_dn_new(sctx, ldb, NSS_USER_BASE),
LDB_SCOPE_SUBTREE,
expression, attrs, NULL,
- sctx, getpw_callback,
+ sctx, get_gen_callback,
NULL);
if (ret != LDB_SUCCESS) {
return nss_ldb_error_to_errno(ret);
@@ -163,7 +166,7 @@ int nss_ldb_getpwnam(TALLOC_CTX *mem_ctx,
struct nss_ldb_search_ctx *sctx;
char *expression;
- sctx = init_sctx(mem_ctx, fn, ptr);
+ sctx = init_sctx(mem_ctx, ldb, fn, ptr);
if (!sctx) {
return ENOMEM;
}
@@ -174,7 +177,7 @@ int nss_ldb_getpwnam(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- return do_search(sctx, ldb, expression);
+ return pwd_search(sctx, ldb, expression);
}
int nss_ldb_getpwuid(TALLOC_CTX *mem_ctx,
@@ -187,7 +190,7 @@ int nss_ldb_getpwuid(TALLOC_CTX *mem_ctx,
unsigned long long int filter_uid = uid;
char *expression;
- sctx = init_sctx(mem_ctx, fn, ptr);
+ sctx = init_sctx(mem_ctx, ldb, fn, ptr);
if (!sctx) {
return ENOMEM;
}
@@ -198,7 +201,7 @@ int nss_ldb_getpwuid(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- return do_search(sctx, ldb, expression);
+ return pwd_search(sctx, ldb, expression);
}
int nss_ldb_enumpwent(TALLOC_CTX *mem_ctx,
@@ -208,14 +211,160 @@ int nss_ldb_enumpwent(TALLOC_CTX *mem_ctx,
{
struct nss_ldb_search_ctx *sctx;
- sctx = init_sctx(mem_ctx, fn, ptr);
+ sctx = init_sctx(mem_ctx, ldb, fn, ptr);
+ if (!sctx) {
+ return ENOMEM;
+ }
+
+ return pwd_search(sctx, ldb, NSS_PWENT_FILTER);
+}
+
+
+
+static int get_grp_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ struct nss_ldb_search_ctx *sctx;
+ struct ldb_result *res;
+ int n;
+
+ sctx = talloc_get_type(req->context, struct nss_ldb_search_ctx);
+ res = sctx->res;
+
+ if (!ares) {
+ return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return request_error(sctx, ares->error);
+ }
+
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
+ res->msgs = talloc_realloc(res, res->msgs,
+ struct ldb_message *,
+ res->count + 2);
+ if (!res->msgs) {
+ return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ res->msgs[res->count + 1] = NULL;
+
+ res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+ res->count++;
+ break;
+
+ case LDB_REPLY_REFERRAL:
+ if (res->refs) {
+ for (n = 0; res->refs[n]; n++) /*noop*/ ;
+ } else {
+ n = 0;
+ }
+
+ res->refs = talloc_realloc(res, res->refs, char *, n + 2);
+ if (! res->refs) {
+ return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ res->refs[n] = talloc_steal(res->refs, ares->referral);
+ res->refs[n + 1] = NULL;
+ break;
+
+ case LDB_REPLY_DONE:
+ res->controls = talloc_steal(res, ares->controls);
+
+ /* no results, return */
+ 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);
+ }
+
+ 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);
+ }
+
+ ret = ldb_request(sctx->ldb, ureq);
+ if (ret != LDB_SUCCESS) {
+ return request_error(sctx, ret);
+ }
+
+ return LDB_SUCCESS;
+ }
+
+ /* anything else is an error */
+ return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ talloc_free(ares);
+ return LDB_SUCCESS;
+}
+
+static int grp_search(struct nss_ldb_search_ctx *sctx,
+ struct ldb_context *ldb,
+ const char *expression)
+{
+ static const char *attrs[] = NSS_GRNAM_ATTRS;
+ struct ldb_request *req;
+ int ret;
+
+ ret = ldb_build_search_req(&req, ldb, sctx,
+ ldb_dn_new(sctx, ldb, NSS_GROUP_BASE),
+ LDB_SCOPE_SUBTREE,
+ expression, attrs, NULL,
+ sctx, get_grp_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 EOK;
+}
+
+int nss_ldb_getgrnam(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 *sctx;
+ char *expression;
+
+ sctx = init_sctx(mem_ctx, ldb, fn, ptr);
if (!sctx) {
return ENOMEM;
}
- return do_search(sctx, ldb, NSS_PWENT_FILTER);
+ expression = talloc_asprintf(sctx, NSS_GRNAM_FILTER, name);
+ if (!expression) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ return grp_search(sctx, ldb, expression);
}
+
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 a57a9119..9998714a 100644
--- a/server/nss/nsssrv_ldb.h
+++ b/server/nss/nsssrv_ldb.h
@@ -6,6 +6,10 @@
#define NSS_PW_HOMEDIR "HomeDirectory"
#define NSS_PW_SHELL "loginShell"
+#define NSS_GR_NAME "gid"
+#define NSS_GR_GIDNUM "gidNumber"
+#define NSS_GR_MEMBER "member"
+
typedef int (*nss_ldb_callback_t)(void *, int, struct ldb_result *);
int nss_ldb_init(TALLOC_CTX *mem_ctx,
@@ -28,3 +32,10 @@ int nss_ldb_enumpwent(TALLOC_CTX *mem_ctx,
struct event_context *ev,
struct ldb_context *ldb,
nss_ldb_callback_t fn, void *ptr);
+
+int nss_ldb_getgrnam(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct ldb_context *ldb,
+ const char *name,
+ nss_ldb_callback_t fn, void *ptr);
+