Просмотр исходного кода

Fix: malformed non-EmulateChrome TLS ClientHello

- The EmulateChrome padding extension was partially
  applied in non-EmulateChrome mode.

- Add EmulateChrome on/off test cases for
  TestObfuscatedSessionTicket. Run test in TravisCI.
Rod Hynes 8 лет назад
Родитель
Сommit
5419c562d7
3 измененных файлов с 30 добавлено и 11 удалено
  1. 2 0
      .travis.yml
  2. 11 10
      psiphon/common/tls/handshake_messages.go
  3. 17 1
      psiphon/common/tls/obfuscated_test.go

+ 2 - 0
.travis.yml

@@ -12,6 +12,7 @@ script:
 - go test -race -v ./common
 - go test -race -v ./common/osl
 - go test -race -v ./common/protocol
+- go test -race -v -run TestObfuscatedSessionTicket ./common/tls
 - go test -race -v ./transferstats
 - go test -race -v ./server
 - go test -race -v ./server/psinet
@@ -19,6 +20,7 @@ script:
 - go test -v -covermode=count -coverprofile=common.coverprofile ./common
 - go test -v -covermode=count -coverprofile=osl.coverprofile ./common/osl
 - go test -v -covermode=count -coverprofile=protocol.coverprofile ./common/protocol
+- go test -v -covermode=count -coverprofile=tls.coverprofile -run TestObfuscatedSessionTicket ./common/tls
 - go test -v -covermode=count -coverprofile=transferstats.coverprofile ./transferstats
 - go test -v -covermode=count -coverprofile=server.coverprofile ./server
 - go test -v -covermode=count -coverprofile=psinet.coverprofile ./server/psinet

+ 11 - 10
psiphon/common/tls/handshake_messages.go

@@ -140,18 +140,19 @@ func (m *clientHelloMsg) marshal() []byte {
 	//
 	// https://github.com/google/boringssl/blob/46db7af2c998cf8514d606408546d9be9699f03c/ssl/t1_lib.c#L2803
 	// https://github.com/google/boringssl/blob/master/LICENSE
-
-	unpaddedLength := length + 2 + 4*numExtensions + extensionsLength
 	paddingLength := uint16(0)
-	if unpaddedLength > 0xff && unpaddedLength < 0x200 {
-		paddingLength = 0x200 - uint16(unpaddedLength)
-		if paddingLength >= 4+1 {
-			paddingLength -= 4
-		} else {
-			paddingLength = 1
+	if m.emulateChrome {
+		unpaddedLength := length + 2 + 4*numExtensions + extensionsLength
+		if unpaddedLength > 0xff && unpaddedLength < 0x200 {
+			paddingLength = 0x200 - uint16(unpaddedLength)
+			if paddingLength >= 4+1 {
+				paddingLength -= 4
+			} else {
+				paddingLength = 1
+			}
+			extensionsLength += int(paddingLength)
+			numExtensions++
 		}
-		extensionsLength += int(paddingLength)
-		numExtensions++
 	}
 
 	if numExtensions > 0 {

+ 17 - 1
psiphon/common/tls/obfuscated_test.go

@@ -37,6 +37,14 @@ import (
 // [Psiphon]
 // TestObfuscatedSessionTicket exercises the Obfuscated Session Tickets facility.
 func TestObfuscatedSessionTicket(t *testing.T) {
+	runObfuscatedSessionTicket(t, false)
+}
+
+func TestObfuscatedSessionTicketEmulateChrome(t *testing.T) {
+	runObfuscatedSessionTicket(t, true)
+}
+
+func runObfuscatedSessionTicket(t *testing.T, emulateChrome bool) {
 
 	var standardSessionTicketKey [32]byte
 	rand.Read(standardSessionTicketKey[:])
@@ -46,7 +54,8 @@ func TestObfuscatedSessionTicket(t *testing.T) {
 
 	// Note: SNI and certificate CN don't match
 	clientConfig := &Config{
-		ServerName: "www.example.com",
+		ServerName:    "www.example.com",
+		EmulateChrome: emulateChrome,
 		ClientSessionCache: NewObfuscatedClientSessionCache(
 			obfuscatedSessionTicketSharedSecret),
 	}
@@ -72,9 +81,14 @@ func TestObfuscatedSessionTicket(t *testing.T) {
 
 	result := make(chan error, 1)
 
+	listening := make(chan struct{}, 1)
+
 	go func() {
 
 		listener, err := Listen("tcp", serverAddress, serverConfig)
+		defer listener.Close()
+
+		listening <- *new(struct{})
 
 		var conn net.Conn
 		if err == nil {
@@ -103,6 +117,8 @@ func TestObfuscatedSessionTicket(t *testing.T) {
 
 	go func() {
 
+		<-listening
+
 		conn, err := Dial("tcp", serverAddress, clientConfig)
 
 		if err == nil {