]> 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>
Fri, 9 Jun 2023 07:00:35 +0000 (07:00 +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 d6a4cad3d7cafa1710c14862e0cee7ee11d8a33d..f487579bf2cf888d5ec83e6f9eb85da4427835fe 100644 (file)
@@ -857,6 +857,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 285d875b6dbc444b8f0522ff1ab7862b50796c4c..00904c1365e2adcb40feecdabde36e65f5d85b93 100644 (file)
@@ -430,7 +430,8 @@ void client_destroy(struct client *client, const char *reason)
                                           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 39fdd3ee248fe608908d0f76bcd11ac3f842ef89..480d2043056c12b00d922a3470625c06ea805eb5 100644 (file)
@@ -205,7 +205,9 @@ struct client {
        struct auth_client_request *reauth_request;
        string_t *auth_response;
        struct timeval 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;
@@ -287,6 +289,7 @@ struct client {
        bool fd_proxying:1;
        bool shutting_down:1;
        bool resource_constraint:1;
+       bool final_response:1;
        /* ... */
 };
 
index 7735a3f1f03b9db63457a20806a7af28ebf79fa6..21efdff1981842766e73be679a369c599edad72c 100644 (file)
@@ -3,12 +3,14 @@
 #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"
@@ -369,9 +371,8 @@ authenticate_callback(struct auth_client_request *request,
                                client->auth_anonymous = TRUE;
                        } else if (str_begins(args[i], "event_", &key)) {
                                event_add_str(client->event_auth, key, value);
-                       } else if (login_binary->sasl_support_final_reply &&
-                                  strcmp(key, "resp") == 0) {
-                               client->sasl_final_resp =
+                       } else if (strcmp(key, "resp") == 0) {
+                               client->sasl_final_delayed_resp =
                                        p_strdup(client->pool, value);
                        }
                }
@@ -398,13 +399,27 @@ authenticate_callback(struct auth_client_request *request,
                        for (i = 0; args[i] != NULL; i++) {
                                const char *key, *value;
                                t_split_key_value_eq(args[i], &key, &value);
-                               args_parse_user(client, key, value);
+                               if (args_parse_user(client, key, value))
+                                       continue;
+                               if (strcmp(key, "resp") == 0) {
+                                       client->sasl_final_delayed_resp =
+                                               p_strdup(client->preproxy_pool, value);
+                               }
                        }
                }
 
-               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;
        }
 }
@@ -604,3 +619,11 @@ void sasl_server_auth_abort(struct client *client)
        sasl_server_auth_cancel(client, "Aborted", 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 6bafb164c4277fec23ad434aae4df20a1e019a0e..d73e3f625848bdbe7eae5d00a57a698d23dc7093 100644 (file)
@@ -37,6 +37,7 @@ void sasl_server_auth_begin(struct client *client, const char *mech_name,
                            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);
 /* Called when client asks for SASL authentication to be aborted by sending