summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2008-10-08 12:20:49 -0400
committerSimo Sorce <idra@samba.org>2008-10-08 12:24:14 -0400
commit07111cfbf95dd0ec4d5985f541073b15b904a329 (patch)
treefce720264b52fb087fb7b30a75ca87ea0a6defff /server
parent77db18dd9e52f3937af360f1a14c4b7cf0fef83d (diff)
downloadsssd-07111cfbf95dd0ec4d5985f541073b15b904a329.tar.gz
sssd-07111cfbf95dd0ec4d5985f541073b15b904a329.tar.bz2
sssd-07111cfbf95dd0ec4d5985f541073b15b904a329.zip
First retrieval of a user (getpwnam only) from an actual ldb file
Diffstat (limited to 'server')
-rw-r--r--server/Makefile.in8
-rw-r--r--server/configure.ac1
-rw-r--r--server/external/libldb.m47
-rw-r--r--server/nss/nss_ldb.h14
-rw-r--r--server/nss/nsssrv.c15
-rw-r--r--server/nss/nsssrv.h8
-rw-r--r--server/nss/nsssrv_cmd.c146
-rw-r--r--server/nss/nsssrv_ldb.c174
-rw-r--r--server/nss/nsssrv_ldb.h19
-rw-r--r--server/server.mk2
10 files changed, 362 insertions, 32 deletions
diff --git a/server/Makefile.in b/server/Makefile.in
index 34be39b3..262e1c95 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -30,6 +30,9 @@ EVENTS_CFLAGS = @EVENTS_CFLAGS@
POPT_LIBS = @POPT_LIBS@
POPT_CFLAGS = @POPT_CFLAGS@
+LDB_LIBS = @LDB_LIBS@
+LDB_CFLAGS = @LDB_CFLAGS@
+
LIBDL = @LIBDL@
SHLIBEXT = @SHLIBEXT@
@@ -39,11 +42,11 @@ SHLD = @SHLD@
SHLD_FLAGS = @SHLD_FLAGS@
LDFLAGS += @LDFLAGS@
-LIBS = @LIBS@ $(TALLOC_LIBS) $(TDB_LIBS) $(EVENTS_LIBS) $(POPT_LIBS)
+LIBS = @LIBS@ $(TALLOC_LIBS) $(TDB_LIBS) $(EVENTS_LIBS) $(POPT_LIBS) $(LDB_LIBS)
PICFLAG = @PICFLAG@
CFLAGS += -g -I$(srcdir)/include -Iinclude -I$(srcdir) -I$(srcdir)/.. \
- $(POPT_CFLAGS) $(TALLOC_CFLAGS) $(TDB_CFLAGS) $(EVENTS_CFLAGS) \
+ $(POPT_CFLAGS) $(TALLOC_CFLAGS) $(TDB_CFLAGS) $(EVENTS_CFLAGS) $(LDB_FLAGS)\
-DLIBDIR=\"$(libdir)\" -DSHLIBEXT=\"$(SHLIBEXT)\" -DUSE_MMAP=1 @CFLAGS@
MDLD = @MDLD@
@@ -92,6 +95,5 @@ installlibs:: installdirs
cp $(STATICLIB) $(LIBSOLIB) $(DESTDIR)$(libdir)
installbin:: installdirs
- cp $(BINS) $(DESTDIR)$(sbindir)
include $(srvdir)/server.mk
diff --git a/server/configure.ac b/server/configure.ac
index 8a4ab4ac..b334d8fa 100644
--- a/server/configure.ac
+++ b/server/configure.ac
@@ -33,6 +33,7 @@ m4_include(pkg.m4)
m4_include(libpopt.m4)
m4_include(libtalloc.m4)
m4_include(libtdb.m4)
+m4_include(libldb.m4)
m4_include(libevents.m4)
m4_include(util/signal.m4)
diff --git a/server/external/libldb.m4 b/server/external/libldb.m4
new file mode 100644
index 00000000..cea4367a
--- /dev/null
+++ b/server/external/libldb.m4
@@ -0,0 +1,7 @@
+AC_SUBST(LDB_OBJ)
+AC_SUBST(LDB_CFLAGS)
+AC_SUBST(LDB_LIBS)
+
+AC_CHECK_HEADER(ldb.h,
+ [AC_CHECK_LIB(ldb, ldb_init, [LDB_LIBS="-lldb"]) ],
+ [PKG_CHECK_MODULES(LDB, ldb >= 0.9.2)])
diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h
new file mode 100644
index 00000000..64ac592b
--- /dev/null
+++ b/server/nss/nss_ldb.h
@@ -0,0 +1,14 @@
+/* nss_ldb private header file */
+
+#define NSS_LDB_PATH "/var/lib/sss/db/sssd.ldb"
+
+#define NSS_USER_BASE "cn=users,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_PW_ATTRS {NSS_PW_NAME, NSS_PW_UIDNUM, NSS_PW_GIDNUM, \
+ NSS_PW_FULLNAME, NSS_PW_HOMEDIR, NSS_PW_SHELL, \
+ NULL}
+
diff --git a/server/nss/nsssrv.c b/server/nss/nsssrv.c
index 5ade80ec..36094a7c 100644
--- a/server/nss/nsssrv.c
+++ b/server/nss/nsssrv.c
@@ -28,11 +28,11 @@
#include <string.h>
#include <sys/time.h>
#include <errno.h>
-#include "talloc.h"
-#include "events.h"
+#include "ldb.h"
#include "util/util.h"
#include "service.h"
#include "nss/nsssrv.h"
+#include "nss/nsssrv_ldb.h"
static void set_nonblocking(int fd)
{
@@ -105,7 +105,7 @@ static void client_recv(struct event_context *ev, struct cli_ctx *cctx)
/* do not read anymore */
EVENT_FD_NOT_READABLE(cctx->cfde);
/* execute command */
- ret = nss_cmd_execute(ev, cctx);
+ ret = nss_cmd_execute(cctx);
if (ret != RES_SUCCESS) {
DEBUG(0, ("Failed to execute request, aborting client!\n"));
talloc_free(cctx);
@@ -181,6 +181,9 @@ static void accept_fd_handler(struct event_context *ev,
DEBUG(0, ("Failed to queue client handler\n"));
}
+ cctx->ev = ev;
+ cctx->ldb = nctx->ldb;
+
talloc_set_destructor(cctx, client_destructor);
DEBUG(2, ("Client connected!\n"));
@@ -231,6 +234,7 @@ failed:
void nss_task_init(struct task_server *task)
{
struct nss_ctx *nctx;
+ int ret;
task_server_set_title(task, "sssd[nsssrv]");
@@ -243,4 +247,9 @@ void nss_task_init(struct task_server *task)
set_unix_socket(task->event_ctx, nctx, SSS_NSS_SOCKET_NAME);
+ ret = nss_ldb_init(nctx, task->event_ctx, &nctx->ldb);
+ if (ret != RES_SUCCESS) {
+ task_server_terminate(task, "fatal error initializing nss_ctx\n");
+ return;
+ }
}
diff --git a/server/nss/nsssrv.h b/server/nss/nsssrv.h
index 075db1d0..6ed679f4 100644
--- a/server/nss/nsssrv.h
+++ b/server/nss/nsssrv.h
@@ -26,15 +26,21 @@
#include <sys/un.h>
#include "talloc.h"
#include "events.h"
+#include "ldb.h"
#include "../nss_client/sss_nss.h"
+struct nss_ldb_ctx;
+
struct nss_ctx {
struct task_server *task;
struct fd_event *lfde;
int lfd;
+ struct ldb_context *ldb;
};
struct cli_ctx {
+ struct event_context *ev;
+ struct ldb_context *ldb;
int cfd;
struct fd_event *cfde;
struct sockaddr_un addr;
@@ -63,6 +69,6 @@ enum sss_nss_command nss_get_cmd(struct nss_packet *packet);
void nss_get_body(struct nss_packet *packet, uint8_t **body, size_t *blen);
/* from nsssrv_cmd.c */
-int nss_cmd_execute(struct event_context *ev, struct cli_ctx *cctx);
+int nss_cmd_execute(struct cli_ctx *cctx);
#endif /* __NSSSRV_H__ */
diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c
index f66dc88c..a1400487 100644
--- a/server/nss/nsssrv_cmd.c
+++ b/server/nss/nsssrv_cmd.c
@@ -19,16 +19,22 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "ldb.h"
+#include "ldb_errors.h"
#include "util/util.h"
#include "nss/nsssrv.h"
+#include "nss/nsssrv_ldb.h"
+
+struct nss_cmd_ctx {
+ struct cli_ctx *cctx;
+};
struct nss_cmd_table {
enum sss_nss_command cmd;
- int (*fn)(struct event_context *ev, struct cli_ctx *cctx);
+ int (*fn)(struct cli_ctx *cctx);
};
-static int nss_cmd_get_version(struct event_context *ev,
- struct cli_ctx *cctx)
+static int nss_cmd_get_version(struct cli_ctx *cctx)
{
uint8_t *body;
size_t blen;
@@ -51,28 +57,75 @@ static int nss_cmd_get_version(struct event_context *ev,
return RES_SUCCESS;
}
-static int nss_cmd_getpwnam(struct event_context *ev,
- struct cli_ctx *cctx)
+static int nss_cmd_getpwnam_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 ldb_message *msg;
uint8_t *body;
- size_t blen;
- int ret;
const char *name;
+ const char *fullname;
+ const char *homedir;
+ const char *shell;
+ uint64_t uid;
+ uint64_t gid;
+ size_t rsize, rp, rl, blen;
+ int ret;
- /* get user name to query */
- nss_get_body(cctx->creq->in, &body, &blen);
- name = (const char *)body;
- /* if not terminated fail */
- if (name[blen -1] != '\0') {
- return RES_INVALID_DATA;
+ if (res->count != 1) {
+ if (res->count > 1) {
+ DEBUG(1, ("getpwnam call returned more than oine result !?!\n"));
+ }
+ if (res->count == 0) {
+ DEBUG(2, ("No results for getpwnam call"));
+ }
+ ret = nss_packet_new(cctx->creq, 2*sizeof(uint32_t),
+ nss_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != RES_SUCCESS) {
+ return ret;
+ }
+ nss_get_body(cctx->creq->out, &body, &blen);
+ ((uint32_t *)body)[0] = 0; /* 0 results */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+ goto done;
}
- /* TODO: async search data and return */
+ msg = res->msgs[0];
+
+ name = ldb_msg_find_attr_as_string(msg, NSS_PW_NAME, NULL);
+ fullname = ldb_msg_find_attr_as_string(msg, NSS_PW_FULLNAME, NULL);
+ homedir = ldb_msg_find_attr_as_string(msg, NSS_PW_HOMEDIR, NULL);
+ shell = ldb_msg_find_attr_as_string(msg, NSS_PW_SHELL, NULL);
+ uid = ldb_msg_find_attr_as_uint64(msg, NSS_PW_UIDNUM, 0);
+ gid = ldb_msg_find_attr_as_uint64(msg, NSS_PW_UIDNUM, 0);
+
+ if (!name || !fullname || !homedir || !shell || !uid || !gid) {
+ DEBUG(1, ("Incomplede user object?!? Aborting\n"));
- /* fake data for now */
+ ret = nss_packet_new(cctx->creq, 2*sizeof(uint32_t),
+ nss_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != RES_SUCCESS) {
+ return ret;
+ }
+ nss_get_body(cctx->creq->out, &body, &blen);
+ ((uint32_t *)body)[0] = 0; /* 0 results */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+ goto done;
+ }
+
+ rsize = 2*sizeof(uint32_t);
+ rsize += 2*sizeof(uint64_t);
+ rsize += strlen(name) + 1;
+ rsize += 2; /* password always set to 'x' */
+ rsize += strlen(fullname) + 1;
+ rsize += strlen(homedir) + 1;
+ rsize += strlen(shell) + 1;
/* create response packet */
- ret = nss_packet_new(cctx->creq, 4+4+(8+8+4+2+4+10+10),
+ ret = nss_packet_new(cctx->creq, rsize,
nss_get_cmd(cctx->creq->in),
&cctx->creq->out);
if (ret != RES_SUCCESS) {
@@ -82,26 +135,71 @@ static int nss_cmd_getpwnam(struct event_context *ev,
((uint32_t *)body)[0] = 1; /* 1 result */
((uint32_t *)body)[1] = 0; /* reserved */
- ((uint64_t *)body)[1] = 1234; /* first result uid */
- ((uint64_t *)body)[2] = 1234; /* first result gid */
-
- name = "foo\0x\0foo\0/home/foo\0/bin/bash\0";
- memcpy(&body[24], name, (8+8+4+2+4+10+10));
-
+ ((uint64_t *)body)[1] = uid; /* first result uid */
+ ((uint64_t *)body)[2] = gid; /* first result gid */
+
+ rp = 2*sizeof(uint32_t) + 2*sizeof(uint64_t);
+ rl = strlen(name)+1;
+ memcpy(&body[rp], name, rl);
+ rp += rl;
+ rl = 2;
+ memcpy(&body[rp], "x", rl);
+ rp += rl;
+ rl = strlen(fullname)+1;
+ memcpy(&body[rp], fullname, rl);
+ rp += rl;
+ rl = strlen(homedir)+1;
+ memcpy(&body[rp], homedir, rl);
+ rp += rl;
+ rl = strlen(shell)+1;
+ memcpy(&body[rp], shell, rl);
+
+done:
/* now that the packet is in place, unlock queue
* making the event writable */
EVENT_FD_WRITEABLE(cctx->cfde);
+ /* free all request related data through the talloc hierarchy */
+ talloc_free(nctx);
+
return RES_SUCCESS;
}
+static int nss_cmd_getpwnam(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_get_body(cctx->creq->in, &body, &blen);
+ name = (const char *)body;
+ /* if not terminated fail */
+ if (name[blen -1] != '\0') {
+ return RES_INVALID_DATA;
+ }
+
+ nctx = talloc(cctx, struct nss_cmd_ctx);
+ if (!nctx) {
+ return RES_NOMEM;
+ }
+ nctx->cctx = cctx;
+
+ ret = nss_ldb_getpwnam(nctx, cctx->ev, cctx->ldb, name,
+ nss_cmd_getpwnam_callback, nctx);
+
+ return ret;
+}
+
struct nss_cmd_table nss_cmds[] = {
{SSS_NSS_GET_VERSION, nss_cmd_get_version},
{SSS_NSS_GETPWNAM, nss_cmd_getpwnam},
{SSS_NSS_NULL, NULL}
};
-int nss_cmd_execute(struct event_context *ev, struct cli_ctx *cctx)
+int nss_cmd_execute(struct cli_ctx *cctx)
{
enum sss_nss_command cmd;
int i;
@@ -110,7 +208,7 @@ int nss_cmd_execute(struct event_context *ev, struct cli_ctx *cctx)
for (i = 0; nss_cmds[i].cmd != SSS_NSS_NULL; i++) {
if (cmd == nss_cmds[i].cmd) {
- return nss_cmds[i].fn(ev, cctx);
+ return nss_cmds[i].fn(cctx);
}
}
diff --git a/server/nss/nsssrv_ldb.c b/server/nss/nsssrv_ldb.c
new file mode 100644
index 00000000..9ceb8f10
--- /dev/null
+++ b/server/nss/nsssrv_ldb.c
@@ -0,0 +1,174 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ldb.h"
+#include "ldb_errors.h"
+#include "util/util.h"
+#include "nss/nsssrv.h"
+#include "nss/nsssrv_ldb.h"
+#include "nss/nss_ldb.h"
+
+struct nss_ldb_search_ctx {
+ nss_ldb_callback_t callback;
+ void *ptr;
+ struct ldb_result *res;
+};
+
+static int request_error(struct nss_ldb_search_ctx *sctx, int ldb_error)
+{
+ sctx->callback(sctx->ptr, ldb_error, sctx->res);
+ return ldb_error;
+}
+
+static int request_done(struct nss_ldb_search_ctx *sctx)
+{
+ return sctx->callback(sctx->ptr, LDB_SUCCESS, sctx->res);
+}
+
+static int getpwnam_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:
+ sctx->res->msgs = talloc_realloc(sctx, 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_move(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_move(res->refs, &ares->referral);
+ res->refs[n + 1] = NULL;
+ break;
+
+ case LDB_REPLY_DONE:
+ res->controls = talloc_move(res, &ares->controls);
+
+ /* this is the last message, and means the request is done */
+ return request_done(sctx);
+ }
+
+ talloc_free(ares);
+ return LDB_SUCCESS;
+}
+
+int nss_ldb_getpwnam(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;
+ struct ldb_request *req;
+ static const char *attrs[] = NSS_PW_ATTRS;
+ char *expression;
+ int ret;
+
+ sctx = talloc(mem_ctx, struct nss_ldb_search_ctx);
+ if (!sctx) {
+ return RES_NOMEM;
+ }
+ sctx->callback = fn;
+ sctx->ptr = ptr;
+ sctx->res = talloc_zero(sctx, struct ldb_result);
+ if (!sctx->res) {
+ talloc_free(sctx);
+ return RES_NOMEM;
+ }
+
+ expression = talloc_asprintf(sctx, NSS_PWNAM_FILTER, name);
+ if (!expression) {
+ talloc_free(sctx);
+ return RES_NOMEM;
+ }
+
+ ret = ldb_build_search_req(&req, ldb, sctx,
+ ldb_dn_new(sctx, ldb, NSS_USER_BASE),
+ LDB_SCOPE_SUBTREE,
+ expression, attrs, NULL,
+ sctx, getpwnam_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ return RES_ERROR;
+ }
+
+ ret = ldb_request(ldb, req);
+ if (ret != LDB_SUCCESS) {
+ return RES_ERROR;
+ }
+
+ return RES_SUCCESS;
+}
+
+int nss_ldb_init(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct ldb_context **ldbp)
+{
+ struct ldb_context *ldb;
+ int ret;
+
+ ldb = ldb_init(mem_ctx, ev);
+ if (!ldb) {
+ return RES_ERROR;
+ }
+
+ ret = ldb_connect(ldb, NSS_LDB_PATH, 0, NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ldb);
+ return RES_ERROR;
+ }
+
+ *ldbp = ldb;
+
+ return RES_SUCCESS;
+}
diff --git a/server/nss/nsssrv_ldb.h b/server/nss/nsssrv_ldb.h
new file mode 100644
index 00000000..a50216d0
--- /dev/null
+++ b/server/nss/nsssrv_ldb.h
@@ -0,0 +1,19 @@
+
+#define NSS_PW_NAME "uid"
+#define NSS_PW_UIDNUM "uidNumber"
+#define NSS_PW_GIDNUM "gidNumber"
+#define NSS_PW_FULLNAME "fullName"
+#define NSS_PW_HOMEDIR "HomeDirectory"
+#define NSS_PW_SHELL "loginShell"
+
+typedef int (*nss_ldb_callback_t)(void *, int, struct ldb_result *);
+
+int nss_ldb_init(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct ldb_context **ldb);
+
+int nss_ldb_getpwnam(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct ldb_context *ldb,
+ const char *name,
+ nss_ldb_callback_t fn, void *ptr);
diff --git a/server/server.mk b/server/server.mk
index 89916af1..2a423e7e 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -1,4 +1,4 @@
-SERVER_OBJ = server.o monitor.o process.o service.o service_task.o util/debug.o util/signal.o util/become_daemon.o nss/nsssrv.o nss/nsssrv_packet.o nss/nsssrv_cmd.o
+SERVER_OBJ = server.o monitor.o process.o service.o service_task.o util/debug.o util/signal.o util/become_daemon.o nss/nsssrv.o nss/nsssrv_packet.o nss/nsssrv_cmd.o nss/nsssrv_ldb.o
install:: all
${INSTALLCMD} -d $(DESTDIR)$(sbindir)