aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Langley <agl@golang.org>2015-11-08 19:10:14 -0800
committerAdam Langley <agl@golang.org>2015-11-09 23:09:48 +0000
commita4dcc692011bf1ceca9b1a363fd83f3e59e399ee (patch)
tree91e28169c78c03656d479a885ccd52bbc7511b96
parent712ffc0861cd6ec425736422415bf650c6cb013f (diff)
downloadgo-a4dcc692011bf1ceca9b1a363fd83f3e59e399ee.tar.xz
crypto/tls: don't send IP literals as SNI values.
https://tools.ietf.org/html/rfc6066#section-3 states: “Literal IPv4 and IPv6 addresses are not permitted in "HostName".” However, if an IP literal was set as Config.ServerName (which could happen as easily as calling Dial with an IP address) then the code would send the IP literal as the SNI value. This change filters out IP literals, as recognised by net.ParseIP, from being sent as the SNI value. Fixes #13111. Change-Id: Ie9ec7acc767ae172b48c9c6dd8d84fa27b1cf0de Reviewed-on: https://go-review.googlesource.com/16742 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Adam Langley <agl@golang.org>
-rw-r--r--src/crypto/tls/common.go3
-rw-r--r--src/crypto/tls/handshake_client.go9
-rw-r--r--src/crypto/tls/handshake_client_test.go27
3 files changed, 37 insertions, 2 deletions
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index d47dc6182f..c68ebfe188 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -286,7 +286,8 @@ type Config struct {
// ServerName is used to verify the hostname on the returned
// certificates unless InsecureSkipVerify is given. It is also included
- // in the client's handshake to support virtual hosting.
+ // in the client's handshake to support virtual hosting unless it is
+ // an IP address.
ServerName string
// ClientAuth determines the server's policy for
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
index 0b591d7309..462acfd1a1 100644
--- a/src/crypto/tls/handshake_client.go
+++ b/src/crypto/tls/handshake_client.go
@@ -49,13 +49,20 @@ func (c *Conn) clientHandshake() error {
return errors.New("tls: NextProtos values too large")
}
+ sni := c.config.ServerName
+ // IP address literals are not permitted as SNI values. See
+ // https://tools.ietf.org/html/rfc6066#section-3.
+ if net.ParseIP(sni) != nil {
+ sni = ""
+ }
+
hello := &clientHelloMsg{
vers: c.config.maxVersion(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
scts: true,
- serverName: c.config.ServerName,
+ serverName: sni,
supportedCurves: c.config.curvePreferences(),
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
index 664fe8de6a..b275da15d0 100644
--- a/src/crypto/tls/handshake_client_test.go
+++ b/src/crypto/tls/handshake_client_test.go
@@ -600,3 +600,30 @@ func TestHandshakClientSCTs(t *testing.T) {
}
runClientTestTLS12(t, test)
}
+
+func TestNoIPAddressesInSNI(t *testing.T) {
+ for _, ipLiteral := range []string{"1.2.3.4", "::1"} {
+ c, s := net.Pipe()
+
+ go func() {
+ client := Client(c, &Config{ServerName: ipLiteral})
+ client.Handshake()
+ }()
+
+ var header [5]byte
+ if _, err := io.ReadFull(s, header[:]); err != nil {
+ t.Fatal(err)
+ }
+ recordLen := int(header[3])<<8 | int(header[4])
+
+ record := make([]byte, recordLen)
+ if _, err := io.ReadFull(s, record[:]); err != nil {
+ t.Fatal(err)
+ }
+ s.Close()
+
+ if bytes.Index(record, []byte(ipLiteral)) != -1 {
+ t.Errorf("IP literal %q found in ClientHello: %x", ipLiteral, record)
+ }
+ }
+}