From d43ba60c91cb323ca921049b7d43b1908c318454 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 6 Jul 2026 07:44:48 +0000 Subject: [PATCH] upstream: Fix cases in GSSAPI and keyboard-interactive authentication where the minimum per-attempt delay was not being enforced. Reported by Orange Cyberdefense Vulnerability Team OpenBSD-Commit-ID: c40bd35cc2428fcaccad7a141703c28baa6da01e CVE: CVE-2026-60001 Upstream: https://github.com/openssh/openssh-portable/commit/d43ba60c91cb323ca921049b7d43b1908c318454 Signed-off-by: Thomas Perale --- auth.h | 3 ++- auth2-chall.c | 6 +++++- auth2-gss.c | 9 ++++++++- auth2.c | 12 +++++++++--- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/auth.h b/auth.h index 634a84aa85f7..0f11458ca2c8 100644 --- a/auth.h +++ b/auth.h @@ -175,6 +175,7 @@ void auth_log(struct ssh *, int, int, const char *, const char *); void auth_maxtries_exceeded(struct ssh *) __attribute__((noreturn)); void userauth_finish(struct ssh *, int, const char *, const char *); int auth_root_allowed(struct ssh *, const char *); +void auth_failure_delay(Authctxt *, double); char *auth2_read_banner(void); int auth2_methods_valid(const char *, int); diff --git a/auth2-chall.c b/auth2-chall.c index f3889079b64f..8a23ca2dca2a 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -296,6 +296,7 @@ input_userauth_info_response(int type, uint32_t seq, struct ssh *ssh) u_int i, nresp; const char *devicename = NULL; char **response = NULL; + double tstart = monotime_double(); if (authctxt == NULL) fatal_f("no authctxt"); @@ -354,6 +355,9 @@ input_userauth_info_response(int type, uint32_t seq, struct ssh *ssh) auth2_challenge_start(ssh); } } + + if (!authenticated) + auth_failure_delay(authctxt, tstart); userauth_finish(ssh, authenticated, "keyboard-interactive", devicename); return 0; diff --git a/auth2-gss.c b/auth2-gss.c index 0535485277a6..355926afcd6e 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -250,6 +250,7 @@ input_gssapi_exchange_complete(int type, uint32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; int r, authenticated; + double tstart = monotime_double(); if (authctxt == NULL) fatal("No authentication or GSSAPI context"); @@ -263,6 +264,8 @@ input_gssapi_exchange_complete(int type, uint32_t plen, struct ssh *ssh) fatal_fr(r, "parse packet"); authenticated = mm_ssh_gssapi_userok(authctxt->user); + if (!authenticated) + auth_failure_delay(authctxt, tstart); authctxt->postponed = 0; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); @@ -283,6 +286,7 @@ input_gssapi_mic(int type, uint32_t plen, struct ssh *ssh) gss_buffer_desc mic, gssbuf; u_char *p; size_t len; + double tstart = monotime_double(); if (authctxt == NULL) fatal("No authentication or GSSAPI context"); @@ -310,6 +314,9 @@ input_gssapi_mic(int type, uint32_t plen, struct ssh *ssh) sshbuf_free(b); free(mic.value); + if (!authenticated) + auth_failure_delay(authctxt, tstart); + authctxt->postponed = 0; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); diff --git a/auth2.c b/auth2.c index 3a168274631e..3f353a719ba0 100644 --- a/auth2.c +++ b/auth2.c @@ -265,6 +265,12 @@ ensure_minimum_time_since(double start, double seconds) nanosleep(&ts, NULL); } +void +auth_failure_delay(Authctxt *authctxt, double tstart) +{ + ensure_minimum_time_since(tstart, user_specific_delay(authctxt->user)); +} + static int input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { @@ -346,8 +352,8 @@ input_userauth_request(int type, uint32_t seq, struct ssh *ssh) authenticated = m->userauth(ssh, method); } if (!authctxt->authenticated && strcmp(method, "none") != 0) - ensure_minimum_time_since(tstart, - user_specific_delay(authctxt->user)); + auth_failure_delay(authctxt, tstart); + userauth_finish(ssh, authenticated, method, NULL); r = 0; out: