From: Stephan Bosch Date: Tue, 28 Oct 2025 13:35:06 +0000 (+0100) Subject: lib-sasl: Enforce absolute limit on SASL message size for both client and server X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8a1b145d4b9d163351c463c734f8242f1d1ca7b7;p=thirdparty%2Fdovecot%2Fcore.git lib-sasl: Enforce absolute limit on SASL message size for both client and server This is a second layer of defence against abuse. The real limit enforced by the auth service can be (is) smaller. Additionally, these limits will make sure the fuzzer does not time out. OSS-Fuzz report: 455796070 --- diff --git a/src/lib-auth-client/auth-client-interface.h b/src/lib-auth-client/auth-client-interface.h index f4dce1db84..b6425a7290 100644 --- a/src/lib-auth-client/auth-client-interface.h +++ b/src/lib-auth-client/auth-client-interface.h @@ -10,6 +10,10 @@ /* GSSAPI can use quite large packets */ #define AUTH_CLIENT_MAX_LINE_LENGTH 16384 +/* Make sure AUTH_CLIENT_MAX_LINE_LENGTH does not exceed the absolute maximum */ +#if AUTH_CLIENT_MAX_LINE_LENGTH > SASL_MAX_MESSAGE_SIZE +# error "AUTH_CLIENT_MAX_LINE_LENGTH exceeds SASL_MAX_MESSAGE_SIZE" +#endif /* auth failure codes */ #define AUTH_CLIENT_FAIL_CODE_AUTHZFAILED "authz_fail" diff --git a/src/lib-sasl/dsasl-client.c b/src/lib-sasl/dsasl-client.c index b5932955cf..bc111afb16 100644 --- a/src/lib-sasl/dsasl-client.c +++ b/src/lib-sasl/dsasl-client.c @@ -124,6 +124,12 @@ dsasl_client_input(struct dsasl_client *client, *error_r = "Unexpected NUL in input data"; return DSASL_CLIENT_RESULT_ERR_PROTOCOL; } + if (input_len > (size_t)SASL_MAX_MESSAGE_SIZE) { + *error_r = t_strdup_printf( + "Excessive challenge size (> %d)", + SASL_MAX_MESSAGE_SIZE); + return DSASL_CLIENT_RESULT_ERR_PROTOCOL; + } return client->mech->input(client, input, input_len, error_r); } diff --git a/src/lib-sasl/sasl-common.h b/src/lib-sasl/sasl-common.h index d51c7ea31b..fff7373b3c 100644 --- a/src/lib-sasl/sasl-common.h +++ b/src/lib-sasl/sasl-common.h @@ -1,6 +1,12 @@ #ifndef SASL_COMMON_H #define SASL_COMMON_H +/* + * Absolute limits + */ + +#define SASL_MAX_MESSAGE_SIZE (64 * 1024) + /* * Mechanism security flags */ diff --git a/src/lib-sasl/sasl-server-request.c b/src/lib-sasl/sasl-server-request.c index 6656fd216f..7cfc4abc3d 100644 --- a/src/lib-sasl/sasl-server-request.c +++ b/src/lib-sasl/sasl-server-request.c @@ -140,6 +140,22 @@ void sasl_server_request_destroy(struct sasl_server_req_ctx *rctx) sasl_server_request_unref(rctx); } +static bool +sasl_server_request_fail_on_size(struct sasl_server_request *req, + size_t data_size) +{ + if (data_size > (size_t)SASL_MAX_MESSAGE_SIZE) { + /* We should normally never get here, because the limit enforced + by the auth service is smaller. + */ + e_debug(req->event, "Excessive response size (> %d)", + SASL_MAX_MESSAGE_SIZE); + sasl_server_request_failure(req->mech); + return TRUE; + } + return FALSE; +} + static bool sasl_server_request_fail_on_nuls(struct sasl_server_request *req, const unsigned char *data, size_t data_size) @@ -177,6 +193,8 @@ void sasl_server_request_initial(struct sasl_server_req_ctx *rctx, i_assert(req->state == SASL_SERVER_REQUEST_STATE_NEW); req->state = SASL_SERVER_REQUEST_STATE_SERVER; + if (sasl_server_request_fail_on_size(req, data_size)) + return; if (sasl_server_request_fail_on_nuls(req, data, data_size)) return; @@ -212,6 +230,8 @@ void sasl_server_request_input(struct sasl_server_req_ctx *rctx, i_assert(!req->finished_with_data); req->state = SASL_SERVER_REQUEST_STATE_SERVER; + if (sasl_server_request_fail_on_size(req, data_size)) + return; if (sasl_server_request_fail_on_nuls(req, data, data_size)) return;