Mercurial > dovecot > core-2.2
changeset 10903:6e639833c3fc HEAD
auth: Initial support for per-protocol auth settings.
Currently the list of services is hard-coded. This should be changed so that
config lookup returns the service names.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 13 Mar 2010 22:54:41 +0200 |
parents | 2b56c8b1e5ad |
children | 612db456c090 |
files | 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 |
diffstat | 27 files changed, 258 insertions(+), 96 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-client-connection.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-client-connection.c Sat Mar 13 22:54:41 2010 +0200 @@ -174,8 +174,7 @@ 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) {
--- a/src/auth/auth-master-connection.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-master-connection.c Sat Mar 13 22:54:41 2010 +0200 @@ -122,7 +122,7 @@ 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 @@ auth_request_unref(&auth_request); return -1; } + + auth_request_init(auth_request); *request_r = auth_request; return 1; }
--- a/src/auth/auth-request-handler.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-request-handler.c Sat Mar 13 22:54:41 2010 +0200 @@ -302,8 +302,7 @@ } } -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 @@ 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 @@ 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 @@ /* 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;
--- a/src/auth/auth-request-handler.h Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-request-handler.h Sat Mar 13 22:54:41 2010 +0200 @@ -29,8 +29,7 @@ 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);
--- a/src/auth/auth-request.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-request.c Sat Mar 13 22:54:41 2010 +0200 @@ -30,20 +30,18 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } /* 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 @@ 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 @@ 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 @@ { va_list va; - if (!auth_request->auth->set->debug) + if (!auth_request->set->debug) return; va_start(va, format); @@ -1548,7 +1554,7 @@ { va_list va; - if (!auth_request->auth->set->verbose) + if (!auth_request->set->verbose) return; va_start(va, format);
--- a/src/auth/auth-request.h Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-request.h Sat Mar 13 22:54:41 2010 +0200 @@ -56,7 +56,7 @@ 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 * -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);
--- a/src/auth/auth-settings.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-settings.c Sat Mar 13 22:54:41 2010 +0200 @@ -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 @@ 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]; }
--- a/src/auth/auth-settings.h Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-settings.h Sat Mar 13 22:54:41 2010 +0200 @@ -52,6 +52,6 @@ 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
--- a/src/auth/auth-worker-client.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth-worker-client.c Sat Mar 13 22:54:41 2010 +0200 @@ -57,7 +57,7 @@ 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 @@ } } + auth_request_init(auth_request); return auth_request; } @@ -170,7 +171,7 @@ 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;
--- a/src/auth/auth.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth.c Sat Mar 13 22:54:41 2010 +0200 @@ -20,6 +20,8 @@ .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 @@ } 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 @@ 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 @@ 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); +}
--- a/src/auth/auth.h Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/auth.h Sat Mar 13 22:54:41 2010 +0200 @@ -21,6 +21,7 @@ struct auth { pool_t pool; + const char *service; const struct auth_settings *set; const struct mechanisms_register *reg; @@ -29,9 +30,19 @@ 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
--- a/src/auth/db-ldap.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/db-ldap.c Sat Mar 13 22:54:41 2010 +0200 @@ -1085,7 +1085,7 @@ 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 @@ 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
--- a/src/auth/main.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/main.c Sat Mar 13 22:54:41 2010 +0200 @@ -38,7 +38,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ } } + auth = auth_find_service(NULL); switch (*type) { case AUTH_SOCKET_MASTER: (void)auth_master_connection_create(auth, conn->fd, FALSE); @@ -198,7 +200,7 @@ } } - global_auth_settings = auth_settings_read(master_service); + global_auth_settings = auth_settings_read(NULL); main_preinit(); master_service_init_finish(master_service);
--- a/src/auth/mech-anonymous.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/mech-anonymous.c Sat Mar 13 22:54:41 2010 +0200 @@ -7,9 +7,9 @@ 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 @@ } request->user = p_strdup(request->pool, - request->auth->set->anonymous_username); + request->set->anonymous_username); auth_request_success(request, NULL, 0); }
--- a/src/auth/mech-digest-md5.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/mech-digest-md5.c Sat Mar 13 22:54:41 2010 +0200 @@ -56,7 +56,7 @@ 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 @@ 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); }
--- a/src/auth/mech-gssapi.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/mech-gssapi.c Sat Mar 13 22:54:41 2010 +0200 @@ -143,7 +143,7 @@ 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 @@ 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));
--- a/src/auth/mech-rpa.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/mech-rpa.c Sat Mar 13 22:54:41 2010 +0200 @@ -329,7 +329,7 @@ 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 @@ 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); }
--- a/src/auth/mech-winbind.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/mech-winbind.c Sat Mar 13 22:54:41 2010 +0200 @@ -96,7 +96,8 @@ } 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 @@ 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 @@ 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); }
--- a/src/auth/passdb-cache.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/passdb-cache.c Sat Mar 13 22:54:41 2010 +0200 @@ -14,7 +14,7 @@ { 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');
--- a/src/auth/passdb-ldap.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/passdb-ldap.c Sat Mar 13 22:54:41 2010 +0200 @@ -145,7 +145,7 @@ 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);
--- a/src/auth/passdb-pam.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/passdb-pam.c Sat Mar 13 22:54:41 2010 +0200 @@ -174,7 +174,7 @@ 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);
--- a/src/auth/passdb.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/passdb.c Sat Mar 13 22:54:41 2010 +0200 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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->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_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 @@ 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_deinit(void) { + array_free(&passdb_modules); array_free(&passdb_interfaces); }
--- a/src/auth/passdb.h Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/passdb.h Sat Mar 13 22:54:41 2010 +0200 @@ -62,10 +62,10 @@ /* 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
--- a/src/auth/userdb-ldap.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/userdb-ldap.c Sat Mar 13 22:54:41 2010 +0200 @@ -193,7 +193,7 @@ 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;
--- a/src/auth/userdb-prefetch.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/userdb-prefetch.c Sat Mar 13 22:54:41 2010 +0200 @@ -16,7 +16,7 @@ /* 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 @@ "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, "
--- a/src/auth/userdb.c Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/userdb.c Sat Mar 13 22:54:41 2010 +0200 @@ -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 @@ 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 @@ 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->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 @@ 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_deinit(void) { + array_free(&userdb_modules); array_free(&userdb_interfaces); }
--- a/src/auth/userdb.h Sat Mar 13 22:23:58 2010 +0200 +++ b/src/auth/userdb.h Sat Mar 13 22:54:41 2010 +0200 @@ -29,10 +29,10 @@ /* 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 {