ssh: report verified signature format to callback

VerifiedPublicKeyCallback currently receives the public-key algorithm
declared in the outer authentication request. For RSA authentication,
that value can differ from the format of the signature that was
successfully verified because compatible RSA algorithm combinations are
accepted.

This can cause post-verification policy or audit decisions to use the
request algorithm instead of the signature format actually verified.

Pass sig.Format to VerifiedPublicKeyCallback so signatureAlgorithm
identifies the successfully verified signature format. Clarify the
callback documentation and add a regression test covering compatible
but different RSA request algorithms and signature formats.

Fixes golang/go#80411

Change-Id: Ib405378d75367a90536e0814c9d26d4dec9aaa25
GitHub-Last-Rev: 1a4acd4e639361be1f2948a4aef1013436a75ecf
GitHub-Pull-Request: golang/crypto#364
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/800740
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Akira
2026-07-17 15:41:46 -07:00
committed by Gopher Robot
parent 10b54ffa51
commit ff03dafdb0
2 changed files with 60 additions and 2 deletions
+4 -2
View File
@@ -229,7 +229,9 @@ type ServerConfig struct {
// Permissions object can be the same object, optionally modified, or a
// completely new object. If VerifiedPublicKeyCallback is non-nil,
// PublicKeyCallback is not allowed to return a PartialSuccessError, which
// can instead be returned by VerifiedPublicKeyCallback.
// can instead be returned by VerifiedPublicKeyCallback. The
// signatureAlgorithm argument is the format of the signature that was
// successfully verified.
//
// VerifiedPublicKeyCallback does not affect which authentication methods
// are included in the list of methods that can be attempted by the client.
@@ -891,7 +893,7 @@ userAuthLoop:
// Only call VerifiedPublicKeyCallback after the key has been accepted
// and successfully verified. If authErr is non-nil, the key is not
// considered verified and the callback must not run.
perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo)
perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, sig.Format)
}
}
case "gssapi-with-mic":
+56
View File
@@ -544,6 +544,62 @@ func TestVerifiedPublicKeyCallback(t *testing.T) {
<-done
}
func TestVerifiedPublicKeyCallbackSignatureFormat(t *testing.T) {
c1, c2, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
}
defer c1.Close()
defer c2.Close()
var gotSignatureAlgorithm string
serverConf := &ServerConfig{
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
return nil, nil
},
VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) {
gotSignatureAlgorithm = signatureAlgorithm
return permissions, nil
},
}
serverConf.AddHostKey(testSigners["rsa"])
serverDone := make(chan error, 1)
go func() {
conn, _, _, err := NewServerConn(c1, serverConf)
if err == nil {
conn.Close()
}
serverDone <- err
}()
clientConf := &ClientConfig{
User: "user",
Auth: []AuthMethod{
// The selected algorithm and signature format differ for
// compatibility with old RSA clients.
configurablePublicKeyCallback{
signer: testSigners["rsa"].(AlgorithmSigner),
signatureAlgo: KeyAlgoRSASHA256,
signatureFormat: KeyAlgoRSA,
},
},
HostKeyCallback: InsecureIgnoreHostKey(),
}
clientConn, _, _, clientErr := NewClientConn(c2, "", clientConf)
if clientErr == nil {
clientConn.Close()
}
serverErr := <-serverDone
if clientErr != nil || serverErr != nil {
t.Fatalf("connection failed: client error: %v; server error: %v", clientErr, serverErr)
}
if gotSignatureAlgorithm != KeyAlgoRSA {
t.Errorf("signature algorithm = %q; want verified signature format %q", gotSignatureAlgorithm, KeyAlgoRSA)
}
}
func TestVerifiedPublicCallbackPartialSuccess(t *testing.T) {
c1, c2, err := netPipe()
if err != nil {