From: Aki Tuomi Date: Mon, 15 May 2023 11:27:55 +0000 (+0300) Subject: login-common: Serve final response for client on failure X-Git-Tag: 2.4.0~2706 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9c008893f963248d522173180734f0e8a4cced8;p=thirdparty%2Fdovecot%2Fcore.git login-common: Serve final response for client on failure --- diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c index d6a4cad3d7..f487579bf2 100644 --- a/src/login-common/client-common-auth.c +++ b/src/login-common/client-common-auth.c @@ -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; diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 285d875b6d..00904c1365 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -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); } diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 39fdd3ee24..480d204305 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -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; /* ... */ }; diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c index 7735a3f1f0..21efdff198 100644 --- a/src/login-common/sasl-server.c +++ b/src/login-common/sasl-server.c @@ -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); +} diff --git a/src/login-common/sasl-server.h b/src/login-common/sasl-server.h index 6bafb164c4..d73e3f6258 100644 --- a/src/login-common/sasl-server.h +++ b/src/login-common/sasl-server.h @@ -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