scram: cap server-supplied iteration count

The server-first-message in SCRAM SASL authentication carries an
i=<iteration_count> field that controls the PBKDF2 work factor.
Previously irssi parsed this with strtoul and only rejected the zero
case, then passed the value directly to PKCS5_PBKDF2_HMAC.

Because the call is synchronous on the glib main loop and the 20-second
SASL_TIMEOUT source is registered via g_timeout_add, a malicious
server can send i=4294967295 (or larger) and deterministically hang
irssi for the duration of the iteration count. Each reconnect attempt
repeats the DoS.

RFC 5802 section 5.1 explicitly allows a client to enforce a maximum
iteration count. 100000 is well above any real-world server
configuration (typically a few thousand) and bounds the worst-case
PBKDF2 cost to a fraction of a second on modern hardware.
This commit is contained in:
Acts1631 2026-07-02 16:33:19 -04:00 committed by Acts1631
commit 801c342a53

View file

@ -169,6 +169,19 @@ static scram_status process_server_first(SCRAM_SESSION_REC *session, const char
return SCRAM_ERROR;
}
/* RFC 5802 section 5.1: "A client MAY enforce a maximum iteration count."
* Reject values that would cause PKCS5_PBKDF2_HMAC to block the main loop
* for an unreasonable amount of time. 100000 is well above any real-world
* server configuration (typically a few thousand) and bounds the worst-case
* PBKDF2 cost to a fraction of a second on modern hardware. */
if (iteration_count > 100000) {
session->error = g_strdup_printf("Iteration count too high: %u",
iteration_count);
g_free(server_nonce_b64);
g_free(salt);
return SCRAM_ERROR;
}
client_nonce_len = strlen(session->client_nonce_b64);
// The server can append his nonce to the client's nonce