aboutsummaryrefslogtreecommitdiffstats
path: root/modules/ssh
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2021-10-20 20:55:33 +0100
committerGitHub <noreply@github.com>2021-10-20 15:55:33 -0400
commit35b918f574464eeca89fcf0d5f3a07a58a4b5a38 (patch)
treee313796b0aa74127a93673a252809e85059ee8d3 /modules/ssh
parent98f70137567481c7caca68062017516498c039c4 (diff)
downloadgitea-35b918f574464eeca89fcf0d5f3a07a58a4b5a38.tar.gz
gitea-35b918f574464eeca89fcf0d5f3a07a58a4b5a38.zip
Offer rsa-sha2-512 and rsa-sha2-256 algorithms in internal SSH (#17281)
* Offer rsa-sha2-512 and rsa-sha2-256 algorithms in internal SSH 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> * as per review Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'modules/ssh')
-rw-r--r--modules/ssh/ssh.go56
1 files changed, 56 insertions, 0 deletions
diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go
index efe9525345..909ed32c5e 100644
--- a/modules/ssh/ssh.go
+++ b/modules/ssh/ssh.go
@@ -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)
}
+// 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.
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
// Private Key generated is PEM encoded