]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Fixed support for per-service auth settings.
authorTimo Sirainen <tss@iki.fi>
Fri, 19 Mar 2010 15:24:22 +0000 (17:24 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 19 Mar 2010 15:24:22 +0000 (17:24 +0200)
--HG--
branch : HEAD

src/auth/auth-settings.c
src/auth/auth-settings.h
src/auth/auth.c
src/auth/auth.h
src/auth/main.c

index 48bac1cc21cce656413cb51047f82357df7bbe09..714eaf9f425bc3f1bfdd9a8e3db91e64539f85b5 100644 (file)
@@ -3,16 +3,13 @@
 #include "lib.h"
 #include "array.h"
 #include "settings-parser.h"
-#include "master-service.h"
+#include "master-service-private.h"
 #include "master-service-settings.h"
 #include "service-settings.h"
 #include "auth-settings.h"
 
 #include <stddef.h>
 
-extern const struct setting_parser_info auth_setting_parser_info;
-extern const struct setting_parser_info auth_root_setting_parser_info;
-
 static bool auth_settings_check(void *_set, pool_t pool, const char **error_r);
 static bool auth_passdb_settings_check(void *_set, pool_t pool, const char **error_r);
 static bool auth_userdb_settings_check(void *_set, pool_t pool, const char **error_r);
@@ -306,25 +303,29 @@ auth_userdb_settings_check(void *_set, pool_t pool ATTR_UNUSED,
 
 struct auth_settings *global_auth_settings;
 
-struct auth_settings *auth_settings_read(const char *service)
+struct auth_settings *
+auth_settings_read(const char *service, pool_t pool,
+                  struct master_service_settings_output *output_r)
 {
        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;
+       struct setting_parser_context *set_parser;
        const char *error;
-       void **sets;
 
        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)
+                                        output_r, &error) < 0)
                i_fatal("Error reading configuration: %s", error);
 
-       sets = master_service_settings_get_others(master_service);
-       return sets[0];
+       set_parser = settings_parser_dup(master_service->set_parser, pool);
+       if (!settings_parser_check(set_parser, pool, &error))
+               i_unreached();
+
+       return settings_parser_get_list(set_parser)[1];
 }
index fc7c4bf0d0de5fb4423cb3b9811788e585ed1546..55dea737ebfabe5098fdd91329a27aef00ddc1a0 100644 (file)
@@ -2,6 +2,7 @@
 #define AUTH_SETTINGS_H
 
 struct master_service;
+struct master_service_settings_output;
 
 struct auth_passdb_settings {
        const char *driver;
@@ -50,8 +51,11 @@ struct auth_settings {
        const char *const *realms_arr;
 };
 
+extern const struct setting_parser_info auth_setting_parser_info;
 extern struct auth_settings *global_auth_settings;
 
-struct auth_settings *auth_settings_read(const char *service);
+struct auth_settings *
+auth_settings_read(const char *service, pool_t pool,
+                  struct master_service_settings_output *output_r);
 
 #endif
index 7c2c4774a1e07d9c84e49c61f50d0a1d77949baa..2a71dd308def710a9ef0ff558c1f48bc39967212 100644 (file)
@@ -2,6 +2,8 @@
 
 #include "auth-common.h"
 #include "array.h"
+#include "settings-parser.h"
+#include "master-service-settings.h"
 #include "mech.h"
 #include "userdb.h"
 #include "passdb.h"
@@ -45,16 +47,14 @@ auth_userdb_preinit(struct auth *auth, const struct auth_userdb_settings *set)
 }
 
 struct auth *
-auth_preinit(const struct auth_settings *set, const char *service,
+auth_preinit(const struct auth_settings *set, const char *service, pool_t pool,
             const struct mechanisms_register *reg)
 {
        struct auth_passdb_settings *const *passdbs;
        struct auth_userdb_settings *const *userdbs;
        struct auth *auth;
-       pool_t pool;
        unsigned int i, count, db_count, passdb_count, last_passdb = 0;
 
-       pool = pool_alloconly_create("auth", 2048);
        auth = p_new(pool, struct auth, 1);
        auth->pool = pool;
        auth->service = p_strdup(pool, service);
@@ -228,30 +228,43 @@ struct auth *auth_find_service(const char *name)
                        if (strcmp(a[i]->service, name) == 0)
                                return a[i];
                }
+               /* not found. maybe we can instead find a !service */
+               for (i = 1; i < count; i++) {
+                       if (a[i]->service[0] == '!' &&
+                           strcmp(a[i]->service + 1, name) != 0)
+                               return a[i];
+               }
        }
        return a[0];
 }
 
-void auths_preinit(const struct auth_settings *set,
-                  const struct mechanisms_register *reg)
+void auths_preinit(const struct auth_settings *set, pool_t pool,
+                  const struct mechanisms_register *reg,
+                  const char *const *services)
 {
-       static const char *services[] = {
-               "imap", "pop3", "lda", "lmtp", "managesieve"
-       };
+       struct master_service_settings_output set_output;
        const struct auth_settings *service_set;
        struct auth *auth;
        unsigned int i;
+       const char *not_service = NULL;
 
        i_array_init(&auths, 8);
 
-       auth = auth_preinit(set, NULL, reg);
+       auth = auth_preinit(set, NULL, pool, 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);
+       for (i = 0; services[i] != NULL; i++) {
+               if (services[i][0] == '!') {
+                       if (not_service != NULL) {
+                               i_fatal("Can't have multiple protocol "
+                                       "!services (seen %s and %s)",
+                                       not_service, services[i]);
+                       }
+                       not_service = services[i];
+               }
+               service_set = auth_settings_read(services[i], pool,
+                                                &set_output);
+               auth = auth_preinit(service_set, services[i], pool, reg);
                array_append(&auths, &auth, 1);
        }
 }
index 69b3d00245183bef390603d73c8c831ec0da61e2..2f8ab37b0ee96a2dd1ed27e05af9d97c5464effe 100644 (file)
@@ -33,15 +33,16 @@ struct auth {
 extern struct auth_penalty *auth_penalty;
 
 struct auth *
-auth_preinit(const struct auth_settings *set, const char *service,
+auth_preinit(const struct auth_settings *set, const char *service, pool_t pool,
             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_preinit(const struct auth_settings *set, pool_t pool,
+                  const struct mechanisms_register *reg,
+                  const char *const *services);
 void auths_init(void);
 void auths_deinit(void);
 
index 76d06285f43c3e9feb852ed62bccb8ab0851fe91..538c3223fb7b7b1936fe03abeb1b04c3ecde1717 100644 (file)
@@ -10,7 +10,9 @@
 #include "sql-api.h"
 #include "module-dir.h"
 #include "randgen.h"
+#include "settings-parser.h"
 #include "master-service.h"
+#include "master-service-settings.h"
 #include "master-interface.h"
 #include "password-scheme.h"
 #include "passdb-cache.h"
@@ -38,13 +40,36 @@ bool worker = FALSE, shutdown_request = FALSE;
 time_t process_start_time;
 struct auth_penalty *auth_penalty;
 
+static pool_t auth_set_pool;
 static struct module *modules = NULL;
 static struct mechanisms_register *mech_reg;
 static ARRAY_DEFINE(listen_fd_types, enum auth_socket_type);
 
+static const char *const *read_global_settings(void)
+{
+       struct master_service_settings_output set_output;
+       const char **services;
+       unsigned int i, count;
+
+       auth_set_pool = pool_alloconly_create("auth settings", 8192);
+       global_auth_settings =
+               auth_settings_read(NULL, auth_set_pool, &set_output);
+
+       /* strdup() the service names, because they're allocated from
+          set parser pool, and we'll later clear it. */
+       count = str_array_length(set_output.specific_services);
+       services = p_new(auth_set_pool, const char *, count + 1);
+       for (i = 0; i < count; i++) {
+               services[i] = p_strdup(auth_set_pool,
+                                      set_output.specific_services[i]);
+       }
+       return services;
+}
+
 static void main_preinit(void)
 {
        struct module_dir_load_settings mod_set;
+       const char *const *services;
 
        /* Open /dev/urandom before chrooting */
        random_init();
@@ -58,6 +83,8 @@ static void main_preinit(void)
        passdbs_init();
        userdbs_init();
 
+       services = read_global_settings();
+
        memset(&mod_set, 0, sizeof(mod_set));
        mod_set.version = master_service_get_version_string(master_service);
        mod_set.require_init_funcs = TRUE;
@@ -69,7 +96,8 @@ static void main_preinit(void)
        auth_penalty = auth_penalty_init(AUTH_PENALTY_ANVIL_PATH);
        mech_init(global_auth_settings);
        mech_reg = mech_register_init(global_auth_settings);
-       auths_preinit(global_auth_settings, mech_reg);
+       auths_preinit(global_auth_settings, auth_set_pool,
+                     mech_reg, services);
 
        /* Password lookups etc. may require roots, allow it. */
        restrict_access_by_env(NULL, FALSE);
@@ -134,6 +162,7 @@ static void main_deinit(void)
        random_deinit();
 
        array_free(&listen_fd_types);
+       pool_unref(&auth_set_pool);
 }
 
 static void worker_connected(const struct master_service_connection *conn)
@@ -190,6 +219,7 @@ static void client_connected(const struct master_service_connection *conn)
        }
 }
 
+
 int main(int argc, char *argv[])
 {
        int c;
@@ -207,9 +237,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       global_auth_settings = auth_settings_read(NULL);
        main_preinit();
-
        master_service_init_finish(master_service);
        main_init();
        master_service_run(master_service, worker ? worker_connected :