From: Timo Sirainen Date: Mon, 31 May 2004 20:10:02 +0000 (+0300) Subject: Delay reporting failed authentications X-Git-Tag: 1.1.alpha1~4004 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3685c7c8ca227960360c720b8bd515801a9e5ad6;p=thirdparty%2Fdovecot%2Fcore.git Delay reporting failed authentications --HG-- branch : HEAD --- diff --git a/src/auth/main.c b/src/auth/main.c index cf24101fe3..95edcf02bf 100644 --- a/src/auth/main.c +++ b/src/auth/main.c @@ -51,10 +51,14 @@ static void open_logfile(void) static void drop_privileges(void) { + unsigned int seed; + open_logfile(); /* Open /dev/urandom before chrooting */ random_init(); + random_fill(&seed, sizeof(seed)); + srand(seed); /* Password lookups etc. may require roots, allow it. */ restrict_access_by_env(FALSE); @@ -156,6 +160,8 @@ static void main_deinit(void) if (lib_signal_kill != 0) i_warning("Killed with signal %d", lib_signal_kill); + auth_failure_buf_flush(); + master = buffer_get_modifyable_data(masters_buf, &size); size /= sizeof(*master); for (i = 0; i < size; i++) { diff --git a/src/auth/mech-cram-md5.c b/src/auth/mech-cram-md5.c index c22a201e32..4131c1b1bf 100644 --- a/src/auth/mech-cram-md5.c +++ b/src/auth/mech-cram-md5.c @@ -132,13 +132,9 @@ static void credentials_callback(const char *result, struct cram_auth_request *auth = (struct cram_auth_request *) request; - if (verify_credentials(auth, result)) { - if (verbose) { - i_info("cram-md5(%s): authenticated", - get_log_prefix(&auth->auth_request)); - } + if (verify_credentials(auth, result)) mech_auth_finish(request, NULL, 0, TRUE); - } else { + else { if (verbose) { i_info("cram-md5(%s): authentication failed", get_log_prefix(&auth->auth_request)); diff --git a/src/auth/mech-digest-md5.c b/src/auth/mech-digest-md5.c index 0acdbd5135..da29741ed6 100644 --- a/src/auth/mech-digest-md5.c +++ b/src/auth/mech-digest-md5.c @@ -511,16 +511,16 @@ static void credentials_callback(const char *result, (struct digest_auth_request *) request; struct auth_client_request_reply reply; + if (!verify_credentials(auth, result)) { + mech_auth_finish(request, NULL, 0, FALSE); + return; + } + mech_init_auth_client_reply(&reply); reply.id = request->id; - - if (!verify_credentials(auth, result)) - reply.result = AUTH_CLIENT_RESULT_FAILURE; - else { - reply.result = AUTH_CLIENT_RESULT_CONTINUE; - reply.data_size = strlen(auth->rspauth); - auth->authenticated = TRUE; - } + reply.result = AUTH_CLIENT_RESULT_CONTINUE; + reply.data_size = strlen(auth->rspauth); + auth->authenticated = TRUE; request->callback(&reply, auth->rspauth, request->conn); } diff --git a/src/auth/mech.c b/src/auth/mech.c index 278442a09f..8271fc4a67 100644 --- a/src/auth/mech.c +++ b/src/auth/mech.c @@ -22,6 +22,9 @@ static int set_use_cyrus_sasl; static int ssl_require_client_cert; static struct auth_client_request_reply failure_reply; +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; @@ -224,24 +227,24 @@ void mech_auth_finish(struct auth_request *auth_request, struct auth_client_request_reply reply; void *reply_data; + if (!success) { + /* failure. don't announce it immediately to avoid + a) timing attacks, b) flooding */ + buffer_append(auth_failures_buf, + &auth_request, sizeof(auth_request)); + return; + } + memset(&reply, 0, sizeof(reply)); reply.id = auth_request->id; + reply.result = AUTH_CLIENT_RESULT_SUCCESS; - if (success) { - reply_data = mech_auth_success(&reply, auth_request, - data, data_size); - reply.result = AUTH_CLIENT_RESULT_SUCCESS; - } else { - reply_data = NULL; - reply.result = AUTH_CLIENT_RESULT_FAILURE; - } - + reply_data = mech_auth_success(&reply, auth_request, data, data_size); auth_request->callback(&reply, reply_data, auth_request->conn); - if (!success || AUTH_MASTER_IS_DUMMY(auth_request->conn->master)) { - /* request is no longer needed, either because the - authentication failed or because we don't have master - process */ + if (AUTH_MASTER_IS_DUMMY(auth_request->conn->master)) { + /* we don't have master process, the request is no longer + needed */ mech_request_free(auth_request, auth_request->id); } } @@ -355,6 +358,31 @@ const char *get_log_prefix(const struct auth_request *auth_request) return str_c(str); } +void auth_failure_buf_flush(void) +{ + struct auth_request **auth_request; + struct auth_client_request_reply reply; + size_t i, size; + + auth_request = buffer_get_modifyable_data(auth_failures_buf, &size); + size /= sizeof(*auth_request); + + memset(&reply, 0, sizeof(reply)); + reply.result = AUTH_CLIENT_RESULT_FAILURE; + + for (i = 0; i < size; i++) { + reply.id = auth_request[i]->id; + auth_request[i]->callback(&reply, NULL, auth_request[i]->conn); + mech_request_free(auth_request[i], auth_request[i]->id); + } + buffer_set_used_size(auth_failures_buf, 0); +} + +static void auth_failure_timeout(void *context __attr_unused__) +{ + auth_failure_buf_flush(); +} + extern struct mech_module mech_plain; extern struct mech_module mech_cram_md5; extern struct mech_module mech_digest_md5; @@ -431,11 +459,17 @@ void mech_init(void) if (set_use_cyrus_sasl) mech_cyrus_sasl_init_lib(); #endif - ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL; + ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL; + + auth_failures_buf = + buffer_create_dynamic(default_pool, 1024, (size_t)-1); + 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_cram_md5); mech_unregister_module(&mech_digest_md5); diff --git a/src/auth/mech.h b/src/auth/mech.h index a64288deb3..6a7d05470d 100644 --- a/src/auth/mech.h +++ b/src/auth/mech.h @@ -99,6 +99,8 @@ auth_request_get_var_expand_table(const struct auth_request *auth_request, 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);