Skip to content

Auth: 1/2/4 s after failed logins, AuthMinLength 10, no decoy hashing - #370

Merged
go-while merged 3 commits into
mainfrom
fix/auth-failure-backoff
Nov 11, 2026
Merged

go-while merged 3 commits into
mainfrom
fix/auth-failure-backoff

Conversation

@go-while

@go-while go-while commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

Login handling as go-while decided (#366 was closed as declined: "We are not a banking system and we don't want CPU cycles wasted on bots bruteforcing accounts. No fake password hashing to prevent timing attacks.").

Changes

  • No decoy hashing. dummy_password_check and auth_file_sample_hash are gone. An unknown user, a locked or empty password field, or a plain-text field no longer costs a crypt(). The real checks (auto_cryptcheck, constant-time hashes_differ, plain-text handling) are unchanged.
  • Failed logins wait 1, 2 and 4 s per session, and the session is closed after the 3rd failure, as before. A successful login doesn't wait. A client that reconnects starts at 1 s again.
  • AuthFailureDelay keeps its name, since 1.3.22 configs set it. 0 turns the waiting off; any other value (0–3600 still parse) turns the 1/2/4 s rule on. The default is on.
  • New option AuthMinLength (default 10, 0 = off, range 0–255), one value for the user name and the password. A shorter name or password gets 481 after the failure wait, without a lookup, password check or PAM call, and counts as a failure. It is checked at PASS, so USER reveals nothing. The log line names the reason, never the password.
  • Docs: newscache.conf(5), the manual, the sample configs, FEDORA.md and docker/newscache.conf now say administrators must use user names and passwords of at least 10 bytes (AuthMinLength counts bytes). The examples were changed to match (alice-reader, reader-one/password-one).

Tests

  • Removed TestAuthUnknownUserTiming, TestAuthFailureDelay and TestAuthFailureDelayFixed.
  • The harness writes AuthMinLength 0, so the existing tests keep their short test users.
  • New tests:
    • TestAuthFailureBackoff: 1/2/4 s, then close. Also with AuthFailureDelay 15.
    • TestAuthMinLength: 9 bytes refused even with the right password and counted as a failure; 0 turns the check off; a 10-byte, 9-character name logs in.
    • TestAuthMinLengthConfig: -p prints both options; out-of-range values are errors.
    • TestAuthSuccessNoDelay and TestAuthFailureNoDelayOff.
  • All of the new tests fail on main where the behaviour changed.

Tested (by the implementing agent)

  • The full e2e suite and make check pass.
  • --with-pam --enable-plainpass builds cleanly.

For the release branch
The 1.3.23 NEWS entries about the flat 1 s AuthFailureDelay and the dummy hash check become wrong. changes/fix-auth-failure-backoff.md replaces them when the release PR moves it in. REVIEW.md rows #283, #292 and #378 need an update in the next docs batch.

NEWS: changes/fix-auth-failure-backoff.md.

🤖 Generated with Claude Code

go-while and others added 3 commits November 11, 2026 12:54
Failed logins now wait per session only: the first failed AUTHINFO PASS
gets its 481 after 1 s, the second after 2 s, the third after 4 s, and
the session is closed after the third failure, as before. A successful
login answers at once. AuthFailureDelay keeps its name so that 1.3.22
configurations still parse: 0 turns the wait off, any other value
(1 to 3600) turns it on; the default is 1.

The new option AuthMinLength (default 10, 0 to 255, 0 = off) refuses a
user name or password shorter than that many bytes when AUTHINFO PASS
arrives, after the failure wait and without a lookup, password check or
PAM call. It counts as a failed login. AUTHINFO USER still answers 381,
so it reveals nothing. The log line gives the reason without the
password. newscache -p prints the option.

dummy_password_check() and auth_file_sample_hash() are gone. They hashed
the client's password for an unknown user, a locked or empty field and
a plain-text field (--enable-plainpass), so that those answered as
slowly as a wrong password. We don't want CPU time spent on bots
guessing accounts. The real checks (auto_cryptcheck, the constant-time
hashes_differ, the plain-text comparison) are unchanged.

Tests: TestAuthUnknownUserTiming is removed; TestAuthFailureBackoff,
TestAuthSuccessNoDelay, TestAuthFailureNoDelayOff, TestAuthMinLength and
TestAuthMinLengthConfig are added in place of the 1-second tests. The e2e
harness writes "AuthMinLength 0" unless a test sets it, because the
existing tests log in as tester/secret and the system's test users.
The sample auth file and the documentation examples use names and
passwords of at least 10 characters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AuthMinLength counts bytes, and a 9-character name of multibyte
characters can be 10 bytes long, so the docs said something else than
the check does. They now say bytes too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@go-while
go-while merged commit e75da90 into main Nov 11, 2026
30 of 31 checks passed
@go-while
go-while deleted the fix/auth-failure-backoff branch November 11, 2026 19:28
go-while added a commit that referenced this pull request Nov 12, 2026
Found by nc-oc-gpt61t: the bullet said the log names the user only
after a password check, but #370's AuthMinLength refusals name it too
(with the reason), as the New options entry says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant