Commit Graph
19 Commits
Author SHA1 Message Date
Nicola Murino 5adb68b3e6 ssh: cap total userauth attempts per server connection
serverAuthenticate only bounded real failures via MaxAuthTries.
PartialSuccessError responses and the publickey isQuery short-circuit
both kept the loop running without incrementing authFailures, so a
client could keep the server processing SSH_MSG_USERAUTH_REQUEST
messages indefinitely on a single connection.

Add an unconditional cap, maxAuthServerAttempts = 128, on the total
number of userauth requests handled per connection. The counter is
incremented at the top of the loop before method dispatch, so every
method and every isQuery / partial-success path counts. When the cap
is exceeded the server sends SSH_MSG_DISCONNECT with reason 2 ("too
many authentication attempts"), mirroring the MaxAuthTries handling.
The bound is well below OpenSSH's hard cap of 1024 but above any
realistic multi-step auth flow.

Change-Id: I56779fc55cd00ddfd32ec938f8de3a49be0145dc
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781903
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
2026-05-27 09:40:09 -07:00
Nicola Murino d59570d1a3 ssh: add AuthCallback to ClientConfig
Add ClientAuthCallback, a hook invoked before each authentication
attempt that allows the client to dynamically select an auth method
based on server capabilities, partial successes, or previous failures.

clientAuthenticate tracks partial successes in a slice and passes
them to AuthCallback via ClientAuthContext.PartialSuccessMethods,
along with the list of failed methods and currently allowed methods.
When AuthCallback returns a non-nil AuthMethod, it is used for the
next attempt, bypassing the static findNext selection. When it
returns (nil, nil), the static config.Auth selection proceeds as
before. If AuthCallback returns (nil, error) the handshake aborts
immediately with that error.

To bound resource use when AuthCallback keeps supplying methods, the
client caps the total number of authentication attempts (failures and
partial successes combined) at 64; exceeding the cap aborts the
handshake with an error.

Fixes golang/go#76146

Change-Id: I0d02bea7b9dd724e95e5d9d49d85306666c0df7a
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/717140
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-05-21 19:36:57 -07:00
Neal Patel 533fb3f7e4 ssh: fix source-address critical option bypass
Previously, CVE-2024-45337 fixed an authorization bypass
for misused ssh server configurations; if any other type
of callback is passed other than public key, then the
source-address validation would be skipped.

Fixes CVE-2026-46595
Fixes golang/go#79570

Change-Id: I08d86a961048a232c8672f23000e693ed5a0e2fd
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781642
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Neal Patel <nealpatel@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
2026-05-21 17:03:26 -07:00
Nicola Murino b61cf853a8 ssh: enforce user presence verification for security keys
Previously the library did not verify the "User Presence" (UP) bit in
signatures generated by FIDO/U2F security keys
(sk-ecdsa-sha2-nistp256@openssh.com and sk-ssh-ed25519@openssh.com).
This allowed signatures without physical interaction to be accepted
if the underlying hardware produced them, deviating from the default
secure behavior expected by the FIDO standards and OpenSSH.

skECDSAPublicKey.Verify and skEd25519PublicKey.Verify now enforce
the user-presence bit (0x01, constant flagUserPresence) by default.
Signatures whose flags byte has UP clear fail with the sentinel
errSKMissingUserPresence.

The server public-key authentication path honors the OpenSSH
"no-touch-required" extension as an opt-out. noTouchAllowed reports
true when the extension is present either in the Permissions
returned by PublicKeyCallback (authorized_keys-level opt-out) or in
the certificate's own Extensions (CA-level opt-out); in that case
skKeyWithoutUP is used to derive a clone of the SK public key (and,
for certificates, a clone of the wrapping Certificate whose inner
Key is the cloned SK key) whose Verify accepts UP-clear signatures.
The originals are never mutated, so a per-session opt-out cannot
leak across authentication attempts or connections. Matching
OpenSSH, the opt-out is read only from Extensions, never from
CriticalOptions.

skKeyWithoutUP is iterative and unwraps at most one level of
*Certificate: the SSH cert format forbids Certificate.Key from being
another Certificate (parseCert rejects it) but callers can still
construct such a value directly in Go, so a recursive descent would
be driven to unbounded depth by malformed or cyclic input. Any such
pathological *Certificate is returned unchanged.

CertChecker.CheckCert applies skKeyWithoutUP unconditionally to the
certificate's CA key before verifying the CA signature, matching
OpenSSH, which calls sshkey_verify with detailsp==NULL in
sshkey.c:cert_parse and never extracts or enforces UP/UV flags on
CA signatures. The UP bit on a CA signature reflects the CA
operator's presence at cert-issuance time, which has no bearing on
whether the user being authenticated is present now, so enforcing it
here would only break interop with certificates issued by
non-interactive SK CAs without a corresponding security benefit. The
skKeyWithoutUP call is a no-op for non-SK CA keys (the common case).

This change breaks backward compatibility for clients or keys that
generate user-authentication signatures without the User Presence
flag set. Previously those signatures were accepted by the server.
They will now be rejected with "ssh: signature missing required user
presence flag" unless the "no-touch-required" extension is
explicitly granted to the session by the server callbacks, or
carried by the user certificate.

This issue was found during a security audit by NCC Group
Cryptography Services, sponsored by Teleport.

Fixes golang/go#79566
Fixes CVE-2026-39831

Change-Id: I74b6de3bb6a2d7a0f34d7fa36bbbbf06f0b3fc6b
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781662
Reviewed-by: Neal Patel <nealpatel@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-05-21 17:03:20 -07:00
Nicola Murino b25012b37b ssh: enforce nil Permissions when returning PartialSuccessError
In serverAuthenticate, the permissions variable is reset to nil at the
beginning of the authentication loop. If an authentication callback
returns a PartialSuccessError along with non-nil Permissions, those
permissions are currently silently discarded before the next
authentication step.

This change returns an error if a callback returns both a PartialSuccessError
and non-nil Permissions, preventing API misuse where the user might
erroneously expect those permissions to be preserved or merged into the
final session permissions.

This issue was found during a security audit by NCC Group Cryptography
Services, sponsored by Teleport.

Fixes golang/go#79562
Fixes CVE-2026-39828

Change-Id: I632c9e46e2b5e8804ef88081063a3612a2462f9f
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781621
Reviewed-by: Neal Patel <nealpatel@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
2026-05-21 17:00:58 -07:00
cuishuang 1faea2975c all: fix some typos in comment
Change-Id: Ia209f0a6d9b19d14e655c65d1287a1416b48c487
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/707535
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Sean Liao <sean@liao.dev>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
2025-10-08 13:58:26 -07:00
Nicola Murino 2beaa59a3c ssh: add VerifiedPublicKeyCallback
Fixes golang/go#70795

Change-Id: I9b7c91f35f89495d1e9b5f6ec0c036c02a61d774
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/636335
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jorge Hernández <jorgehcrda39@gmail.com>
2025-09-27 12:43:41 -07:00
Nicola Murino ac58737d25 ssh: export supported algorithms
Fixes golang/go#61537

Change-Id: If3478121e3ae445391e3faeceeb889d75e9e3214
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/531935
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
2025-05-15 10:43:30 -07:00
Brad Fitzpatrick a8ea4be81f ssh: add ServerConfig.PreAuthConnCallback, ServerPreAuthConn (banner) interface
Fixes golang/go#68688

Change-Id: Id5f72b32c61c9383a26ec182339486a432c7cdf5
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/613856
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
2025-01-18 11:27:23 -08:00
Roland Shoemaker b4f1988a35 ssh: make the public key cache a 1-entry FIFO cache
Users of the the ssh package seem to extremely commonly misuse the
PublicKeyCallback API, assuming that the key passed in the last call
before a connection is established is the key used for authentication.
Some users then make authorization decisions based on this key. This
property is not documented, and may not be correct, due to the caching
behavior of the package, resulting in users making incorrect
authorization decisions about the connection.

This change makes the cache a one entry FIFO cache, making the assumed
property, that the last call to PublicKeyCallback represents the key
actually used for authentication, actually hold.

Thanks to Damien Tournoud, Patrick Dawkins, Vince Parker, and
Jules Duvivier from the Platform.sh / Upsun engineering team
for reporting this issue.

Fixes golang/go#70779
Fixes CVE-2024-45337

Change-Id: Ife7c7b4045d8b6bcd7e3a417bdfae370c709797f
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/635315
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-12-11 09:50:49 -08:00
Ilia Mirkin 6879722274 ssh: remove go 1.21+ dependency on slices
Fixes golang/go#68469

Change-Id: Ieea3c444b0458d169a6ff224e59b3b815264de89
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/598775
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2024-07-17 17:59:23 +00:00
Andrew Lytvynov 44c9b0ff9e ssh: allow server auth callbacks to send additional banners
Add a new BannerError error type that auth callbacks can return to send
banner to the client. While the BannerCallback can send the initial
banner message, auth callbacks might want to communicate more
information to the client to help them diagnose failures.

Updates golang/go#64962

Change-Id: I97a26480ff4064b95a0a26042b0a5e19737cfb62
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/558695
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2024-05-22 20:07:48 +00:00
Nicola Murino b92bf9480d ssh: respect MaxAuthTries also for "none" auth attempts
Only the first "none" auth attempt is allowed without penality

Change-Id: Ibe776e968ba406445eeb94e8f1959383b88c98f7
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/575995
Reviewed-by: Filippo Valsorda <filippo@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Commit-Queue: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
2024-04-04 14:49:27 +00:00
Edoardo Spadolini 4e5a26183e ssh: close net.Conn on all NewServerConn errors
This PR ensures that the net.Conn passed to ssh.NewServerConn is closed
on all error return paths, not just after a failed handshake. This matches
the behavior of ssh.NewClientConn.

Change-Id: Id8a51d10ae8d575cbbe26f2ef6b37de7cca840ec
GitHub-Last-Rev: 81bb2e58a881a9a85935740bda06b034b32a8ce3
GitHub-Pull-Request: golang/crypto#279
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/549095
Run-TryBot: Nicola Murino <nicola.murino@gmail.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2023-12-14 18:23:28 +00:00
Nicola Murino eb61739cd9 ssh: allow to configure public key auth algorithms on the server side
Fixes golang/go#61244

Change-Id: I29b43e379cf0cdb07b0d6935666491b997157e73
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/510775
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Commit-Queue: Nicola Murino <nicola.murino@gmail.com>
Run-TryBot: Nicola Murino <nicola.murino@gmail.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
2023-11-08 19:10:19 +00:00
Dave Cheney 06790d30c2 go.crypto/ssh: improve test reliability
Fixes golang/go#3989.

Tested for several hours on an 8 core ec2 instance with
random GOMAXPROC values.

Also, rolls server_test.go into session_test using the
existing dial() framework.

R=fullung, agl, kardianos
CC=golang-dev
https://golang.org/cl/6475063
2012-08-28 08:06:15 +10:00
Dave Cheney e751d5236a go.crypto/ssh: improve TestServerWindow robustness
Fix a few resource leaks and prevent the test from
hanging if an error occurs reading from the remote
server.

R=agl, gustav.paul, kardianos
CC=golang-dev
https://golang.org/cl/6423065
2012-07-21 14:19:30 +10:00
Dave Cheney 58afe880f1 go.crypto/ssh: server_test should bind to localhost only
Hopefully fix build error under windows.

Binding to the wildcard is poor form for our darwin users
as it triggers the firewall popup. Dialing the wildcard
looks like it's implementation specific as well.

R=agl, kardianos
CC=golang-dev
https://golang.org/cl/6104046
2012-04-21 10:44:56 +10:00
Daniel Theophanes 81e0b644eb go.crypt/ssh: Add additional test for server.
R=golang-dev, agl
CC=golang-dev
https://golang.org/cl/6075046
2012-04-19 16:46:46 -04:00