From: Timo Sirainen Date: Fri, 19 Mar 2010 15:24:22 +0000 (+0200) Subject: auth: Fixed support for per-service auth settings. X-Git-Tag: 2.0.beta4~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5d60e31c7b701b606067a20bc88dcc8a6de7bbd6;p=thirdparty%2Fdovecot%2Fcore.git auth: Fixed support for per-service auth settings. --HG-- branch : HEAD --- diff --git a/src/auth/auth-settings.c b/src/auth/auth-settings.c index 48bac1cc21..714eaf9f42 100644 --- a/src/auth/auth-settings.c +++ b/src/auth/auth-settings.c @@ -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 -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]; } diff --git a/src/auth/auth-settings.h b/src/auth/auth-settings.h index fc7c4bf0d0..55dea737eb 100644 --- a/src/auth/auth-settings.h +++ b/src/auth/auth-settings.h @@ -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 diff --git a/src/auth/auth.c b/src/auth/auth.c index 7c2c4774a1..2a71dd308d 100644 --- a/src/auth/auth.c +++ b/src/auth/auth.c @@ -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); } } diff --git a/src/auth/auth.h b/src/auth/auth.h index 69b3d00245..2f8ab37b0e 100644 --- a/src/auth/auth.h +++ b/src/auth/auth.h @@ -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); diff --git a/src/auth/main.c b/src/auth/main.c index 76d06285f4..538c3223fb 100644 --- a/src/auth/main.c +++ b/src/auth/main.c @@ -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 :