]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Initial support for per-protocol auth settings.
authorTimo Sirainen <tss@iki.fi>
Sat, 13 Mar 2010 20:54:41 +0000 (22:54 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 13 Mar 2010 20:54:41 +0000 (22:54 +0200)
Currently the list of services is hard-coded. This should be changed so that
config lookup returns the service names.

--HG--
branch : HEAD

27 files changed:
src/auth/auth-client-connection.c
src/auth/auth-master-connection.c
src/auth/auth-request-handler.c
src/auth/auth-request-handler.h
src/auth/auth-request.c
src/auth/auth-request.h
src/auth/auth-settings.c
src/auth/auth-settings.h
src/auth/auth-worker-client.c
src/auth/auth.c
src/auth/auth.h
src/auth/db-ldap.c
src/auth/main.c
src/auth/mech-anonymous.c
src/auth/mech-digest-md5.c
src/auth/mech-gssapi.c
src/auth/mech-rpa.c
src/auth/mech-winbind.c
src/auth/passdb-cache.c
src/auth/passdb-ldap.c
src/auth/passdb-pam.c
src/auth/passdb.c
src/auth/passdb.h
src/auth/userdb-ldap.c
src/auth/userdb-prefetch.c
src/auth/userdb.c
src/auth/userdb.h

index b17a21e8bf2bf396482e269376f59caa8292f4b3..943188d226a7dda60b2b9807f07c2464dbb01800 100644 (file)
@@ -174,8 +174,7 @@ auth_client_handle_line(struct auth_client_connection *conn, const char *line)
                                conn->auth->set->debug_passwords ? line :
                                auth_line_hide_pass(line));
                }
-               return auth_request_handler_auth_begin(conn->auth,
-                                                      conn->request_handler,
+               return auth_request_handler_auth_begin(conn->request_handler,
                                                       line + 5);
        }
        if (strncmp(line, "CONT\t", 5) == 0) {
index 03fc41fe0657103825aa00cf67f9b841006262d7..f1711a68688c0dc5cdd9e1cc2217c752456c5115 100644 (file)
@@ -122,7 +122,7 @@ master_input_auth_request(struct auth_master_connection *conn, const char *args,
                return -1;
        }
 
-       auth_request = auth_request_new_dummy(conn->auth);
+       auth_request = auth_request_new_dummy();
        auth_request->id = (unsigned int)strtoul(list[0], NULL, 10);
        auth_request->context = conn;
        auth_master_connection_ref(conn);
@@ -151,6 +151,8 @@ master_input_auth_request(struct auth_master_connection *conn, const char *args,
                auth_request_unref(&auth_request);
                return -1;
        }
+
+       auth_request_init(auth_request);
        *request_r = auth_request;
        return 1;
 }
index 9fe6bf47ecfaf51a2390d1ae7de1603e7972c4aa..714836c961ab0be6636680bfcd6fd6065dff95a2 100644 (file)
@@ -302,8 +302,7 @@ auth_penalty_callback(unsigned int penalty, struct auth_request *request)
        }
 }
 
-bool auth_request_handler_auth_begin(struct auth *auth,
-                                    struct auth_request_handler *handler,
+bool auth_request_handler_auth_begin(struct auth_request_handler *handler,
                                     const char *args)
 {
        const struct mech_module *mech;
@@ -332,7 +331,7 @@ bool auth_request_handler_auth_begin(struct auth *auth,
                return FALSE;
        }
 
-       request = auth_request_new(auth, mech, auth_callback, handler);
+       request = auth_request_new(mech, auth_callback, handler);
        request->handler = handler;
        request->connect_uid = handler->connect_uid;
        request->client_pid = handler->client_pid;
@@ -375,12 +374,13 @@ bool auth_request_handler_auth_begin(struct auth *auth,
                auth_request_unref(&request);
                return FALSE;
        }
+       auth_request_init(request);
 
        request->to_abort = timeout_add(AUTH_REQUEST_TIMEOUT * 1000,
                                        auth_request_timeout, request);
        hash_table_insert(handler->requests, POINTER_CAST(id), request);
 
-       if (request->auth->set->ssl_require_client_cert &&
+       if (request->set->ssl_require_client_cert &&
            !request->valid_client_cert) {
                /* we fail without valid certificate */
                 auth_request_handler_auth_fail(handler, request,
@@ -579,7 +579,7 @@ void auth_request_handler_flush_failures(bool flush_all)
 
                /* FIXME: assumess that failure_delay is always the same. */
                diff = ioloop_time - auth_request->last_access;
-               if (diff < (time_t)auth_request->auth->set->failure_delay &&
+               if (diff < (time_t)auth_request->set->failure_delay &&
                    !flush_all)
                        break;
 
index f020c028b65cbfef0f92d01290b7b94fb41794dd..b7d3c1279151d24c4750140dd516640cb038ffe2 100644 (file)
@@ -29,8 +29,7 @@ void auth_request_handler_set(struct auth_request_handler *handler,
                              unsigned int connect_uid,
                              unsigned int client_pid);
 
-bool auth_request_handler_auth_begin(struct auth *auth,
-                                    struct auth_request_handler *handler,
+bool auth_request_handler_auth_begin(struct auth_request_handler *handler,
                                     const char *args);
 bool auth_request_handler_auth_continue(struct auth_request_handler *handler,
                                        const char *args);
index 87318644130126afcb12bba177158f8ce4c99e83..7e7a60858f67bdd752eeabe1727fadc3cfee773c 100644 (file)
@@ -30,20 +30,18 @@ static void get_log_prefix(string_t *str, struct auth_request *auth_request,
                           const char *subsystem);
 
 struct auth_request *
-auth_request_new(struct auth *auth, const struct mech_module *mech,
+auth_request_new(const struct mech_module *mech,
                 mech_callback_t *callback, void *context)
 {
        struct auth_request *request;
 
        request = mech->auth_new();
        request->state = AUTH_REQUEST_STATE_NEW;
-       request->passdb = auth->passdbs;
-       request->userdb = auth->userdbs;
 
        request->refcount = 1;
        request->last_access = ioloop_time;
 
-       request->auth = auth;
+       request->set = global_auth_settings;
        request->mech = mech;
        request->mech_name = mech == NULL ? NULL : mech->mech_name;
        request->callback = callback;
@@ -51,7 +49,7 @@ auth_request_new(struct auth *auth, const struct mech_module *mech,
        return request;
 }
 
-struct auth_request *auth_request_new_dummy(struct auth *auth)
+struct auth_request *auth_request_new_dummy(void)
 {
        struct auth_request *auth_request;
        pool_t pool;
@@ -62,18 +60,26 @@ struct auth_request *auth_request_new_dummy(struct auth *auth)
 
        auth_request->refcount = 1;
        auth_request->last_access = ioloop_time;
-
-       if (auth == NULL) {
-               auth = p_new(pool, struct auth, 1);
-               auth->set = global_auth_settings;
-       }
-       auth_request->auth = auth;
-       auth_request->passdb = auth->passdbs;
-       auth_request->userdb = auth->userdbs;
+       auth_request->set = global_auth_settings;
 
        return auth_request;
 }
 
+void auth_request_init(struct auth_request *request)
+{
+       struct auth *auth;
+
+       auth = auth_request_get_auth(request);
+       request->set = auth->set;
+       request->passdb = auth->passdbs;
+       request->userdb = auth->userdbs;
+}
+
+struct auth *auth_request_get_auth(struct auth_request *request)
+{
+       return auth_find_service(request->service);
+}
+
 void auth_request_success(struct auth_request *request,
                          const void *data, size_t data_size)
 {
@@ -181,7 +187,7 @@ bool auth_request_import(struct auth_request *request,
        else if (strcmp(key, "original_username") == 0)
                request->original_username = p_strdup(request->pool, value);
        else if (strcmp(key, "cert_username") == 0) {
-               if (request->auth->set->ssl_username_from_cert) {
+               if (request->set->ssl_username_from_cert) {
                        /* get username from SSL certificate. it overrides
                           the username given by the auth mechanism. */
                        request->user = p_strdup(request->pool, value);
@@ -347,7 +353,7 @@ static bool auth_request_master_lookup_finish(struct auth_request *request)
 
        /* the authentication continues with passdb lookup for the
           requested_login_user. */
-       request->passdb = request->auth->passdbs;
+       request->passdb = auth_request_get_auth(request)->passdbs;
        return FALSE;
 }
 
@@ -543,7 +549,7 @@ auth_request_lookup_credentials_finish(enum passdb_result result,
                        request->credentials_scheme,
                        request->private_callback.lookup_credentials);
        } else {
-               if (request->auth->set->debug_passwords &&
+               if (request->set->debug_passwords &&
                    result == PASSDB_RESULT_OK) {
                        auth_request_log_debug(request, "password",
                                "Credentials: %s",
@@ -724,10 +730,10 @@ void auth_request_userdb_callback(enum userdb_result result,
                   request->client_pid != 0) {
                /* this was an actual login attempt, the user should
                   have been found. */
-               if (request->auth->userdbs->next == NULL) {
+               if (auth_request_get_auth(request)->userdbs->next == NULL) {
                        auth_request_log_error(request, "userdb",
                                "user not found from userdb %s",
-                               request->auth->userdbs->userdb->iface->name);
+                               request->userdb->userdb->iface->name);
                } else {
                        auth_request_log_error(request, "userdb",
                                "user not found from any userdbs");
@@ -787,7 +793,7 @@ static char *
 auth_request_fix_username(struct auth_request *request, const char *username,
                           const char **error_r)
 {
-       const struct auth_settings *set = request->auth->set;
+       const struct auth_settings *set = request->set;
        unsigned char *p;
        char *user;
 
@@ -835,7 +841,7 @@ auth_request_fix_username(struct auth_request *request, const char *username,
 bool auth_request_set_username(struct auth_request *request,
                               const char *username, const char **error_r)
 {
-       const struct auth_settings *set = request->auth->set;
+       const struct auth_settings *set = request->set;
        const char *p, *login_username = NULL;
 
        if (*set->master_user_separator != '\0' && !request->userdb_lookup) {
@@ -905,7 +911,7 @@ bool auth_request_set_login_username(struct auth_request *request,
        }
 
         /* lookup request->user from masterdb first */
-        request->passdb = request->auth->masterdbs;
+        request->passdb = auth_request_get_auth(request)->masterdbs;
 
         request->requested_login_user =
                 auth_request_fix_username(request, username, error_r);
@@ -1326,7 +1332,7 @@ void auth_request_log_password_mismatch(struct auth_request *request,
                                        const char *subsystem)
 {
        string_t *str;
-       const char *log_type = request->auth->set->verbose_passwords;
+       const char *log_type = request->set->verbose_passwords;
 
        if (strcmp(log_type, "no") == 0) {
                auth_request_log_info(request, subsystem, "Password mismatch");
@@ -1401,7 +1407,7 @@ int auth_request_password_verify(struct auth_request *request,
        i_assert(ret >= 0);
        if (ret == 0) {
                auth_request_log_password_mismatch(request, subsystem);
-               if (request->auth->set->debug_passwords) T_BEGIN {
+               if (request->set->debug_passwords) T_BEGIN {
                        log_password_failure(request, plain_password,
                                             crypted_password, scheme,
                                             request->original_username,
@@ -1532,7 +1538,7 @@ void auth_request_log_debug(struct auth_request *auth_request,
 {
        va_list va;
 
-       if (!auth_request->auth->set->debug)
+       if (!auth_request->set->debug)
                return;
 
        va_start(va, format);
@@ -1548,7 +1554,7 @@ void auth_request_log_info(struct auth_request *auth_request,
 {
        va_list va;
 
-       if (!auth_request->auth->set->verbose)
+       if (!auth_request->set->verbose)
                return;
 
        va_start(va, format);
index 580939e3acbe4737555fa91bb12e5c4fec9fd8c8..3d13a1ffd94d69f8ea8f1d399dee651ed0162e8a 100644 (file)
@@ -56,7 +56,7 @@ struct auth_request {
 
        const struct mech_module *mech;
        struct auth_request_handler *handler;
-       struct auth *auth;
+       const struct auth_settings *set;
         struct auth_passdb *passdb;
         struct auth_userdb *userdb;
 
@@ -111,9 +111,12 @@ struct auth_request {
 };
 
 struct auth_request *
-auth_request_new(struct auth *auth, const struct mech_module *mech,
+auth_request_new(const struct mech_module *mech,
                 mech_callback_t *callback, void *context);
-struct auth_request *auth_request_new_dummy(struct auth *auth);
+struct auth_request *auth_request_new_dummy(void);
+void auth_request_init(struct auth_request *request);
+struct auth *auth_request_get_auth(struct auth_request *request);
+
 void auth_request_ref(struct auth_request *request);
 void auth_request_unref(struct auth_request **request);
 
index d93498d260ae1346abfb05f85506ea0837e05aa9..0eb2fc3f7a368a56876124a5660dfe09ea11908b 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "settings-parser.h"
+#include "master-service.h"
 #include "master-service-settings.h"
 #include "service-settings.h"
 #include "auth-settings.h"
@@ -305,19 +306,25 @@ auth_userdb_settings_check(void *_set, pool_t pool ATTR_UNUSED,
 
 struct auth_settings *global_auth_settings;
 
-struct auth_settings *
-auth_settings_read(struct master_service *service)
+struct auth_settings *auth_settings_read(const char *service)
 {
        static const struct setting_parser_info *set_roots[] = {
                &auth_setting_parser_info,
                NULL
        };
+       struct master_service_settings_input input;
+       struct master_service_settings_output output;
        const char *error;
        void **sets;
 
-       if (master_service_settings_read_simple(service, set_roots, &error) < 0)
+       memset(&input, 0, sizeof(input));
+       input.roots = set_roots;
+       input.module = "auth";
+       input.service = service;
+       if (master_service_settings_read(master_service, &input,
+                                        &output, &error) < 0)
                i_fatal("Error reading configuration: %s", error);
 
-       sets = master_service_settings_get_others(service);
+       sets = master_service_settings_get_others(master_service);
        return sets[0];
 }
index bd7b7df4938f47199c2a532f813de2fc7c271943..fc7c4bf0d0de5fb4423cb3b9811788e585ed1546 100644 (file)
@@ -52,6 +52,6 @@ struct auth_settings {
 
 extern struct auth_settings *global_auth_settings;
 
-struct auth_settings *auth_settings_read(struct master_service *service);
+struct auth_settings *auth_settings_read(const char *service);
 
 #endif
index 7da14c45da64506bf49446e8070635e2bbd3ab35..f32791a5306e4d364bc4fa7e373e723570b45f32 100644 (file)
@@ -57,7 +57,7 @@ worker_auth_request_new(struct auth_worker_client *client, unsigned int id,
        struct auth_request *auth_request;
        const char *key, *value, *const *tmp;
 
-       auth_request = auth_request_new_dummy(client->auth);
+       auth_request = auth_request_new_dummy();
 
        client->refcount++;
        auth_request->context = client;
@@ -76,6 +76,7 @@ worker_auth_request_new(struct auth_worker_client *client, unsigned int id,
                }
        }
 
+       auth_request_init(auth_request);
        return auth_request;
 }
 
@@ -170,7 +171,7 @@ auth_worker_handle_passv(struct auth_worker_client *client,
 
        if (passdb == NULL) {
                /* could be a masterdb */
-               passdb = auth_request->auth->masterdbs;
+               passdb = auth_request_get_auth(auth_request)->masterdbs;
                while (passdb != NULL && passdb->passdb->id != passdb_id)
                        passdb = passdb->next;
 
index e9a535f2bc7d6bbed292013dad37ac95e80a8d6b..725fc9acfa52dbef80e262e1b0f8958e02efa21d 100644 (file)
@@ -20,6 +20,8 @@ struct auth_userdb_settings userdb_dummy_set = {
        .args = ""
 };
 
+static ARRAY_DEFINE(auths, struct auth *);
+
 static void
 auth_passdb_preinit(struct auth *auth, const struct auth_passdb_settings *set)
 {
@@ -51,7 +53,8 @@ auth_userdb_preinit(struct auth *auth, const struct auth_userdb_settings *set)
 }
 
 struct auth *
-auth_preinit(struct auth_settings *set, const struct mechanisms_register *reg)
+auth_preinit(const struct auth_settings *set, const char *service,
+            const struct mechanisms_register *reg)
 {
        struct auth_passdb_settings *const *passdbs;
        struct auth_userdb_settings *const *userdbs;
@@ -62,6 +65,7 @@ auth_preinit(struct auth_settings *set, const struct mechanisms_register *reg)
        pool = pool_alloconly_create("auth", 2048);
        auth = p_new(pool, struct auth, 1);
        auth->pool = pool;
+       auth->service = p_strdup(pool, service);
        auth->set = set;
        auth->reg = reg;
 
@@ -227,3 +231,63 @@ void auth_deinit(struct auth **_auth)
 
        pool_unref(&auth->pool);
 }
+
+struct auth *auth_find_service(const char *name)
+{
+       struct auth *const *a;
+       unsigned int i, count;
+
+       a = array_get(&auths, &count);
+       if (name != NULL) {
+               for (i = 1; i < count; i++) {
+                       if (strcmp(a[i]->service, name) == 0)
+                               return a[i];
+               }
+       }
+       return a[0];
+}
+
+void auths_preinit(const struct auth_settings *set,
+                  const struct mechanisms_register *reg)
+{
+       static const char *services[] = {
+               "imap", "pop3", "lda", "lmtp", "managesieve"
+       };
+       const struct auth_settings *service_set;
+       struct auth *auth;
+       unsigned int i;
+
+       i_array_init(&auths, 8);
+
+       auth = auth_preinit(set, NULL, reg);
+       array_append(&auths, &auth, 1);
+
+       /* FIXME: this is ugly.. the service names should be coming from
+          the first config lookup */
+       for (i = 0; i < N_ELEMENTS(services); i++) {
+               service_set = auth_settings_read(services[i]);
+               auth = auth_preinit(service_set, services[i], reg);
+               array_append(&auths, &auth, 1);
+       }
+}
+
+void auths_init(void)
+{
+       struct auth *const *auth;
+
+       array_foreach(&auths, auth)
+               auth_init(*auth);
+}
+
+void auths_deinit(void)
+{
+       struct auth **auth;
+       unsigned int i, count;
+
+       /* deinit in reverse order, because modules have been allocated by
+          the first auth pool that used them */
+       auth = array_get_modifiable(&auths, &count);
+       for (i = count; i > 0; i--)
+               auth_deinit(&auth[i-1]);
+       array_free(&auths);
+}
index 14128394eed065f6fab3018cf586bc3601e59b3a..69b3d00245183bef390603d73c8c831ec0da61e2 100644 (file)
@@ -21,6 +21,7 @@ struct auth_userdb {
 
 struct auth {
        pool_t pool;
+       const char *service;
        const struct auth_settings *set;
 
        const struct mechanisms_register *reg;
@@ -29,9 +30,19 @@ struct auth {
        struct auth_userdb *userdbs;
 };
 
+extern struct auth_penalty *auth_penalty;
+
 struct auth *
-auth_preinit(struct auth_settings *set, const struct mechanisms_register *reg);
+auth_preinit(const struct auth_settings *set, const char *service,
+            const struct mechanisms_register *mech_reg);
 void auth_init(struct auth *auth);
 void auth_deinit(struct auth **auth);
 
+struct auth *auth_find_service(const char *name);
+
+void auths_preinit(const struct auth_settings *set,
+                  const struct mechanisms_register *reg);
+void auths_init(void);
+void auths_deinit(void);
+
 #endif
index b5e45360b8fac7da0f1e3d0083990affffff82e4..d0aa5bce9ae66def93e405219fd239a1e6dbc157 100644 (file)
@@ -1085,7 +1085,7 @@ db_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
                ctx->static_attrs = t_strsplit(str_c(str), ",");
        }
 
-       if (auth_request->auth->set->debug)
+       if (auth_request->set->debug)
                ctx->debug = t_str_new(256);
 
        ctx->attr = ldap_first_attribute(conn->ld, entry, &ctx->ber);
@@ -1157,7 +1157,7 @@ db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx)
        if (ctx->debug != NULL) {
                if (!first)
                        str_append_c(ctx->debug, '/');
-               if (ctx->auth_request->auth->set->debug_passwords ||
+               if (ctx->auth_request->set->debug_passwords ||
                    strcmp(ctx->name, "password") != 0)
                        str_append(ctx->debug, ctx->value);
                else
index 4decdf4b1971c442db97c5f378d5bb6c0cdddeba..fd2f9e97f00e6e5ad1b55995bacdcfe8376cee58 100644 (file)
@@ -38,7 +38,6 @@ time_t process_start_time;
 struct auth_penalty *auth_penalty;
 
 static struct module *modules = NULL;
-static struct auth *auth;
 static struct mechanisms_register *mech_reg;
 static ARRAY_DEFINE(listen_fd_types, enum auth_socket_type);
 
@@ -66,10 +65,10 @@ static void main_preinit(void)
        modules = module_dir_load(AUTH_MODULE_DIR, NULL, &mod_set);
        module_dir_init(modules);
 
+       auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
        mech_init(global_auth_settings);
        mech_reg = mech_register_init(global_auth_settings);
-       auth = auth_preinit(global_auth_settings, mech_reg);
-       auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
+       auths_preinit(global_auth_settings, mech_reg);
 
        /* Password lookups etc. may require roots, allow it. */
        restrict_access_by_env(NULL, FALSE);
@@ -89,7 +88,7 @@ static void main_init(void)
        child_wait_init();
        password_schemes_init();
        auth_worker_server_init();
-       auth_init(auth);
+       auths_init();
        auth_request_handler_init();
        auth_master_connections_init();
        auth_client_connections_init();
@@ -112,8 +111,8 @@ static void main_deinit(void)
        auth_master_connections_deinit();
         auth_worker_server_deinit();
 
-       mech_deinit(auth->set);
-       auth_deinit(&auth);
+       mech_deinit(global_auth_settings);
+       auths_deinit();
        mech_register_deinit(&mech_reg);
        auth_penalty_deinit(&auth_penalty);
 
@@ -137,13 +136,15 @@ static void worker_connected(const struct master_service_connection *conn)
                (void)close(conn->fd);
                return;
        }
-       (void)auth_worker_client_create(auth, conn->fd);
+
+       (void)auth_worker_client_create(auth_find_service(NULL), conn->fd);
 }
 
 static void client_connected(const struct master_service_connection *conn)
 {
        enum auth_socket_type *type;
        const char *name, *suffix;
+       struct auth *auth;
 
        type = array_idx_modifiable(&listen_fd_types, conn->listen_fd);
        if (*type == AUTH_SOCKET_UNKNOWN) {
@@ -166,6 +167,7 @@ static void client_connected(const struct master_service_connection *conn)
                }
        }
 
+       auth = auth_find_service(NULL);
        switch (*type) {
        case AUTH_SOCKET_MASTER:
                (void)auth_master_connection_create(auth, conn->fd, FALSE);
@@ -198,7 +200,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       global_auth_settings = auth_settings_read(master_service);
+       global_auth_settings = auth_settings_read(NULL);
        main_preinit();
 
        master_service_init_finish(master_service);
index 1caa1a41589674872d7003ea503288dcccd531d5..8ab5296dabae2679ee7eb1dcb873842ad0bae9ce 100644 (file)
@@ -7,9 +7,9 @@ static void
 mech_anonymous_auth_continue(struct auth_request *request,
                             const unsigned char *data, size_t data_size)
 {
-       i_assert(*request->auth->set->anonymous_username != '\0');
+       i_assert(*request->set->anonymous_username != '\0');
 
-       if (request->auth->set->verbose) {
+       if (request->set->verbose) {
                /* temporarily set the user to the one that was given,
                   so that the log message goes right */
                request->user =
@@ -18,7 +18,7 @@ mech_anonymous_auth_continue(struct auth_request *request,
        }
 
        request->user = p_strdup(request->pool,
-                                request->auth->set->anonymous_username);
+                                request->set->anonymous_username);
 
        auth_request_success(request, NULL, 0);
 }
index 07976f929396795b3d0b15cc7018929d41840a8f..42a668bd96b575caeb77c412559b6b82902893d1 100644 (file)
@@ -56,7 +56,7 @@ struct digest_auth_request {
 
 static string_t *get_digest_challenge(struct digest_auth_request *request)
 {
-       struct auth *auth = request->auth_request.auth;
+       const struct auth_settings *set = request->auth_request.set;
        buffer_t buf;
        string_t *str;
        const char *const *tmp;
@@ -84,12 +84,12 @@ static string_t *get_digest_challenge(struct digest_auth_request *request)
        request->nonce = p_strdup(request->pool, buf.data);
 
        str = t_str_new(256);
-       if (*auth->set->realms_arr == NULL) {
+       if (*set->realms_arr == NULL) {
                /* If no realms are given, at least Cyrus SASL client defaults
                   to destination host name */
                str_append(str, "realm=\"\",");
        } else {
-               for (tmp = auth->set->realms_arr; *tmp != NULL; tmp++)
+               for (tmp = set->realms_arr; *tmp != NULL; tmp++)
                        str_printfa(str, "realm=\"%s\",", *tmp);
        }
 
index 54864951654a77dcb9bd4f895dbcb01b88c3483b..7cab58862e5398a69c0ae5b85c872fdddbfe435b 100644 (file)
@@ -143,7 +143,7 @@ obtain_service_credentials(struct auth_request *request, gss_cred_id_t *ret_r)
                mech_gssapi_initialize(request->auth);
        }
 
-       if (strcmp(request->auth->set->gssapi_hostname, "$ALL") == 0) {
+       if (strcmp(request->set->gssapi_hostname, "$ALL") == 0) {
                auth_request_log_debug(request, "gssapi",
                                       "Using all keytab entries");
                *ret_r = GSS_C_NO_CREDENTIAL;
@@ -161,7 +161,7 @@ obtain_service_credentials(struct auth_request *request, gss_cred_id_t *ret_r)
        principal_name = t_str_new(128);
        str_append(principal_name, service_name);
        str_append_c(principal_name, '@');
-       str_append(principal_name, request->auth->set->gssapi_hostname);
+       str_append(principal_name, request->set->gssapi_hostname);
 
        auth_request_log_debug(request, "gssapi",
                "Obtaining credentials for %s", str_c(principal_name));
index 4977995e4dc1dc70dea2168ed2b9dd28a914dfdc..cbe70705483039af7666ede09772db58dbca8b71 100644 (file)
@@ -329,7 +329,7 @@ rpa_add_realm(string_t *realms, const char *realm, const char *service)
 static const unsigned char *
 mech_rpa_build_token2(struct rpa_auth_request *request, size_t *size)
 {
-       struct auth *auth = request->auth_request.auth;
+       const struct auth_settings *set = request->auth_request.set;
        unsigned int realms_len, length;
        string_t *realms;
        buffer_t *buf;
@@ -337,13 +337,13 @@ mech_rpa_build_token2(struct rpa_auth_request *request, size_t *size)
        const char *const *tmp;
 
        realms = t_str_new(64);
-       for (tmp = auth->set->realms_arr; *tmp != NULL; tmp++) {
+       for (tmp = set->realms_arr; *tmp != NULL; tmp++) {
                rpa_add_realm(realms, *tmp, request->auth_request.service);
        }
 
        if (str_len(realms) == 0) {
-               rpa_add_realm(realms, *auth->set->default_realm != '\0' ?
-                             auth->set->default_realm : my_hostname,
+               rpa_add_realm(realms, *set->default_realm != '\0' ?
+                             set->default_realm : my_hostname,
                              request->auth_request.service);
        }
 
index daef851a15e11325d58a5b5eb5e56dd93dbaab4e..357080d9a0688b743a5e44abd604a9fa5890a76d 100644 (file)
@@ -96,7 +96,8 @@ static void sigchld_handler(const siginfo_t *si ATTR_UNUSED,
 }
 
 static void
-winbind_helper_connect(struct auth *auth, struct winbind_helper *winbind)
+winbind_helper_connect(const struct auth_settings *set,
+                      struct winbind_helper *winbind)
 {
        int infd[2], outfd[2];
        pid_t pid;
@@ -132,7 +133,7 @@ winbind_helper_connect(struct auth *auth, struct winbind_helper *winbind)
                    dup2(infd[1], STDOUT_FILENO) < 0)
                        i_fatal("dup2() failed: %m");
 
-               args[0] = auth->set->winbind_helper_path;
+               args[0] = set->winbind_helper_path;
                args[1] = winbind->param;
                args[2] = NULL;
                execv(args[0], (void *)args);
@@ -284,7 +285,7 @@ mech_winbind_auth_initial(struct auth_request *auth_request,
        struct winbind_auth_request *request =
                (struct winbind_auth_request *)auth_request;
 
-       winbind_helper_connect(auth_request->auth, request->winbind);
+       winbind_helper_connect(auth_request->set, request->winbind);
        mech_generic_auth_initial(auth_request, data, data_size);
 }
 
index 54e4c7305d9a88562272068675cb3451c189ee62..b4cb1ceae1654d002e269abc670f4ee3a011612e 100644 (file)
@@ -14,7 +14,7 @@ passdb_cache_log_hit(struct auth_request *request, const char *value)
 {
        const char *p;
 
-       if (!request->auth->set->debug_passwords &&
+       if (!request->set->debug_passwords &&
            *value != '\0' && *value != '\t') {
                /* hide the password */
                p = strchr(value, '\t');
index b93e524721eac78d0c820b32237231751df33f93..f090f396077cd01c28676f5fe1c013a454dc0829 100644 (file)
@@ -145,7 +145,7 @@ ldap_auth_bind_callback(struct ldap_connection *conn,
                        passdb_result = PASSDB_RESULT_OK;
                else if (ret == LDAP_INVALID_CREDENTIALS) {
                        str = "invalid credentials";
-                       if (auth_request->auth->set->debug_passwords) {
+                       if (auth_request->set->debug_passwords) {
                                str = t_strconcat(str, " (given password: ",
                                                  auth_request->mech_password,
                                                  ")", NULL);
index 0a6b1468d83436c02102e316f5c5923774b915b8..a560f28058bf35bc9343e3d5ce9d23267102c3b9 100644 (file)
@@ -174,7 +174,7 @@ static int try_pam_auth(struct auth_request *request, pam_handle_t *pamh,
                        auth_request_log_error(request, "pam", "%s", str);
                } else if (status == PAM_AUTH_ERR) {
                        str = t_strconcat(str, " (password mismatch?)", NULL);
-                       if (request->auth->set->debug_passwords) {
+                       if (request->set->debug_passwords) {
                                str = t_strconcat(str, " (given password: ",
                                                  request->mech_password,
                                                  ")", NULL);
index bf7b8c7b01edb9eef87fc7bde8740d5dc13a79e0..4c9304173085253dcc160fc8f15d739d73c1686b 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 
 static ARRAY_DEFINE(passdb_interfaces, struct passdb_module_interface *);
+static ARRAY_DEFINE(passdb_modules, struct passdb_module *);
 
 static struct passdb_module_interface *passdb_interface_find(const char *name)
 {
@@ -94,7 +95,7 @@ bool passdb_get_credentials(struct auth_request *auth_request,
                        const char *error = t_strdup_printf(
                                "Requested %s scheme, but we have only %s",
                                wanted_scheme, input_scheme);
-                       if (auth_request->auth->set->debug_passwords) {
+                       if (auth_request->set->debug_passwords) {
                                error = t_strdup_printf("%s (input: %s)",
                                                        error, input);
                        }
@@ -112,7 +113,7 @@ bool passdb_get_credentials(struct auth_request *auth_request,
                        username = t_strconcat(username, "@",
                                               auth_request->realm, NULL);
                }
-               if (auth_request->auth->set->debug_passwords) {
+               if (auth_request->set->debug_passwords) {
                        auth_request_log_debug(auth_request, "password",
                                "Generating %s from user '%s', password '%s'",
                                wanted_scheme, username, plaintext);
@@ -154,12 +155,30 @@ void passdb_handle_credentials(enum passdb_result result,
        callback(result, credentials, size, auth_request);
 }
 
+static struct passdb_module *
+passdb_find(const char *driver, const char *args, unsigned int *idx_r)
+{
+       struct passdb_module *const *passdbs;
+       unsigned int i, count;
+
+       passdbs = array_get(&passdb_modules, &count);
+       for (i = 0; i < count; i++) {
+               if (strcmp(passdbs[i]->iface.name, driver) == 0 &&
+                   strcmp(passdbs[i]->args, args) == 0) {
+                       *idx_r = i;
+                       return passdbs[i];
+               }
+       }
+       return NULL;
+}
+
 struct passdb_module *
 passdb_preinit(pool_t pool, const char *driver, const char *args)
 {
        static unsigned int auth_passdb_id = 0;
        struct passdb_module_interface *iface;
        struct passdb_module *passdb;
+       unsigned int idx;
 
        iface = passdb_interface_find(driver);
        if (iface == NULL)
@@ -168,10 +187,13 @@ passdb_preinit(pool_t pool, const char *driver, const char *args)
                i_fatal("Support not compiled in for passdb driver '%s'",
                        driver);
        }
-
        if (iface->preinit == NULL && iface->init == NULL && *args != '\0')
                i_fatal("passdb %s: No args are supported: %s", driver, args);
 
+       passdb = passdb_find(driver, args, &idx);
+       if (passdb != NULL)
+               return passdb;
+
        if (iface->preinit == NULL)
                passdb = p_new(pool, struct passdb_module, 1);
        else
@@ -179,15 +201,15 @@ passdb_preinit(pool_t pool, const char *driver, const char *args)
        passdb->id = ++auth_passdb_id;
        passdb->iface = *iface;
        passdb->args = p_strdup(pool, args);
+       array_append(&passdb_modules, &passdb, 1);
        return passdb;
 }
 
 void passdb_init(struct passdb_module *passdb)
 {
-       if (passdb->iface.init != NULL && !passdb->initialized) {
-               passdb->initialized = TRUE;
+       if (passdb->iface.init != NULL && passdb->init_refcount == 0)
                passdb->iface.init(passdb);
-       }
+       passdb->init_refcount++;
 
        i_assert(passdb->default_pass_scheme != NULL ||
                 passdb->cache_key == NULL);
@@ -195,7 +217,16 @@ void passdb_init(struct passdb_module *passdb)
 
 void passdb_deinit(struct passdb_module *passdb)
 {
-       i_assert(passdb->initialized);
+       unsigned int idx;
+
+       i_assert(passdb->init_refcount > 0);
+
+       if (--passdb->init_refcount > 0)
+               return;
+
+       if (passdb_find(passdb->iface.name, passdb->args, &idx) == NULL)
+               i_unreached();
+       array_delete(&passdb_modules, idx, 1);
 
        if (passdb->iface.deinit != NULL)
                passdb->iface.deinit(passdb);
@@ -215,6 +246,7 @@ extern struct passdb_module_interface passdb_sia;
 void passdbs_init(void)
 {
        i_array_init(&passdb_interfaces, 16);
+       i_array_init(&passdb_modules, 16);
        passdb_register_module(&passdb_passwd);
        passdb_register_module(&passdb_bsdauth);
        passdb_register_module(&passdb_passwd_file);
@@ -229,5 +261,6 @@ void passdbs_init(void)
 
 void passdbs_deinit(void)
 {
+       array_free(&passdb_modules);
        array_free(&passdb_interfaces);
 }
index e4cc5813842235131e7f93d71bb21399ee972ad8..a83105bf650ae8f5a1c23194daf6a8af67c4056a 100644 (file)
@@ -62,10 +62,10 @@ struct passdb_module {
         /* id is used by blocking passdb to identify the passdb */
        unsigned int id;
 
-       struct passdb_module_interface iface;
+       /* number of time init() has been called */
+       int init_refcount;
 
-       /* init() has been called */
-       unsigned int initialized:1;
+       struct passdb_module_interface iface;
 };
 
 /* Try to get credentials in wanted scheme (request->credentials_scheme) from
index 58776b8bad12fa5f03f8b0b9f06ef1fc01903218..d31d8b2d12b0a29b09665d2559e4d66cf283e79e 100644 (file)
@@ -193,7 +193,7 @@ userdb_ldap_iterate_init(struct userdb_module *userdb,
        request = &ctx->request;
        request->ctx = ctx;
 
-       request->request.request.auth_request = auth_request_new_dummy(NULL);
+       request->request.request.auth_request = auth_request_new_dummy();
        request->request.base = conn->set.base;
        request->request.filter = conn->set.iterate_filter;
        request->request.attributes = conn->iterate_attr_names;
index 6403d7ac4781dfcc0c5d8fd4a01785103b9943b9..bbdf280c0a145056b981d5cc688e5c1d33df64fa 100644 (file)
@@ -16,7 +16,7 @@ static void prefetch_lookup(struct auth_request *auth_request,
        /* auth_request_set_field() should have already placed the userdb_*
           values to userdb_reply. */
        if (auth_request->userdb_reply == NULL) {
-               if (auth_request->auth->userdbs->next == NULL) {
+               if (auth_request_get_auth(auth_request)->userdbs->next == NULL) {
                        /* no other userdbs */
                        if (auth_request->userdb_lookup) {
                                auth_request_log_error(auth_request, "prefetch",
@@ -26,7 +26,7 @@ static void prefetch_lookup(struct auth_request *auth_request,
                                        "passdb didn't return userdb entries");
                        }
                } else if (!auth_request->userdb_lookup ||
-                          auth_request->auth->set->debug) {
+                          auth_request->set->debug) {
                        /* more userdbs, they may know the user */
                        auth_request_log_debug(auth_request, "prefetch",
                                "passdb didn't return userdb entries, "
index fc22c26ee9b6f9ccc5d722c918679e7570e48b47..7480e9fc01d5f07d70a11e358ebd5cc0c488ef26 100644 (file)
@@ -10,6 +10,7 @@
 #include <grp.h>
 
 static ARRAY_DEFINE(userdb_interfaces, struct userdb_module_interface *);
+static ARRAY_DEFINE(userdb_modules, struct userdb_module *);
 
 static struct userdb_module_interface *userdb_interface_find(const char *name)
 {
@@ -106,12 +107,30 @@ gid_t userdb_parse_gid(struct auth_request *request, const char *str)
        return gr->gr_gid;
 }
 
+static struct userdb_module *
+userdb_find(const char *driver, const char *args, unsigned int *idx_r)
+{
+       struct userdb_module *const *userdbs;
+       unsigned int i, count;
+
+       userdbs = array_get(&userdb_modules, &count);
+       for (i = 0; i < count; i++) {
+               if (strcmp(userdbs[i]->iface->name, driver) == 0 &&
+                   strcmp(userdbs[i]->args, args) == 0) {
+                       *idx_r = i;
+                       return userdbs[i];
+               }
+       }
+       return NULL;
+}
+
 struct userdb_module *
 userdb_preinit(pool_t pool, const char *driver, const char *args)
 {
        static unsigned int auth_userdb_id = 0;
        struct userdb_module_interface *iface;
        struct userdb_module *userdb;
+       unsigned int idx;
 
        iface = userdb_interface_find(driver);
        if (iface == NULL)
@@ -120,10 +139,13 @@ userdb_preinit(pool_t pool, const char *driver, const char *args)
                i_fatal("Support not compiled in for userdb driver '%s'",
                        driver);
        }
-
        if (iface->preinit == NULL && iface->init == NULL && *args != '\0')
                i_fatal("userdb %s: No args are supported: %s", driver, args);
 
+       userdb = userdb_find(driver, args, &idx);
+       if (userdb != NULL)
+               return userdb;
+
        if (iface->preinit == NULL)
                userdb = p_new(pool, struct userdb_module, 1);
        else
@@ -131,20 +153,30 @@ userdb_preinit(pool_t pool, const char *driver, const char *args)
        userdb->id = ++auth_userdb_id;
        userdb->iface = iface;
        userdb->args = p_strdup(pool, args);
+       array_append(&userdb_modules, &userdb, 1);
        return userdb;
 }
 
 void userdb_init(struct userdb_module *userdb)
 {
-       if (userdb->iface->init != NULL && !userdb->initialized) {
-               userdb->initialized = TRUE;
+       if (userdb->iface->init != NULL && userdb->init_refcount == 0)
                userdb->iface->init(userdb);
-       }
+       userdb->init_refcount++;
 }
 
 void userdb_deinit(struct userdb_module *userdb)
 {
-       i_assert(userdb->initialized);
+       unsigned int idx;
+
+       i_assert(userdb->init_refcount > 0);
+
+       if (--userdb->init_refcount > 0)
+               return;
+
+       if (userdb_find(userdb->iface->name, userdb->args, &idx) == NULL)
+               i_unreached();
+       array_delete(&userdb_modules, idx, 1);
+
        if (userdb->iface->deinit != NULL)
                userdb->iface->deinit(userdb);
 }
@@ -162,6 +194,7 @@ extern struct userdb_module_interface userdb_checkpassword;
 void userdbs_init(void)
 {
        i_array_init(&userdb_interfaces, 16);
+       i_array_init(&userdb_modules, 16);
        userdb_register_module(&userdb_passwd);
        userdb_register_module(&userdb_passwd_file);
        userdb_register_module(&userdb_prefetch);
@@ -175,5 +208,6 @@ void userdbs_init(void)
 
 void userdbs_deinit(void)
 {
+       array_free(&userdb_modules);
        array_free(&userdb_interfaces);
 }
index e1933e72d5ffe3d94cacbfd97c6b2ea973edcfed..928afaf8f48b6e02868c707a2ba21b420d98976d 100644 (file)
@@ -29,10 +29,10 @@ struct userdb_module {
         /* id is used by blocking userdb to identify the userdb */
        unsigned int id;
 
-       const struct userdb_module_interface *iface;
+       /* number of time init() has been called */
+       int init_refcount;
 
-       /* init() has been called */
-       unsigned int initialized:1;
+       const struct userdb_module_interface *iface;
 };
 
 struct userdb_iterate_context {