Skip to content
This repository has been archived by the owner on Jul 24, 2023. It is now read-only.

Commit

Permalink
Relax RSA signature check (#2)
Browse files Browse the repository at this point in the history
Based on golang#221

This PR also relaxes the check for SSH certificates. Older OpenSSH clients versions (7.4 included in CentOS 7 for example) that don't understand `[email protected]` or `[email protected]` send SSH certificates signed SHA2 and the public key type set to `[email protected]`. Currently, this combination is rejected by `go/crypto`. OpenSSH implemented their own workaround for the problem https://github.com/openssh/openssh-portable/blob/25c8a2bbcc10c493d27faea57c42a6bf13fa51f2/ssh-rsa.c#L505-L518
openssh/openssh-portable@4ba0d54
  • Loading branch information
jakule authored Dec 21, 2022
1 parent 9726750 commit 903e656
Showing 1 changed file with 31 additions and 1 deletion.
32 changes: 31 additions & 1 deletion ssh/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,36 @@ func (l ServerAuthError) Error() string {
// It is returned in ServerAuthError.Errors from NewServerConn.
var ErrNoAuth = errors.New("ssh: no auth passed yet")

func isRSAType(algo string) bool {
return algo == KeyAlgoRSASHA512 || algo == KeyAlgoRSASHA256 || algo == KeyAlgoRSA
}

func isRSACertType(algo string) bool {
return algo == CertAlgoRSAv01
}

func algoCompatible(algo string, publicKey PublicKey, sig *Signature) bool {
if underlyingAlgo(algo) == sig.Format {
return true
}

// Buggy SSH clients may send ssh-rsa2-512 as the public key algorithm but
// actually include a rsa-sha signature.
// According to RFC 8332 Section 3.2:
// A server MAY, but is not required to, accept this variant or another variant that
// corresponds to a good-faith implementation and is considered safe to
// accept.
if publicKey.Type() == KeyAlgoRSA && isRSAType(algo) && isRSAType(sig.Format) {
return true
}

if publicKey.Type() == CertAlgoRSAv01 && isRSACertType(algo) && isRSAType(sig.Format) {
return true
}

return false
}

func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
sessionID := s.transport.getSessionID()
var cache pubKeyCache
Expand Down Expand Up @@ -567,7 +597,7 @@ userAuthLoop:
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
break
}
if underlyingAlgo(algo) != sig.Format {
if !algoCompatible(algo, pubKey, sig) {
authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo)
break
}
Expand Down

0 comments on commit 903e656

Please sign in to comment.