From bcfa19128347ebaa2ee2b00da9f7dc0df6f13c84 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 26 May 2026 12:13:47 +0200 Subject: [PATCH] CVE-2026-59849 auth: Fix state machine to aovid infinite loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After going through the whole list of certificates, the iterator was set to NULL and at the beginning of the next loop reset to the start of the list again, which caused infinite loop. Adding one more intermediate state solves the issue. Found by AISLE in partnership with Red Hat Signed-off-by: Jakub Jelen Reviewed-by: Pavol Žáčik --- src/auth.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/auth.c b/src/auth.c index 16324af0..eb2abaca 100644 --- a/src/auth.c +++ b/src/auth.c @@ -1451,6 +1451,7 @@ enum ssh_auth_auto_state_e { SSH_AUTH_AUTO_STATE_PUBKEY, SSH_AUTH_AUTO_STATE_KEY_IMPORTED, SSH_AUTH_AUTO_STATE_CERTIFICATE_FILE, + SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION_INIT, SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION, SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED }; @@ -1682,6 +1683,7 @@ int ssh_userauth_publickey_auto(ssh_session session, } if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED || state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_FILE || + state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION_INIT || state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION) { ssh_key k = state->pubkey; if (state->state != SSH_AUTH_AUTO_STATE_KEY_IMPORTED) { @@ -1732,14 +1734,15 @@ int ssh_userauth_publickey_auto(ssh_session session, continue; } /* if the file does not exists, try configuration options */ - state->state = SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION; + state->state = SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION_INIT; } /* Try certificate files loaded through options */ + if (state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION_INIT) { + state->cert_it = ssh_list_get_iterator(session->opts.certificate); + state->state = SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION; + } if (state->state == SSH_AUTH_AUTO_STATE_CERTIFICATE_OPTION) { SSH_KEY_FREE(state->cert); - if (state->cert_it == NULL) { - state->cert_it = ssh_list_get_iterator(session->opts.certificate); - } while (state->cert_it != NULL) { const char *cert_file = state->cert_it->data; ssh_key cert = NULL;