diff options
| author | Adam Eijdenberg <adam@continusec.com> | 2017-05-16 13:11:29 +1000 |
|---|---|---|
| committer | Han-Wen Nienhuys <hanwen@google.com> | 2017-05-23 10:10:29 +0000 |
| commit | 7e9105388ebff089b3f99f0ef676ea55a6da3a7e (patch) | |
| tree | 3897b171620dad13e27364c6365e928a00d10b9b /ssh/certs.go | |
| parent | 6c586e17d90a7d08bbbc4069984180dce3b04117 (diff) | |
| download | go-x-crypto-7e9105388ebff089b3f99f0ef676ea55a6da3a7e.tar.xz | |
x/crypto/ssh: fix host certificate principal evaluation to check for hostname only
SSH host certificates are expected to contain hostnames only,
not "host:port" format.
This change allows Go clients to connect to OpenSSH servers that
use host certificates.
Note, this change will break any clients that use ssh.NewClientConn()
with an `addr` that is not in `host:port` format (they will see a
"missing port in address" error).
Fixes bug 20273.
Change-Id: I5a306c6b7b419a737e1f0f9c5ca8c585e21a45a4
Reviewed-on: https://go-review.googlesource.com/43475
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'ssh/certs.go')
| -rw-r--r-- | ssh/certs.go | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/ssh/certs.go b/ssh/certs.go index 2fc8af1..b1f0220 100644 --- a/ssh/certs.go +++ b/ssh/certs.go @@ -298,8 +298,17 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) if cert.CertType != HostCert { return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) } + if !c.IsHostAuthority(cert.SignatureKey, addr) { + return fmt.Errorf("ssh: no authorities for hostname: %v", addr) + } + + hostname, _, err := net.SplitHostPort(addr) + if err != nil { + return err + } - return c.CheckCert(addr, cert) + // Pass hostname only as principal for host certificates (consistent with OpenSSH) + return c.CheckCert(hostname, cert) } // Authenticate checks a user certificate. Authenticate can be used as @@ -316,6 +325,9 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis if cert.CertType != UserCert { return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) } + if !c.IsUserAuthority(cert.SignatureKey) { + return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") + } if err := c.CheckCert(conn.User(), cert); err != nil { return nil, err @@ -364,16 +376,6 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { } } - // if this is a host cert, principal is the remote hostname as passed - // to CheckHostCert. - if cert.CertType == HostCert && !c.IsHostAuthority(cert.SignatureKey, principal) { - return fmt.Errorf("ssh: no authorities for hostname: %v", principal) - } - - if cert.CertType == UserCert && !c.IsUserAuthority(cert.SignatureKey) { - return fmt.Errorf("ssh: certificate signed by unrecognized authority") - } - clock := c.Clock if clock == nil { clock = time.Now |
