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:
+4
-2
@@ -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":
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user