SslContext to support TLS/SSL protocols
Motivation: SslContext and SslContextBuilder do not support a way to specify the desired TLS protocols. This currently requires that the user extracts the SSLEngine once a context is built and manually call SSLEngine#setEnabledProtocols(String[]). Something this critical should be supported at the SslContext level. Modifications: - SslContextBuilder should accept a list of protocols to configure for each SslEngine Result: SslContext consistently sets the supported TLS/SSL protocols.
This commit is contained in:
parent
e18c85b768
commit
a2304287a1
@ -248,16 +248,17 @@ public final class JdkSslClientContext extends JdkSslContext {
|
||||
trustCertCollectionFile), trustManagerFactory,
|
||||
toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout), true,
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, false);
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
JdkSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
ApplicationProtocolConfig apn, String[] protocols, long sessionCacheSize, long sessionTimeout)
|
||||
throws SSLException {
|
||||
super(newSSLContext(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, sessionCacheSize, sessionTimeout), true,
|
||||
ciphers, cipherFilter, toNegotiator(apn, false), ClientAuth.NONE, false);
|
||||
ciphers, cipherFilter, toNegotiator(apn, false), ClientAuth.NONE, protocols, false);
|
||||
}
|
||||
|
||||
private static SSLContext newSSLContext(X509Certificate[] trustCertCollection,
|
||||
|
@ -52,7 +52,7 @@ public class JdkSslContext extends SslContext {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(JdkSslContext.class);
|
||||
|
||||
static final String PROTOCOL = "TLS";
|
||||
static final String[] PROTOCOLS;
|
||||
static final String[] DEFAULT_PROTOCOLS;
|
||||
static final List<String> DEFAULT_CIPHERS;
|
||||
static final Set<String> SUPPORTED_CIPHERS;
|
||||
|
||||
@ -80,9 +80,9 @@ public class JdkSslContext extends SslContext {
|
||||
"TLSv1.2", "TLSv1.1", "TLSv1");
|
||||
|
||||
if (!protocols.isEmpty()) {
|
||||
PROTOCOLS = protocols.toArray(new String[protocols.size()]);
|
||||
DEFAULT_PROTOCOLS = protocols.toArray(new String[protocols.size()]);
|
||||
} else {
|
||||
PROTOCOLS = engine.getEnabledProtocols();
|
||||
DEFAULT_PROTOCOLS = engine.getEnabledProtocols();
|
||||
}
|
||||
|
||||
// Choose the sensible default list of cipher suites.
|
||||
@ -120,7 +120,7 @@ public class JdkSslContext extends SslContext {
|
||||
DEFAULT_CIPHERS = Collections.unmodifiableList(ciphers);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Default protocols (JDK): {} ", Arrays.asList(PROTOCOLS));
|
||||
logger.debug("Default protocols (JDK): {} ", Arrays.asList(DEFAULT_PROTOCOLS));
|
||||
logger.debug("Default cipher suites (JDK): {}", DEFAULT_CIPHERS);
|
||||
}
|
||||
}
|
||||
@ -133,6 +133,7 @@ public class JdkSslContext extends SslContext {
|
||||
}
|
||||
}
|
||||
|
||||
private final String[] protocols;
|
||||
private final String[] cipherSuites;
|
||||
private final List<String> unmodifiableCipherSuites;
|
||||
private final JdkApplicationProtocolNegotiator apn;
|
||||
@ -150,7 +151,7 @@ public class JdkSslContext extends SslContext {
|
||||
public JdkSslContext(SSLContext sslContext, boolean isClient,
|
||||
ClientAuth clientAuth) {
|
||||
this(sslContext, isClient, null, IdentityCipherSuiteFilter.INSTANCE,
|
||||
JdkDefaultApplicationProtocolNegotiator.INSTANCE, clientAuth, false);
|
||||
JdkDefaultApplicationProtocolNegotiator.INSTANCE, clientAuth, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,16 +167,17 @@ public class JdkSslContext extends SslContext {
|
||||
public JdkSslContext(SSLContext sslContext, boolean isClient, Iterable<String> ciphers,
|
||||
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
ClientAuth clientAuth) {
|
||||
this(sslContext, isClient, ciphers, cipherFilter, toNegotiator(apn, !isClient), clientAuth, false);
|
||||
this(sslContext, isClient, ciphers, cipherFilter, toNegotiator(apn, !isClient), clientAuth, null, false);
|
||||
}
|
||||
|
||||
JdkSslContext(SSLContext sslContext, boolean isClient, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
JdkApplicationProtocolNegotiator apn, ClientAuth clientAuth, boolean startTls) {
|
||||
JdkApplicationProtocolNegotiator apn, ClientAuth clientAuth, String[] protocols, boolean startTls) {
|
||||
super(startTls);
|
||||
this.apn = checkNotNull(apn, "apn");
|
||||
this.clientAuth = checkNotNull(clientAuth, "clientAuth");
|
||||
cipherSuites = checkNotNull(cipherFilter, "cipherFilter").filterCipherSuites(
|
||||
ciphers, DEFAULT_CIPHERS, SUPPORTED_CIPHERS);
|
||||
this.protocols = protocols == null ? DEFAULT_PROTOCOLS : protocols;
|
||||
unmodifiableCipherSuites = Collections.unmodifiableList(Arrays.asList(cipherSuites));
|
||||
this.sslContext = checkNotNull(sslContext, "sslContext");
|
||||
this.isClient = isClient;
|
||||
@ -232,7 +234,7 @@ public class JdkSslContext extends SslContext {
|
||||
|
||||
private SSLEngine configureAndWrapEngine(SSLEngine engine) {
|
||||
engine.setEnabledCipherSuites(cipherSuites);
|
||||
engine.setEnabledProtocols(PROTOCOLS);
|
||||
engine.setEnabledProtocols(protocols);
|
||||
engine.setUseClientMode(isClient());
|
||||
if (isServer()) {
|
||||
switch (clientAuth) {
|
||||
|
@ -215,17 +215,17 @@ public final class JdkSslServerContext extends JdkSslContext {
|
||||
super(newSSLContext(toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout), false,
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, false);
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
JdkSslServerContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout,
|
||||
ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls) throws SSLException {
|
||||
super(newSSLContext(trustCertCollection, trustManagerFactory, keyCertChain, key,
|
||||
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout), false,
|
||||
ciphers, cipherFilter, toNegotiator(apn, true), clientAuth, startTls);
|
||||
ciphers, cipherFilter, toNegotiator(apn, true), clientAuth, protocols, startTls);
|
||||
}
|
||||
|
||||
private static SSLContext newSSLContext(X509Certificate[] trustCertCollection,
|
||||
|
@ -175,17 +175,17 @@ public final class OpenSslClientContext extends OpenSslContext {
|
||||
throws SSLException {
|
||||
this(toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter, apn, null, sessionCacheSize, sessionTimeout);
|
||||
}
|
||||
|
||||
OpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
||||
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
|
||||
long sessionCacheSize, long sessionTimeout)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain,
|
||||
ClientAuth.NONE, false);
|
||||
ClientAuth.NONE, protocols, false);
|
||||
boolean success = false;
|
||||
try {
|
||||
sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
|
||||
|
@ -29,18 +29,18 @@ import javax.net.ssl.SSLException;
|
||||
public abstract class OpenSslContext extends ReferenceCountedOpenSslContext {
|
||||
OpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apnCfg,
|
||||
long sessionCacheSize, long sessionTimeout, int mode, Certificate[] keyCertChain,
|
||||
ClientAuth clientAuth, boolean startTls)
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apnCfg, sessionCacheSize, sessionTimeout, mode, keyCertChain,
|
||||
clientAuth, startTls, false);
|
||||
clientAuth, protocols, startTls, false);
|
||||
}
|
||||
|
||||
OpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize,
|
||||
long sessionTimeout, int mode, Certificate[] keyCertChain,
|
||||
ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, mode, keyCertChain, clientAuth, startTls,
|
||||
false);
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls) throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, mode, keyCertChain, clientAuth, protocols,
|
||||
startTls, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -323,16 +323,17 @@ public final class OpenSslServerContext extends OpenSslContext {
|
||||
this(toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter,
|
||||
apn, sessionCacheSize, sessionTimeout, ClientAuth.NONE, false);
|
||||
apn, sessionCacheSize, sessionTimeout, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
OpenSslServerContext(
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls)
|
||||
throws SSLException {
|
||||
this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
|
||||
cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, startTls);
|
||||
cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@ -340,9 +341,10 @@ public final class OpenSslServerContext extends OpenSslContext {
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
|
||||
clientAuth, startTls);
|
||||
clientAuth, protocols, startTls);
|
||||
// Create a new SSL_CTX and configure it.
|
||||
boolean success = false;
|
||||
try {
|
||||
|
@ -54,10 +54,10 @@ public final class ReferenceCountedOpenSslClientContext extends ReferenceCounted
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
||||
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
long sessionCacheSize, long sessionTimeout)
|
||||
String[] protocols, long sessionCacheSize, long sessionTimeout)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain,
|
||||
ClientAuth.NONE, false, true);
|
||||
ClientAuth.NONE, protocols, false, true);
|
||||
boolean success = false;
|
||||
try {
|
||||
sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
|
||||
|
@ -140,6 +140,7 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
|
||||
final Certificate[] keyCertChain;
|
||||
final ClientAuth clientAuth;
|
||||
final String[] protocols;
|
||||
final OpenSslEngineMap engineMap = new DefaultOpenSslEngineMap();
|
||||
private volatile boolean rejectRemoteInitiatedRenegotiation;
|
||||
private volatile int bioNonApplicationBufferSize = DEFAULT_BIO_NON_APPLICATION_BUFFER_SIZE;
|
||||
@ -211,16 +212,17 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
|
||||
ReferenceCountedOpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
ApplicationProtocolConfig apnCfg, long sessionCacheSize, long sessionTimeout,
|
||||
int mode, Certificate[] keyCertChain, ClientAuth clientAuth, boolean startTls,
|
||||
boolean leakDetection) throws SSLException {
|
||||
int mode, Certificate[] keyCertChain, ClientAuth clientAuth, String[] protocols,
|
||||
boolean startTls, boolean leakDetection) throws SSLException {
|
||||
this(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode, keyCertChain,
|
||||
clientAuth, startTls, leakDetection);
|
||||
clientAuth, protocols, startTls, leakDetection);
|
||||
}
|
||||
|
||||
ReferenceCountedOpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize,
|
||||
long sessionTimeout, int mode, Certificate[] keyCertChain,
|
||||
ClientAuth clientAuth, boolean startTls, boolean leakDetection) throws SSLException {
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls, boolean leakDetection)
|
||||
throws SSLException {
|
||||
super(startTls);
|
||||
|
||||
OpenSsl.ensureAvailability();
|
||||
@ -231,6 +233,7 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
leak = leakDetection ? leakDetector.track(this) : null;
|
||||
this.mode = mode;
|
||||
this.clientAuth = isServer() ? checkNotNull(clientAuth, "clientAuth") : ClientAuth.NONE;
|
||||
this.protocols = protocols;
|
||||
|
||||
if (mode == SSL.SSL_MODE_SERVER) {
|
||||
rejectRemoteInitiatedRenegotiation =
|
||||
@ -305,19 +308,19 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
List<String> nextProtoList = apn.protocols();
|
||||
/* Set next protocols for next protocol negotiation extension, if specified */
|
||||
if (!nextProtoList.isEmpty()) {
|
||||
String[] protocols = nextProtoList.toArray(new String[nextProtoList.size()]);
|
||||
String[] appProtocols = nextProtoList.toArray(new String[nextProtoList.size()]);
|
||||
int selectorBehavior = opensslSelectorFailureBehavior(apn.selectorFailureBehavior());
|
||||
|
||||
switch (apn.protocol()) {
|
||||
case NPN:
|
||||
SSLContext.setNpnProtos(ctx, protocols, selectorBehavior);
|
||||
SSLContext.setNpnProtos(ctx, appProtocols, selectorBehavior);
|
||||
break;
|
||||
case ALPN:
|
||||
SSLContext.setAlpnProtos(ctx, protocols, selectorBehavior);
|
||||
SSLContext.setAlpnProtos(ctx, appProtocols, selectorBehavior);
|
||||
break;
|
||||
case NPN_AND_ALPN:
|
||||
SSLContext.setNpnProtos(ctx, protocols, selectorBehavior);
|
||||
SSLContext.setAlpnProtos(ctx, protocols, selectorBehavior);
|
||||
SSLContext.setNpnProtos(ctx, appProtocols, selectorBehavior);
|
||||
SSLContext.setAlpnProtos(ctx, appProtocols, selectorBehavior);
|
||||
break;
|
||||
default:
|
||||
throw new Error();
|
||||
|
@ -237,6 +237,10 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
||||
// needed JNI methods.
|
||||
setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth);
|
||||
|
||||
if (context.protocols != null) {
|
||||
setEnabledProtocols(context.protocols);
|
||||
}
|
||||
|
||||
// Use SNI if peerHost was specified
|
||||
// See https://github.com/netty/netty/issues/4746
|
||||
if (clientMode && peerHost != null) {
|
||||
|
@ -49,18 +49,20 @@ public final class ReferenceCountedOpenSslServerContext extends ReferenceCounted
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls)
|
||||
throws SSLException {
|
||||
this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
|
||||
cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, startTls);
|
||||
cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls);
|
||||
}
|
||||
|
||||
private ReferenceCountedOpenSslServerContext(
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
|
||||
clientAuth, startTls, true);
|
||||
clientAuth, protocols, startTls, true);
|
||||
// Create a new SSL_CTX and configure it.
|
||||
boolean success = false;
|
||||
try {
|
||||
|
@ -384,7 +384,7 @@ public abstract class SslContext {
|
||||
toX509Certificates(keyCertChainFile),
|
||||
toPrivateKey(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter, apn,
|
||||
sessionCacheSize, sessionTimeout, ClientAuth.NONE, false);
|
||||
sessionCacheSize, sessionTimeout, ClientAuth.NONE, null, false);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SSLException) {
|
||||
throw (SSLException) e;
|
||||
@ -398,7 +398,8 @@ public abstract class SslContext {
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, boolean startTls) throws SSLException {
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls)
|
||||
throws SSLException {
|
||||
|
||||
if (provider == null) {
|
||||
provider = defaultServerProvider();
|
||||
@ -409,17 +410,17 @@ public abstract class SslContext {
|
||||
return new JdkSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, startTls);
|
||||
clientAuth, protocols, startTls);
|
||||
case OPENSSL:
|
||||
return new OpenSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, startTls);
|
||||
clientAuth, protocols, startTls);
|
||||
case OPENSSL_REFCNT:
|
||||
return new ReferenceCountedOpenSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, startTls);
|
||||
clientAuth, protocols, startTls);
|
||||
default:
|
||||
throw new Error(provider.toString());
|
||||
}
|
||||
@ -727,8 +728,7 @@ public abstract class SslContext {
|
||||
return newClientContextInternal(provider, toX509Certificates(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509Certificates(keyCertChainFile), toPrivateKey(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter,
|
||||
apn,
|
||||
sessionCacheSize, sessionTimeout);
|
||||
apn, null, sessionCacheSize, sessionTimeout);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SSLException) {
|
||||
throw (SSLException) e;
|
||||
@ -741,7 +741,7 @@ public abstract class SslContext {
|
||||
SslProvider provider,
|
||||
X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
if (provider == null) {
|
||||
provider = defaultClientProvider();
|
||||
@ -750,15 +750,15 @@ public abstract class SslContext {
|
||||
case JDK:
|
||||
return new JdkSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
case OPENSSL:
|
||||
return new OpenSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
case OPENSSL_REFCNT:
|
||||
return new ReferenceCountedOpenSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
default:
|
||||
throw new Error(provider.toString());
|
||||
}
|
||||
|
@ -16,15 +16,16 @@
|
||||
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* Builder for configuring a new SslContext for creation.
|
||||
@ -137,6 +138,7 @@ public final class SslContextBuilder {
|
||||
private long sessionCacheSize;
|
||||
private long sessionTimeout;
|
||||
private ClientAuth clientAuth = ClientAuth.NONE;
|
||||
private String[] protocols;
|
||||
private boolean startTls;
|
||||
|
||||
private SslContextBuilder(boolean forServer) {
|
||||
@ -384,6 +386,16 @@ public final class SslContextBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The TLS protocol versions to enable.
|
||||
* @param protocols The protocols to enable, or {@code null} to enable the default protocols.
|
||||
* @see SSLEngine#setEnabledCipherSuites(String[])
|
||||
*/
|
||||
public SslContextBuilder protocols(String... protocols) {
|
||||
this.protocols = protocols == null ? null : protocols.clone();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code true} if the first write request shouldn't be encrypted.
|
||||
*/
|
||||
@ -401,11 +413,11 @@ public final class SslContextBuilder {
|
||||
if (forServer) {
|
||||
return SslContext.newServerContextInternal(provider, trustCertCollection,
|
||||
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, clientAuth, startTls);
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls);
|
||||
} else {
|
||||
return SslContext.newClientContextInternal(provider, trustCertCollection,
|
||||
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,13 +63,11 @@ import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SNIHostName;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLException;
|
||||
@ -1633,6 +1631,43 @@ public abstract class SSLEngineTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProtocolMatch() throws Exception {
|
||||
testProtocol(new String[] {"TLSv1.2"}, new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"});
|
||||
}
|
||||
|
||||
@Test(expected = SSLHandshakeException.class)
|
||||
public void testProtocolNoMatch() throws Exception {
|
||||
testProtocol(new String[] {"TLSv1.2"}, new String[] {"TLSv1", "TLSv1.1"});
|
||||
}
|
||||
|
||||
private void testProtocol(String[] clientProtocols, String[] serverProtocols) throws Exception {
|
||||
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||
|
||||
clientSslCtx = SslContextBuilder
|
||||
.forClient()
|
||||
.trustManager(cert.cert())
|
||||
.sslProvider(sslClientProvider())
|
||||
.protocols(clientProtocols)
|
||||
.build();
|
||||
SSLEngine client = clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||
|
||||
serverSslCtx = SslContextBuilder
|
||||
.forServer(cert.certificate(), cert.privateKey())
|
||||
.sslProvider(sslServerProvider())
|
||||
.protocols(serverProtocols)
|
||||
.build();
|
||||
SSLEngine server = serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||
|
||||
try {
|
||||
handshake(client, server);
|
||||
} finally {
|
||||
cleanupClientSslEngine(client);
|
||||
cleanupServerSslEngine(server);
|
||||
cert.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPacketBufferSizeLimit() throws Exception {
|
||||
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||
|
Loading…
Reference in New Issue
Block a user