Skip to content
This repository was archived by the owner on Mar 27, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions src/src/auths/cram_md5.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,21 @@ HDEBUG(D_auth)

/* We now have to compare the digest, which is 16 bytes in binary, with the
data received, which is expressed in lower case hex. We checked above that
there were 32 characters of data left. */
there were 32 characters of data left. Use constant-time comparison to
prevent timing side-channel. */

for (i = 0; i < 16; i++)
{
int a = *clear++;
int b = *clear++;
if (((((a >= 'a')? a - 'a' + 10 : a - '0') << 4) +
((b >= 'a')? b - 'a' + 10 : b - '0')) != digest[i]) return FAIL;
}
{
volatile unsigned char result = 0;
for (i = 0; i < 16; i++)
{
int a = *clear++;
int b = *clear++;
unsigned char hex_val = (((a >= 'a')? a - 'a' + 10 : a - '0') << 4) +
((b >= 'a')? b - 'a' + 10 : b - '0');
result |= hex_val ^ digest[i];
}
if (result != 0) return FAIL;
}

/* Expand server_condition as an authorization check */
return auth_check_serv_cond(ablock);
Expand Down
10 changes: 8 additions & 2 deletions src/src/auths/spa.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,14 @@ if (off >= sizeof(SPAAuthResponse) - 24)
}
s = (US responseptr) + off;

if (memcmp(ntRespData, s, 24) == 0)
return auth_check_serv_cond(ablock); /* success. we have a winner. */
/* Use constant-time comparison to prevent timing side-channel */
{
volatile unsigned char result = 0;
for (int i = 0; i < 24; i++)
result |= ntRespData[i] ^ s[i];
if (result == 0)
return auth_check_serv_cond(ablock); /* success. we have a winner. */
}

/* Expand server_condition as an authorization check (PH) */

Expand Down
15 changes: 15 additions & 0 deletions src/src/mime.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,21 @@ int rc = OK;
uschar * header = NULL;
struct mime_boundary_context nested_context;

/* Limit MIME nesting depth to prevent stack overflow from crafted messages.
RFC 2046 does not specify a maximum, but 100 levels is far beyond any
legitimate use. */

{
int depth = 0;
for (struct mime_boundary_context *p = context; p; p = p->parent)
if (++depth > 100)
{
log_write(0, LOG_MAIN,
"MIME: nesting depth limit (100) exceeded, skipping");
return OK;
}
}

/* reserve a line buffer to work in. Assume tainted data. */
header = store_get(MIME_MAX_HEADER_SIZE+1, GET_TAINTED);

Expand Down
2 changes: 1 addition & 1 deletion src/src/receive.c
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ for (;;)
{
if (chunking_data_left > 0)
{
unsigned len = MAX(chunking_data_left, thismessage_size_limit - message_size + 1);
unsigned len = MIN(chunking_data_left, thismessage_size_limit - message_size + 1);
const uschar * buf = bdat_getbuf(&len);

if (!buf) return END_EOF;
Expand Down