Adam Eijdenberg
2017-May-15 00:24 UTC
Golang CertChecker hostname validation differs to OpenSSH
Hi all, Last week I noticed that the CertChecker in the Go implementation of x/crypto/ssh seems to be doing host principal validation incorrectly and filed the following bug: https://github.com/golang/go/issues/20273 By default they are looking for a principal named "host:port" inside of the certificate presented by the server, instead of just looking for the host as I believe OpenSSH does. e.g. the following error is generated: ssh: handshake failed: ssh: principal "localhost:2022" not in the set of valid principals for given certificate: ["localhost"] Before I ping the bug again, it would be good to get a second opinion as to whether that behaviour is correct or not. Cheers, Adam
Peter Moody
2017-May-15 01:39 UTC
Golang CertChecker hostname validation differs to OpenSSH
I think I wrote the code in question for the golang library (https://github.com/golang/crypto/commit/527d12e53572562de9fd348d50e1ee4096803cec) my reading of the sshd manpage is that ssh is more permissive than it should be SSH_KNOWN_HOSTS FILE FORMAT : ... A hostname or address may optionally be enclosed within `[' and `]' brackets then followed by `:' and a non-standard port number. I actually noticed this last week and meant to email this list to ask the openssh devs of the 'correct' behavior. On Sun, May 14, 2017 at 5:24 PM, Adam Eijdenberg <adam at continusec.com> wrote:> Hi all, > > Last week I noticed that the CertChecker in the Go implementation of > x/crypto/ssh seems to be doing host principal validation incorrectly > and filed the following bug: > https://github.com/golang/go/issues/20273 > > By default they are looking for a principal named "host:port" inside > of the certificate presented by the server, instead of just looking > for the host as I believe OpenSSH does. > > e.g. the following error is generated: > > ssh: handshake failed: ssh: principal "localhost:2022" not in the set > of valid principals for given certificate: ["localhost"] > > Before I ping the bug again, it would be good to get a second opinion > as to whether that behaviour is correct or not. > > Cheers, Adam > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Peter Moody
2017-May-15 01:43 UTC
Golang CertChecker hostname validation differs to OpenSSH
specifically, this is what openssh says when connecting to a a host with a otherwise valid hostcert on a non standard port debug1: Host 'foo.bar.com' is known and matches the ED25519-CERT host certificate. debug1: Found CA key in /etc/ssh/ssh_known_hosts:1 debug1: found matching key w/out port and this is when the port is correctly included in the known hosts debug1: Host '[foo.bar.com]:1234' is known and matches the ED25519-CERT host certificate. debug1: Found CA key in /etc/ssh/ssh_known_hosts:1 it definitely feels to me like the first behavior is incorrect. On Sun, May 14, 2017 at 6:39 PM, Peter Moody <mindrot at hda3.com> wrote:> I think I wrote the code in question for the golang library > (https://github.com/golang/crypto/commit/527d12e53572562de9fd348d50e1ee4096803cec) > > my reading of the sshd manpage is that ssh is more permissive than it should be > > SSH_KNOWN_HOSTS FILE FORMAT : > ... > > A hostname or address may optionally be enclosed within `[' and `]' > brackets then followed by `:' and a non-standard port number. > > I actually noticed this last week and meant to email this list to ask > the openssh devs of the 'correct' behavior. > > > On Sun, May 14, 2017 at 5:24 PM, Adam Eijdenberg <adam at continusec.com> wrote: >> Hi all, >> >> Last week I noticed that the CertChecker in the Go implementation of >> x/crypto/ssh seems to be doing host principal validation incorrectly >> and filed the following bug: >> https://github.com/golang/go/issues/20273 >> >> By default they are looking for a principal named "host:port" inside >> of the certificate presented by the server, instead of just looking >> for the host as I believe OpenSSH does. >> >> e.g. the following error is generated: >> >> ssh: handshake failed: ssh: principal "localhost:2022" not in the set >> of valid principals for given certificate: ["localhost"] >> >> Before I ping the bug again, it would be good to get a second opinion >> as to whether that behaviour is correct or not. >> >> Cheers, Adam >> _______________________________________________ >> openssh-unix-dev mailing list >> openssh-unix-dev at mindrot.org >> https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Adam Eijdenberg
2017-May-15 09:01 UTC
Golang CertChecker hostname validation differs to OpenSSH
On Mon, May 15, 2017 at 11:39 AM, Peter Moody <mindrot at hda3.com> wrote:> my reading of the sshd manpage is that ssh is more permissive than it should be > > SSH_KNOWN_HOSTS FILE FORMAT : > ... > > A hostname or address may optionally be enclosed within `[' and `]' > brackets then followed by `:' and a non-standard port number.Hi Peter, I'm not sure that quite answers the same question. ie at one level there is a decision that is made about whether a line in the known hosts file should be evaluated for a given host/port - and I think that's what you are referring to above. However once a line from known hosts is allowed for evaluation for a host/port, there's a second matter of checking whether the certificate presented contains the appropriate principal. I think this what "check_host_cert()" does, and as far as I can tell, OpenSSH only passes it the hostname (not "host:port"). See: https://github.com/openssh/openssh-portable/blob/f382362e8dfb6b277f16779ab1936399d7f2af78/sshconnect.c#L866 (for better or for worse, this would be roughly inline with X.509v3 cert host matching, which also doesn't match on port numbers)
Damien Miller
2017-May-16 16:46 UTC
Golang CertChecker hostname validation differs to OpenSSH
On Mon, 15 May 2017, Adam Eijdenberg wrote:> Hi all, > > Last week I noticed that the CertChecker in the Go implementation of > x/crypto/ssh seems to be doing host principal validation incorrectly > and filed the following bug: > https://github.com/golang/go/issues/20273 > > By default they are looking for a principal named "host:port" inside > of the certificate presented by the server, instead of just looking > for the host as I believe OpenSSH does.Darren will know better, since IIRC he added the port specifier to known_hosts originally. But I believe the behaviour is: If the default port is in use then the host principal is just the hostname. If a non-default port, then the host principals is "[host]:port". If a non-default port is in use and "[host]:port" doesn't match, then try the plain hostname. -d
Adam Eijdenberg
2017-May-16 22:10 UTC
Golang CertChecker hostname validation differs to OpenSSH
On Wed, May 17, 2017 at 2:46 AM, Damien Miller <djm at mindrot.org> wrote:> On Mon, 15 May 2017, Adam Eijdenberg wrote: >> https://github.com/golang/go/issues/20273 >> >> By default they are looking for a principal named "host:port" inside >> of the certificate presented by the server, instead of just looking >> for the host as I believe OpenSSH does. > > Darren will know better, since IIRC he added the port specifier to > known_hosts originally. But I believe the behaviour is: > > If the default port is in use then the host principal is just the hostname. > > If a non-default port, then the host principals is "[host]:port". > > If a non-default port is in use and "[host]:port" doesn't match, then > try the plain hostname.Hi Damien, I think we're still talking a bit at cross purposes. My question did not relate to how the known_hosts file is processed (which from examining code yesterday I think is roughly as you describe) but rather how should we be validating that a certificate presented by a host includes an appropriate principal for that host. OpenSSH checks whether the hostname is a principal, whereas the Go library is instead checking whether "host:port" is a principal. Uri (earlier in this thread) does answer this question clearly (that the principal should be the hostname only), and, now that I've found PROTOCOL.certkeys, this seems to be spelt out unambiguously there too: "valid principals" is a string containing zero or more principals as strings packed inside it. These principals list the names for which this certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and usernames for SSH_CERT_TYPE_USER certificates. As a special case, a zero-length "valid principals" field means the certificate is valid for any principal of the specified type. Cheers, Adam