by willchan@chromium.org:
I'm not sure if I'm reading this correctly, but AFAICT, the default tls.Config does not
verify the certificate matches the server hostname. It seems that the hostname
verification is enabled by setting tls.Config.ServerName. Did I get that right? It seems
non-obvious that tls.Config.ServerName would do this, as the comments say:
"""
// ServerName is included in the client's handshake to support virtual
// hosting.
"""
My expectation on reading that comment was that tls.Config.ServerName only controlled
SNI. But, AFAICT, this is also used for controlling certificate hostname verification:
http://golang.org/src/pkg/crypto/tls/handshake_client.go:
126 if !c.config.InsecureSkipVerify {
127 opts := x509.VerifyOptions{
128 Roots: c.config.RootCAs,
129 CurrentTime: c.config.time(),
130 DNSName: c.config.ServerName,
131 Intermediates: x509.NewCertPool(),
132 }
So, VerifyOptions{DNSName} comes from tls.Config.ServerName.
http://golang.org/src/pkg/crypto/x509/verify.go:
228 if len(opts.DNSName) > 0 {
229 err = c.VerifyHostname(opts.DNSName)
230 if err != nil {
231 return
232 }
233 }
AFAICT, this means that if tls.Config.ServerName is empty (which I think is the
default), then server host verification is disabled. Am I understanding the code
correctly?
Assuming that's correct, then my next question is that is this intended? It does indeed
make sense that tls.Config.ServerName must be empty by default. That said, it seems like
it'd be nice to encourage people to enable certificate hostname verification, perhaps by
erroring out when it's not enabled and tls.Config.InsecureSkipVerify isn't set. It seems
like an easy error to make (spoken from personal experience).
by willchan@chromium.org: