1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.ssl;
29
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.net.InetSocketAddress;
34 import java.net.ServerSocket;
35 import java.net.Socket;
36 import java.net.URL;
37 import java.security.KeyStore;
38 import java.security.KeyStoreException;
39 import java.security.NoSuchAlgorithmException;
40 import java.security.Principal;
41 import java.security.Security;
42 import java.security.UnrecoverableKeyException;
43 import java.security.cert.CertificateException;
44 import java.security.cert.X509Certificate;
45 import java.util.Arrays;
46 import java.util.LinkedHashSet;
47 import java.util.Map;
48 import java.util.Set;
49 import java.util.concurrent.Callable;
50 import java.util.concurrent.ExecutorService;
51 import java.util.concurrent.Executors;
52 import java.util.concurrent.Future;
53 import java.util.concurrent.TimeUnit;
54 import java.util.concurrent.atomic.AtomicReference;
55
56 import javax.net.ssl.KeyManagerFactory;
57 import javax.net.ssl.SSLContext;
58 import javax.net.ssl.SSLException;
59 import javax.net.ssl.SSLHandshakeException;
60 import javax.net.ssl.SSLParameters;
61 import javax.net.ssl.SSLPeerUnverifiedException;
62 import javax.net.ssl.SSLServerSocket;
63 import javax.net.ssl.SSLSession;
64 import javax.net.ssl.SSLSocket;
65 import javax.net.ssl.TrustManagerFactory;
66
67 import org.apache.hc.core5.util.ReflectionUtils;
68 import org.apache.hc.core5.util.Timeout;
69 import org.junit.After;
70 import org.junit.Assert;
71 import org.junit.Assume;
72 import org.junit.BeforeClass;
73 import org.junit.Rule;
74 import org.junit.Test;
75 import org.junit.rules.ExpectedException;
76
77
78
79
80 public class TestSSLContextBuilder {
81
82 private static final String PROVIDER_SUN_JSSE = "SunJSSE";
83
84 private static boolean isWindows() {
85 return System.getProperty("os.name").contains("Windows");
86 }
87
88 @BeforeClass
89 public static void determineJavaVersion() {
90 Assume.assumeTrue("Java version must be 8 or greater", ReflectionUtils.determineJRELevel() >= 8);
91 }
92
93 @Rule
94 public ExpectedException thrown = ExpectedException.none();
95
96 private static final Timeout TIMEOUT = Timeout.ofSeconds(5);
97 private ExecutorService executorService;
98
99 @After
100 public void cleanup() throws Exception {
101 if (this.executorService != null) {
102 this.executorService.shutdown();
103 this.executorService.awaitTermination(5, TimeUnit.SECONDS);
104 }
105 }
106
107 private URL getResource(final String name) {
108 return getClass().getResource(name);
109 }
110
111 @Test
112 public void testBuildAllDefaults() throws Exception {
113 final SSLContext sslContext = SSLContextBuilder.create()
114 .setKeyStoreType(KeyStore.getDefaultType())
115 .setKeyManagerFactoryAlgorithm(KeyManagerFactory.getDefaultAlgorithm())
116 .setTrustManagerFactoryAlgorithm(TrustManagerFactory.getDefaultAlgorithm())
117 .setProvider(PROVIDER_SUN_JSSE)
118 .setProtocol("TLS")
119 .setSecureRandom(null)
120 .loadTrustMaterial((KeyStore) null, null)
121 .loadKeyMaterial((KeyStore) null, null, null)
122 .build();
123 Assert.assertNotNull(sslContext);
124 Assert.assertEquals("TLS", sslContext.getProtocol());
125 Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
126 }
127
128 @Test
129 public void testBuildAllNull() throws Exception {
130 final SSLContext sslContext = SSLContextBuilder.create()
131 .setKeyStoreType(null)
132 .setKeyManagerFactoryAlgorithm(null)
133 .setTrustManagerFactoryAlgorithm(null)
134 .setProtocol(null)
135 .setProvider((String) null)
136 .setSecureRandom(null)
137 .loadTrustMaterial((KeyStore) null, null)
138 .loadKeyMaterial((KeyStore) null, null, null)
139 .build();
140 Assert.assertNotNull(sslContext);
141 Assert.assertEquals("TLS", sslContext.getProtocol());
142 Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
143 }
144
145 @Test
146 public void testBuildAllNull_deprecated() throws Exception {
147 final SSLContext sslContext = SSLContextBuilder.create()
148 .setProtocol(null)
149 .setSecureRandom(null)
150 .loadTrustMaterial((KeyStore) null, null)
151 .loadKeyMaterial((KeyStore) null, null, null)
152 .build();
153 Assert.assertNotNull(sslContext);
154 Assert.assertEquals("TLS", sslContext.getProtocol());
155 }
156
157 @Test
158 public void testBuildDefault() throws Exception {
159 new SSLContextBuilder().build();
160 }
161
162 @Test(expected=NoSuchAlgorithmException.class)
163 public void testBuildNoSuchKeyManagerFactoryAlgorithm() throws Exception {
164 final URL resource1 = getResource("/test-keypasswd.p12");
165 final String storePassword = "nopassword";
166 final String keyPassword = "password";
167 SSLContextBuilder.create()
168 .setKeyManagerFactoryAlgorithm(" BAD ")
169 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
170 .build();
171 }
172
173 @Test(expected= KeyStoreException.class)
174 public void testBuildNoSuchKeyStoreType() throws Exception {
175 final URL resource1 = getResource("/test-keypasswd.p12");
176 final String storePassword = "nopassword";
177 final String keyPassword = "password";
178 SSLContextBuilder.create()
179 .setKeyStoreType(" BAD ")
180 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
181 .build();
182 }
183
184 @Test(expected=NoSuchAlgorithmException.class)
185 public void testBuildNoSuchTrustManagerFactoryAlgorithm() throws Exception {
186 final URL resource1 = getResource("/test-keypasswd.p12");
187 final String storePassword = "nopassword";
188 SSLContextBuilder.create()
189 .setTrustManagerFactoryAlgorithm(" BAD ")
190 .loadTrustMaterial(resource1, storePassword.toCharArray())
191 .build();
192 }
193
194 @Test
195 public void testBuildWithProvider() throws Exception {
196 final URL resource1 = getResource("/test-server.p12");
197 final String storePassword = "nopassword";
198 final String keyPassword = "nopassword";
199 final SSLContext sslContext=SSLContextBuilder.create()
200 .setProvider(Security.getProvider(PROVIDER_SUN_JSSE))
201 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
202 .build();
203 Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
204 }
205
206 @Test
207 public void testBuildWithProviderName() throws Exception {
208 final URL resource1 = getResource("/test-server.p12");
209 final String storePassword = "nopassword";
210 final String keyPassword = "nopassword";
211 final SSLContext sslContext=SSLContextBuilder.create()
212 .setProvider(PROVIDER_SUN_JSSE)
213 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
214 .build();
215 Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
216 }
217
218 @Test
219 public void testKeyWithAlternatePasswordInvalid() throws Exception {
220
221 thrown.expect(UnrecoverableKeyException.class);
222
223 final URL resource1 = getResource("/test-keypasswd.p12");
224 final String storePassword = "nopassword";
225 final String keyPassword = "!password";
226 SSLContextBuilder.create()
227 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
228 .loadTrustMaterial(resource1, storePassword.toCharArray())
229 .build();
230 }
231
232 @Test
233 public void testSSLHandshakeServerTrusted() throws Exception {
234 final URL resource1 = getResource("/test.p12");
235 final String storePassword = "nopassword";
236 final String keyPassword = "nopassword";
237 final SSLContext serverSslContext = SSLContextBuilder.create()
238 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
239 .build();
240 Assert.assertNotNull(serverSslContext);
241 final SSLContext clientSslContext = SSLContextBuilder.create()
242 .loadTrustMaterial(resource1, storePassword.toCharArray())
243 .build();
244 Assert.assertNotNull(clientSslContext);
245 final ServerSocket serverSocket = serverSslContext.getServerSocketFactory().createServerSocket();
246 serverSocket.bind(new InetSocketAddress(0));
247
248 this.executorService = Executors.newSingleThreadExecutor();
249 final Future<Boolean> future = this.executorService.submit(new Callable<Boolean>() {
250 @Override
251 public Boolean call() throws Exception {
252 try (Socket socket = serverSocket.accept()) {
253 final OutputStream outputStream = socket.getOutputStream();
254 outputStream.write(new byte[]{'H', 'i'});
255 outputStream.flush();
256 }
257 return Boolean.TRUE;
258 }
259 });
260
261 final int localPort = serverSocket.getLocalPort();
262 try (final Socket clientSocket = clientSslContext.getSocketFactory().createSocket()) {
263 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
264 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
265 final InputStream inputStream = clientSocket.getInputStream();
266 Assert.assertEquals('H', inputStream.read());
267 Assert.assertEquals('i', inputStream.read());
268 Assert.assertEquals(-1, inputStream.read());
269 }
270
271 final Boolean result = future.get(5, TimeUnit.SECONDS);
272 Assert.assertNotNull(result);
273 }
274
275 @Test
276 public void testSSLHandshakeServerNotTrusted() throws Exception {
277 thrown.expect(IOException.class);
278
279 final URL resource1 = getResource("/test-server.p12");
280 final String storePassword = "nopassword";
281 final String keyPassword = "nopassword";
282 final SSLContext serverSslContext = SSLContextBuilder.create()
283 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
284 .build();
285 Assert.assertNotNull(serverSslContext);
286 final URL resource2 = getResource("/test.p12");
287 final SSLContext clientSslContext = SSLContextBuilder.create()
288 .loadTrustMaterial(resource2, storePassword.toCharArray())
289 .build();
290 Assert.assertNotNull(clientSslContext);
291 final ServerSocket serverSocket = serverSslContext.getServerSocketFactory().createServerSocket();
292 serverSocket.bind(new InetSocketAddress(0));
293
294 this.executorService = Executors.newSingleThreadExecutor();
295 this.executorService.submit(new Callable<Boolean>() {
296 @Override
297 public Boolean call() throws Exception {
298 try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
299 socket.getSession();
300 }
301 return Boolean.FALSE;
302 }
303 });
304 final int localPort = serverSocket.getLocalPort();
305 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
306 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
307 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
308 clientSocket.startHandshake();
309 }
310 }
311
312 @Test
313 public void testSSLHandshakeServerCustomTrustStrategy() throws Exception {
314 final URL resource1 = getResource("/test-server.p12");
315 final String storePassword = "nopassword";
316 final String keyPassword = "nopassword";
317 final SSLContext serverSslContext = SSLContextBuilder.create()
318 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
319 .build();
320 Assert.assertNotNull(serverSslContext);
321
322 final AtomicReference<X509Certificate[]> certChainRef = new AtomicReference<>();
323
324 final TrustStrategy trustStrategy = new TrustStrategy() {
325
326 @Override
327 public boolean isTrusted(
328 final X509Certificate[] chain, final String authType) throws CertificateException {
329 certChainRef.set(chain);
330 return true;
331 }
332
333 };
334
335 final SSLContext clientSslContext = SSLContextBuilder.create()
336 .loadTrustMaterial(trustStrategy)
337 .build();
338
339 Assert.assertNotNull(clientSslContext);
340 final ServerSocket serverSocket = serverSslContext.getServerSocketFactory().createServerSocket();
341 serverSocket.bind(new InetSocketAddress(0));
342
343 this.executorService = Executors.newSingleThreadExecutor();
344 final Future<Boolean> future = this.executorService.submit(new Callable<Boolean>() {
345 @Override
346 public Boolean call() throws Exception {
347 try (Socket socket = serverSocket.accept()) {
348 final OutputStream outputStream = socket.getOutputStream();
349 outputStream.write(new byte[]{'H', 'i'});
350 outputStream.flush();
351 }
352 return Boolean.TRUE;
353 }
354 });
355
356 final int localPort = serverSocket.getLocalPort();
357 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
358 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
359 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
360 final InputStream inputStream = clientSocket.getInputStream();
361 Assert.assertEquals('H', inputStream.read());
362 Assert.assertEquals('i', inputStream.read());
363 Assert.assertEquals(-1, inputStream.read());
364 }
365
366 final Boolean result = future.get(5, TimeUnit.SECONDS);
367 Assert.assertNotNull(result);
368
369 final X509Certificate[] certs = certChainRef.get();
370 Assert.assertNotNull(certs);
371 Assert.assertEquals(2, certs.length);
372 final X509Certificate cert1 = certs[0];
373 final Principal subjectDN1 = cert1.getSubjectDN();
374 Assert.assertNotNull(subjectDN1);
375 Assert.assertEquals("CN=Test Server, OU=HttpComponents Project, O=Apache Software Foundation", subjectDN1.getName());
376 final X509Certificate cert2 = certs[1];
377 final Principal subjectDN2 = cert2.getSubjectDN();
378 Assert.assertNotNull(subjectDN2);
379 Assert.assertEquals("EMAILADDRESS=dev@hc.apache.org, " +
380 "CN=Test CA, OU=HttpComponents Project, O=Apache Software Foundation", subjectDN2.getName());
381 final Principal issuerDN = cert2.getIssuerDN();
382 Assert.assertNotNull(issuerDN);
383 Assert.assertEquals("EMAILADDRESS=dev@hc.apache.org, " +
384 "CN=Test CA, OU=HttpComponents Project, O=Apache Software Foundation", issuerDN.getName());
385
386 }
387
388 @Test
389 public void testSSLHandshakeClientUnauthenticated() throws Exception {
390 final URL resource1 = getResource("/test-server.p12");
391 final String storePassword = "nopassword";
392 final String keyPassword = "nopassword";
393 final SSLContext serverSslContext = SSLContextBuilder.create()
394 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
395 .build();
396 Assert.assertNotNull(serverSslContext);
397 final URL resource2 = getResource("/test-client.p12");
398 final SSLContext clientSslContext = SSLContextBuilder.create()
399 .loadTrustMaterial(resource2, storePassword.toCharArray())
400 .build();
401 Assert.assertNotNull(clientSslContext);
402 final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
403 serverSocket.setWantClientAuth(true);
404 serverSocket.bind(new InetSocketAddress(0));
405
406 this.executorService = Executors.newSingleThreadExecutor();
407 final Future<Principal> future = this.executorService.submit(new Callable<Principal>() {
408 @Override
409 public Principal call() throws Exception {
410 final SSLSocket socket = (SSLSocket) serverSocket.accept();
411 Principal clientPrincipal = null;
412 try {
413 final SSLSession session = socket.getSession();
414 try {
415 clientPrincipal = session.getPeerPrincipal();
416 } catch (final SSLPeerUnverifiedException ignore) {
417 }
418 final OutputStream outputStream = socket.getOutputStream();
419 outputStream.write(new byte [] {'H', 'i'});
420 outputStream.flush();
421 } finally {
422 socket.close();
423 }
424 return clientPrincipal;
425 }
426 });
427
428 final int localPort = serverSocket.getLocalPort();
429 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
430 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
431 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
432 clientSocket.startHandshake();
433 final InputStream inputStream = clientSocket.getInputStream();
434 Assert.assertEquals('H', inputStream.read());
435 Assert.assertEquals('i', inputStream.read());
436 Assert.assertEquals(-1, inputStream.read());
437 }
438
439 final Principal clientPrincipal = future.get(5, TimeUnit.SECONDS);
440 Assert.assertNull(clientPrincipal);
441 }
442
443 @Test
444 public void testSSLHandshakeClientUnauthenticatedError() throws Exception {
445 thrown.expect(IOException.class);
446
447 final URL resource1 = getResource("/test-server.p12");
448 final String storePassword = "nopassword";
449 final String keyPassword = "nopassword";
450 final SSLContext serverSslContext = SSLContextBuilder.create()
451 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
452 .build();
453 Assert.assertNotNull(serverSslContext);
454 final URL resource2 = getResource("/test-client.p12");
455 final SSLContext clientSslContext = SSLContextBuilder.create()
456 .loadTrustMaterial(resource2, storePassword.toCharArray())
457 .build();
458 Assert.assertNotNull(clientSslContext);
459 final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
460 serverSocket.setNeedClientAuth(true);
461 serverSocket.bind(new InetSocketAddress(0));
462
463 this.executorService = Executors.newSingleThreadExecutor();
464 this.executorService.submit(new Callable<Boolean>() {
465 @Override
466 public Boolean call() throws Exception {
467 try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
468 socket.getSession();
469 }
470 return Boolean.FALSE;
471 }
472 });
473
474 final int localPort = serverSocket.getLocalPort();
475 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
476 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
477 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
478 clientSocket.startHandshake();
479 final InputStream inputStream = clientSocket.getInputStream();
480 Assert.assertEquals(-1, inputStream.read());
481 }
482 }
483
484 @Test
485 public void testSSLHandshakeClientAuthenticated() throws Exception {
486 final URL resource1 = getResource("/test-server.p12");
487 final String storePassword = "nopassword";
488 final String keyPassword = "nopassword";
489 final SSLContext serverSslContext = SSLContextBuilder.create()
490 .loadTrustMaterial(resource1, storePassword.toCharArray())
491 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
492 .build();
493 Assert.assertNotNull(serverSslContext);
494 final URL resource2 = getResource("/test-client.p12");
495 final SSLContext clientSslContext = SSLContextBuilder.create()
496 .loadTrustMaterial(resource2, storePassword.toCharArray())
497 .loadKeyMaterial(resource2, storePassword.toCharArray(), storePassword.toCharArray())
498 .build();
499 Assert.assertNotNull(clientSslContext);
500 final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
501 serverSocket.setNeedClientAuth(true);
502 serverSocket.bind(new InetSocketAddress(0));
503
504 this.executorService = Executors.newSingleThreadExecutor();
505 final Future<Principal> future = this.executorService.submit(new Callable<Principal>() {
506 @Override
507 public Principal call() throws Exception {
508 try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
509 final SSLSession session = socket.getSession();
510 final Principal clientPrincipal = session.getPeerPrincipal();
511 final OutputStream outputStream = socket.getOutputStream();
512 outputStream.write(new byte[]{'H', 'i'});
513 outputStream.flush();
514 return clientPrincipal;
515 }
516 }
517 });
518 final int localPort = serverSocket.getLocalPort();
519 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
520 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
521 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
522 clientSocket.startHandshake();
523 final InputStream inputStream = clientSocket.getInputStream();
524 Assert.assertEquals('H', inputStream.read());
525 Assert.assertEquals('i', inputStream.read());
526 Assert.assertEquals(-1, inputStream.read());
527 }
528
529 final Principal clientPrincipal = future.get(5, TimeUnit.SECONDS);
530 Assert.assertNotNull(clientPrincipal);
531 }
532
533 @Test
534 public void testSSLHandshakeClientAuthenticatedPrivateKeyStrategy() throws Exception {
535 final URL resource1 = getResource("/test-server.p12");
536 final String storePassword = "nopassword";
537 final String keyPassword = "nopassword";
538 final SSLContext serverSslContext = SSLContextBuilder.create()
539 .loadTrustMaterial(resource1, storePassword.toCharArray())
540 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
541 .build();
542 Assert.assertNotNull(serverSslContext);
543
544 final PrivateKeyStrategy privateKeyStrategy = new PrivateKeyStrategy() {
545 @Override
546 public String chooseAlias(final Map<String, PrivateKeyDetails> aliases,
547 final SSLParameters sslParameters) {
548 return aliases.containsKey("client2") ? "client2" : null;
549 }
550 };
551
552 final URL resource2 = getResource("/test-client.p12");
553 final SSLContext clientSslContext = SSLContextBuilder.create()
554 .loadTrustMaterial(resource2, storePassword.toCharArray())
555 .loadKeyMaterial(resource2, storePassword.toCharArray(), storePassword.toCharArray(), privateKeyStrategy)
556 .build();
557 Assert.assertNotNull(clientSslContext);
558 final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
559 serverSocket.setNeedClientAuth(true);
560 serverSocket.bind(new InetSocketAddress(0));
561
562 this.executorService = Executors.newSingleThreadExecutor();
563 final Future<Principal> future = this.executorService.submit(new Callable<Principal>() {
564 @Override
565 public Principal call() throws Exception {
566 try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
567 final SSLSession session = socket.getSession();
568 final Principal clientPrincipal = session.getPeerPrincipal();
569 final OutputStream outputStream = socket.getOutputStream();
570 outputStream.write(new byte[]{'H', 'i'});
571 outputStream.flush();
572 return clientPrincipal;
573 }
574 }
575 });
576 final int localPort = serverSocket.getLocalPort();
577 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
578 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
579 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
580 clientSocket.startHandshake();
581 final InputStream inputStream = clientSocket.getInputStream();
582 Assert.assertEquals('H', inputStream.read());
583 Assert.assertEquals('i', inputStream.read());
584 Assert.assertEquals(-1, inputStream.read());
585 }
586
587 final Principal clientPrincipal = future.get(5, TimeUnit.SECONDS);
588 Assert.assertNotNull(clientPrincipal);
589 Assert.assertEquals("CN=Test Client 2,OU=HttpComponents Project,O=Apache Software Foundation", clientPrincipal.getName());
590 }
591
592
593 @Test
594 public void testSSLHandshakeProtocolMismatch1() throws Exception {
595 if (isWindows()) {
596 thrown.expect(IOException.class);
597 } else {
598 thrown.expect(SSLHandshakeException.class);
599 }
600
601 final URL resource1 = getResource("/test-server.p12");
602 final String storePassword = "nopassword";
603 final String keyPassword = "nopassword";
604 final SSLContext serverSslContext = SSLContextBuilder.create()
605 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
606 .build();
607 Assert.assertNotNull(serverSslContext);
608 final URL resource2 = getResource("/test-client.p12");
609 final SSLContext clientSslContext = SSLContextBuilder.create()
610 .loadTrustMaterial(resource2, storePassword.toCharArray())
611 .build();
612 Assert.assertNotNull(clientSslContext);
613 final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
614 final Set<String> supportedServerProtocols = new LinkedHashSet<>(Arrays.asList(serverSocket.getSupportedProtocols()));
615 Assert.assertTrue(supportedServerProtocols.contains("TLSv1"));
616 serverSocket.setEnabledProtocols(new String[] {"TLSv1"});
617 serverSocket.bind(new InetSocketAddress(0));
618
619 this.executorService = Executors.newSingleThreadExecutor();
620 this.executorService.submit(new Callable<Boolean>() {
621 @Override
622 public Boolean call() throws Exception {
623 try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
624 socket.getSession();
625 }
626 return Boolean.FALSE;
627 }
628 });
629
630 final int localPort = serverSocket.getLocalPort();
631 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
632 final Set<String> supportedClientProtocols = new LinkedHashSet<>(Arrays.asList(clientSocket.getSupportedProtocols()));
633 Assert.assertTrue(supportedClientProtocols.contains("SSLv3"));
634 clientSocket.setEnabledProtocols(new String[] {"SSLv3"} );
635 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
636 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
637 clientSocket.startHandshake();
638 }
639 }
640
641 @Test
642 public void testSSLHandshakeProtocolMismatch2() throws Exception {
643 if (isWindows()) {
644 thrown.expect(IOException.class);
645 } else {
646 thrown.expect(SSLException.class);
647 }
648
649 final URL resource1 = getResource("/test-server.p12");
650 final String storePassword = "nopassword";
651 final String keyPassword = "nopassword";
652 final SSLContext serverSslContext = SSLContextBuilder.create()
653 .loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
654 .build();
655 Assert.assertNotNull(serverSslContext);
656 final URL resource2 = getResource("/test-client.p12");
657 final SSLContext clientSslContext = SSLContextBuilder.create()
658 .loadTrustMaterial(resource2, storePassword.toCharArray())
659 .build();
660 Assert.assertNotNull(clientSslContext);
661 final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
662 final Set<String> supportedServerProtocols = new LinkedHashSet<>(Arrays.asList(serverSocket.getSupportedProtocols()));
663 Assert.assertTrue(supportedServerProtocols.contains("SSLv3"));
664 serverSocket.setEnabledProtocols(new String[] {"SSLv3"});
665 serverSocket.bind(new InetSocketAddress(0));
666
667 this.executorService = Executors.newSingleThreadExecutor();
668 this.executorService.submit(new Callable<Boolean>() {
669 @Override
670 public Boolean call() throws Exception {
671 try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
672 socket.getSession();
673 }
674 return Boolean.FALSE;
675 }
676 });
677
678 final int localPort = serverSocket.getLocalPort();
679 try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
680 final Set<String> supportedClientProtocols = new LinkedHashSet<>(
681 Arrays.asList(clientSocket.getSupportedProtocols()));
682 Assert.assertTrue(supportedClientProtocols.contains("TLSv1"));
683 clientSocket.setEnabledProtocols(new String[] { "TLSv1" });
684 clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
685 clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
686 clientSocket.startHandshake();
687 final InputStream inputStream = clientSocket.getInputStream();
688 Assert.assertEquals(-1, inputStream.read());
689 }
690 }
691
692 }