]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: reject SNI values with a trailing dot.
authorAdam Langley <agl@golang.org>
Mon, 5 Dec 2016 18:24:30 +0000 (10:24 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 1 Feb 2017 21:59:57 +0000 (21:59 +0000)
SNI values may not include a trailing dot according to
https://tools.ietf.org/html/rfc6066#section-3. Although crypto/tls
handled this correctly as a client, it didn't reject this as a server.

This change makes sending an SNI value with a trailing dot a fatal
error.

Updates #18114.

Change-Id: Ib7897ab40e98d4a7a4646ff8469a55233621f631
Reviewed-on: https://go-review.googlesource.com/33904
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_messages.go
src/crypto/tls/handshake_messages_test.go
src/crypto/tls/handshake_server_test.go

index 6eda18dbfce9eaaf86dd6b0c8d9a0bede2e17106..a4ca5d34fb878cb03ee612e61ee936375ba2fa11 100644 (file)
@@ -815,7 +815,7 @@ func hostnameInSNI(name string) string {
        if net.ParseIP(host) != nil {
                return ""
        }
-       if len(name) > 0 && name[len(name)-1] == '.' {
+       for len(name) > 0 && name[len(name)-1] == '.' {
                name = name[:len(name)-1]
        }
        return name
index 694bd918d85b612891587224ddbbac77def3c346..0c7581f3e36768688c082f752b920de41ff9c772 100644 (file)
@@ -4,7 +4,10 @@
 
 package tls
 
-import "bytes"
+import (
+       "bytes"
+       "strings"
+)
 
 type clientHelloMsg struct {
        raw                          []byte
@@ -393,6 +396,12 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
                                }
                                if nameType == 0 {
                                        m.serverName = string(d[:nameLen])
+                                       // An SNI value may not include a
+                                       // trailing dot. See
+                                       // https://tools.ietf.org/html/rfc6066#section-3.
+                                       if strings.HasSuffix(m.serverName, ".") {
+                                               return false
+                                       }
                                        break
                                }
                                d = d[nameLen:]
index f1154d4d01d7be3b85dd62742b9e261e69cf9cbb..7add97c32c1071041e426b3b9a2a11283b0d1641 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bytes"
        "math/rand"
        "reflect"
+       "strings"
        "testing"
        "testing/quick"
 )
@@ -123,6 +124,9 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        }
        if rand.Intn(10) > 5 {
                m.serverName = randomString(rand.Intn(255), rand)
+               for strings.HasSuffix(m.serverName, ".") {
+                       m.serverName = m.serverName[:len(m.serverName)-1]
+               }
        }
        m.ocspStapling = rand.Intn(10) > 5
        m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
index bcd3d43ea3cbe08d7a8b8abd466b1ca7f544e4d6..63845c170d7804afc786bed99e01430b948708b5 100644 (file)
@@ -137,6 +137,10 @@ func TestNoRC4ByDefault(t *testing.T) {
        testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
 }
 
+func TestRejectSNIWithTrailingDot(t *testing.T) {
+       testClientHelloFailure(t, testConfig, &clientHelloMsg{vers: VersionTLS12, serverName: "foo.com."}, "unexpected message")
+}
+
 func TestDontSelectECDSAWithRSAKey(t *testing.T) {
        // Test that, even when both sides support an ECDSA cipher suite, it
        // won't be selected if the server's private key doesn't support it.