瀏覽代碼

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>
v1.2.3
Adam Langley 9 年之前
父節點
當前提交
25dd71bbe6
共有 3 個文件被更改,包括 37 次插入2 次删除
  1. +2
    -1
      common.go
  2. +8
    -1
      handshake_client.go
  3. +27
    -0
      handshake_client_test.go

+ 2
- 1
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


+ 8
- 1
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,


+ 27
- 0
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)
}
}
}

Loading…
取消
儲存