changeset 1150:18a2074a4d3d HEAD

Support for dynamic authentication modules.
author Timo Sirainen <tss@iki.fi>
date Tue, 11 Feb 2003 20:01:38 +0200
parents 38f6130abec2
children 058f6c26f405
files configure.in src/auth/Makefile.am src/auth/auth-module.c src/auth/auth-module.h src/auth/passdb.c src/auth/userdb.c
diffstat 6 files changed, 162 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Tue Feb 11 19:42:31 2003 +0200
+++ b/configure.in	Tue Feb 11 20:01:38 2003 +0200
@@ -814,6 +814,17 @@
 	])
 fi
 
+dnl * dynamic modules?
+AC_CHECK_LIB(dl, dlopen, [
+  PASSDB_LIBS="$PASSDB_LIBS -ldl"
+  AC_DEFINE(AUTH_MODULES,, Define if you want to build with dynamic auth modules)
+  auth_modules=yes
+  userdb="$userdb (modules)"
+  passdb="$passdb (modules)"
+])
+
+AM_CONDITIONAL(AUTH_MODULES, test "$auth_modules" = "yes")
+
 AC_SUBST(PASSDB_LIBS)
 
 dnl **
@@ -917,8 +928,8 @@
 echo
 echo "Install prefix ...................... : $prefix"
 echo "File offsets ........................ : ${offt_bits}bit"
-echo "Building with user database modules . :$userdb"
-echo "Building with password lookup modules :$passdb"
 echo "Building with SSL support ........... : $have_ssl"
 echo "Building with IPv6 support .......... : $want_ipv6"
 echo "Building with pop3 server ........... : $want_pop3d"
+echo "Building with user database modules . :$userdb"
+echo "Building with password lookup modules :$passdb"
--- a/src/auth/Makefile.am	Tue Feb 11 19:42:31 2003 +0200
+++ b/src/auth/Makefile.am	Tue Feb 11 20:01:38 2003 +0200
@@ -5,6 +5,7 @@
 INCLUDES = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-settings \
+	-DAUTH_MODULE_DIR=\""$(libdir)/dovecot/auth"\" \
 	$(VPOPMAIL_CFLAGS)
 
 dovecot_auth_LDADD = \
@@ -14,7 +15,12 @@
 	$(SASL_LIBS) \
 	$(VPOPMAIL_LIBS)
 
+if AUTH_MODULES
+dovecot_auth_LDFLAGS = -export-dynamic
+endif
+
 dovecot_auth_SOURCES = \
+	auth-module.c \
 	db-ldap.c \
 	db-passwd-file.c \
 	login-connection.c \
@@ -43,6 +49,7 @@
 	auth-login-interface.h \
 	auth-master-interface.h \
 	auth-mech-desc.h \
+	auth-module.h \
 	db-ldap.h \
 	db-passwd-file.h \
 	common.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/auth-module.c	Tue Feb 11 20:01:38 2003 +0200
@@ -0,0 +1,101 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "lib.h"
+
+#ifdef AUTH_MODULES
+
+#include "auth-module.h"
+
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+struct auth_module {
+	struct auth_module *next;
+
+	int refcount;
+	char *name;
+	void *handle;
+};
+
+static struct auth_module *auth_modules = NULL;
+
+static struct auth_module *auth_module_find(const char *name)
+{
+	struct auth_module *module;
+
+	for (module = auth_modules; module != NULL; module = module->next) {
+		if (strcmp(module->name, name) == 0)
+			return module;
+	}
+
+	return NULL;
+}
+
+struct auth_module *auth_module_open(const char *name)
+{
+        struct auth_module *module;
+	const char *path;
+	struct stat st;
+	void *handle;
+
+	module = auth_module_find(name);
+	if (module != NULL) {
+		module->refcount++;
+		return module;
+	}
+
+	path = t_strconcat(AUTH_MODULE_DIR"/", name, ".so", NULL);
+	if (stat(path, &st) < 0) {
+		if (errno != ENOENT)
+			i_error("stat(%s) failed: %m", path);
+		return NULL;
+	}
+
+	handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
+	if (handle == NULL)
+		i_error("dlopen(%s) failed: %s", path, dlerror());
+
+	module = i_new(struct auth_module, 1);
+	module->refcount = 1;
+	module->name = i_strdup(name);
+	module->handle = handle;
+
+	module->next = auth_modules;
+	auth_modules = module;
+	return module;
+}
+
+void auth_module_close(struct auth_module *module)
+{
+	struct auth_module **pos;
+
+	if (--module->refcount > 0)
+		return;
+
+	for (pos = &auth_modules; *pos != NULL; pos = &(*pos)->next) {
+		if (*pos == module) {
+			*pos = module->next;
+			break;
+		}
+	}
+
+	if (dlclose(module->handle) != 0)
+		i_error("dlclose() failed: %s", dlerror());
+	i_free(module->name);
+	i_free(module);
+}
+
+void *auth_module_sym(struct auth_module *module, const char *name)
+{
+	const char *error;
+	void *ret;
+
+	ret = dlsym(module->handle, name);
+
+	error = dlerror();
+	if (error != NULL)
+		i_error("dlsym(%s) failed: %s", name, error);
+	return ret;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/auth-module.h	Tue Feb 11 20:01:38 2003 +0200
@@ -0,0 +1,9 @@
+#ifndef __AUTH_MODULE_H
+#define __AUTH_MODULE_H
+
+struct auth_module *auth_module_open(const char *name);
+void auth_module_close(struct auth_module *module);
+
+void *auth_module_sym(struct auth_module *module, const char *name);
+
+#endif
--- a/src/auth/passdb.c	Tue Feb 11 19:42:31 2003 +0200
+++ b/src/auth/passdb.c	Tue Feb 11 20:01:38 2003 +0200
@@ -2,10 +2,15 @@
 
 #include "common.h"
 #include "mech.h"
+#include "auth-module.h"
 #include "passdb.h"
 
 #include <stdlib.h>
 
+#ifdef AUTH_MODULES
+static struct auth_module *passdb_module = NULL;
+#endif
+
 struct passdb_module *passdb;
 
 const char *passdb_credentials_to_str(enum passdb_credentials credentials)
@@ -61,6 +66,13 @@
 	if (strcasecmp(name, "ldap") == 0)
 		passdb = &passdb_ldap;
 #endif
+#ifdef AUTH_MODULES
+	passdb_module = auth_module_open(name);
+	if (passdb_module != NULL) {
+		passdb = auth_module_sym(passdb_module,
+					 t_strconcat("passdb_", name, NULL));
+	}
+#endif
 
 	if (passdb == NULL)
 		i_fatal("Unknown passdb type '%s'", name);
@@ -82,4 +94,8 @@
 {
 	if (passdb != NULL && passdb->deinit != NULL)
 		passdb->deinit();
+#ifdef AUTH_MODULES
+	if (passdb_module != NULL)
+                auth_module_close(passdb_module);
+#endif
 }
--- a/src/auth/userdb.c	Tue Feb 11 19:42:31 2003 +0200
+++ b/src/auth/userdb.c	Tue Feb 11 20:01:38 2003 +0200
@@ -1,10 +1,15 @@
 /* Copyright (C) 2002-2003 Timo Sirainen */
 
 #include "common.h"
+#include "auth-module.h"
 #include "userdb.h"
 
 #include <stdlib.h>
 
+#ifdef AUTH_MODULES
+static struct auth_module *userdb_module = NULL;
+#endif
+
 struct userdb_module *userdb;
 
 void userdb_init(void)
@@ -40,6 +45,13 @@
 	if (strcasecmp(name, "ldap") == 0)
 		userdb = &userdb_ldap;
 #endif
+#ifdef AUTH_MODULES
+	userdb_module = auth_module_open(name);
+	if (userdb_module != NULL) {
+		userdb = auth_module_sym(userdb_module,
+					 t_strconcat("userdb_", name, NULL));
+	}
+#endif
 
 	if (userdb == NULL)
 		i_fatal("Unknown userdb type '%s'", name);
@@ -53,4 +65,8 @@
 {
 	if (userdb != NULL && userdb->deinit != NULL)
 		userdb->deinit();
+#ifdef AUTH_MODULES
+	if (userdb_module != NULL)
+                auth_module_close(userdb_module);
+#endif
 }