]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Delay reporting failed authentications
authorTimo Sirainen <tss@iki.fi>
Mon, 31 May 2004 20:10:02 +0000 (23:10 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 31 May 2004 20:10:02 +0000 (23:10 +0300)
--HG--
branch : HEAD

src/auth/main.c
src/auth/mech-cram-md5.c
src/auth/mech-digest-md5.c
src/auth/mech.c
src/auth/mech.h

index cf24101fe385e16ddb6cada184831c794dd1d938..95edcf02bfb9e8bbdbd82fc53203b562513ca157 100644 (file)
@@ -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++) {
index c22a201e3215b56474cdbe56ad728a05544e6d74..4131c1b1bf22872dddd20b648fcb93bce36c05f7 100644 (file)
@@ -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));
index 0acdbd51353f2bda1491110557aa39d4eb32952d..da29741ed60e21787621aa331e31476ed33571c8 100644 (file)
@@ -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);
 }
index 278442a09fc084ef2c18572149a0aced61eaff01..8271fc4a67759f0211aaa014772fc49b63fab53c 100644 (file)
@@ -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);
index a64288deb3b961e3da205d20e6b61895c20639e3..6a7d05470d2bc8b2cc13c1db97001aa9c219d0b6 100644 (file)
@@ -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);