]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: don't send IP literals as SNI values.
authorAdam Langley <agl@golang.org>
Mon, 9 Nov 2015 03:10:14 +0000 (19:10 -0800)
committerAdam Langley <agl@golang.org>
Mon, 9 Nov 2015 23:09:48 +0000 (23:09 +0000)
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>

src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_client_test.go

index d47dc6182f0d91c2aad1da67a1030edca9448cc3..c68ebfe188b41a9609f40cccb4c2c93720e12602 100644 (file)
@@ -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
index 0b591d7309c2592b9067b8ba796519806260e1fd..462acfd1a121ac12eebcd6a89db622355347fe36 100644 (file)
@@ -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,
index 664fe8de6a0c73b0439cffcc5621955f49c955fd..b275da15d02cef502826d10a5d10183984096137 100644 (file)
@@ -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)
+               }
+       }
+}