From: Stephan Bosch Date: Wed, 1 Nov 2023 23:07:25 +0000 (+0100) Subject: auth: auth-request - Handle final failure response X-Git-Tag: 2.4.0~2415 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=88f4c57adde8dd2f2c1817fd1190c49faba16143;p=thirdparty%2Fdovecot%2Fcore.git auth: auth-request - Handle final failure response --- diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c index 3c563afa03..d1d52948f4 100644 --- a/src/auth/auth-request.c +++ b/src/auth/auth-request.c @@ -273,6 +273,8 @@ static void auth_request_success_continue(struct auth_policy_check_ctx *ctx) if (ctx->success_data->used > 0 && !request->fields.final_resp_ok) { /* we'll need one more SASL round, since client doesn't support the final SASL response */ + i_assert(!request->final_resp_sent); + request->final_resp_sent = TRUE; auth_request_handler_reply_continue(request, ctx->success_data->data, ctx->success_data->used); return; @@ -289,6 +291,21 @@ void auth_request_fail_with_reply(struct auth_request *request, { i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE); + /* Sending challenge data (final_data_size > 0) as part of the final + authentication command response is never an option in SASL, but when + the authentication client sets the "final-resp-ok" field it indicates + that it will handle the final protocol sequence, avoiding the need to + do that here. */ + if (final_data_size > 0 && !request->fields.final_resp_ok) { + /* Otherwise, we need to send the data as part of a normal + challenge and wait for a dummy client response. */ + i_assert(!request->final_resp_sent); + request->final_resp_sent = TRUE; + auth_request_handler_reply_continue(request, final_data, + final_data_size); + return; + } + auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED); auth_request_refresh_last_access(request); auth_request_log_finished(request); @@ -398,7 +415,11 @@ void auth_request_continue(struct auth_request *request, { i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE); - if (request->fields.successful) { + if (request->final_resp_sent) { + if (!request->fields.successful) { + auth_request_fail(request); + return; + } auth_request_success(request, "", 0); return; } diff --git a/src/auth/auth-request.h b/src/auth/auth-request.h index f289666660..636b9146a6 100644 --- a/src/auth/auth-request.h +++ b/src/auth/auth-request.h @@ -231,6 +231,9 @@ struct auth_request { needs to be tracked outside regular extra fields, because they get rolled back on passdb failure. */ bool failure_nodelay:1; + /* Sent final response (challenge). Waiting for dummy client response. + */ + bool final_resp_sent:1; bool event_finished_sent:1;