crypto/tls has two functions for creating a client connection: Dial,
which most users are expected to use, and Client, which is the
lower-level API.
Dial does what you expect: it gives you a secure connection to the
host that you specify and the majority of users of crypto/tls appear
to work fine with it.
Client gives more control but needs more care. Specifically, if it
isn't given a server name in the tls.Config then it doesn't check that
the server's certificates match any hostname - because it doesn't have
one to check against. It's assumed that users of the low-level API
call VerifyHostname on the certificate themselves if they didn't
supply a hostname.
A review of the uses of Client both within Google and in a couple of
external libraries has shown that nearly all of them got this wrong.
To a fair extent, this is a documentation problem. Client simply says
that a nil Config uses the defaults and Config didn't document how
important ServerName was when using the that API. This is my screwup
which will be fixed in Go 1.3[1].
However, in light of the results of the review I now believe that this
API is too dangerous and so we propose changing tls.Conn.Handshake so
that it returns an error when neither ServerName nor
InsecureSkipVerify is given in the tls.Config.
This might break some existing code and that's not something that we
do lightly[2]. However, it appears the nearly all the code that will
break has a security problem and so we believe that this might be
justified.
In many cases, users of tls.Client were only using it because they
wanted to use it with net.DialTimeout. I'll be adding tls.DialTimeout
in time for Go 1.3 so that these cases can safely use the high-level
API.
[1]
https://code.google.com/p/go/source/detail?r=50f617f47bbc1d0fe1372a596c3f0537d5f6fbf9
[2]
http://golang.org/doc/go1compat
Cheers
AGL