diff --git a/u_conn_test.go b/u_conn_test.go index daec15ed..2ce4b515 100644 --- a/u_conn_test.go +++ b/u_conn_test.go @@ -196,6 +196,38 @@ func TestUTLSRemoveSNIExtension(t *testing.T) { runUTLSClientTestForVersion(t, test, "TLSv12-", "-tls1_2", hello, true) } +func TestUTLSServerNameIP(t *testing.T) { + hello := &helloID{HelloChrome_70} + + config := getUTLSTestConfig() + config.ServerName = "1.1.1.1" + + opensslCipherName := "ECDHE-RSA-AES128-GCM-SHA256" + test := &clientTest{ + name: "UTLS-" + opensslCipherName + "-" + hello.helloName() + "-ServerNameIP", + args: []string{"-cipher", opensslCipherName}, + config: config, + } + + runUTLSClientTestForVersion(t, test, "TLSv12-", "-tls1_2", hello, true) +} + +func TestUTLSEmptyServerName(t *testing.T) { + hello := &helloID{HelloChrome_70} + + config := getUTLSTestConfig() + config.ServerName = "" + + opensslCipherName := "ECDHE-RSA-AES128-GCM-SHA256" + test := &clientTest{ + name: "UTLS-" + opensslCipherName + "-" + hello.helloName() + "-EmptyServerName", + args: []string{"-cipher", opensslCipherName}, + config: config, + } + + runUTLSClientTestForVersion(t, test, "TLSv12-", "-tls1_2", hello, true) +} + /* * HELPER FUNCTIONS BELOW @@ -212,6 +244,7 @@ func getUTLSTestConfig() *Config { MinVersion: VersionSSL30, MaxVersion: VersionTLS13, CipherSuites: allCipherSuites(), + ServerName: "foobar.com", } return testUTLSConfig } diff --git a/u_tls_extensions.go b/u_tls_extensions.go index 2e4d0476..4330f36b 100644 --- a/u_tls_extensions.go +++ b/u_tls_extensions.go @@ -49,29 +49,43 @@ type SNIExtension struct { func (e *SNIExtension) writeToUConn(uc *UConn) error { uc.config.ServerName = e.ServerName - uc.HandshakeState.Hello.ServerName = e.ServerName + hostName := hostnameInSNI(e.ServerName) + uc.HandshakeState.Hello.ServerName = hostName + return nil } func (e *SNIExtension) Len() int { - return 4 + 2 + 1 + 2 + len(e.ServerName) + // Literal IP addresses, absolute FQDNs, and empty strings are not permitted as SNI values. + // See RFC 6066, Section 3. + hostName := hostnameInSNI(e.ServerName) + if len(hostName) == 0 { + return 0 + } + return 4 + 2 + 1 + 2 + len(hostName) } func (e *SNIExtension) Read(b []byte) (int, error) { + // Literal IP addresses, absolute FQDNs, and empty strings are not permitted as SNI values. + // See RFC 6066, Section 3. + hostName := hostnameInSNI(e.ServerName) + if len(hostName) == 0 { + return 0, io.EOF + } if len(b) < e.Len() { return 0, io.ErrShortBuffer } // RFC 3546, section 3.1 b[0] = byte(extensionServerName >> 8) b[1] = byte(extensionServerName) - b[2] = byte((len(e.ServerName) + 5) >> 8) - b[3] = byte((len(e.ServerName) + 5)) - b[4] = byte((len(e.ServerName) + 3) >> 8) - b[5] = byte(len(e.ServerName) + 3) + b[2] = byte((len(hostName) + 5) >> 8) + b[3] = byte((len(hostName) + 5)) + b[4] = byte((len(hostName) + 3) >> 8) + b[5] = byte(len(hostName) + 3) // b[6] Server Name Type: host_name (0) - b[7] = byte(len(e.ServerName) >> 8) - b[8] = byte(len(e.ServerName)) - copy(b[9:], []byte(e.ServerName)) + b[7] = byte(len(hostName) >> 8) + b[8] = byte(len(hostName)) + copy(b[9:], []byte(hostName)) return e.Len(), io.EOF }