]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Cleanups, LDAP support compiles again and generally looks ok, even if it
authorTimo Sirainen <tss@iki.fi>
Fri, 31 Jan 2003 06:56:57 +0000 (08:56 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 31 Jan 2003 06:56:57 +0000 (08:56 +0200)
doesn't necessarily work :) Works now with new master config.

--HG--
branch : HEAD

18 files changed:
src/auth/.cvsignore
src/auth/Makefile.am
src/auth/db-ldap.c [new file with mode: 0644]
src/auth/db-ldap.h [new file with mode: 0644]
src/auth/db-passwd-file.c [moved from src/auth/passwd-file.c with 95% similarity]
src/auth/db-passwd-file.h [moved from src/auth/passwd-file.h with 68% similarity]
src/auth/login-connection.c
src/auth/main.c
src/auth/mech-cyrus-sasl2.c
src/auth/mech.c
src/auth/passdb-passwd-file.c
src/auth/passdb.c
src/auth/userdb-ldap.c [new file with mode: 0644]
src/auth/userdb-passwd-file.c
src/auth/userdb-passwd.c
src/auth/userdb-static.c
src/auth/userdb.c
src/auth/userdb.h

index a1c92bc3883bf58f58832a2422e5979acca6ec65..c6ce7f42b37e2464c2fc4571f1b3e59dc19651af 100644 (file)
@@ -6,4 +6,4 @@
 Makefile
 Makefile.in
 so_locations
-imap-auth
+dovecot-auth
index ba363de3351df5f614786976cbdf3ede0944ec9b..3ef03a17c6ae9a6630f8a9e0404b4c9a12faac83 100644 (file)
@@ -1,18 +1,22 @@
 pkglibexecdir = $(libexecdir)/dovecot
 
-pkglibexec_PROGRAMS = imap-auth
+pkglibexec_PROGRAMS = dovecot-auth
 
 INCLUDES = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-settings \
        $(VPOPMAIL_CFLAGS)
 
-imap_auth_LDADD = \
+dovecot_auth_LDADD = \
+       ../lib-settings/libsettings.a \
        ../lib/liblib.a \
        $(PASSDB_LIBS) \
        $(SASL_LIBS) \
        $(VPOPMAIL_LIBS)
 
-imap_auth_SOURCES = \
+dovecot_auth_SOURCES = \
+       db-ldap.c \
+       db-passwd-file.c \
        login-connection.c \
        main.c \
        master-connection.c \
@@ -27,8 +31,8 @@ imap_auth_SOURCES = \
        passdb-pam.c \
        passdb-shadow.c \
        passdb-vpopmail.c \
-       passwd-file.c \
        userdb.c \
+       userdb-ldap.c \
        userdb-passwd.c \
        userdb-passwd-file.c \
        userdb-static.c \
@@ -38,12 +42,12 @@ noinst_HEADERS = \
        auth-login-interface.h \
        auth-master-interface.h \
        auth-mech-desc.h \
+       db-passwd-file.h \
        common.h \
        login-connection.h \
        master-connection.h \
        mech.h \
        mycrypt.h \
        passdb.h \
-       passwd-file.h \
        userdb.h \
        userdb-vpopmail.h
diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c
new file mode 100644 (file)
index 0000000..b7de99d
--- /dev/null
@@ -0,0 +1,266 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "config.h"
+#undef HAVE_CONFIG_H
+
+#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
+
+#include "common.h"
+#include "ioloop.h"
+#include "hash.h"
+#include "settings.h"
+#include "db-ldap.h"
+
+#include <stddef.h>
+
+#define DEF(type, name) \
+       { type, #name, offsetof(struct ldap_settings, name) }
+
+static struct setting_def setting_defs[] = {
+       DEF(SET_STR, hosts),
+       DEF(SET_STR, user),
+       DEF(SET_STR, pass),
+       DEF(SET_STR, deref),
+       DEF(SET_STR, base),
+       DEF(SET_STR, attrs),
+       DEF(SET_STR, filter)
+};
+
+struct ldap_settings default_ldap_settings = {
+       MEMBER(hosts) "localhost",
+       MEMBER(user) NULL,
+       MEMBER(pass) NULL,
+       MEMBER(deref) "never",
+       MEMBER(base) NULL,
+       MEMBER(attrs) NULL,
+       MEMBER(filter) NULL
+};
+
+static int ldap_conn_open(struct ldap_connection *conn);
+
+static int deref2str(const char *str)
+{
+       if (strcasecmp(str, "never") == 0)
+               return LDAP_DEREF_NEVER;
+       if (strcasecmp(str, "searching") == 0)
+               return LDAP_DEREF_SEARCHING;
+       if (strcasecmp(str, "finding") == 0)
+               return LDAP_DEREF_FINDING;
+       if (strcasecmp(str, "always") == 0)
+               return LDAP_DEREF_ALWAYS;
+
+       i_fatal("LDAP: Unknown deref option '%s'", str);
+}
+
+static const char *get_ldap_error(struct ldap_connection *conn)
+{
+       int ret, err;
+
+       ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
+       if (ret != LDAP_SUCCESS) {
+               i_error("LDAP: Can't get error number: %s",
+                       ldap_err2string(ret));
+               return "??";
+       }
+
+       return ldap_err2string(err);
+}
+
+void db_ldap_search(struct ldap_connection *conn, const char *base, int scope,
+                   const char *filter, char **attributes,
+                   struct ldap_request *request)
+{
+       int msgid;
+
+       if (!conn->connected) {
+               if (!ldap_conn_open(conn)) {
+                       request->callback(conn, request, NULL);
+                       return;
+               }
+       }
+
+       msgid = ldap_search(conn->ld, base, scope, filter, attributes, 0);
+       if (msgid == -1) {
+               i_error("LDAP: ldap_search() failed (filter %s): %s",
+                       filter, get_ldap_error(conn));
+               request->callback(conn, request, NULL);
+               return;
+       }
+
+       hash_insert(conn->requests, POINTER_CAST(msgid), request);
+}
+
+static void ldap_input(void *context)
+{
+       struct ldap_connection *conn = context;
+        struct ldap_request *request;
+       struct timeval timeout;
+       LDAPMessage *res;
+       int ret, msgid;
+
+       for (;;) {
+               memset(&timeout, 0, sizeof(timeout));
+               ret = ldap_result(conn->ld, LDAP_RES_ANY, 1, &timeout, &res);
+               if (ret <= 0) {
+                       if (ret < 0) {
+                               i_error("LDAP: ldap_result() failed: %s",
+                                       get_ldap_error(conn));
+                       }
+                       return;
+               }
+
+               ret = ldap_result2error(conn->ld, res, 0);
+               if (ret != LDAP_SUCCESS) {
+                       i_error("LDAP: ldap_result() failed: %s",
+                               ldap_err2string(ret));
+               } else {
+                       msgid = ldap_msgid(res);
+
+                       request = hash_lookup(conn->requests,
+                                             POINTER_CAST(msgid));
+                       if (request != NULL) {
+                               request->callback(conn, request, res);
+                               hash_remove(conn->requests,
+                                           POINTER_CAST(msgid));
+                               i_free(request);
+                       } else {
+                               i_error("LDAP: Reply with unknown msgid %d",
+                                       msgid);
+                       }
+               }
+
+               ldap_msgfree(res);
+       }
+}
+
+static int ldap_conn_open(struct ldap_connection *conn)
+{
+       int ret, fd;
+
+       if (conn->connected)
+               return TRUE;
+
+       if (conn->ld == NULL) {
+               conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
+               if (conn->ld == NULL)
+                       i_fatal("LDAP: ldap_init() failed with hosts: %s",
+                               conn->set.hosts);
+
+               ret = ldap_set_option(conn->ld, LDAP_OPT_DEREF,
+                                     (void *) &conn->set.ldap_deref);
+               if (ret != LDAP_SUCCESS) {
+                       i_fatal("LDAP: Can't set deref option: %s",
+                               ldap_err2string(ret));
+               }
+       }
+
+       /* NOTE: we use blocking connect, we couldn't do anything anyway
+          until it's done. */
+       ret = ldap_simple_bind_s(conn->ld, conn->set.user, conn->set.pass);
+       if (ret != LDAP_SUCCESS) {
+               i_error("LDAP: ldap_simple_bind_s() failed: %s",
+                       ldap_err2string(ret));
+               return FALSE;
+       }
+
+       conn->connected = TRUE;
+
+       /* register LDAP input to ioloop */
+       ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *) &fd);
+       if (ret != LDAP_SUCCESS) {
+               i_fatal("LDAP: Can't get connection fd: %s",
+                       ldap_err2string(ret));
+       }
+
+       conn->io = io_add(fd, IO_READ, ldap_input, conn);
+       return TRUE;
+}
+
+static void ldap_conn_close(struct ldap_connection *conn)
+{
+       if (conn->connected) {
+               io_remove(conn->io);
+               conn->io = NULL;
+
+               conn->connected = FALSE;
+       }
+
+       if (conn->ld != NULL) {
+               ldap_unbind(conn->ld);
+               conn->ld = NULL;
+       }
+}
+
+void db_ldap_set_attrs(struct ldap_connection *conn, const char *value,
+                      unsigned int **attrs, char ***attr_names)
+{
+       const char *const *attr;
+       unsigned int i, dest, size;
+
+       attr = t_strsplit(value, ",");
+       if (*attr == NULL || **attr == '\0')
+               i_fatal("Missing uid field in attrs");
+
+       for (size = 0; attr[size] != NULL; size++) ;
+
+       /* +1 for terminating NULL */
+       *attrs = p_new(conn->pool, unsigned int, size);
+       *attr_names = p_new(conn->pool, char *, size + 1);
+       for (i = 0, dest = 0; *attr != NULL; i++, attr++) {
+               if (**attr != '\0') {
+                       (*attrs)[dest] = i;
+                       (*attr_names)[dest] = p_strdup(conn->pool, *attr);
+                       dest++;
+               }
+       }
+}
+
+static const char *parse_setting(const char *key, const char *value,
+                                void *context)
+{
+       struct ldap_connection *conn = context;
+
+       return parse_setting_from_defs(conn->pool, setting_defs,
+                                      &conn->set, key, value);
+}
+
+struct ldap_connection *db_ldap_init(const char *config_path)
+{
+       struct ldap_connection *conn;
+       pool_t pool;
+
+       pool = pool_alloconly_create("ldap_connection", 1024);
+       conn = p_new(pool, struct ldap_connection, 1);
+       conn->pool = pool;
+
+       conn->refcount = 1;
+       conn->requests = hash_create(default_pool, pool, 0, NULL, NULL);
+
+       conn->set = default_ldap_settings;
+       settings_read(config_path, parse_setting, conn);
+
+       if (conn->set.user == NULL)
+               i_fatal("LDAP: No user given");
+       if (conn->set.pass == NULL)
+               i_fatal("LDAP: No password given");
+       if (conn->set.base == NULL)
+               i_fatal("LDAP: No base given");
+
+        conn->set.ldap_deref = deref2str(conn->set.deref);
+
+       (void)ldap_conn_open(conn);
+       return conn;
+}
+
+void db_ldap_unref(struct ldap_connection *conn)
+{
+       if (--conn->refcount > 0)
+               return;
+
+       ldap_conn_close(conn);
+
+       hash_destroy(conn->requests);
+       pool_unref(conn->pool);
+}
+
+#endif
diff --git a/src/auth/db-ldap.h b/src/auth/db-ldap.h
new file mode 100644 (file)
index 0000000..4a4fe47
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __DB_LDAP_H
+#define __DB_LDAP_H
+
+#include <ldap.h>
+
+struct ldap_connection;
+struct ldap_request;
+
+typedef void db_search_callback_t(struct ldap_connection *conn,
+                                 struct ldap_request *request,
+                                 LDAPMessage *res);
+
+struct ldap_settings {
+       const char *hosts;
+       const char *user;
+       const char *pass;
+       const char *deref;
+       const char *base;
+       const char *attrs;
+       const char *filter;
+
+       int ldap_deref;
+};
+
+struct ldap_connection {
+       pool_t pool;
+       int refcount;
+
+       char *config_path;
+        struct ldap_settings set;
+
+       LDAP *ld;
+       struct io *io;
+       struct hash_table *requests;
+
+       unsigned int connected:1;
+};
+
+struct ldap_request {
+       db_search_callback_t *callback;
+       void *context;
+};
+
+void db_ldap_search(struct ldap_connection *conn, const char *base, int scope,
+                   const char *filter, char **attributes,
+                   struct ldap_request *request);
+
+void db_ldap_set_attrs(struct ldap_connection *conn, const char *value,
+                      unsigned int **attrs, char ***attr_names);
+
+struct ldap_connection *db_ldap_init(const char *config_path);
+void db_ldap_unref(struct ldap_connection *conn);
+
+#endif
similarity index 95%
rename from src/auth/passwd-file.c
rename to src/auth/db-passwd-file.c
index e59c52414ee28fc31b65a6d19e57ca2d1e05883c..346e7b74e2d81f265e458aea85f716b330a921b9 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "common.h"
 #include "userdb.h"
-#include "passwd-file.h"
+#include "db-passwd-file.h"
 
 #include "buffer.h"
 #include "istream.h"
@@ -169,7 +169,20 @@ static void passwd_file_close(struct passwd_file *pw)
        }
 }
 
-struct passwd_file *passwd_file_parse(const char *path)
+static void passwd_file_sync(struct passwd_file *pw)
+{
+       struct stat st;
+
+       if (stat(pw->path, &st) < 0)
+               i_fatal("stat() failed for %s: %m", pw->path);
+
+       if (st.st_mtime != pw->stamp) {
+               passwd_file_close(pw);
+               passwd_file_open(pw);
+       }
+}
+
+struct passwd_file *db_passwd_file_parse(const char *path)
 {
        struct passwd_file *pw;
 
@@ -181,7 +194,7 @@ struct passwd_file *passwd_file_parse(const char *path)
        return pw;
 }
 
-void passwd_file_unref(struct passwd_file *pw)
+void db_passwd_file_unref(struct passwd_file *pw)
 {
        if (--pw->refcount == 0) {
                passwd_file_close(pw);
@@ -190,22 +203,9 @@ void passwd_file_unref(struct passwd_file *pw)
        }
 }
 
-static void passwd_file_sync(struct passwd_file *pw)
-{
-       struct stat st;
-
-       if (stat(pw->path, &st) < 0)
-               i_fatal("stat() failed for %s: %m", pw->path);
-
-       if (st.st_mtime != pw->stamp) {
-               passwd_file_close(pw);
-               passwd_file_open(pw);
-       }
-}
-
 struct passwd_user *
-passwd_file_lookup_user(struct passwd_file *pw,
-                       const char *user, const char *realm)
+db_passwd_file_lookup(struct passwd_file *pw,
+                     const char *user, const char *realm)
 {
        struct passwd_user *pu;
 
similarity index 68%
rename from src/auth/passwd-file.h
rename to src/auth/db-passwd-file.h
index 45c1aafc91d0f21b7a17f273af283eeb844dbe1f..66b664335b0a0b38cdda7d1f37b89739ea582324 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __PASSWD_FILE_H
-#define __PASSWD_FILE_H
+#ifndef __DB_PASSWD_FILE_H
+#define __DB_PASSWD_FILE_H
 
 enum password_type {
        PASSWORD_NONE,
@@ -39,10 +39,10 @@ extern struct passwd_file *userdb_pwf;
 extern struct passwd_file *passdb_pwf;
 
 struct passwd_user *
-passwd_file_lookup_user(struct passwd_file *pw,
-                       const char *user, const char *realm);
+db_passwd_file_lookup(struct passwd_file *pw,
+                     const char *user, const char *realm);
 
-struct passwd_file *passwd_file_parse(const char *path);
-void passwd_file_unref(struct passwd_file *pw);
+struct passwd_file *db_passwd_file_parse(const char *path);
+void db_passwd_file_unref(struct passwd_file *pw);
 
 #endif
index 1b5bc82f5ddb00c6115b0df74057775b59f31f64..87909d4141dbda2dc57d22f50ea0c101c3454d4e 100644 (file)
@@ -72,12 +72,12 @@ static void login_input_handshake(struct login_connection *conn)
        i_stream_skip(conn->input, sizeof(rec));
 
        if (rec.pid == 0) {
-               i_error("BUG: imap-login said it's PID 0");
+               i_error("BUG: login said it's PID 0");
                login_connection_destroy(conn);
        } else if (login_connection_lookup(rec.pid) != NULL) {
                /* well, it might have just reconnected very fast .. although
                   there's not much reason for it. */
-               i_error("BUG: imap-login gave a PID of existing connection");
+               i_error("BUG: login gave a PID of existing connection");
                login_connection_destroy(conn);
        } else {
                conn->pid = rec.pid;
@@ -133,7 +133,7 @@ static void login_input_request(struct login_connection *conn)
                safe_memset(data + sizeof(request), 0, request.data_size);
        } else {
                /* unknown request */
-               i_error("BUG: imap-login sent us unknown request %u", type);
+               i_error("BUG: login sent us unknown request %u", type);
                login_connection_destroy(conn);
        }
 }
@@ -151,7 +151,7 @@ static void login_input(void *context)
                return;
        case -2:
                /* buffer full */
-               i_error("BUG: imap-login sent us more than %d bytes of data",
+               i_error("BUG: login sent us more than %d bytes of data",
                        (int)MAX_INBUF_SIZE);
                login_connection_destroy(conn);
                return;
index 680409c6e1486987c4859c16c09fe091f5c4ebfc..c370f2243c72cfbc953bc331409938f490728f69 100644 (file)
@@ -41,17 +41,17 @@ static void auth_accept(void *context __attr_unused__)
 
 static void open_logfile(void)
 {
-       if (getenv("IMAP_USE_SYSLOG") != NULL)
-               i_set_failure_syslog("imap-auth", LOG_NDELAY, LOG_MAIL);
+       if (getenv("USE_SYSLOG") != NULL)
+               i_set_failure_syslog("dovecot-auth", LOG_NDELAY, LOG_MAIL);
        else {
                /* log to file or stderr */
-               i_set_failure_file(getenv("IMAP_LOGFILE"), "imap-auth");
+               i_set_failure_file(getenv("LOGFILE"), "dovecot-auth");
        }
 
-       if (getenv("IMAP_INFOLOGFILE") != NULL)
-               i_set_info_file(getenv("IMAP_INFOLOGFILE"));
+       if (getenv("INFOLOGFILE") != NULL)
+               i_set_info_file(getenv("INFOLOGFILE"));
 
-       i_set_failure_timestamp_format(getenv("IMAP_LOGSTAMP"));
+       i_set_failure_timestamp_format(getenv("LOGSTAMP"));
 }
 
 static void drop_privileges(void)
index 9afb425e7f5459fddaf71ab7eab6ddab72f3e263..3fa1d75981d62847aa3bca6130257ddc1cb349da 100644 (file)
@@ -240,7 +240,7 @@ void mech_cyrus_sasl_init_lib(void)
 {
        int ret;
 
-       ret = sasl_server_init(sasl_callbacks, "imap-auth");
+       ret = sasl_server_init(sasl_callbacks, "dovecot-auth");
        if (ret != SASL_OK) {
                i_fatal("sasl_server_init() failed: %s",
                        sasl_errstring(ret, NULL, NULL));
index 3b739e2d68960874db12e35b0a64e5091f2adc5a..de18a47cd182570d3206305e7d309d1b8ad4af37 100644 (file)
@@ -64,7 +64,7 @@ void mech_request_new(struct login_connection *conn,
 
        if ((auth_mechanisms & request->mech) == 0) {
                /* unsupported mechanism */
-               i_error("BUG: imap-login requested unsupported "
+               i_error("BUG: login requested unsupported "
                        "auth mechanism %d", request->mech);
                failure_reply.id = request->id;
                callback(&failure_reply, NULL, conn);
index 1fa2c011a0bdfc81d4977ae12ca1537b2e1ac4ae..87cbc5e8d997080d44da996f425c614a5394ac27 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "common.h"
 #include "passdb.h"
-#include "passwd-file.h"
+#include "db-passwd-file.h"
 
 #include "hex-binary.h"
 #include "md5.h"
@@ -24,7 +24,7 @@ passwd_file_verify_plain(const char *user, const char *realm,
        unsigned char digest[16];
        const char *str;
 
-       pu = passwd_file_lookup_user(passdb_pwf, user, realm);
+       pu = db_passwd_file_lookup(passdb_pwf, user, realm);
        if (pu == NULL) {
                callback(PASSDB_RESULT_USER_UNKNOWN, context);
                return;
@@ -99,7 +99,7 @@ passwd_file_lookup_credentials(const char *user, const char *realm,
 {
        struct passwd_user *pu;
 
-       pu = passwd_file_lookup_user(passdb_pwf, user, realm);
+       pu = db_passwd_file_lookup(passdb_pwf, user, realm);
        if (pu == NULL) {
                callback(NULL, context);
                return;
@@ -141,13 +141,13 @@ static void passwd_file_init(const char *args)
                passdb_pwf = userdb_pwf;
                 passdb_pwf->refcount++;
        } else {
-               passdb_pwf = passwd_file_parse(args);
+               passdb_pwf = db_passwd_file_parse(args);
        }
 }
 
 static void passwd_file_deinit(void)
 {
-       passwd_file_unref(passdb_pwf);
+       db_passwd_file_unref(passdb_pwf);
 }
 
 struct passdb_module passdb_passwd_file = {
index a2c50d0ba6214d9b661b682ddbf5a45967e18260..911b23692cb0b843366c82b25ef57830252df522 100644 (file)
@@ -30,6 +30,9 @@ void passdb_init(void)
        if (name == NULL)
                i_fatal("PASSDB environment is unset");
 
+       args = strchr(name, ' ');
+       name = t_strcut(name, ' ');
+
 #ifdef PASSDB_PASSWD
        if (strcasecmp(name, "passwd") == 0)
                passdb = &passdb_passwd;
@@ -55,12 +58,8 @@ void passdb_init(void)
                i_fatal("Unknown passdb type '%s'", name);
 
        /* initialize */
-       if (passdb->init != NULL) {
-               args = getenv("PASSDB_ARGS");
-               if (args == NULL) args = "";
-
-               passdb->init(args);
-       }
+       if (passdb->init != NULL)
+               passdb->init(args != NULL ? args+1 : "");
 
        if ((auth_mechanisms & AUTH_MECH_PLAIN) &&
            passdb->verify_plain == NULL)
diff --git a/src/auth/userdb-ldap.c b/src/auth/userdb-ldap.c
new file mode 100644 (file)
index 0000000..88c4436
--- /dev/null
@@ -0,0 +1,189 @@
+/* Copyright (C) 2003 Timo Sirainen */
+
+#include "config.h"
+#undef HAVE_CONFIG_H
+
+#if defined(PASSDB_LDAP) || defined(USERDB_LDAP)
+
+#include "common.h"
+#include "ioloop.h"
+#include "hash.h"
+#include "str.h"
+#include "db-ldap.h"
+#include "userdb.h"
+
+#include <ldap.h>
+#include <stdlib.h>
+
+/* using posixAccount */
+#define DEFAULT_ATTRIBUTES "uid,homeDirectory,,uid,uidNumber,gidNumber"
+
+enum ldap_user_attr {
+       ATTR_VIRTUAL_USER = 0,
+       ATTR_HOME,
+       ATTR_MAIL,
+       ATTR_SYSTEM_USER,
+       ATTR_UID_NUMBER,
+       ATTR_GID_NUMBER,
+       ATTR_CHROOT,
+
+       ATTR_COUNT
+};
+
+struct userdb_ldap_connection {
+       struct ldap_connection *conn;
+
+        unsigned int *attrs;
+       char **attr_names;
+};
+
+struct userdb_ldap_request {
+       struct ldap_request request;
+        userdb_callback_t *userdb_callback;
+};
+
+static struct userdb_ldap_connection *userdb_ldap_conn;
+
+static void parse_attr(struct userdb_ldap_connection *conn,
+                      struct user_data *user,
+                      const char *attr, const char *value)
+{
+       enum ldap_user_attr i;
+
+       for (i = 0; i < ATTR_COUNT; i++) {
+               if (strcasecmp(conn->attr_names[i], attr) == 0)
+                       break;
+       }
+
+       if (i == ATTR_COUNT) {
+               i_error("LDAP: Unknown attribute '%s'", attr);
+               return;
+       }
+
+       switch (i) {
+       case ATTR_VIRTUAL_USER:
+               user->virtual_user = t_strdup(value);
+               break;
+       case ATTR_HOME:
+               user->home = t_strdup(value);
+               break;
+       case ATTR_MAIL:
+               user->mail = t_strdup(value);
+               break;
+       case ATTR_SYSTEM_USER:
+               user->system_user = t_strdup(value);
+               break;
+       case ATTR_UID_NUMBER:
+               user->uid = atoi(value);
+               break;
+       case ATTR_GID_NUMBER:
+               user->gid = atoi(value);
+               break;
+       case ATTR_CHROOT:
+               user->chroot = value[0] == 'Y' || value[0] == 'y';
+               break;
+
+       case ATTR_COUNT:
+               break;
+       }
+}
+
+static void handle_request(struct ldap_connection *conn,
+                          struct ldap_request *request, LDAPMessage *res)
+{
+       struct userdb_ldap_request *urequest =
+               (struct userdb_ldap_request *) request;
+       struct user_data user;
+       LDAPMessage *entry;
+       BerElement *ber;
+       char *attr, **vals;
+
+       entry = ldap_first_entry(conn->ld, res);
+       if (entry == NULL) {
+               i_error("LDAP: ldap_first_entry failed()");
+               return;
+       }
+
+       t_push();
+       memset(&user, 0, sizeof(user));
+
+       attr = ldap_first_attribute(conn->ld, entry, &ber);
+       while (attr != NULL) {
+               vals = ldap_get_values(conn->ld, entry, attr);
+               if (vals != NULL && vals[0] != NULL && vals[1] == NULL) {
+                       parse_attr(userdb_ldap_conn, &user, attr, vals[0]);
+                       ldap_value_free(vals);
+                       ldap_memfree(attr);
+               }
+
+               attr = ldap_next_attribute(conn->ld, entry, ber);
+       }
+
+       if (user.virtual_user == NULL)
+               i_error("LDAP: No username in reply");
+       else {
+               if (ldap_next_entry(conn->ld, entry) != NULL) {
+                       i_error("LDAP: Multiple replies found for user %s",
+                               user.virtual_user);
+               } else {
+                       urequest->userdb_callback(&user, request->context);
+               }
+       }
+
+       t_pop();
+}
+
+static void userdb_ldap_lookup(const char *user, const char *realm,
+                              userdb_callback_t *callback, void *context)
+{
+       struct ldap_connection *conn = userdb_ldap_conn->conn;
+       struct userdb_ldap_request *request;
+       const char *filter;
+
+       if (realm != NULL)
+               user = t_strconcat(user, "@", realm, NULL);
+
+       if (conn->set.filter == NULL) {
+               filter = t_strdup_printf("(%s=%s)",
+                       userdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER], user);
+       } else {
+               filter = t_strdup_printf("(&%s(%s=%s))", conn->set.filter,
+                       userdb_ldap_conn->attr_names[ATTR_VIRTUAL_USER], user);
+       }
+
+       request = i_new(struct userdb_ldap_request, 1);
+       request->request.callback = handle_request;
+       request->request.context = context;
+       request->userdb_callback = callback;
+
+       db_ldap_search(conn, conn->set.base, LDAP_SCOPE_SUBTREE,
+                      filter, userdb_ldap_conn->attr_names,
+                      &request->request);
+}
+
+static void userdb_ldap_init(const char *args)
+{
+       struct userdb_ldap_connection *conn;
+
+       conn = i_new(struct userdb_ldap_connection, 1);
+       conn->conn = db_ldap_init(args);
+
+       db_ldap_set_attrs(conn->conn, conn->conn->set.attrs ?
+                         conn->conn->set.attrs : DEFAULT_ATTRIBUTES,
+                         &conn->attrs, &conn->attr_names);
+}
+
+static void userdb_ldap_deinit(void)
+{
+       db_ldap_unref(userdb_ldap_conn->conn);
+       i_free(userdb_ldap_conn);
+}
+
+struct userdb_module userdb_ldap = {
+       userdb_ldap_init,
+       userdb_ldap_deinit,
+
+       userdb_ldap_lookup
+};
+
+#endif
index 2028622b118d91e0bf7da373ec7fcf37a69f9078..34d7667b1b919bfad6a6843f4ffb96b3c18998db 100644 (file)
@@ -7,38 +7,34 @@
 
 #include "common.h"
 #include "userdb.h"
-#include "passwd-file.h"
+#include "db-passwd-file.h"
 
 struct passwd_file *userdb_pwf = NULL;
 
 static void passwd_file_lookup(const char *user, const char *realm,
                               userdb_callback_t *callback, void *context)
 {
-       struct user_data *data;
+       struct user_data data;
        struct passwd_user *pu;
-       pool_t pool;
 
-       pu = passwd_file_lookup_user(userdb_pwf, user, realm);
+       pu = db_passwd_file_lookup(userdb_pwf, user, realm);
        if (pu == NULL) {
                callback(NULL, context);
                return;
        }
 
-       pool = pool_alloconly_create("user_data", 512);
-       data = p_new(pool, struct user_data, 1);
-       data->pool = pool;
+       memset(&data, 0, sizeof(data));
+       data.uid = pu->uid;
+       data.gid = pu->gid;
 
-       data->uid = pu->uid;
-       data->gid = pu->gid;
+       data.virtual_user = realm == NULL ? user :
+               t_strconcat(user, "@", realm, NULL);
+       data.home = pu->home;
+       data.mail = pu->mail;
 
-       data->virtual_user = realm == NULL ? p_strdup(data->pool, user) :
-               p_strconcat(data->pool, user, "@", realm, NULL);
-       data->home = p_strdup(data->pool, pu->home);
-       data->mail = p_strdup(data->pool, pu->mail);
+       data.chroot = pu->chroot;
 
-       data->chroot = pu->chroot;
-
-       callback(data, context);
+       callback(&data, context);
 }
 
 static void passwd_file_init(const char *args)
@@ -47,13 +43,13 @@ static void passwd_file_init(const char *args)
                userdb_pwf = passdb_pwf;
                 userdb_pwf->refcount++;
        } else {
-               userdb_pwf = passwd_file_parse(args);
+               userdb_pwf = db_passwd_file_parse(args);
        }
 }
 
 static void passwd_file_deinit(void)
 {
-       passwd_file_unref(userdb_pwf);
+       db_passwd_file_unref(userdb_pwf);
 }
 
 struct userdb_module userdb_passwd_file = {
index 7ae4ad7c00f209ae72994d5efc7a09f9869701ac..70b18679da087aa839fee7a4d9fe9dfe3a1a6a6c 100644 (file)
@@ -13,9 +13,8 @@
 static void passwd_lookup(const char *user, const char *realm,
                          userdb_callback_t *callback, void *context)
 {
-       struct user_data *data;
+       struct user_data data;
        struct passwd *pw;
-       pool_t pool;
 
        if (realm != NULL)
                user = t_strconcat(user, "@", realm, NULL);
@@ -29,18 +28,14 @@ static void passwd_lookup(const char *user, const char *realm,
                return;
        }
 
-       pool = pool_alloconly_create("user_data", 512);
-       data = p_new(pool, struct user_data, 1);
-       data->pool = pool;
+       memset(&data, 0, sizeof(data));
+       data.uid = pw->pw_uid;
+       data.gid = pw->pw_gid;
 
-       data->uid = pw->pw_uid;
-       data->gid = pw->pw_gid;
+       data.virtual_user = data.system_user = pw->pw_name;
+       data.home = pw->pw_dir;
 
-       data->system_user = p_strdup(data->pool, pw->pw_name);
-       data->virtual_user = data->system_user;
-       data->home = p_strdup(data->pool, pw->pw_dir);
-
-       callback(data, context);
+       callback(&data, context);
 }
 
 struct userdb_module userdb_passwd = {
index 7e5895da190a0a7c41f16a81a1dc31c60f7c2e81..7d0585c0e2a0f31a46404c3f063eaa4f3b0dc907 100644 (file)
@@ -19,28 +19,23 @@ static char *static_home_template;
 static void static_lookup(const char *user, const char *realm,
                          userdb_callback_t *callback, void *context)
 {
-       struct user_data *data;
-       pool_t pool;
+       struct user_data data;
        string_t *str;
 
        if (realm != NULL)
                user = t_strconcat(user, "@", realm, NULL);
 
-       pool = pool_alloconly_create("user_data", 512);
-       data = p_new(pool, struct user_data, 1);
-       data->pool = pool;
+       memset(&data, 0, sizeof(data));
+       data.uid = static_uid;
+       data.gid = static_gid;
 
-       data->uid = static_uid;
-       data->gid = static_gid;
-
-       data->system_user = p_strdup(data->pool, user);
-       data->virtual_user = data->system_user;
+       data.virtual_user = data.system_user = user;
 
        str = t_str_new(256);
        var_expand(str, static_home_template, user, NULL);
-       data->home = p_strdup(data->pool, str_c(str));
+       data.home = str_c(str);
 
-       callback(data, context);
+       callback(&data, context);
 }
 
 static void static_init(const char *args)
index 7d89cd9c52afc5ff78239c5bc6dc5d86027b2f37..8152cfa9d3491f4c41864e2d748d0cbbb102b5a8 100644 (file)
@@ -17,6 +17,9 @@ void userdb_init(void)
        if (name == NULL)
                i_fatal("USERDB environment is unset");
 
+       args = strchr(name, ' ');
+       name = t_strcut(name, ' ');
+
 #ifdef USERDB_PASSWD
        if (strcasecmp(name, "passwd") == 0)
                userdb = &userdb_passwd;
@@ -38,12 +41,8 @@ void userdb_init(void)
                i_fatal("Unknown userdb type '%s'", name);
 
        /* initialize */
-       if (userdb->init != NULL) {
-               args = getenv("USERDB_ARGS");
-               if (args == NULL) args = "";
-
-               userdb->init(args);
-       }
+       if (userdb->init != NULL)
+               userdb->init(args != NULL ? args+1 : "");
 }
 
 void userdb_deinit(void)
index ea8ca9a7242c5b113ceb6e9652bbc9f40ca76bba..a9c5835c70a73cbc46f32d91553331cf671c4313 100644 (file)
@@ -2,13 +2,11 @@
 #define __USERDB_H
 
 struct user_data {
-       pool_t pool;
+       const char *virtual_user;
+       const char *home;
+       const char *mail;
 
-       char *virtual_user;
-       char *home;
-       char *mail;
-
-       char *system_user;
+       const char *system_user;
        uid_t uid;
        gid_t gid;