From: Timo Sirainen Date: Fri, 31 Jan 2003 06:56:57 +0000 (+0200) Subject: Cleanups, LDAP support compiles again and generally looks ok, even if it X-Git-Tag: 1.1.alpha1~5044 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=965ed6ea3fc8f7637bd0d159d2fdb283a191ce34;p=thirdparty%2Fdovecot%2Fcore.git Cleanups, LDAP support compiles again and generally looks ok, even if it doesn't necessarily work :) Works now with new master config. --HG-- branch : HEAD --- diff --git a/src/auth/.cvsignore b/src/auth/.cvsignore index a1c92bc388..c6ce7f42b3 100644 --- a/src/auth/.cvsignore +++ b/src/auth/.cvsignore @@ -6,4 +6,4 @@ Makefile Makefile.in so_locations -imap-auth +dovecot-auth diff --git a/src/auth/Makefile.am b/src/auth/Makefile.am index ba363de335..3ef03a17c6 100644 --- a/src/auth/Makefile.am +++ b/src/auth/Makefile.am @@ -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 index 0000000000..b7de99da51 --- /dev/null +++ b/src/auth/db-ldap.c @@ -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 + +#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 index 0000000000..4a4fe47e49 --- /dev/null +++ b/src/auth/db-ldap.h @@ -0,0 +1,54 @@ +#ifndef __DB_LDAP_H +#define __DB_LDAP_H + +#include + +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 diff --git a/src/auth/passwd-file.c b/src/auth/db-passwd-file.c similarity index 95% rename from src/auth/passwd-file.c rename to src/auth/db-passwd-file.c index e59c52414e..346e7b74e2 100644 --- a/src/auth/passwd-file.c +++ b/src/auth/db-passwd-file.c @@ -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; diff --git a/src/auth/passwd-file.h b/src/auth/db-passwd-file.h similarity index 68% rename from src/auth/passwd-file.h rename to src/auth/db-passwd-file.h index 45c1aafc91..66b664335b 100644 --- a/src/auth/passwd-file.h +++ b/src/auth/db-passwd-file.h @@ -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 diff --git a/src/auth/login-connection.c b/src/auth/login-connection.c index 1b5bc82f5d..87909d4141 100644 --- a/src/auth/login-connection.c +++ b/src/auth/login-connection.c @@ -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; diff --git a/src/auth/main.c b/src/auth/main.c index 680409c6e1..c370f2243c 100644 --- a/src/auth/main.c +++ b/src/auth/main.c @@ -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) diff --git a/src/auth/mech-cyrus-sasl2.c b/src/auth/mech-cyrus-sasl2.c index 9afb425e7f..3fa1d75981 100644 --- a/src/auth/mech-cyrus-sasl2.c +++ b/src/auth/mech-cyrus-sasl2.c @@ -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)); diff --git a/src/auth/mech.c b/src/auth/mech.c index 3b739e2d68..de18a47cd1 100644 --- a/src/auth/mech.c +++ b/src/auth/mech.c @@ -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); diff --git a/src/auth/passdb-passwd-file.c b/src/auth/passdb-passwd-file.c index 1fa2c011a0..87cbc5e8d9 100644 --- a/src/auth/passdb-passwd-file.c +++ b/src/auth/passdb-passwd-file.c @@ -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 = { diff --git a/src/auth/passdb.c b/src/auth/passdb.c index a2c50d0ba6..911b23692c 100644 --- a/src/auth/passdb.c +++ b/src/auth/passdb.c @@ -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 index 0000000000..88c4436b27 --- /dev/null +++ b/src/auth/userdb-ldap.c @@ -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 +#include + +/* 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 diff --git a/src/auth/userdb-passwd-file.c b/src/auth/userdb-passwd-file.c index 2028622b11..34d7667b1b 100644 --- a/src/auth/userdb-passwd-file.c +++ b/src/auth/userdb-passwd-file.c @@ -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 = { diff --git a/src/auth/userdb-passwd.c b/src/auth/userdb-passwd.c index 7ae4ad7c00..70b18679da 100644 --- a/src/auth/userdb-passwd.c +++ b/src/auth/userdb-passwd.c @@ -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 = { diff --git a/src/auth/userdb-static.c b/src/auth/userdb-static.c index 7e5895da19..7d0585c0e2 100644 --- a/src/auth/userdb-static.c +++ b/src/auth/userdb-static.c @@ -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) diff --git a/src/auth/userdb.c b/src/auth/userdb.c index 7d89cd9c52..8152cfa9d3 100644 --- a/src/auth/userdb.c +++ b/src/auth/userdb.c @@ -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) diff --git a/src/auth/userdb.h b/src/auth/userdb.h index ea8ca9a724..a9c5835c70 100644 --- a/src/auth/userdb.h +++ b/src/auth/userdb.h @@ -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;