From d43ba60c91cb323ca921049b7d43b1908c318454 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 6 Jul 2026 07:44:48 +0000
Subject: 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
Conflict:Adapt context (GSSAPI patches: PRIVSEP, use_privsep guard, indent)
Reference:https://anongit.mindrot.org/openssh.git/commit/?id=c40bd35cc2428fcaccad7a141703c28baa6da01e
@@ -176,6 +176,7 @@
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);
@@ -296,6 +296,7 @@
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 @@
auth2_challenge_start(ssh);
}
}
+
+ if (!authenticated)
+ auth_failure_delay(authctxt, tstart);
userauth_finish(ssh, authenticated, "keyboard-interactive",
devicename);
return 0;
@@ -287,6 +287,7 @@
{
Authctxt *authctxt = ssh->authctxt;
int r, authenticated;
+ double tstart = monotime_double();
const char *displayname;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
@@ -307,6 +308,9 @@
(displayname = ssh_gssapi_displayname()) != NULL)
auth2_record_info(authctxt, "%s", displayname);
+
+ 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);
@@ -328,6 +332,7 @@
const char *displayname;
u_char *p;
size_t len;
+ double tstart = monotime_double();
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
@@ -368,6 +373,9 @@
(displayname = ssh_gssapi_displayname()) != NULL)
auth2_record_info(authctxt, "%s", displayname);
+ 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);
@@ -267,6 +267,12 @@
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)
{
@@ -365,8 +371,7 @@
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: