]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
login-common: Serve final response for client on failure
authorAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 15 May 2023 11:27:55 +0000 (14:27 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 29 Aug 2023 07:08:45 +0000 (07:08 +0000)
src/login-common/client-common-auth.c
src/login-common/client-common.c
src/login-common/client-common.h
src/login-common/sasl-server.c
src/login-common/sasl-server.h

index 5dba7da8dd24ee6313d294f65b71c4ad0d3e5a1c..ec5194bc5336cac4bcd5b347bf10b08626e75ca4 100644 (file)
@@ -709,6 +709,13 @@ void client_auth_parse_response(struct client *client)
        if (client_auth_read_line(client) <= 0)
                return;
 
+       /* This has to happen before * handling, otherwise
+          client can abort failed request. */
+       if (client->final_response) {
+               sasl_server_auth_delayed_final(client);
+               return;
+       }
+
        if (strcmp(str_c(client->auth_response), "*") == 0) {
                sasl_server_auth_abort(client);
                return;
index 24892f5fa976ed3b7ed08220105deb8f2f935998..fc44d2bc294bc14cb35e47a25c0dabc80a64d0fc 100644 (file)
@@ -345,7 +345,8 @@ void client_destroy(struct client *client, const char *reason)
                master_auth_request_abort(master_auth, client->master_tag);
                client->refcount--;
        } else if (client->auth_request != NULL ||
-                  client->anvil_query != NULL) {
+                  client->anvil_query != NULL ||
+                  client->final_response) {
                i_assert(client->authenticating);
                sasl_server_auth_abort(client);
        }
index 064cba6aaea24a33edaacb0e97b48e4b25d8b9b8..a21dea12f0b3ee2bf6baf30b55e1be4cbe98236e 100644 (file)
@@ -205,6 +205,9 @@ struct client {
        string_t *auth_response;
        time_t auth_first_started, auth_finished;
        const char *sasl_final_resp;
+       const char *sasl_final_delayed_resp;
+       enum sasl_server_reply delayed_final_reply;
+       const char *const *final_args;
        const char *const *auth_passdb_args;
        struct anvil_query *anvil_query;
        struct anvil_request *anvil_request;
@@ -245,6 +248,7 @@ struct client {
        bool ssl_servername_settings_read:1;
        bool banner_sent:1;
        bool authenticating:1;
+       bool auth_client_continue_pending:1;
        bool auth_try_aborted:1;
        bool auth_initializing:1;
        bool auth_process_comm_fail:1;
@@ -257,6 +261,7 @@ struct client {
        bool notified_auth_ready:1;
        bool notified_disconnect:1;
        bool fd_proxying:1;
+       bool final_response:1;
        /* ... */
 };
 
index 6e4de56e5484509a32e64c1fa8a662074643f2c5..acede60a920546acf1f4d3cc58e6e14b79d2fb3e 100644 (file)
@@ -1,12 +1,16 @@
 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
 
 #include "login-common.h"
+#include "array.h"
+#include "md5.h"
+#include "sasl-server.h"
 #include "str.h"
 #include "base64.h"
 #include "buffer.h"
 #include "hex-binary.h"
 #include "ioloop.h"
 #include "istream.h"
+#include "strfuncs.h"
 #include "write-full.h"
 #include "strescape.h"
 #include "str-sanitize.h"
@@ -368,10 +372,9 @@ authenticate_callback(struct auth_client_request *request,
                                                      t_strdup_until(key, value),
                                                      value+1);
                                }
-                       } else if (str_begins(args[i], "resp=") &&
-                                  login_binary->sasl_support_final_reply) {
-                               client->sasl_final_resp =
-                                       p_strdup(client->pool, args[i] + 5);
+                       } else if (str_begins(args[i], "resp=")) {
+                               client->sasl_final_delayed_resp =
+                                       p_strdup(client->pool, args[i]+5);
                        }
                }
 
@@ -394,13 +397,29 @@ authenticate_callback(struct auth_client_request *request,
 
                if (args != NULL) {
                        /* parse our username if it's there */
-                       for (i = 0; args[i] != NULL; i++)
-                               (void)args_parse_user(client, args[i]);
+                       for (i = 0; args[i] != NULL; i++) {
+                               if (args_parse_user(client, args[i]))
+                                       continue;
+                               if (str_begins(args[i], "resp=")) {
+                                       client->sasl_final_delayed_resp =
+                                               p_strdup(client->preproxy_pool,
+                                                        t_strdup(args[i]+5));
+                               }
+                       }
                }
 
-               client->authenticating = FALSE;
-               call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
-                                    NULL, args);
+               if (client->sasl_final_delayed_resp != NULL &&
+                   !login_binary->sasl_support_final_reply) {
+                       client->final_response = TRUE;
+                       client->final_args = p_strarray_dup(client->preproxy_pool, args);
+                       client->delayed_final_reply = SASL_SERVER_REPLY_AUTH_FAILED;
+                       client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
+                                             client->sasl_final_delayed_resp, NULL);
+               } else {
+                       client->authenticating = FALSE;
+                       call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
+                                            NULL, args);
+               }
                break;
        }
 }
@@ -574,3 +593,11 @@ void sasl_server_auth_abort(struct client *client)
        }
        sasl_server_auth_cancel(client, NULL, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
 }
+
+void sasl_server_auth_delayed_final(struct client *client)
+{
+       client->final_response = FALSE;
+       client->authenticating = FALSE;
+       client->auth_client_continue_pending = FALSE;
+       call_client_callback(client, client->delayed_final_reply, NULL, client->final_args);
+}
index 62210b737b5cd5d0ec1c8e278a69639dbe0de8a4..66d0cb4b9e25e10410896d0f62108d2bb0af36e4 100644 (file)
@@ -33,6 +33,7 @@ void sasl_server_auth_begin(struct client *client,
                            enum sasl_server_auth_flags flags,
                            const char *initial_resp_base64,
                            sasl_server_callback_t *callback);
+void sasl_server_auth_delayed_final(struct client *client);
 void sasl_server_auth_failed(struct client *client, const char *reason,
        const char *code) ATTR_NULL(3);
 void sasl_server_auth_abort(struct client *client);