Skip to content

Commit 9f08b6c

Browse files
committed
crypto/tls: don't send IP literals as SNI values.
(This relands commit a4dcc69.) 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: I6e544a78a01388f8fe98150589d073b917087f75 Reviewed-on: https://go-review.googlesource.com/16776 Run-TryBot: Adam Langley <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> Reviewed-by: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 7bacfc6 commit 9f08b6c

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

src/crypto/tls/common.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,8 @@ type Config struct {
286286

287287
// ServerName is used to verify the hostname on the returned
288288
// certificates unless InsecureSkipVerify is given. It is also included
289-
// in the client's handshake to support virtual hosting.
289+
// in the client's handshake to support virtual hosting unless it is
290+
// an IP address.
290291
ServerName string
291292

292293
// ClientAuth determines the server's policy for

src/crypto/tls/handshake_client.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,20 @@ func (c *Conn) clientHandshake() error {
4949
return errors.New("tls: NextProtos values too large")
5050
}
5151

52+
sni := c.config.ServerName
53+
// IP address literals are not permitted as SNI values. See
54+
// https://tools.ietf.org/html/rfc6066#section-3.
55+
if net.ParseIP(sni) != nil {
56+
sni = ""
57+
}
58+
5259
hello := &clientHelloMsg{
5360
vers: c.config.maxVersion(),
5461
compressionMethods: []uint8{compressionNone},
5562
random: make([]byte, 32),
5663
ocspStapling: true,
5764
scts: true,
58-
serverName: c.config.ServerName,
65+
serverName: sni,
5966
supportedCurves: c.config.curvePreferences(),
6067
supportedPoints: []uint8{pointFormatUncompressed},
6168
nextProtoNeg: len(c.config.NextProtos) > 0,

src/crypto/tls/handshake_client_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,3 +600,30 @@ func TestHandshakClientSCTs(t *testing.T) {
600600
}
601601
runClientTestTLS12(t, test)
602602
}
603+
604+
func TestNoIPAddressesInSNI(t *testing.T) {
605+
for _, ipLiteral := range []string{"1.2.3.4", "::1"} {
606+
c, s := net.Pipe()
607+
608+
go func() {
609+
client := Client(c, &Config{ServerName: ipLiteral})
610+
client.Handshake()
611+
}()
612+
613+
var header [5]byte
614+
if _, err := io.ReadFull(s, header[:]); err != nil {
615+
t.Fatal(err)
616+
}
617+
recordLen := int(header[3])<<8 | int(header[4])
618+
619+
record := make([]byte, recordLen)
620+
if _, err := io.ReadFull(s, record[:]); err != nil {
621+
t.Fatal(err)
622+
}
623+
s.Close()
624+
625+
if bytes.Index(record, []byte(ipLiteral)) != -1 {
626+
t.Errorf("IP literal %q found in ClientHello: %x", ipLiteral, record)
627+
}
628+
}
629+
}

src/net/http/client_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -642,14 +642,18 @@ func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
642642

643643
func TestClientWithCorrectTLSServerName(t *testing.T) {
644644
defer afterTest(t)
645+
646+
const serverName = "example.com"
645647
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
646-
if r.TLS.ServerName != "127.0.0.1" {
647-
t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
648+
if r.TLS.ServerName != serverName {
649+
t.Errorf("expected client to set ServerName %q, got: %q", serverName, r.TLS.ServerName)
648650
}
649651
}))
650652
defer ts.Close()
651653

652-
c := &Client{Transport: newTLSTransport(t, ts)}
654+
trans := newTLSTransport(t, ts)
655+
trans.TLSClientConfig.ServerName = serverName
656+
c := &Client{Transport: trans}
653657
if _, err := c.Get(ts.URL); err != nil {
654658
t.Fatalf("expected successful TLS connection, got error: %v", err)
655659
}

0 commit comments

Comments
 (0)