From 7e5c9ad6dab475d5cc1bde5a6ee9918ae97cacb6 Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Mon, 15 May 2023 14:27:55 +0300 Subject: [PATCH] login-common: Serve final response for client on failure --- src/login-common/client-common-auth.c | 7 +++++ src/login-common/client-common.c | 3 +- src/login-common/client-common.h | 5 +++ src/login-common/sasl-server.c | 45 +++++++++++++++++++++------ src/login-common/sasl-server.h | 1 + 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c index 5dba7da8dd..ec5194bc53 100644 --- a/src/login-common/client-common-auth.c +++ b/src/login-common/client-common-auth.c @@ -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; diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 24892f5fa9..fc44d2bc29 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -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); } diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 064cba6aae..a21dea12f0 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -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; /* ... */ }; diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c index 6e4de56e54..acede60a92 100644 --- a/src/login-common/sasl-server.c +++ b/src/login-common/sasl-server.c @@ -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); +} diff --git a/src/login-common/sasl-server.h b/src/login-common/sasl-server.h index 62210b737b..66d0cb4b9e 100644 --- a/src/login-common/sasl-server.h +++ b/src/login-common/sasl-server.h @@ -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); -- 2.47.3