Эх сурвалжийг харах

Don't select TLS profiles unsuitable for SESSION-TICKET

Rod Hynes 6 жил өмнө
parent
commit
3dedb29844

+ 12 - 0
psiphon/common/protocol/protocol.go

@@ -211,6 +211,10 @@ func TunnelProtocolIsCompatibleWithFragmentor(protocol string) bool {
 		protocol == TUNNEL_PROTOCOL_FRONTED_MEEK_HTTP
 }
 
+func TunnelProtocolRequiresTLS12SessionTickets(protocol string) bool {
+	return protocol == TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET
+}
+
 func TunnelProtocolSupportsPassthrough(protocol string) bool {
 	return protocol == TUNNEL_PROTOCOL_UNFRONTED_MEEK_HTTPS ||
 		protocol == TUNNEL_PROTOCOL_UNFRONTED_MEEK_SESSION_TICKET
@@ -284,6 +288,14 @@ func TLSProfileIsRandomized(tlsProfile string) bool {
 	return tlsProfile == TLS_PROFILE_RANDOMIZED
 }
 
+func TLS12ProfileOmitsSessionTickets(tlsProfile string) bool {
+	if tlsProfile == TLS_PROFILE_IOS_111 ||
+		tlsProfile == TLS_PROFILE_IOS_121 {
+		return true
+	}
+	return false
+}
+
 type TLSProfiles []string
 
 func (profiles TLSProfiles) Validate(customTLSProfiles []string) error {

+ 6 - 2
psiphon/dialParameters.go

@@ -372,10 +372,14 @@ func MakeDialParameters(
 	if (!isReplay || !replayTLSProfile) &&
 		protocol.TunnelProtocolUsesMeekHTTPS(dialParams.TunnelProtocol) {
 
+		dialParams.SelectedTLSProfile = true
+
+		requireTLS12SessionTickets := protocol.TunnelProtocolRequiresTLS12SessionTickets(
+			dialParams.TunnelProtocol)
 		isFronted := protocol.TunnelProtocolUsesFrontedMeek(dialParams.TunnelProtocol)
+		dialParams.TLSProfile = SelectTLSProfile(
+			requireTLS12SessionTickets, isFronted, serverEntry.FrontingProviderID, p)
 
-		dialParams.SelectedTLSProfile = true
-		dialParams.TLSProfile = SelectTLSProfile(isFronted, serverEntry.FrontingProviderID, p)
 		dialParams.NoDefaultTLSSessionID = p.WeightedCoinFlip(
 			parameters.NoDefaultTLSSessionIDProbability)
 	}

+ 14 - 1
psiphon/tlsDialer.go

@@ -161,6 +161,7 @@ func (config *CustomTLSConfig) EnableClientSessionCache() {
 
 // SelectTLSProfile picks a TLS profile at random from the available candidates.
 func SelectTLSProfile(
+	requireTLS12SessionTickets bool,
 	isFronted bool,
 	frontingProviderID string,
 	p parameters.ClientParametersAccessor) string {
@@ -219,6 +220,18 @@ func SelectTLSProfile(
 				continue
 			}
 
+			// requireTLS12SessionTickets is specified for
+			// UNFRONTED-MEEK-SESSION-TICKET-OSSH, a protocol which depends on using
+			// obfuscated session tickets to ensure that the server doesn't send its
+			// certificate in the TLS handshake. TLS 1.2 profiles which omit session
+			// tickets should not be selected. As TLS 1.3 encrypts the server
+			// certificate message, there's no exclusion for TLS 1.3.
+
+			if requireTLS12SessionTickets &&
+				protocol.TLS12ProfileOmitsSessionTickets(tlsProfile) {
+				continue
+			}
+
 			if protocol.TLSProfileIsRandomized(tlsProfile) {
 				randomizedTLSProfiles = append(randomizedTLSProfiles, tlsProfile)
 			} else {
@@ -390,7 +403,7 @@ func CustomTLSDial(
 	selectedTLSProfile := config.TLSProfile
 
 	if selectedTLSProfile == "" {
-		selectedTLSProfile = SelectTLSProfile(false, "", p)
+		selectedTLSProfile = SelectTLSProfile(false, false, "", p)
 	}
 
 	tlsConfigInsecureSkipVerify := false

+ 12 - 3
psiphon/tlsDialer_test.go

@@ -207,7 +207,7 @@ func TestSelectTLSProfile(t *testing.T) {
 	numSelections := 10000
 
 	for i := 0; i < numSelections; i++ {
-		profile := SelectTLSProfile(false, "", clientParameters.Get())
+		profile := SelectTLSProfile(false, false, "", clientParameters.Get())
 		selected[profile] += 1
 	}
 
@@ -286,7 +286,7 @@ func TestSelectTLSProfile(t *testing.T) {
 	customTLSProfileNames := clientParameters.Get().CustomTLSProfileNames()
 
 	for i := 0; i < numSelections; i++ {
-		profile := SelectTLSProfile(false, "", clientParameters.Get())
+		profile := SelectTLSProfile(false, false, "", clientParameters.Get())
 		if !common.Contains(customTLSProfileNames, profile) {
 			t.Errorf("unexpected non-custom TLS profile selected")
 		}
@@ -305,11 +305,20 @@ func TestSelectTLSProfile(t *testing.T) {
 	}
 
 	for i := 0; i < numSelections; i++ {
-		profile := SelectTLSProfile(true, frontingProviderID, clientParameters.Get())
+		profile := SelectTLSProfile(false, true, frontingProviderID, clientParameters.Get())
 		if common.Contains(disableTLSProfiles, profile) {
 			t.Errorf("unexpected disabled TLS profile selected")
 		}
 	}
+
+	// Session ticket incapable TLS 1.2 profiles should not be selected
+
+	for i := 0; i < numSelections; i++ {
+		profile := SelectTLSProfile(true, false, "", clientParameters.Get())
+		if protocol.TLS12ProfileOmitsSessionTickets(profile) {
+			t.Errorf("unexpected session ticket incapable TLS profile selected")
+		}
+	}
 }
 
 func BenchmarkRandomizedGetClientHelloVersion(b *testing.B) {