blob: 819fec34f3b24c9e2e17c41f8784f8d58b0b51cd [file] [log] [blame]
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.hc.core5.ssl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;
import org.apache.hc.core5.util.ReflectionUtils;
import org.apache.hc.core5.util.Timeout;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* Unit tests for {@link SSLContextBuilder}.
*/
public class TestSSLContextBuilder {
private static final String PROVIDER_SUN_JSSE = "SunJSSE";
private static boolean isWindows() {
return System.getProperty("os.name").contains("Windows");
}
@BeforeClass
public static void determineJavaVersion() {
Assume.assumeTrue("Java version must be 8 or greater", ReflectionUtils.determineJRELevel() >= 8);
}
@Rule
public final ExpectedException thrown = ExpectedException.none();
private static final Timeout TIMEOUT = Timeout.ofSeconds(5);
private ExecutorService executorService;
@After
public void cleanup() throws Exception {
if (this.executorService != null) {
this.executorService.shutdown();
this.executorService.awaitTermination(5, TimeUnit.SECONDS);
}
}
private URL getResource(final String name) {
return getClass().getResource(name);
}
@Test
public void testBuildAllDefaults() throws Exception {
final SSLContext sslContext = SSLContextBuilder.create()
.setKeyStoreType(KeyStore.getDefaultType())
.setKeyManagerFactoryAlgorithm(KeyManagerFactory.getDefaultAlgorithm())
.setTrustManagerFactoryAlgorithm(TrustManagerFactory.getDefaultAlgorithm())
.setProvider(PROVIDER_SUN_JSSE)
.setProtocol("TLS")
.setSecureRandom(null)
.loadTrustMaterial((KeyStore) null, null)
.loadKeyMaterial((KeyStore) null, null, null)
.build();
Assert.assertNotNull(sslContext);
Assert.assertEquals("TLS", sslContext.getProtocol());
Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
}
@Test
public void testBuildAllNull() throws Exception {
final SSLContext sslContext = SSLContextBuilder.create()
.setKeyStoreType(null)
.setKeyManagerFactoryAlgorithm(null)
.setTrustManagerFactoryAlgorithm(null)
.setProtocol(null)
.setProvider((String) null)
.setSecureRandom(null)
.loadTrustMaterial((KeyStore) null, null)
.loadKeyMaterial((KeyStore) null, null, null)
.build();
Assert.assertNotNull(sslContext);
Assert.assertEquals("TLS", sslContext.getProtocol());
Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
}
@Test
public void testBuildAllNull_deprecated() throws Exception {
final SSLContext sslContext = SSLContextBuilder.create()
.setProtocol(null)
.setSecureRandom(null)
.loadTrustMaterial((KeyStore) null, null)
.loadKeyMaterial((KeyStore) null, null, null)
.build();
Assert.assertNotNull(sslContext);
Assert.assertEquals("TLS", sslContext.getProtocol());
}
@Test
public void testBuildDefault() throws Exception {
new SSLContextBuilder().build();
}
@Test(expected=NoSuchAlgorithmException.class)
public void testBuildNoSuchKeyManagerFactoryAlgorithm() throws Exception {
final URL resource1 = getResource("/test-keypasswd.p12");
final String storePassword = "nopassword";
final String keyPassword = "password";
SSLContextBuilder.create()
.setKeyManagerFactoryAlgorithm(" BAD ")
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
}
@Test(expected= KeyStoreException.class)
public void testBuildNoSuchKeyStoreType() throws Exception {
final URL resource1 = getResource("/test-keypasswd.p12");
final String storePassword = "nopassword";
final String keyPassword = "password";
SSLContextBuilder.create()
.setKeyStoreType(" BAD ")
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
}
@Test(expected=NoSuchAlgorithmException.class)
public void testBuildNoSuchTrustManagerFactoryAlgorithm() throws Exception {
final URL resource1 = getResource("/test-keypasswd.p12");
final String storePassword = "nopassword";
SSLContextBuilder.create()
.setTrustManagerFactoryAlgorithm(" BAD ")
.loadTrustMaterial(resource1, storePassword.toCharArray())
.build();
}
@Test
public void testBuildWithProvider() throws Exception {
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext sslContext=SSLContextBuilder.create()
.setProvider(Security.getProvider(PROVIDER_SUN_JSSE))
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
}
@Test
public void testBuildWithProviderName() throws Exception {
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext sslContext=SSLContextBuilder.create()
.setProvider(PROVIDER_SUN_JSSE)
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertEquals(PROVIDER_SUN_JSSE, sslContext.getProvider().getName());
}
@Test
public void testKeyWithAlternatePasswordInvalid() throws Exception {
thrown.expect(UnrecoverableKeyException.class);
final URL resource1 = getResource("/test-keypasswd.p12");
final String storePassword = "nopassword";
final String keyPassword = "!password";
SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.loadTrustMaterial(resource1, storePassword.toCharArray())
.build();
}
@Test
public void testSSLHandshakeServerTrusted() throws Exception {
final URL resource1 = getResource("/test.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource1, storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final ServerSocket serverSocket = serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
final Future<Boolean> future = this.executorService.submit(() -> {
try (Socket socket = serverSocket.accept()) {
final OutputStream outputStream = socket.getOutputStream();
outputStream.write(new byte[]{'H', 'i'});
outputStream.flush();
}
return Boolean.TRUE;
});
final int localPort = serverSocket.getLocalPort();
try (final Socket clientSocket = clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals('H', inputStream.read());
Assert.assertEquals('i', inputStream.read());
Assert.assertEquals(-1, inputStream.read());
}
final Boolean result = future.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(result);
}
@Test
public void testSSLHandshakeServerNotTrusted() throws Exception {
thrown.expect(IOException.class);
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final URL resource2 = getResource("/test.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final ServerSocket serverSocket = serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
this.executorService.submit(() -> {
try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
socket.getSession();
}
return Boolean.FALSE;
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
}
}
@Test
public void testSSLHandshakeServerCustomTrustStrategy() throws Exception {
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final AtomicReference<X509Certificate[]> certChainRef = new AtomicReference<>();
final TrustStrategy trustStrategy = (chain, authType) -> {
certChainRef.set(chain);
return true;
};
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(trustStrategy)
.build();
Assert.assertNotNull(clientSslContext);
final ServerSocket serverSocket = serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
final Future<Boolean> future = this.executorService.submit(() -> {
try (Socket socket = serverSocket.accept()) {
final OutputStream outputStream = socket.getOutputStream();
outputStream.write(new byte[]{'H', 'i'});
outputStream.flush();
}
return Boolean.TRUE;
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals('H', inputStream.read());
Assert.assertEquals('i', inputStream.read());
Assert.assertEquals(-1, inputStream.read());
}
final Boolean result = future.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(result);
final X509Certificate[] certs = certChainRef.get();
Assert.assertNotNull(certs);
Assert.assertEquals(2, certs.length);
final X509Certificate cert1 = certs[0];
final Principal subjectDN1 = cert1.getSubjectDN();
Assert.assertNotNull(subjectDN1);
Assert.assertEquals("CN=Test Server, OU=HttpComponents Project, O=Apache Software Foundation", subjectDN1.getName());
final X509Certificate cert2 = certs[1];
final Principal subjectDN2 = cert2.getSubjectDN();
Assert.assertNotNull(subjectDN2);
Assert.assertEquals("EMAILADDRESS=dev@hc.apache.org, " +
"CN=Test CA, OU=HttpComponents Project, O=Apache Software Foundation", subjectDN2.getName());
final Principal issuerDN = cert2.getIssuerDN();
Assert.assertNotNull(issuerDN);
Assert.assertEquals("EMAILADDRESS=dev@hc.apache.org, " +
"CN=Test CA, OU=HttpComponents Project, O=Apache Software Foundation", issuerDN.getName());
}
@Test
public void testSSLHandshakeClientUnauthenticated() throws Exception {
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final URL resource2 = getResource("/test-client.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.setWantClientAuth(true);
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
final Future<Principal> future = this.executorService.submit(() -> {
final SSLSocket socket = (SSLSocket) serverSocket.accept();
Principal clientPrincipal = null;
try {
final SSLSession session = socket.getSession();
try {
clientPrincipal = session.getPeerPrincipal();
} catch (final SSLPeerUnverifiedException ignore) {
}
final OutputStream outputStream = socket.getOutputStream();
outputStream.write(new byte [] {'H', 'i'});
outputStream.flush();
} finally {
socket.close();
}
return clientPrincipal;
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals('H', inputStream.read());
Assert.assertEquals('i', inputStream.read());
Assert.assertEquals(-1, inputStream.read());
}
final Principal clientPrincipal = future.get(5, TimeUnit.SECONDS);
Assert.assertNull(clientPrincipal);
}
@Test
public void testSSLHandshakeClientUnauthenticatedError() throws Exception {
thrown.expect(IOException.class);
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final URL resource2 = getResource("/test-client.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.setNeedClientAuth(true);
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
this.executorService.submit(() -> {
try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
socket.getSession();
}
return Boolean.FALSE;
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals(-1, inputStream.read());
}
}
@Test
public void testSSLHandshakeClientAuthenticated() throws Exception {
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource1, storePassword.toCharArray())
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final URL resource2 = getResource("/test-client.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.loadKeyMaterial(resource2, storePassword.toCharArray(), storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.setNeedClientAuth(true);
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
final Future<Principal> future = this.executorService.submit(() -> {
try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
final SSLSession session = socket.getSession();
final Principal clientPrincipal = session.getPeerPrincipal();
final OutputStream outputStream = socket.getOutputStream();
outputStream.write(new byte[]{'H', 'i'});
outputStream.flush();
return clientPrincipal;
}
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals('H', inputStream.read());
Assert.assertEquals('i', inputStream.read());
Assert.assertEquals(-1, inputStream.read());
}
final Principal clientPrincipal = future.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(clientPrincipal);
}
@Test
public void testSSLHandshakeClientAuthenticatedPrivateKeyStrategy() throws Exception {
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource1, storePassword.toCharArray())
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final PrivateKeyStrategy privateKeyStrategy = (aliases, sslParameters) -> aliases.containsKey("client2") ? "client2" : null;
final URL resource2 = getResource("/test-client.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.loadKeyMaterial(resource2, storePassword.toCharArray(), storePassword.toCharArray(), privateKeyStrategy)
.build();
Assert.assertNotNull(clientSslContext);
final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
serverSocket.setNeedClientAuth(true);
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
final Future<Principal> future = this.executorService.submit(() -> {
try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
final SSLSession session = socket.getSession();
final Principal clientPrincipal = session.getPeerPrincipal();
final OutputStream outputStream = socket.getOutputStream();
outputStream.write(new byte[]{'H', 'i'});
outputStream.flush();
return clientPrincipal;
}
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals('H', inputStream.read());
Assert.assertEquals('i', inputStream.read());
Assert.assertEquals(-1, inputStream.read());
}
final Principal clientPrincipal = future.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(clientPrincipal);
Assert.assertEquals("CN=Test Client 2,OU=HttpComponents Project,O=Apache Software Foundation", clientPrincipal.getName());
}
@Test
public void testSSLHandshakeProtocolMismatch1() throws Exception {
if (isWindows()) {
thrown.expect(IOException.class);
} else {
thrown.expect(SSLHandshakeException.class);
}
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final URL resource2 = getResource("/test-client.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
final Set<String> supportedServerProtocols = new LinkedHashSet<>(Arrays.asList(serverSocket.getSupportedProtocols()));
Assert.assertTrue(supportedServerProtocols.contains("TLSv1"));
serverSocket.setEnabledProtocols(new String[] {"TLSv1"});
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
this.executorService.submit(() -> {
try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
socket.getSession();
}
return Boolean.FALSE;
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
final Set<String> supportedClientProtocols = new LinkedHashSet<>(Arrays.asList(clientSocket.getSupportedProtocols()));
Assert.assertTrue(supportedClientProtocols.contains("SSLv3"));
clientSocket.setEnabledProtocols(new String[] {"SSLv3"} );
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
}
}
@Test
public void testSSLHandshakeProtocolMismatch2() throws Exception {
if (isWindows()) {
thrown.expect(IOException.class);
} else {
thrown.expect(SSLException.class);
}
final URL resource1 = getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(), keyPassword.toCharArray())
.build();
Assert.assertNotNull(serverSslContext);
final URL resource2 = getResource("/test-client.p12");
final SSLContext clientSslContext = SSLContextBuilder.create()
.loadTrustMaterial(resource2, storePassword.toCharArray())
.build();
Assert.assertNotNull(clientSslContext);
final SSLServerSocket serverSocket = (SSLServerSocket) serverSslContext.getServerSocketFactory().createServerSocket();
final Set<String> supportedServerProtocols = new LinkedHashSet<>(Arrays.asList(serverSocket.getSupportedProtocols()));
Assert.assertTrue(supportedServerProtocols.contains("SSLv3"));
serverSocket.setEnabledProtocols(new String[] {"SSLv3"});
serverSocket.bind(new InetSocketAddress(0));
this.executorService = Executors.newSingleThreadExecutor();
this.executorService.submit(() -> {
try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
socket.getSession();
}
return Boolean.FALSE;
});
final int localPort = serverSocket.getLocalPort();
try (final SSLSocket clientSocket = (SSLSocket) clientSslContext.getSocketFactory().createSocket()) {
final Set<String> supportedClientProtocols = new LinkedHashSet<>(
Arrays.asList(clientSocket.getSupportedProtocols()));
Assert.assertTrue(supportedClientProtocols.contains("TLSv1"));
clientSocket.setEnabledProtocols(new String[] { "TLSv1" });
clientSocket.connect(new InetSocketAddress("localhost", localPort), TIMEOUT.toMillisecondsIntBound());
clientSocket.setSoTimeout(TIMEOUT.toMillisecondsIntBound());
clientSocket.startHandshake();
final InputStream inputStream = clientSocket.getInputStream();
Assert.assertEquals(-1, inputStream.read());
}
}
}