forked from gitea/gitea
Backport #17281 There is a subtle bug in the SSH library x/crypto/ssh which makes the incorrect assumption that the public key type is the same as the signature algorithm type. This means that only ssh-rsa signatures are offered by default. This PR adds a workaround around this problem. Fix #17175 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
a87b813955
commit
8ace5c1161
|
@ -316,10 +316,66 @@ func Listen(host string, port int, ciphers []string, keyExchanges []string, macs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Workaround slightly broken behaviour in x/crypto/ssh/handshake.go:458-463
|
||||||
|
//
|
||||||
|
// Fundamentally the issue here is that HostKeyAlgos make the incorrect assumption
|
||||||
|
// that the PublicKey().Type() matches the signature algorithm.
|
||||||
|
//
|
||||||
|
// Therefore we need to add duplicates for the RSA with different signing algorithms.
|
||||||
|
signers := make([]ssh.Signer, 0, len(srv.HostSigners))
|
||||||
|
for _, signer := range srv.HostSigners {
|
||||||
|
if signer.PublicKey().Type() == "ssh-rsa" {
|
||||||
|
signers = append(signers,
|
||||||
|
&wrapSigner{
|
||||||
|
Signer: signer,
|
||||||
|
algorithm: gossh.SigAlgoRSASHA2512,
|
||||||
|
},
|
||||||
|
&wrapSigner{
|
||||||
|
Signer: signer,
|
||||||
|
algorithm: gossh.SigAlgoRSASHA2256,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
signers = append(signers, signer)
|
||||||
|
}
|
||||||
|
srv.HostSigners = signers
|
||||||
|
|
||||||
go listen(&srv)
|
go listen(&srv)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrapSigner wraps a signer and overrides its public key type with the provided algorithm
|
||||||
|
type wrapSigner struct {
|
||||||
|
ssh.Signer
|
||||||
|
algorithm string
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKey returns an associated PublicKey instance.
|
||||||
|
func (s *wrapSigner) PublicKey() gossh.PublicKey {
|
||||||
|
return &wrapPublicKey{
|
||||||
|
PublicKey: s.Signer.PublicKey(),
|
||||||
|
algorithm: s.algorithm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign returns raw signature for the given data. This method
|
||||||
|
// will apply the hash specified for the keytype to the data using
|
||||||
|
// the algorithm assigned for this key
|
||||||
|
func (s *wrapSigner) Sign(rand io.Reader, data []byte) (*gossh.Signature, error) {
|
||||||
|
return s.Signer.(gossh.AlgorithmSigner).SignWithAlgorithm(rand, data, s.algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapPublicKey wraps a PublicKey and overrides its type
|
||||||
|
type wrapPublicKey struct {
|
||||||
|
gossh.PublicKey
|
||||||
|
algorithm string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the algorithm
|
||||||
|
func (k *wrapPublicKey) Type() string {
|
||||||
|
return k.algorithm
|
||||||
|
}
|
||||||
|
|
||||||
// GenKeyPair make a pair of public and private keys for SSH access.
|
// GenKeyPair make a pair of public and private keys for SSH access.
|
||||||
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
|
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
|
||||||
// Private Key generated is PEM encoded
|
// Private Key generated is PEM encoded
|
||||||
|
|
Loading…
Reference in New Issue