Issue #918 - Support certificates hot reload.

Introduced SslContextFactory.reload(Consumer) to perform atomic
reload of SslContextFactory.
This commit is contained in:
Simone Bordet 2016-09-30 17:46:56 +02:00
parent 7471f5c8f2
commit 38d48395b0
4 changed files with 374 additions and 74 deletions

View File

@ -0,0 +1,265 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server.ssl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
public class SslContextFactoryReloadTest
{
public static final String KEYSTORE_1 = "src/test/resources/reload_keystore_1.jks";
public static final String KEYSTORE_2 = "src/test/resources/reload_keystore_2.jks";
private Server server;
private SslContextFactory sslContextFactory;
private ServerConnector connector;
private void start(Handler handler) throws Exception
{
server = new Server();
sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(KEYSTORE_1);
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyStoreType("JKS");
sslContextFactory.setKeyStoreProvider(null);
HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.addCustomizer(new SecureRequestCustomizer());
connector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(httpsConfig));
server.addConnector(connector);
server.setHandler(handler);
server.start();
}
@After
public void dispose() throws Exception
{
if (server != null)
server.stop();
}
@Test
public void testReload() throws Exception
{
start(new EchoHandler());
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(null, SslContextFactory.TRUST_ALL_CERTS, null);
SSLSocketFactory socketFactory = ctx.getSocketFactory();
try (SSLSocket client1 = (SSLSocket)socketFactory.createSocket("localhost", connector.getLocalPort()))
{
String serverDN1 = client1.getSession().getPeerPrincipal().getName();
Assert.assertThat(serverDN1, Matchers.startsWith("CN=localhost1"));
String request = "" +
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
OutputStream output1 = client1.getOutputStream();
output1.write(request.getBytes(StandardCharsets.UTF_8));
output1.flush();
HttpTester.Response response1 = HttpTester.parseResponse(HttpTester.from(client1.getInputStream()));
Assert.assertNotNull(response1);
Assert.assertThat(response1.getStatus(), Matchers.equalTo(HttpStatus.OK_200));
// Reconfigure SslContextFactory.
sslContextFactory.reload(sslContextFactory ->
{
sslContextFactory.setKeyStorePath(KEYSTORE_2);
sslContextFactory.setKeyStorePassword("storepwd");
});
// New connection should use the new keystore.
try (SSLSocket client2 = (SSLSocket)socketFactory.createSocket("localhost", connector.getLocalPort()))
{
String serverDN2 = client2.getSession().getPeerPrincipal().getName();
Assert.assertThat(serverDN2, Matchers.startsWith("CN=localhost2"));
OutputStream output2 = client1.getOutputStream();
output2.write(request.getBytes(StandardCharsets.UTF_8));
output2.flush();
HttpTester.Response response2 = HttpTester.parseResponse(HttpTester.from(client1.getInputStream()));
Assert.assertNotNull(response2);
Assert.assertThat(response2.getStatus(), Matchers.equalTo(HttpStatus.OK_200));
}
// Must still be possible to make requests with the first connection.
output1.write(request.getBytes(StandardCharsets.UTF_8));
output1.flush();
response1 = HttpTester.parseResponse(HttpTester.from(client1.getInputStream()));
Assert.assertNotNull(response1);
Assert.assertThat(response1.getStatus(), Matchers.equalTo(HttpStatus.OK_200));
}
}
@Test
public void testReloadWhileServing() throws Exception
{
start(new EchoHandler());
Scheduler scheduler = new ScheduledExecutorScheduler();
scheduler.start();
try
{
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(null, SslContextFactory.TRUST_ALL_CERTS, null);
SSLSocketFactory socketFactory = ctx.getSocketFactory();
// Perform 4 reloads while connections are being served.
AtomicInteger reloads = new AtomicInteger(4);
long reloadPeriod = 500;
AtomicBoolean running = new AtomicBoolean(true);
scheduler.schedule(new Runnable()
{
@Override
public void run()
{
if (reloads.decrementAndGet() == 0)
{
running.set(false);
}
else
{
try
{
sslContextFactory.reload(sslContextFactory ->
{
if (sslContextFactory.getKeyStorePath().endsWith(KEYSTORE_1))
sslContextFactory.setKeyStorePath(KEYSTORE_2);
else
sslContextFactory.setKeyStorePath(KEYSTORE_1);
});
scheduler.schedule(this, reloadPeriod, TimeUnit.MILLISECONDS);
}
catch (Exception x)
{
running.set(false);
reloads.set(-1);
}
}
}
}, reloadPeriod, TimeUnit.MILLISECONDS);
byte[] content = new byte[16 * 1024];
while (running.get())
{
try (SSLSocket client = (SSLSocket)socketFactory.createSocket("localhost", connector.getLocalPort()))
{
// We need to invalidate the session every time we open a new SSLSocket.
// This is because when the client uses session resumption, it caches
// the server certificates and then checks that it is the same during
// a new TLS handshake. If the SslContextFactory is reloaded during the
// TLS handshake, the client will see the new certificate and blow up.
// Note that browsers can handle this case better: they will just not
// use session resumption and fallback to the normal TLS handshake.
client.getSession().invalidate();
String request1 = "" +
"POST / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Length: " + content.length + "\r\n" +
"\r\n";
OutputStream outputStream = client.getOutputStream();
outputStream.write(request1.getBytes(StandardCharsets.UTF_8));
outputStream.write(content);
outputStream.flush();
InputStream inputStream = client.getInputStream();
HttpTester.Response response1 = HttpTester.parseResponse(HttpTester.from(inputStream));
Assert.assertNotNull(response1);
Assert.assertThat(response1.getStatus(), Matchers.equalTo(HttpStatus.OK_200));
String request2 = "" +
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"\r\n";
outputStream.write(request2.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
HttpTester.Response response2 = HttpTester.parseResponse(HttpTester.from(inputStream));
Assert.assertNotNull(response2);
Assert.assertThat(response2.getStatus(), Matchers.equalTo(HttpStatus.OK_200));
}
}
Assert.assertEquals(0, reloads.get());
}
finally
{
scheduler.stop();
}
}
private static class EchoHandler extends AbstractHandler
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
if (HttpMethod.POST.is(request.getMethod()))
IO.copy(request.getInputStream(), response.getOutputStream());
else
response.setContentLength(0);
}
}
}

Binary file not shown.

Binary file not shown.

View File

@ -44,6 +44,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -209,6 +210,15 @@ public class SslContextFactory extends AbstractLifeCycle
*/
@Override
protected void doStart() throws Exception
{
super.doStart();
synchronized (this)
{
load();
}
}
private void load() throws Exception
{
SSLContext context = _setContext;
KeyStore keyStore = _setKeyStore;
@ -244,7 +254,6 @@ public class SslContextFactory extends AbstractLifeCycle
Collection<? extends CRL> crls = loadCRL(getCrlPath());
// Look for X.509 certificates to create alias map
_certHosts.clear();
if (keyStore != null)
{
for (String alias : Collections.list(keyStore.aliases()))
@ -321,12 +330,22 @@ public class SslContextFactory extends AbstractLifeCycle
@Override
protected void doStop() throws Exception
{
synchronized (this)
{
unload();
}
super.doStop();
}
private void unload()
{
_factory = null;
_selectedProtocols = null;
_selectedCipherSuites = null;
_aliasX509.clear();
_certHosts.clear();
_certWilds.clear();
super.doStop();
}
public String[] getSelectedProtocols()
@ -376,7 +395,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setExcludeProtocols(String... protocols)
{
checkNotStarted();
_excludeProtocols.clear();
_excludeProtocols.addAll(Arrays.asList(protocols));
}
@ -386,7 +404,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void addExcludeProtocols(String... protocol)
{
checkNotStarted();
_excludeProtocols.addAll(Arrays.asList(protocol));
}
@ -405,7 +422,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setIncludeProtocols(String... protocols)
{
checkNotStarted();
_includeProtocols.clear();
_includeProtocols.addAll(Arrays.asList(protocols));
}
@ -427,7 +443,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setExcludeCipherSuites(String... cipherSuites)
{
checkNotStarted();
_excludeCipherSuites.clear();
_excludeCipherSuites.addAll(Arrays.asList(cipherSuites));
}
@ -437,7 +452,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void addExcludeCipherSuites(String... cipher)
{
checkNotStarted();
_excludeCipherSuites.addAll(Arrays.asList(cipher));
}
@ -458,7 +472,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setIncludeCipherSuites(String... cipherSuites)
{
checkNotStarted();
_includeCipherSuites.clear();
_includeCipherSuites.addAll(Arrays.asList(cipherSuites));
}
@ -486,7 +499,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStorePath(String keyStorePath)
{
checkNotStarted();
try
{
_keyStoreResource = Resource.newResource(keyStorePath);
@ -510,7 +522,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreProvider(String keyStoreProvider)
{
checkNotStarted();
_keyStoreProvider = keyStoreProvider;
}
@ -527,7 +538,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreType(String keyStoreType)
{
checkNotStarted();
_keyStoreType = keyStoreType;
}
@ -550,7 +560,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setCertAlias(String certAlias)
{
checkNotStarted();
_certAlias = certAlias;
}
@ -559,7 +568,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStorePath(String trustStorePath)
{
checkNotStarted();
try
{
_trustStoreResource = Resource.newResource(trustStorePath);
@ -583,7 +591,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreProvider(String trustStoreProvider)
{
checkNotStarted();
_trustStoreProvider = trustStoreProvider;
}
@ -600,7 +607,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreType(String trustStoreType)
{
checkNotStarted();
_trustStoreType = trustStoreType;
}
@ -619,7 +625,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setNeedClientAuth(boolean needClientAuth)
{
checkNotStarted();
_needClientAuth = needClientAuth;
}
@ -638,7 +643,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setWantClientAuth(boolean wantClientAuth)
{
checkNotStarted();
_wantClientAuth = wantClientAuth;
}
@ -655,7 +659,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setValidateCerts(boolean validateCerts)
{
checkNotStarted();
_validateCerts = validateCerts;
}
@ -672,7 +675,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setValidatePeerCerts(boolean validatePeerCerts)
{
checkNotStarted();
_validatePeerCerts = validatePeerCerts;
}
@ -685,7 +687,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStorePassword(String password)
{
checkNotStarted();
if (password == null)
{
if (_keyStoreResource != null)
@ -694,7 +695,9 @@ public class SslContextFactory extends AbstractLifeCycle
_keyStorePassword = null;
}
else
{
_keyStorePassword = new Password(password);
}
}
/**
@ -705,7 +708,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyManagerPassword(String password)
{
checkNotStarted();
if (password == null)
{
if (System.getProperty(KEYPASSWORD_PROPERTY) != null)
@ -714,7 +716,9 @@ public class SslContextFactory extends AbstractLifeCycle
_keyManagerPassword = null;
}
else
{
_keyManagerPassword = new Password(password);
}
}
/**
@ -726,17 +730,17 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStorePassword(String password)
{
checkNotStarted();
if (password == null)
{
// Do we need a truststore password?
if (_trustStoreResource != null && !_trustStoreResource.equals(_keyStoreResource))
_trustStorePassword = Password.getPassword(PASSWORD_PROPERTY, null, null);
else
_trustStorePassword = null;
}
else
{
_trustStorePassword = new Password(password);
}
}
/**
@ -754,7 +758,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setProvider(String provider)
{
checkNotStarted();
_sslProvider = provider;
}
@ -773,7 +776,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setProtocol(String protocol)
{
checkNotStarted();
_sslProtocol = protocol;
}
@ -794,14 +796,31 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSecureRandomAlgorithm(String algorithm)
{
checkNotStarted();
_secureRandomAlgorithm = algorithm;
}
/**
* @deprecated use {@link #getKeyManagerFactoryAlgorithm()} instead
*/
@Deprecated
public String getSslKeyManagerFactoryAlgorithm()
{
return getKeyManagerFactoryAlgorithm();
}
/**
* @deprecated use {@link #setKeyManagerFactoryAlgorithm(String)} instead
*/
@Deprecated
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
{
setKeyManagerFactoryAlgorithm(algorithm);
}
/**
* @return The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
*/
public String getSslKeyManagerFactoryAlgorithm()
public String getKeyManagerFactoryAlgorithm()
{
return _keyManagerFactoryAlgorithm;
}
@ -809,9 +828,8 @@ public class SslContextFactory extends AbstractLifeCycle
/**
* @param algorithm The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
*/
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
public void setKeyManagerFactoryAlgorithm(String algorithm)
{
checkNotStarted();
_keyManagerFactoryAlgorithm = algorithm;
}
@ -847,7 +865,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustManagerFactoryAlgorithm(String algorithm)
{
checkNotStarted();
_trustManagerFactoryAlgorithm = algorithm;
}
@ -880,7 +897,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setCrlPath(String crlPath)
{
checkNotStarted();
_crlPath = crlPath;
}
@ -899,7 +915,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setMaxCertPathLength(int maxCertPathLength)
{
checkNotStarted();
_maxCertPathLength = maxCertPathLength;
}
@ -908,7 +923,13 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public SSLContext getSslContext()
{
return isStarted() ? _factory._context : _setContext;
if (!isStarted())
return _setContext;
synchronized (this)
{
return _factory._context;
}
}
/**
@ -916,10 +937,17 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSslContext(SSLContext sslContext)
{
checkNotStarted();
_setContext = sslContext;
}
/**
* @return the endpoint identification algorithm
*/
public String getEndpointIdentificationAlgorithm()
{
return _endpointIdentificationAlgorithm;
}
/**
* When set to "HTTPS" hostname verification will be enabled
*
@ -927,7 +955,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm)
{
this._endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
_endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
}
/**
@ -939,7 +967,8 @@ public class SslContextFactory extends AbstractLifeCycle
*/
protected KeyStore loadKeyStore(Resource resource) throws Exception
{
return CertificateUtils.getKeyStore(resource, getKeyStoreType(), getKeyStoreProvider(), _keyStorePassword == null ? null : _keyStorePassword.toString());
String storePassword = _keyStorePassword == null ? null : _keyStorePassword.toString();
return CertificateUtils.getKeyStore(resource, getKeyStoreType(), getKeyStoreProvider(), storePassword);
}
/**
@ -964,7 +993,6 @@ public class SslContextFactory extends AbstractLifeCycle
if (passwd == null)
passwd = _keyStorePassword == null ? null : _keyStorePassword.toString();
}
return CertificateUtils.getKeyStore(resource, type, provider, passwd);
}
@ -989,7 +1017,7 @@ public class SslContextFactory extends AbstractLifeCycle
if (keyStore != null)
{
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(getSslKeyManagerFactoryAlgorithm());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(getKeyManagerFactoryAlgorithm());
keyManagerFactory.init(keyStore, _keyManagerPassword == null ? (_keyStorePassword == null ? null : _keyStorePassword.toString().toCharArray()) : _keyManagerPassword.toString().toCharArray());
managers = keyManagerFactory.getKeyManagers();
@ -1187,30 +1215,12 @@ public class SslContextFactory extends AbstractLifeCycle
/**
* Check if the lifecycle has been started and throw runtime exception
*/
protected void checkNotStarted()
{
if (isStarted())
throw new IllegalStateException("Cannot modify configuration when " + getState());
}
/**
* Check if the lifecycle has been started and throw runtime exception
*/
protected void checkIsStarted()
private void checkIsStarted()
{
if (!isStarted())
throw new IllegalStateException("!STARTED: " + this);
}
/**
* Check if the lifecycle has been started and throw runtime exception
*/
protected void checkIsRunning()
{
if (!isRunning())
throw new IllegalStateException("!RUNNING: " + this);
}
/**
* @return true if CRL Distribution Points support is enabled
*/
@ -1226,7 +1236,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEnableCRLDP(boolean enableCRLDP)
{
checkNotStarted();
_enableCRLDP = enableCRLDP;
}
@ -1245,7 +1254,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEnableOCSP(boolean enableOCSP)
{
checkNotStarted();
_enableOCSP = enableOCSP;
}
@ -1264,7 +1272,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setOcspResponderURL(String ocspResponderURL)
{
checkNotStarted();
_ocspResponderURL = ocspResponderURL;
}
@ -1275,13 +1282,18 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStore(KeyStore keyStore)
{
checkNotStarted();
_setKeyStore = keyStore;
}
public KeyStore getKeyStore()
{
return isStarted() ? _factory._keyStore : _setKeyStore;
if (!isStarted())
return _setKeyStore;
synchronized (this)
{
return _factory._keyStore;
}
}
/**
@ -1291,13 +1303,18 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(KeyStore trustStore)
{
checkNotStarted();
_setTrustStore = trustStore;
}
public KeyStore getTrustStore()
{
return isStarted() ? _factory._trustStore : _setTrustStore;
if (!isStarted())
return _setTrustStore;
synchronized (this)
{
return _factory._trustStore;
}
}
/**
@ -1307,7 +1324,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreResource(Resource resource)
{
checkNotStarted();
_keyStoreResource = resource;
}
@ -1323,7 +1339,6 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreResource(Resource resource)
{
checkNotStarted();
_trustStoreResource = resource;
}
@ -1406,12 +1421,14 @@ public class SslContextFactory extends AbstractLifeCycle
{
checkIsStarted();
SSLServerSocketFactory factory = _factory._context.getServerSocketFactory();
SSLContext context = getSslContext();
SSLServerSocketFactory factory = context.getServerSocketFactory();
SSLServerSocket socket =
(SSLServerSocket)(host == null ?
factory.createServerSocket(port, backlog) :
factory.createServerSocket(port, backlog, InetAddress.getByName(host)));
socket.setSSLParameters(customize(socket.getSSLParameters()));
return socket;
}
@ -1419,9 +1436,11 @@ public class SslContextFactory extends AbstractLifeCycle
{
checkIsStarted();
SSLSocketFactory factory = _factory._context.getSocketFactory();
SSLContext context = getSslContext();
SSLSocketFactory factory = context.getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket();
socket.setSSLParameters(customize(socket.getSSLParameters()));
return socket;
}
@ -1436,9 +1455,12 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public SSLEngine newSSLEngine()
{
checkIsRunning();
SSLEngine sslEngine = _factory._context.createSSLEngine();
checkIsStarted();
SSLContext context = getSslContext();
SSLEngine sslEngine = context.createSSLEngine();
customize(sslEngine);
return sslEngine;
}
@ -1453,10 +1475,13 @@ public class SslContextFactory extends AbstractLifeCycle
public SSLEngine newSSLEngine(String host, int port)
{
checkIsStarted();
SSLEngine sslEngine = isSessionCachingEnabled()
? _factory._context.createSSLEngine(host, port)
: _factory._context.createSSLEngine();
SSLContext context = getSslContext();
SSLEngine sslEngine = isSessionCachingEnabled() ?
context.createSSLEngine(host, port) :
context.createSSLEngine();
customize(sslEngine);
return sslEngine;
}
@ -1510,7 +1535,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public SSLParameters customize(SSLParameters sslParams)
{
sslParams.setEndpointIdentificationAlgorithm(_endpointIdentificationAlgorithm);
sslParams.setEndpointIdentificationAlgorithm(getEndpointIdentificationAlgorithm());
sslParams.setUseCipherSuitesOrder(isUseCipherSuitesOrder());
if (!_certHosts.isEmpty() || !_certWilds.isEmpty())
sslParams.setSNIMatchers(Collections.singletonList(new AliasSNIMatcher()));
@ -1525,6 +1550,16 @@ public class SslContextFactory extends AbstractLifeCycle
return sslParams;
}
public void reload(Consumer<SslContextFactory> consumer) throws Exception
{
synchronized (this)
{
consumer.accept(this);
unload();
load();
}
}
public static X509Certificate[] getCertChain(SSLSession sslSession)
{
try