Mercurial > dovecot > original-hg > dovecot-1.2
changeset 3064:2d33734b16d5 HEAD
Split auth_request* functions from mech.c to auth-request.c
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 07 Jan 2005 20:51:10 +0200 |
parents | a0fbf92b41c3 |
children | 29d83a8bb50d |
files | src/auth/Makefile.am src/auth/auth-cache.c src/auth/auth-client-connection.c src/auth/auth-master-connection.c src/auth/auth-request.c src/auth/auth-request.h src/auth/main.c src/auth/mech-anonymous.c src/auth/mech-apop.c src/auth/mech-cram-md5.c src/auth/mech-digest-md5.c src/auth/mech-login.c src/auth/mech-ntlm.c src/auth/mech-plain.c src/auth/mech-rpa.c src/auth/mech.c src/auth/mech.h src/auth/userdb.h |
diffstat | 18 files changed, 443 insertions(+), 410 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/Makefile.am Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/Makefile.am Fri Jan 07 20:51:10 2005 +0200 @@ -36,6 +36,7 @@ auth-client-connection.c \ auth-master-connection.c \ auth-module.c \ + auth-request.c \ db-ldap.c \ db-sql.c \ db-passwd-file.c \ @@ -76,6 +77,7 @@ auth-master-interface.h \ auth-master-connection.h \ auth-module.h \ + auth-request.h \ db-ldap.h \ db-sql.h \ db-passwd-file.h \
--- a/src/auth/auth-cache.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/auth-cache.c Fri Jan 07 20:51:10 2005 +0200 @@ -6,7 +6,7 @@ #include "str.h" #include "strescape.h" #include "var-expand.h" -#include "mech.h" +#include "auth-request.h" #include "auth-cache.h" #include <time.h>
--- a/src/auth/auth-client-connection.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/auth-client-connection.c Fri Jan 07 20:51:10 2005 +0200 @@ -11,7 +11,7 @@ #include "str.h" #include "str-sanitize.h" #include "safe-memset.h" -#include "mech.h" +#include "auth-request.h" #include "auth-client-connection.h" #include "auth-master-connection.h"
--- a/src/auth/auth-master-connection.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/auth-master-connection.c Fri Jan 07 20:51:10 2005 +0200 @@ -8,8 +8,8 @@ #include "istream.h" #include "ostream.h" #include "network.h" -#include "mech.h" #include "userdb.h" +#include "auth-request.h" #include "auth-master-interface.h" #include "auth-client-connection.h" #include "auth-master-connection.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/auth-request.c Fri Jan 07 20:51:10 2005 +0200 @@ -0,0 +1,317 @@ +/* Copyright (C) 2002-2005 Timo Sirainen */ + +#include "common.h" +#include "ioloop.h" +#include "buffer.h" +#include "hash.h" +#include "str.h" +#include "safe-memset.h" +#include "str-sanitize.h" +#include "var-expand.h" +#include "auth-request.h" +#include "auth-client-connection.h" +#include "auth-master-connection.h" +#include "passdb.h" +#include "passdb-cache.h" + +struct auth_request_extra { + struct auth_request *request; + string_t *str; + char *user_password, *password; +}; + +static buffer_t *auth_failures_buf; +static struct timeout *to_auth_failures; + +struct auth_request *auth_request_new(struct mech_module *mech) +{ + struct auth_request *request; + + request = mech->auth_new(); + if (request == NULL) + return NULL; + + request->mech = mech; + request->created = ioloop_time; + return request; +} + +void auth_request_destroy(struct auth_request *request) +{ + i_assert(request->refcount > 0); + + if (request->destroyed) + return; + request->destroyed = TRUE; + + if (request->conn != NULL) { + hash_remove(request->conn->auth_requests, + POINTER_CAST(request->id)); + } + auth_request_unref(request); +} + +void auth_request_success(struct auth_request *request, + const void *data, size_t data_size) +{ + request->successful = TRUE; + if (request->conn != NULL) { + request->callback(request, AUTH_CLIENT_RESULT_SUCCESS, + data, data_size); + } + + if (request->no_login || request->conn == NULL || + AUTH_MASTER_IS_DUMMY(request->conn->master)) { + /* we don't have master process, the request is no longer + needed */ + auth_request_destroy(request); + } +} + +void auth_request_fail(struct auth_request *request) +{ + if (request->no_failure_delay) { + /* passdb specifically requested to to delay the reply. */ + request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0); + auth_request_destroy(request); + return; + } + + /* failure. don't announce it immediately to avoid + a) timing attacks, b) flooding */ + if (auth_failures_buf->used > 0) { + const struct auth_request *const *requests; + + requests = auth_failures_buf->data; + requests += auth_failures_buf->used/sizeof(*requests)-1; + i_assert(*requests != request); + } + + buffer_append(auth_failures_buf, &request, sizeof(request)); + + /* make sure the request isn't found anymore */ + auth_request_ref(request); + auth_request_destroy(request); +} + +void auth_request_internal_failure(struct auth_request *request) +{ + request->internal_failure = TRUE; + auth_request_fail(request); +} + +void auth_request_ref(struct auth_request *request) +{ + request->refcount++; +} + +int auth_request_unref(struct auth_request *request) +{ + i_assert(request->refcount > 0); + if (--request->refcount > 0) + return TRUE; + + request->mech->auth_free(request); + return FALSE; +} + +struct auth_request_extra * +auth_request_extra_begin(struct auth_request *request, + const char *user_password) +{ + struct auth_request_extra *extra; + + extra = i_new(struct auth_request_extra, 1); + extra->request = request; + extra->user_password = i_strdup(user_password); + return extra; +} + +void auth_request_extra_next(struct auth_request_extra *extra, + const char *name, const char *value) +{ + string_t *str; + + i_assert(value != NULL); + + if (strcmp(name, "password") == 0) { + i_assert(extra->password == NULL); + extra->password = i_strdup(value); + return; + } + + if (strcmp(name, "nodelay") == 0) { + /* don't delay replying to client of the failure */ + extra->request->no_failure_delay = TRUE; + return; + } + + str = extra->str; + if (str == NULL) + extra->str = str = str_new(extra->request->pool, 64); + + if (strcmp(name, "nologin") == 0) { + /* user can't actually login - don't keep this + reply for master */ + extra->request->no_login = TRUE; + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, name); + } else if (strcmp(name, "proxy") == 0) { + /* we're proxying authentication for this user. send + password back if using plaintext authentication. */ + extra->request->proxy = TRUE; + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, name); + } else { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_printfa(str, "%s=%s", name, value); + } +} + +void auth_request_extra_finish(struct auth_request_extra *extra, + const char *cache_key) +{ + string_t *str; + + if (passdb_cache != NULL && cache_key != NULL) { + str = t_str_new(64); + if (extra->str != NULL) + str_append_str(str, extra->str); + if (extra->request->no_failure_delay) { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, "nodelay"); + } + auth_cache_insert(passdb_cache, extra->request, cache_key, + t_strconcat(extra->password == NULL ? "" : + extra->password, + str_len(str) > 0 ? "\t" : "", + str_c(str), NULL)); + } + + if (extra->user_password != NULL) { + if (extra->request->proxy) { + /* we're proxying - send back the password that was + sent by user (not the password in passdb). */ + str_printfa(extra->str, "\tpass=%s", + extra->user_password); + } + safe_memset(extra->user_password, 0, + strlen(extra->user_password)); + i_free(extra->user_password); + } + + if (extra->str != NULL) + extra->request->extra_fields = str_c(extra->str); + + if (extra->password != NULL) { + safe_memset(extra->password, 0, strlen(extra->password)); + i_free(extra->password); + } + i_free(extra); +} + +static const char *escape_none(const char *str) +{ + return str; +} + +const struct var_expand_table * +auth_request_get_var_expand_table(const struct auth_request *auth_request, + const char *(*escape_func)(const char *)) +{ + static struct var_expand_table static_tab[] = { + { 'u', NULL }, + { 'n', NULL }, + { 'd', NULL }, + { 's', NULL }, + { 'h', NULL }, + { 'l', NULL }, + { 'r', NULL }, + { 'p', NULL }, + { '\0', NULL } + }; + struct var_expand_table *tab; + + if (escape_func == NULL) + escape_func = escape_none; + + tab = t_malloc(sizeof(static_tab)); + memcpy(tab, static_tab, sizeof(static_tab)); + + tab[0].value = escape_func(auth_request->user); + tab[1].value = escape_func(t_strcut(auth_request->user, '@')); + tab[2].value = strchr(auth_request->user, '@'); + if (tab[2].value != NULL) + tab[2].value = escape_func(tab[2].value+1); + tab[3].value = auth_request->service; + /* tab[4] = we have no home dir */ + if (auth_request->local_ip.family != 0) + tab[5].value = net_ip2addr(&auth_request->local_ip); + if (auth_request->remote_ip.family != 0) + tab[6].value = net_ip2addr(&auth_request->remote_ip); + tab[7].value = dec2str(auth_request->conn->pid); + return tab; +} + +const char *get_log_prefix(const struct auth_request *auth_request) +{ +#define MAX_LOG_USERNAME_LEN 64 + const char *ip; + string_t *str; + + str = t_str_new(64); + + if (auth_request->user == NULL) + str_append(str, "?"); + else { + str_sanitize_append(str, auth_request->user, + MAX_LOG_USERNAME_LEN); + } + + ip = net_ip2addr(&auth_request->remote_ip); + if (ip != NULL) { + str_append_c(str, ','); + str_append(str, ip); + } + return str_c(str); +} + +void auth_failure_buf_flush(void) +{ + struct auth_request **auth_request; + size_t i, size; + + auth_request = buffer_get_modifyable_data(auth_failures_buf, &size); + size /= sizeof(*auth_request); + + for (i = 0; i < size; i++) { + if (auth_request[i]->conn != NULL) { + auth_request[i]->callback(auth_request[i], + AUTH_CLIENT_RESULT_FAILURE, + NULL, 0); + } + auth_request_destroy(auth_request[i]); + } + buffer_set_used_size(auth_failures_buf, 0); +} + +static void auth_failure_timeout(void *context __attr_unused__) +{ + auth_failure_buf_flush(); +} + +void auth_requests_init(void) +{ + auth_failures_buf = buffer_create_dynamic(default_pool, 1024); + to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL); +} + +void auth_requests_deinit(void) +{ + buffer_free(auth_failures_buf); + timeout_remove(to_auth_failures); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/auth-request.h Fri Jan 07 20:51:10 2005 +0200 @@ -0,0 +1,64 @@ +#ifndef __AUTH_REQUEST_H +#define __AUTH_REQUEST_H + +#include "network.h" +#include "mech.h" + +struct auth_client_connection; + +struct auth_request { + int refcount; + + pool_t pool; + char *user; + const char *extra_fields; + + struct mech_module *mech; + struct auth_client_connection *conn; + + unsigned int id; + time_t created; + + const char *service; + struct ip_addr local_ip, remote_ip; + mech_callback_t *callback; + + unsigned int successful:1; + unsigned int internal_failure:1; + unsigned int accept_input:1; + unsigned int no_failure_delay:1; + unsigned int no_login:1; + unsigned int proxy:1; + unsigned int destroyed:1; + /* ... mechanism specific data ... */ +}; + +void auth_request_success(struct auth_request *request, + const void *data, size_t data_size); +void auth_request_fail(struct auth_request *request); +void auth_request_internal_failure(struct auth_request *request); + +struct auth_request *auth_request_new(struct mech_module *mech); +void auth_request_destroy(struct auth_request *request); +void auth_request_ref(struct auth_request *request); +int auth_request_unref(struct auth_request *request); + +struct auth_request_extra * +auth_request_extra_begin(struct auth_request *request, const char *password); +void auth_request_extra_next(struct auth_request_extra *extra, + const char *name, const char *value); +void auth_request_extra_finish(struct auth_request_extra *extra, + const char *cache_key); + +const struct var_expand_table * +auth_request_get_var_expand_table(const struct auth_request *auth_request, + const char *(*escape_func)(const char *)); + +const char *get_log_prefix(const struct auth_request *auth_request); + +void auth_failure_buf_flush(void); + +void auth_requests_init(void); +void auth_requests_deinit(void); + +#endif
--- a/src/auth/main.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/main.c Fri Jan 07 20:51:10 2005 +0200 @@ -12,6 +12,7 @@ #include "userdb.h" #include "passdb.h" #include "password-scheme.h" +#include "auth-request.h" #include "auth-master-connection.h" #include "auth-client-connection.h" @@ -202,6 +203,7 @@ lib_init_signals(sig_quit); mech_init(); + auth_requests_init(); env = getenv("AUTH_PROCESS"); standalone = env == NULL; @@ -267,6 +269,7 @@ password_schemes_deinit(); passdb_deinit(); userdb_deinit(); + auth_requests_deinit(); mech_deinit(); random_deinit();
--- a/src/auth/mech-anonymous.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-anonymous.c Fri Jan 07 20:51:10 2005 +0200 @@ -22,7 +22,7 @@ request->callback = callback; request->user = p_strdup(request->pool, anonymous_username); - mech_auth_success(request, NULL, 0); + auth_request_success(request, NULL, 0); } static void
--- a/src/auth/mech-apop.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-apop.c Fri Jan 07 20:51:10 2005 +0200 @@ -56,15 +56,15 @@ switch (result) { case PASSDB_RESULT_OK: if (verify_credentials(request, credentials)) - mech_auth_success(auth_request, NULL, 0); + auth_request_success(auth_request, NULL, 0); else - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(auth_request); + auth_request_internal_failure(auth_request); break; default: - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; } } @@ -87,7 +87,7 @@ i_info("apop(%s): no initial respone", get_log_prefix(auth_request)); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } @@ -107,7 +107,7 @@ i_info("apop(%s): invalid challenge", get_log_prefix(auth_request)); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } request->challenge = p_strdup(request->pool, (const char *)data); @@ -124,7 +124,7 @@ i_info("apop(%s): malformed data", get_log_prefix(auth_request)); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } tmp++; @@ -135,7 +135,7 @@ i_info("apop(%s): %s", get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; }
--- a/src/auth/mech-cram-md5.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-cram-md5.c Fri Jan 07 20:51:10 2005 +0200 @@ -119,15 +119,15 @@ switch (result) { case PASSDB_RESULT_OK: if (verify_credentials(request, credentials)) - mech_auth_success(auth_request, NULL, 0); + auth_request_success(auth_request, NULL, 0); else - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(auth_request); + auth_request_internal_failure(auth_request); break; default: - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; } } @@ -160,7 +160,7 @@ if (verbose) i_info("cram-md5(%s): %s", get_log_prefix(auth_request), error); - mech_auth_fail(auth_request); + auth_request_fail(auth_request); } static void
--- a/src/auth/mech-digest-md5.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-digest-md5.c Fri Jan 07 20:51:10 2005 +0200 @@ -524,19 +524,21 @@ switch (result) { case PASSDB_RESULT_OK: if (!verify_credentials(request, credentials)) { - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } request->authenticated = TRUE; - auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE, - request->rspauth, strlen(request->rspauth)); + auth_request->callback(auth_request, + AUTH_CLIENT_RESULT_CONTINUE, + request->rspauth, + strlen(request->rspauth)); break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(auth_request); + auth_request_internal_failure(auth_request); break; default: - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; } } @@ -553,7 +555,7 @@ if (request->authenticated) { /* authentication is done, we were just waiting the last word from client */ - mech_auth_success(auth_request, NULL, 0); + auth_request_success(auth_request, NULL, 0); return; } @@ -583,7 +585,7 @@ get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); } static void
--- a/src/auth/mech-login.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-login.c Fri Jan 07 20:51:10 2005 +0200 @@ -19,13 +19,13 @@ { switch (result) { case PASSDB_RESULT_OK: - mech_auth_success(request, NULL, 0); + auth_request_success(request, NULL, 0); break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(request); + auth_request_internal_failure(request); break; default: - mech_auth_fail(request); + auth_request_fail(request); break; } } @@ -48,7 +48,7 @@ i_info("login(%s): %s", get_log_prefix(request), error); } - mech_auth_fail(request); + auth_request_fail(request); return; }
--- a/src/auth/mech-ntlm.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-ntlm.c Fri Jan 07 20:51:10 2005 +0200 @@ -75,15 +75,15 @@ switch (result) { case PASSDB_RESULT_OK: if (lm_verify_credentials(request, credentials)) - mech_auth_success(auth_request, NULL, 0); + auth_request_success(auth_request, NULL, 0); else - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(auth_request); + auth_request_internal_failure(auth_request); break; default: - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; } } @@ -158,16 +158,16 @@ case PASSDB_RESULT_OK: ret = ntlm_verify_credentials(request, credentials); if (ret > 0) { - mech_auth_success(auth_request, NULL, 0); + auth_request_success(auth_request, NULL, 0); return; } if (ret < 0) { - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(auth_request); + auth_request_internal_failure(auth_request); return; default: break; @@ -203,7 +203,7 @@ get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } @@ -228,7 +228,7 @@ get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } @@ -244,7 +244,7 @@ i_info("ntlm(%s): %s", get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; }
--- a/src/auth/mech-plain.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-plain.c Fri Jan 07 20:51:10 2005 +0200 @@ -10,13 +10,13 @@ { switch (result) { case PASSDB_RESULT_OK: - mech_auth_success(request, NULL, 0); + auth_request_success(request, NULL, 0); break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(request); + auth_request_internal_failure(request); break; default: - mech_auth_fail(request); + auth_request_fail(request); break; } } @@ -58,7 +58,7 @@ i_info("plain(%s): invalid input", get_log_prefix(request)); } - mech_auth_fail(request); + auth_request_fail(request); } else { /* split and save user/realm */ if (strchr(authenid, '@') == NULL && default_realm != NULL) { @@ -75,7 +75,7 @@ i_info("plain(%s): %s", get_log_prefix(request), error); } - mech_auth_fail(request); + auth_request_fail(request); } else { passdb->verify_plain(request, pass, verify_callback); }
--- a/src/auth/mech-rpa.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech-rpa.c Fri Jan 07 20:51:10 2005 +0200 @@ -425,7 +425,7 @@ switch (result) { case PASSDB_RESULT_OK: if (!verify_credentials(request, credentials)) - mech_auth_fail(auth_request); + auth_request_fail(auth_request); else { token4 = mech_rpa_build_token4(request, &token4_size); auth_request->callback(auth_request, @@ -435,10 +435,10 @@ } break; case PASSDB_RESULT_INTERNAL_FAILURE: - mech_auth_internal_failure(auth_request); + auth_request_internal_failure(auth_request); break; default: - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; } } @@ -458,7 +458,7 @@ i_info("rpa(%s): invalid token 1, %s", get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } @@ -490,7 +490,7 @@ i_info("rpa(%s): invalid token 3, %s", get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } @@ -499,7 +499,7 @@ i_info("rpa(%s): %s", get_log_prefix(auth_request), error); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); return; } @@ -519,9 +519,9 @@ i_info("rpa(%s): invalid token 5 or client rejects us", get_log_prefix(auth_request)); } - mech_auth_fail(auth_request); + auth_request_fail(auth_request); } else { - mech_auth_success(auth_request, NULL, 0); + auth_request_success(auth_request, NULL, 0); } } @@ -546,7 +546,7 @@ mech_rpa_auth_phase3(auth_request, data, data_size); break; default: - mech_auth_fail(auth_request); + auth_request_fail(auth_request); break; } }
--- a/src/auth/mech.c Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech.c Fri Jan 07 20:51:10 2005 +0200 @@ -2,28 +2,14 @@ #include "common.h" #include "ioloop.h" -#include "buffer.h" -#include "hash.h" #include "mech.h" -#include "safe-memset.h" #include "str.h" -#include "str-sanitize.h" -#include "var-expand.h" -#include "auth-client-connection.h" -#include "auth-master-connection.h" #include "passdb.h" -#include "passdb-cache.h" #include <stdlib.h> -struct auth_request_extra { - struct auth_request *request; - string_t *str; - char *user_password, *password; -}; - struct mech_module_list *mech_modules; -buffer_t *mech_handshake; +string_t *mech_handshake; const char *const *auth_realms; const char *default_realm; @@ -31,9 +17,6 @@ char username_chars[256], username_translation[256]; int ssl_require_client_cert; -static buffer_t *auth_failures_buf; -static struct timeout *to_auth_failures; - void mech_register_module(struct mech_module *module) { struct mech_module_list *list; @@ -99,83 +82,6 @@ return NULL; } -struct auth_request *auth_request_new(struct mech_module *mech) -{ - struct auth_request *request; - - request = mech->auth_new(); - if (request == NULL) - return NULL; - - request->mech = mech; - request->created = ioloop_time; - return request; -} - -void auth_request_destroy(struct auth_request *request) -{ - i_assert(request->refcount > 0); - - if (request->destroyed) - return; - request->destroyed = TRUE; - - if (request->conn != NULL) { - hash_remove(request->conn->auth_requests, - POINTER_CAST(request->id)); - } - auth_request_unref(request); -} - -void mech_auth_success(struct auth_request *request, - const void *data, size_t data_size) -{ - request->successful = TRUE; - if (request->conn != NULL) { - request->callback(request, AUTH_CLIENT_RESULT_SUCCESS, - data, data_size); - } - - if (request->no_login || request->conn == NULL || - AUTH_MASTER_IS_DUMMY(request->conn->master)) { - /* we don't have master process, the request is no longer - needed */ - auth_request_destroy(request); - } -} - -void mech_auth_fail(struct auth_request *request) -{ - if (request->no_failure_delay) { - /* passdb specifically requested to to delay the reply. */ - request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0); - auth_request_destroy(request); - return; - } - - /* failure. don't announce it immediately to avoid - a) timing attacks, b) flooding */ - if (auth_failures_buf->used > 0) { - const struct auth_request *const *requests; - - requests = auth_failures_buf->data; - requests += auth_failures_buf->used/sizeof(*requests)-1; - i_assert(*requests != request); - } - - buffer_append(auth_failures_buf, &request, sizeof(request)); - - /* make sure the request isn't found anymore */ - auth_request_ref(request); - auth_request_destroy(request); -} - -void mech_auth_internal_failure(struct auth_request *request) -{ - request->internal_failure = TRUE; - mech_auth_fail(request); -} - int mech_fix_username(char *username, const char **error_r) { unsigned char *p; @@ -198,210 +104,6 @@ return TRUE; } -void auth_request_ref(struct auth_request *request) -{ - request->refcount++; -} - -int auth_request_unref(struct auth_request *request) -{ - i_assert(request->refcount > 0); - if (--request->refcount > 0) - return TRUE; - - request->mech->auth_free(request); - return FALSE; -} - -struct auth_request_extra * -auth_request_extra_begin(struct auth_request *request, - const char *user_password) -{ - struct auth_request_extra *extra; - - extra = i_new(struct auth_request_extra, 1); - extra->request = request; - extra->user_password = i_strdup(user_password); - return extra; -} - -void auth_request_extra_next(struct auth_request_extra *extra, - const char *name, const char *value) -{ - string_t *str; - - i_assert(value != NULL); - - if (strcmp(name, "password") == 0) { - i_assert(extra->password == NULL); - extra->password = i_strdup(value); - return; - } - - if (strcmp(name, "nodelay") == 0) { - /* don't delay replying to client of the failure */ - extra->request->no_failure_delay = TRUE; - return; - } - - str = extra->str; - if (str == NULL) - extra->str = str = str_new(extra->request->pool, 64); - - if (strcmp(name, "nologin") == 0) { - /* user can't actually login - don't keep this - reply for master */ - extra->request->no_login = TRUE; - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_append(str, name); - } else if (strcmp(name, "proxy") == 0) { - /* we're proxying authentication for this user. send - password back if using plaintext authentication. */ - extra->request->proxy = TRUE; - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_append(str, name); - } else { - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_printfa(str, "%s=%s", name, value); - } -} - -void auth_request_extra_finish(struct auth_request_extra *extra, - const char *cache_key) -{ - string_t *str; - - if (passdb_cache != NULL && cache_key != NULL) { - str = t_str_new(64); - if (extra->str != NULL) - str_append_str(str, extra->str); - if (extra->request->no_failure_delay) { - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_append(str, "nodelay"); - } - auth_cache_insert(passdb_cache, extra->request, cache_key, - t_strconcat(extra->password == NULL ? "" : - extra->password, - str_len(str) > 0 ? "\t" : "", - str_c(str), NULL)); - } - - if (extra->user_password != NULL) { - if (extra->request->proxy) { - /* we're proxying - send back the password that was - sent by user (not the password in passdb). */ - str_printfa(extra->str, "\tpass=%s", - extra->user_password); - } - safe_memset(extra->user_password, 0, - strlen(extra->user_password)); - i_free(extra->user_password); - } - - if (extra->str != NULL) - extra->request->extra_fields = str_c(extra->str); - - if (extra->password != NULL) { - safe_memset(extra->password, 0, strlen(extra->password)); - i_free(extra->password); - } - i_free(extra); -} - -static const char *escape_none(const char *str) -{ - return str; -} - -const struct var_expand_table * -auth_request_get_var_expand_table(const struct auth_request *auth_request, - const char *(*escape_func)(const char *)) -{ - static struct var_expand_table static_tab[] = { - { 'u', NULL }, - { 'n', NULL }, - { 'd', NULL }, - { 's', NULL }, - { 'h', NULL }, - { 'l', NULL }, - { 'r', NULL }, - { 'p', NULL }, - { '\0', NULL } - }; - struct var_expand_table *tab; - - if (escape_func == NULL) - escape_func = escape_none; - - tab = t_malloc(sizeof(static_tab)); - memcpy(tab, static_tab, sizeof(static_tab)); - - tab[0].value = escape_func(auth_request->user); - tab[1].value = escape_func(t_strcut(auth_request->user, '@')); - tab[2].value = strchr(auth_request->user, '@'); - if (tab[2].value != NULL) - tab[2].value = escape_func(tab[2].value+1); - tab[3].value = auth_request->service; - /* tab[4] = we have no home dir */ - if (auth_request->local_ip.family != 0) - tab[5].value = net_ip2addr(&auth_request->local_ip); - if (auth_request->remote_ip.family != 0) - tab[6].value = net_ip2addr(&auth_request->remote_ip); - tab[7].value = dec2str(auth_request->conn->pid); - return tab; -} - -const char *get_log_prefix(const struct auth_request *auth_request) -{ -#define MAX_LOG_USERNAME_LEN 64 - const char *ip; - string_t *str; - - str = t_str_new(64); - - if (auth_request->user == NULL) - str_append(str, "?"); - else { - str_sanitize_append(str, auth_request->user, - MAX_LOG_USERNAME_LEN); - } - - ip = net_ip2addr(&auth_request->remote_ip); - if (ip != NULL) { - str_append_c(str, ','); - str_append(str, ip); - } - return str_c(str); -} - -void auth_failure_buf_flush(void) -{ - struct auth_request **auth_request; - size_t i, size; - - auth_request = buffer_get_modifyable_data(auth_failures_buf, &size); - size /= sizeof(*auth_request); - - for (i = 0; i < size; i++) { - if (auth_request[i]->conn != NULL) { - auth_request[i]->callback(auth_request[i], - AUTH_CLIENT_RESULT_FAILURE, - NULL, 0); - } - auth_request_destroy(auth_request[i]); - } - buffer_set_used_size(auth_failures_buf, 0); -} - -static void auth_failure_timeout(void *context __attr_unused__) -{ - auth_failure_buf_flush(); -} - static void mech_list_verify_passdb(struct passdb_module *passdb) { struct mech_module_list *list; @@ -512,15 +214,10 @@ } ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL; - - auth_failures_buf = buffer_create_dynamic(default_pool, 1024); - to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL); } void mech_deinit(void) { - timeout_remove(to_auth_failures); - mech_unregister_module(&mech_plain); mech_unregister_module(&mech_login); mech_unregister_module(&mech_apop);
--- a/src/auth/mech.h Fri Jan 07 20:25:10 2005 +0200 +++ b/src/auth/mech.h Fri Jan 07 20:51:10 2005 +0200 @@ -1,7 +1,6 @@ #ifndef __MECH_H #define __MECH_H -#include "network.h" #include "auth-client-interface.h" enum auth_client_result { @@ -11,38 +10,12 @@ }; struct auth_request; -struct auth_client_connection; typedef void mech_callback_t(struct auth_request *request, enum auth_client_result result, const void *reply, size_t reply_size); -struct auth_request { - int refcount; - - pool_t pool; - char *user; - const char *extra_fields; - - struct mech_module *mech; - struct auth_client_connection *conn; - - unsigned int id; - time_t created; - - const char *service; - struct ip_addr local_ip, remote_ip; - mech_callback_t *callback; - - unsigned int successful:1; - unsigned int internal_failure:1; - unsigned int accept_input:1; - unsigned int no_failure_delay:1; - unsigned int no_login:1; - unsigned int proxy:1; - unsigned int destroyed:1; - /* ... mechanism specific data ... */ -}; +#include "auth-request.h" struct mech_module { const char *mech_name; @@ -82,33 +55,8 @@ const string_t *auth_mechanisms_get_list(void); -void mech_auth_success(struct auth_request *request, - const void *data, size_t data_size); -void mech_auth_fail(struct auth_request *request); -void mech_auth_internal_failure(struct auth_request *request); - int mech_fix_username(char *username, const char **error_r); -struct auth_request *auth_request_new(struct mech_module *mech); -void auth_request_destroy(struct auth_request *request); -void auth_request_ref(struct auth_request *request); -int auth_request_unref(struct auth_request *request); - -struct auth_request_extra * -auth_request_extra_begin(struct auth_request *request, const char *password); -void auth_request_extra_next(struct auth_request_extra *extra, - const char *name, const char *value); -void auth_request_extra_finish(struct auth_request_extra *extra, - const char *cache_key); - -const struct var_expand_table * -auth_request_get_var_expand_table(const struct auth_request *auth_request, - const char *(*escape_func)(const char *)); - -const char *get_log_prefix(const struct auth_request *auth_request); - -void auth_failure_buf_flush(void); - void mech_init(void); void mech_deinit(void);