dovecot: Added userdb nss which currently supports glibc-compati...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jul 3 01:50:20 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/c9b49ed99d28
changeset: 5870:c9b49ed99d28
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jul 03 01:50:13 2007 +0300
description:
Added userdb nss which currently supports glibc-compatible NSS modules.

diffstat:

4 files changed, 180 insertions(+), 1 deletion(-)
configure.in          |   20 ++++++
src/auth/Makefile.am  |    3 
src/auth/userdb-nss.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++
src/auth/userdb.c     |    4 +

diffs (240 lines):

diff -r 38ff50597e54 -r c9b49ed99d28 configure.in
--- a/configure.in	Tue Jul 03 00:30:48 2007 +0300
+++ b/configure.in	Tue Jul 03 01:50:13 2007 +0300
@@ -81,6 +81,15 @@ AC_ARG_WITH(passwd,
 		want_passwd=yes
 	fi,
 	want_passwd=yes)
+
+AC_ARG_WITH(passwd,
+[  --with-nss              Build with NSS module support (default)],
+	if test x$withval = xno; then
+		want_nss=no
+	else
+		want_nss=yes
+	fi,
+	want_nss=yes)
 
 AC_ARG_WITH(passwd-file,
 [  --with-passwd-file      Build with passwd-like file support (default)],
@@ -1804,6 +1813,17 @@ if test $have_modules = yes; then
   AC_SUBST(MODULE_LIBS)
 fi
 
+if test $want_nss = yes && test $have_modules = yes; then
+  AC_TRY_COMPILE([
+    #include <nss.h>
+  ], [
+    enum nss_status status = NSS_STATUS_TRYAGAIN;
+  ], [
+    AC_DEFINE(USERDB_NSS,, Build with NSS module support)
+    userdb="$userdb nss"
+  ])
+fi
+
 AC_SUBST(AUTH_CFLAGS)
 AC_SUBST(AUTH_LIBS)
 AC_SUBST(SQL_CFLAGS)
diff -r 38ff50597e54 -r c9b49ed99d28 src/auth/Makefile.am
--- a/src/auth/Makefile.am	Tue Jul 03 00:30:48 2007 +0300
+++ b/src/auth/Makefile.am	Tue Jul 03 01:50:13 2007 +0300
@@ -68,11 +68,11 @@ dovecot_auth_SOURCES = \
 	passdb-blocking.c \
 	passdb-bsdauth.c \
 	passdb-cache.c \
+	passdb-checkpassword.c \
 	passdb-ldap.c \
 	passdb-passwd.c \
 	passdb-passwd-file.c \
 	passdb-pam.c \
-	passdb-checkpassword.c \
 	passdb-shadow.c \
 	passdb-sia.c \
 	passdb-vpopmail.c \
@@ -80,6 +80,7 @@ dovecot_auth_SOURCES = \
 	userdb.c \
 	userdb-blocking.c \
 	userdb-ldap.c \
+	userdb-nss.c \
 	userdb-passwd.c \
 	userdb-passwd-file.c \
 	userdb-prefetch.c \
diff -r 38ff50597e54 -r c9b49ed99d28 src/auth/userdb-nss.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/userdb-nss.c	Tue Jul 03 01:50:13 2007 +0300
@@ -0,0 +1,154 @@
+/* Copyright (C) 2007 Timo Sirainen */
+
+/* Currently supports only GLIBC-compatible NSS modules */
+
+#include "common.h"
+
+#ifdef USERDB_NSS
+
+#include "module-dir.h"
+#include "userdb.h"
+
+#include <pwd.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <nss.h>
+
+#define USER_CACHE_KEY "%u"
+
+struct nss_userdb_module {
+	struct userdb_module module;
+
+	char *buf;
+	size_t bufsize;
+
+	struct module nss_module;
+	enum nss_status (*getpwnam_r)(const char *name, struct passwd *pwd,
+				      char *buffer, size_t buflen, int *errnop);
+};
+
+static void
+userdb_nss_lookup(struct auth_request *auth_request,
+		  userdb_callback_t *callback)
+{
+	struct userdb_module *_module = auth_request->userdb->userdb;
+	struct nss_userdb_module *module = (struct nss_userdb_module *)_module;
+	struct auth_stream_reply *reply;
+	struct passwd pw;
+	enum nss_status status;
+	enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE;
+	int err;
+
+	auth_request_log_debug(auth_request, "nss", "lookup");
+
+	status = module->getpwnam_r(auth_request->user, &pw,
+				    module->buf, module->bufsize, &err);
+	switch (status) {
+	case NSS_STATUS_TRYAGAIN:
+		auth_request_log_error(auth_request, "nss",
+				       "returned tryagain (err=%d)", err);
+		break;
+	case NSS_STATUS_UNAVAIL:
+		auth_request_log_error(auth_request, "nss",
+				       "unavailable (err=%d)", err);
+		break;
+	case NSS_STATUS_NOTFOUND:
+		auth_request_log_info(auth_request, "nss", "unknown user");
+		result = USERDB_RESULT_USER_UNKNOWN;
+		break;
+	case NSS_STATUS_SUCCESS:
+		result = USERDB_RESULT_OK;
+		break;
+	default:
+		auth_request_log_info(auth_request, "nss",
+				      "returned %d (err=%d)", status, err);
+		break;
+	}
+
+	if (result != USERDB_RESULT_OK) {
+		callback(result, NULL, auth_request);
+		return;
+	}
+
+	reply = auth_stream_reply_init(auth_request);
+	auth_stream_reply_add(reply, NULL, pw.pw_name);
+	auth_stream_reply_add(reply, "system_user", pw.pw_name);
+	auth_stream_reply_add(reply, "uid", dec2str(pw.pw_uid));
+	auth_stream_reply_add(reply, "gid", dec2str(pw.pw_gid));
+	auth_stream_reply_add(reply, "home", pw.pw_dir);
+
+	callback(USERDB_RESULT_OK, reply, auth_request);
+}
+
+static void
+userdb_nss_load_module(struct nss_userdb_module *module, pool_t pool)
+{
+	const char *name = module->nss_module.name;
+	char *path;
+
+	path = p_strdup_printf(pool, "/usr/lib/libnss_%s.so", name);
+	module->nss_module.handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
+	if (module->nss_module.handle == NULL)
+		i_fatal("dlopen(%s) failed: %s", path, dlerror());
+	module->nss_module.path = path;
+
+	module->getpwnam_r =
+		module_get_symbol(&module->nss_module,
+				  t_strdup_printf("_nss_%s_getpwnam_r", name));
+	if (module->getpwnam_r == NULL)
+		i_fatal("userdb nss: Module %s missing getpwnam_r()", path);
+}
+
+static struct userdb_module *
+userdb_nss_preinit(struct auth_userdb *auth_userdb, const char *args)
+{
+	struct nss_userdb_module *module;
+	const char *const *tmp;
+	pool_t pool = auth_userdb->auth->pool;
+
+	module = p_new(pool, struct nss_userdb_module, 1);
+	module->bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+	module->buf = p_malloc(pool, module->bufsize);
+
+	t_push();
+	for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
+		if (strcmp(*tmp, "blocking=yes") == 0)
+			module->module.blocking = TRUE;
+		else if (strncmp(*tmp, "service=", 8) == 0)
+			module->nss_module.name = p_strdup(pool, *tmp + 8);
+		else
+			i_fatal("userdb nss: Unknown parameter: %s", *tmp);
+	}
+	t_pop();
+
+	if (module->nss_module.name == NULL)
+		i_fatal("userdb nss: Missing service");
+	userdb_nss_load_module(module, pool);
+
+	module->module.cache_key = USER_CACHE_KEY;
+	return &module->module;
+}
+
+static void userdb_nss_deinit(struct userdb_module *_module)
+{
+	struct nss_userdb_module *module = (struct nss_userdb_module *)_module;
+	void (*endpwent)(void);
+
+	endpwent = module_get_symbol(&module->nss_module,
+				     t_strdup_printf("_nss_%s_endpwent",
+						     module->nss_module.name));
+	if (endpwent != NULL)
+		endpwent();
+}
+
+struct userdb_module_interface userdb_nss = {
+	"nss",
+
+	userdb_nss_preinit,
+	NULL,
+	userdb_nss_deinit,
+
+	userdb_nss_lookup
+};
+
+#endif
diff -r 38ff50597e54 -r c9b49ed99d28 src/auth/userdb.c
--- a/src/auth/userdb.c	Tue Jul 03 00:30:48 2007 +0300
+++ b/src/auth/userdb.c	Tue Jul 03 01:50:13 2007 +0300
@@ -16,6 +16,7 @@ extern struct userdb_module_interface us
 extern struct userdb_module_interface userdb_vpopmail;
 extern struct userdb_module_interface userdb_ldap;
 extern struct userdb_module_interface userdb_sql;
+extern struct userdb_module_interface userdb_nss;
 
 struct userdb_module_interface *userdb_interfaces[] = {
 #ifdef USERDB_PASSWD
@@ -38,6 +39,9 @@ struct userdb_module_interface *userdb_i
 #endif
 #ifdef USERDB_SQL
 	&userdb_sql,
+#endif
+#ifdef USERDB_NSS
+	&userdb_nss,
 #endif
 	NULL
 };


More information about the dovecot-cvs mailing list