• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 Square, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.squareup.okhttp;
17 
18 import java.util.Arrays;
19 import java.util.LinkedHashSet;
20 import java.util.Set;
21 import java.util.concurrent.CopyOnWriteArraySet;
22 import javax.net.ssl.SSLSocket;
23 import javax.net.ssl.SSLSocketFactory;
24 import org.junit.Test;
25 
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assert.fail;
31 
32 public final class ConnectionSpecTest {
noTlsVersions()33   @Test public void noTlsVersions() throws Exception {
34     try {
35       new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
36           .tlsVersions(new TlsVersion[0])
37           .build();
38       fail();
39     } catch (IllegalArgumentException expected) {
40       assertEquals("At least one TLS version is required", expected.getMessage());
41     }
42   }
43 
noCipherSuites()44   @Test public void noCipherSuites() throws Exception {
45     try {
46       new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
47           .cipherSuites(new CipherSuite[0])
48           .build();
49       fail();
50     } catch (IllegalArgumentException expected) {
51       assertEquals("At least one cipher suite is required", expected.getMessage());
52     }
53   }
54 
cleartextBuilder()55   @Test public void cleartextBuilder() throws Exception {
56     ConnectionSpec cleartextSpec = new ConnectionSpec.Builder(false).build();
57     assertFalse(cleartextSpec.isTls());
58   }
59 
tlsBuilder_explicitCiphers()60   @Test public void tlsBuilder_explicitCiphers() throws Exception {
61     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
62         .cipherSuites(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA)
63         .tlsVersions(TlsVersion.TLS_1_2)
64         .supportsTlsExtensions(true)
65         .build();
66     assertEquals(Arrays.asList(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA), tlsSpec.cipherSuites());
67     assertEquals(Arrays.asList(TlsVersion.TLS_1_2), tlsSpec.tlsVersions());
68     assertTrue(tlsSpec.supportsTlsExtensions());
69   }
70 
tlsBuilder_defaultCiphers()71   @Test public void tlsBuilder_defaultCiphers() throws Exception {
72     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
73         .tlsVersions(TlsVersion.TLS_1_2)
74         .supportsTlsExtensions(true)
75         .build();
76     assertNull(tlsSpec.cipherSuites());
77     assertEquals(Arrays.asList(TlsVersion.TLS_1_2), tlsSpec.tlsVersions());
78     assertTrue(tlsSpec.supportsTlsExtensions());
79   }
80 
tls_defaultCiphers_noFallbackIndicator()81   @Test public void tls_defaultCiphers_noFallbackIndicator() throws Exception {
82     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
83         .tlsVersions(TlsVersion.TLS_1_2)
84         .supportsTlsExtensions(false)
85         .build();
86 
87     SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
88     socket.setEnabledCipherSuites(new String[] {
89         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
90         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
91     });
92     socket.setEnabledProtocols(new String[] {
93         TlsVersion.TLS_1_2.javaName,
94         TlsVersion.TLS_1_1.javaName,
95     });
96 
97     assertTrue(tlsSpec.isCompatible(socket));
98     tlsSpec.apply(socket, false /* isFallback */);
99 
100     assertEquals(set(TlsVersion.TLS_1_2.javaName), set(socket.getEnabledProtocols()));
101 
102     Set<String> expectedCipherSet =
103         set(
104             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
105             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName);
106     assertEquals(expectedCipherSet, expectedCipherSet);
107   }
108 
tls_defaultCiphers_withFallbackIndicator()109   @Test public void tls_defaultCiphers_withFallbackIndicator() throws Exception {
110     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
111         .tlsVersions(TlsVersion.TLS_1_2)
112         .supportsTlsExtensions(false)
113         .build();
114 
115     SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
116     socket.setEnabledCipherSuites(new String[] {
117         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
118         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
119     });
120     socket.setEnabledProtocols(new String[] {
121         TlsVersion.TLS_1_2.javaName,
122         TlsVersion.TLS_1_1.javaName,
123     });
124 
125     assertTrue(tlsSpec.isCompatible(socket));
126     tlsSpec.apply(socket, true /* isFallback */);
127 
128     assertEquals(set(TlsVersion.TLS_1_2.javaName), set(socket.getEnabledProtocols()));
129 
130     Set<String> expectedCipherSet =
131         set(
132             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
133             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName);
134     if (Arrays.asList(socket.getSupportedCipherSuites()).contains("TLS_FALLBACK_SCSV")) {
135       expectedCipherSet.add("TLS_FALLBACK_SCSV");
136     }
137     assertEquals(expectedCipherSet, expectedCipherSet);
138   }
139 
tls_explicitCiphers()140   @Test public void tls_explicitCiphers() throws Exception {
141     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
142         .cipherSuites(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA)
143         .tlsVersions(TlsVersion.TLS_1_2)
144         .supportsTlsExtensions(false)
145         .build();
146 
147     SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
148     socket.setEnabledCipherSuites(new String[] {
149         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
150         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
151     });
152     socket.setEnabledProtocols(new String[] {
153         TlsVersion.TLS_1_2.javaName,
154         TlsVersion.TLS_1_1.javaName,
155     });
156 
157     assertTrue(tlsSpec.isCompatible(socket));
158     tlsSpec.apply(socket, true /* isFallback */);
159 
160     assertEquals(set(TlsVersion.TLS_1_2.javaName), set(socket.getEnabledProtocols()));
161 
162     Set<String> expectedCipherSet = set(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName);
163     if (Arrays.asList(socket.getSupportedCipherSuites()).contains("TLS_FALLBACK_SCSV")) {
164       expectedCipherSet.add("TLS_FALLBACK_SCSV");
165     }
166     assertEquals(expectedCipherSet, expectedCipherSet);
167   }
168 
tls_stringCiphersAndVersions()169   @Test public void tls_stringCiphersAndVersions() throws Exception {
170     // Supporting arbitrary input strings allows users to enable suites and versions that are not
171     // yet known to the library, but are supported by the platform.
172     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
173         .cipherSuites("MAGIC-CIPHER")
174         .tlsVersions("TLS9k")
175         .build();
176   }
177 
tls_missingRequiredCipher()178   @Test public void tls_missingRequiredCipher() throws Exception {
179     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
180         .cipherSuites(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA)
181         .tlsVersions(TlsVersion.TLS_1_2)
182         .supportsTlsExtensions(false)
183         .build();
184 
185     SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
186     socket.setEnabledProtocols(new String[] {
187         TlsVersion.TLS_1_2.javaName,
188         TlsVersion.TLS_1_1.javaName,
189     });
190 
191     socket.setEnabledCipherSuites(new String[] {
192         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
193         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
194     });
195     assertTrue(tlsSpec.isCompatible(socket));
196 
197     socket.setEnabledCipherSuites(new String[] {
198         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
199     });
200     assertFalse(tlsSpec.isCompatible(socket));
201   }
202 
allEnabledCipherSuites()203   @Test public void allEnabledCipherSuites() throws Exception {
204     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
205         .allEnabledCipherSuites()
206         .build();
207     assertNull(tlsSpec.cipherSuites());
208 
209     SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
210     sslSocket.setEnabledCipherSuites(new String[] {
211         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
212         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
213     });
214 
215     tlsSpec.apply(sslSocket, false);
216     assertEquals(Arrays.asList(
217             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256.javaName,
218             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName),
219         Arrays.asList(sslSocket.getEnabledCipherSuites()));
220   }
221 
allEnabledTlsVersions()222   @Test public void allEnabledTlsVersions() throws Exception {
223     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
224         .allEnabledTlsVersions()
225         .build();
226     assertNull(tlsSpec.tlsVersions());
227 
228     SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
229     sslSocket.setEnabledProtocols(new String[] {
230         TlsVersion.TLS_1_0.javaName(),
231         TlsVersion.TLS_1_1.javaName()
232     });
233 
234     tlsSpec.apply(sslSocket, false);
235     assertEquals(Arrays.asList(TlsVersion.TLS_1_0.javaName(), TlsVersion.TLS_1_1.javaName()),
236         Arrays.asList(sslSocket.getEnabledProtocols()));
237   }
238 
tls_missingTlsVersion()239   @Test public void tls_missingTlsVersion() throws Exception {
240     ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true)
241         .cipherSuites(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA)
242         .tlsVersions(TlsVersion.TLS_1_2)
243         .supportsTlsExtensions(false)
244         .build();
245 
246     SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
247     socket.setEnabledCipherSuites(new String[] {
248         CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.javaName,
249     });
250 
251     socket.setEnabledProtocols(
252         new String[] { TlsVersion.TLS_1_2.javaName, TlsVersion.TLS_1_1.javaName });
253     assertTrue(tlsSpec.isCompatible(socket));
254 
255     socket.setEnabledProtocols(new String[] { TlsVersion.TLS_1_1.javaName });
256     assertFalse(tlsSpec.isCompatible(socket));
257   }
258 
equalsAndHashCode()259   @Test public void equalsAndHashCode() throws Exception {
260     ConnectionSpec allCipherSuites = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
261         .allEnabledCipherSuites()
262         .build();
263     ConnectionSpec allTlsVersions = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
264         .allEnabledTlsVersions()
265         .build();
266 
267     Set<Object> set = new CopyOnWriteArraySet<>();
268     assertTrue(set.add(ConnectionSpec.MODERN_TLS));
269     assertTrue(set.add(ConnectionSpec.COMPATIBLE_TLS));
270     assertTrue(set.add(ConnectionSpec.CLEARTEXT));
271     assertTrue(set.add(allTlsVersions));
272     assertTrue(set.add(allCipherSuites));
273 
274     assertTrue(set.remove(ConnectionSpec.MODERN_TLS));
275     assertTrue(set.remove(ConnectionSpec.COMPATIBLE_TLS));
276     assertTrue(set.remove(ConnectionSpec.CLEARTEXT));
277     assertTrue(set.remove(allTlsVersions));
278     assertTrue(set.remove(allCipherSuites));
279     assertTrue(set.isEmpty());
280   }
281 
allEnabledToString()282   @Test public void allEnabledToString() throws Exception {
283     ConnectionSpec connectionSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
284         .allEnabledTlsVersions()
285         .allEnabledCipherSuites()
286         .build();
287     assertEquals("ConnectionSpec(cipherSuites=[all enabled], tlsVersions=[all enabled], "
288         + "supportsTlsExtensions=true)", connectionSpec.toString());
289   }
290 
simpleToString()291   @Test public void simpleToString() throws Exception {
292     ConnectionSpec connectionSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
293         .tlsVersions(TlsVersion.TLS_1_2)
294         .cipherSuites(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA)
295         .build();
296     assertEquals("ConnectionSpec(cipherSuites=[TLS_RSA_WITH_AES_128_CBC_SHA], tlsVersions=[TLS_1_2], "
297         + "supportsTlsExtensions=true)", connectionSpec.toString());
298   }
299 
set(T... values)300   private static <T> Set<T> set(T... values) {
301     return new LinkedHashSet<>(Arrays.asList(values));
302   }
303 }
304