From: Stephan Bosch Date: Thu, 30 Oct 2025 23:19:45 +0000 (+0100) Subject: lib-sasl: sasl-server-mech-otp - Fix parsing of authid from initial client response X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b8a514b896254a97f111fd54e459b27d3ad70216;p=thirdparty%2Fdovecot%2Fcore.git lib-sasl: sasl-server-mech-otp - Fix parsing of authid from initial client response Before, it assumed this part to be nul-terminated, while it is not. Therefore, it could read out-of-bounds memory, possibly crashing, which is wat became apparent in the fuzzer. The actual auth service code implicitly always provides a NUL termination though, because the client response data comes via t_buffer_create() content which always reserves +1 byte for NUL. Therefore, the auth service would not have encountered this issue. OSS-Fuzz report: 456423266 --- diff --git a/src/lib-sasl/sasl-server-mech-otp.c b/src/lib-sasl/sasl-server-mech-otp.c index 7291adf8f0..af4706c83a 100644 --- a/src/lib-sasl/sasl-server-mech-otp.c +++ b/src/lib-sasl/sasl-server-mech-otp.c @@ -128,22 +128,23 @@ mech_otp_auth_phase1(struct otp_auth_request *request, const unsigned char *data, size_t data_size) { struct sasl_server_mech_request *auth_request = &request->auth_request; + const unsigned char *p1, *p2; const char *authenid; - size_t i, count; /* authorization ID \0 authentication ID FIXME: we'll ignore authorization ID for now. */ authenid = NULL; - count = 0; - for (i = 0; i < data_size; i++) { - if (data[i] == '\0') { - if (++count == 1) - authenid = (const char *) data + i + 1; - } + p1 = memchr(data, '\0', data_size); + if (p1 != NULL) { + p1++; + size_t len = data_size - (p1 - data); + p2 = memchr(p1, '\0', len); + if (p2 == NULL) + authenid = t_strndup(p1, len); } - if (count != 1) { + if (authenid == NULL) { e_info(auth_request->event, "invalid input"); sasl_server_request_failure(auth_request); return;