Adding support for Conscrypt (#6271)
Motivation: Conscrypt is a Java Security provider that wraps OpenSSL (specifically BoringSSL). It's a possible alternative to Netty-tcnative that we should explore. So this commit is just to enable us to further investigate its use. Modifications: Modifying the SslContext creation path to support the Conscrypt provider. Result: Netty will support OpenSSL with conscrypt.
This commit is contained in:
parent
f4c635d30b
commit
1419f5b601
@ -89,6 +89,11 @@
|
||||
<artifactId>${tcnative.artifactId}</artifactId>
|
||||
<classifier>${tcnative.classifier}</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${conscrypt.groupId}</groupId>
|
||||
<artifactId>${conscrypt.artifactId}</artifactId>
|
||||
<classifier>${conscrypt.classifier}</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.npn</groupId>
|
||||
<artifactId>npn-api</artifactId>
|
||||
|
@ -70,6 +70,11 @@
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${conscrypt.groupId}</groupId>
|
||||
<artifactId>${conscrypt.artifactId}</artifactId>
|
||||
<classifier>${conscrypt.classifier}</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
|
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2017 The Netty Project
|
||||
*
|
||||
* The Netty Project 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.
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import static io.netty.handler.ssl.SslUtils.toSSLHandshakeException;
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener;
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLException;
|
||||
import org.conscrypt.Conscrypt;
|
||||
import org.conscrypt.HandshakeListener;
|
||||
|
||||
/**
|
||||
* A {@link JdkSslEngine} that uses the Conscrypt provider or SSL with ALPN.
|
||||
*/
|
||||
abstract class ConscryptAlpnSslEngine extends JdkSslEngine {
|
||||
private static final Class<?> ENGINES_CLASS = getEnginesClass();
|
||||
|
||||
/**
|
||||
* Indicates whether or not conscrypt is available on the current system.
|
||||
*/
|
||||
static boolean isAvailable() {
|
||||
return ENGINES_CLASS != null;
|
||||
}
|
||||
|
||||
static boolean isEngineSupported(SSLEngine engine) {
|
||||
return isAvailable() && isConscryptEngine(engine, ENGINES_CLASS);
|
||||
}
|
||||
|
||||
static ConscryptAlpnSslEngine newClientEngine(SSLEngine engine,
|
||||
JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
return new ClientEngine(engine, applicationNegotiator);
|
||||
}
|
||||
|
||||
static ConscryptAlpnSslEngine newServerEngine(SSLEngine engine,
|
||||
JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
return new ServerEngine(engine, applicationNegotiator);
|
||||
}
|
||||
|
||||
private ConscryptAlpnSslEngine(SSLEngine engine, List<String> protocols) {
|
||||
super(engine);
|
||||
|
||||
// Set the list of supported ALPN protocols on the engine.
|
||||
Conscrypt.Engines.setAlpnProtocols(engine, protocols.toArray(new String[protocols.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum size of the encrypted output buffer required to wrap the given plaintext bytes. Assumes
|
||||
* as a worst case that there is one TLS record per buffer.
|
||||
*
|
||||
* @param plaintextBytes the number of plaintext bytes to be wrapped.
|
||||
* @param numBuffers the number of buffers that the plaintext bytes are spread across.
|
||||
* @return the maximum size of the encrypted output buffer required for the wrap operation.
|
||||
*/
|
||||
final int calculateOutNetBufSize(int plaintextBytes, int numBuffers) {
|
||||
// Assuming a max of one frame per component in a composite buffer.
|
||||
long maxOverhead = (long) Conscrypt.Engines.maxSealOverhead(getWrappedEngine()) * numBuffers;
|
||||
// TODO(nmittler): update this to use MAX_ENCRYPTED_PACKET_LENGTH instead of Integer.MAX_VALUE
|
||||
return (int) min(Integer.MAX_VALUE, plaintextBytes + maxOverhead);
|
||||
}
|
||||
|
||||
final SSLEngineResult unwrap(ByteBuffer[] srcs, ByteBuffer[] dests) throws SSLException {
|
||||
return Conscrypt.Engines.unwrap(getWrappedEngine(), srcs, dests);
|
||||
}
|
||||
|
||||
private static final class ClientEngine extends ConscryptAlpnSslEngine {
|
||||
private final ProtocolSelectionListener protocolListener;
|
||||
|
||||
ClientEngine(SSLEngine engine,
|
||||
JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
super(engine, applicationNegotiator.protocols());
|
||||
// Register for completion of the handshake.
|
||||
Conscrypt.Engines.setHandshakeListener(engine, new HandshakeListener() {
|
||||
@Override
|
||||
public void onHandshakeFinished() throws SSLException {
|
||||
selectProtocol();
|
||||
}
|
||||
});
|
||||
|
||||
protocolListener = checkNotNull(applicationNegotiator
|
||||
.protocolListenerFactory().newListener(this, applicationNegotiator.protocols()),
|
||||
"protocolListener");
|
||||
}
|
||||
|
||||
private void selectProtocol() throws SSLException {
|
||||
String protocol = Conscrypt.Engines.getAlpnSelectedProtocol(getWrappedEngine());
|
||||
try {
|
||||
protocolListener.selected(protocol);
|
||||
} catch (Throwable e) {
|
||||
throw toSSLHandshakeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ServerEngine extends ConscryptAlpnSslEngine {
|
||||
private final ProtocolSelector protocolSelector;
|
||||
|
||||
ServerEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
super(engine, applicationNegotiator.protocols());
|
||||
|
||||
// Register for completion of the handshake.
|
||||
Conscrypt.Engines.setHandshakeListener(engine, new HandshakeListener() {
|
||||
@Override
|
||||
public void onHandshakeFinished() throws SSLException {
|
||||
selectProtocol();
|
||||
}
|
||||
});
|
||||
|
||||
protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory()
|
||||
.newSelector(this,
|
||||
new LinkedHashSet<String>(applicationNegotiator.protocols())),
|
||||
"protocolSelector");
|
||||
}
|
||||
|
||||
private void selectProtocol() throws SSLException {
|
||||
try {
|
||||
String protocol = Conscrypt.Engines.getAlpnSelectedProtocol(getWrappedEngine());
|
||||
protocolSelector.select(protocol != null ? Collections.singletonList(protocol)
|
||||
: Collections.<String>emptyList());
|
||||
} catch (Throwable e) {
|
||||
throw toSSLHandshakeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> getEnginesClass() {
|
||||
try {
|
||||
// Always use bootstrap class loader.
|
||||
Class<?> engineClass = Class.forName("org.conscrypt.Conscrypt$Engines", true,
|
||||
ConscryptAlpnSslEngine.class.getClassLoader());
|
||||
// Ensure that it also has the isConscrypt method.
|
||||
getIsConscryptMethod(engineClass);
|
||||
return engineClass;
|
||||
} catch (Throwable ignore) {
|
||||
// Conscrypt was not loaded.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isConscryptEngine(SSLEngine engine, Class<?> enginesClass) {
|
||||
try {
|
||||
Method method = getIsConscryptMethod(enginesClass);
|
||||
return (Boolean) method.invoke(null, engine);
|
||||
} catch (Throwable ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getIsConscryptMethod(Class<?> enginesClass) throws NoSuchMethodException {
|
||||
return enginesClass.getMethod("isConscrypt", SSLEngine.class);
|
||||
}
|
||||
}
|
@ -21,20 +21,8 @@ import javax.net.ssl.SSLEngine;
|
||||
* The {@link JdkApplicationProtocolNegotiator} to use if you need ALPN and are using {@link SslProvider#JDK}.
|
||||
*/
|
||||
public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator {
|
||||
private static final SslEngineWrapperFactory ALPN_WRAPPER = new SslEngineWrapperFactory() {
|
||||
{
|
||||
if (!JdkAlpnSslEngine.isAvailable()) {
|
||||
throw new RuntimeException("ALPN unsupported. Is your classpatch configured correctly?"
|
||||
+ " See http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-starting");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator,
|
||||
boolean isServer) {
|
||||
return new JdkAlpnSslEngine(engine, applicationNegotiator, isServer);
|
||||
}
|
||||
};
|
||||
private static final boolean AVAILABLE = ConscryptAlpnSslEngine.isAvailable() || JettyAlpnSslEngine.isAvailable();
|
||||
private static final SslEngineWrapperFactory ALPN_WRAPPER = AVAILABLE ? new AlpnWrapper() : new FailureWrapper();
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
@ -117,4 +105,31 @@ public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicati
|
||||
ProtocolSelectionListenerFactory listenerFactory, String... protocols) {
|
||||
super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols);
|
||||
}
|
||||
|
||||
private static final class FailureWrapper implements SslEngineWrapperFactory {
|
||||
@Override
|
||||
public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator,
|
||||
boolean isServer) {
|
||||
throw new RuntimeException("ALPN unsupported. Is your classpatch configured correctly?"
|
||||
+ " For Conscrypt, add the appropriate Conscrypt JAR to classpath and set the security provider."
|
||||
+ " For Jetty-ALPN, see "
|
||||
+ "http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-starting");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AlpnWrapper implements SslEngineWrapperFactory {
|
||||
@Override
|
||||
public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator,
|
||||
boolean isServer) {
|
||||
if (ConscryptAlpnSslEngine.isEngineSupported(engine)) {
|
||||
return isServer ? ConscryptAlpnSslEngine.newServerEngine(engine, applicationNegotiator)
|
||||
: ConscryptAlpnSslEngine.newClientEngine(engine, applicationNegotiator);
|
||||
}
|
||||
if (JettyAlpnSslEngine.isAvailable()) {
|
||||
return isServer ? JettyAlpnSslEngine.newServerEngine(engine, applicationNegotiator)
|
||||
: JettyAlpnSslEngine.newClientEngine(engine, applicationNegotiator);
|
||||
}
|
||||
throw new RuntimeException("Unable to wrap SSLEngine of type " + engine.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project 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.
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener;
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
import org.eclipse.jetty.alpn.ALPN.ClientProvider;
|
||||
import org.eclipse.jetty.alpn.ALPN.ServerProvider;
|
||||
|
||||
final class JdkAlpnSslEngine extends JdkSslEngine {
|
||||
private static boolean available;
|
||||
|
||||
static boolean isAvailable() {
|
||||
updateAvailability();
|
||||
return available;
|
||||
}
|
||||
|
||||
private static void updateAvailability() {
|
||||
// TODO: Add support for ALPN when using Java9 and still be able to configure it the Netty way.
|
||||
if (available || PlatformDependent.javaVersion() > 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Always use bootstrap class loader.
|
||||
Class.forName("sun.security.ssl.ALPNExtension", true, null);
|
||||
available = true;
|
||||
} catch (Exception ignore) {
|
||||
// alpn-boot was not loaded.
|
||||
}
|
||||
}
|
||||
|
||||
JdkAlpnSslEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator, boolean server) {
|
||||
super(engine);
|
||||
checkNotNull(applicationNegotiator, "applicationNegotiator");
|
||||
|
||||
if (server) {
|
||||
final ProtocolSelector protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory()
|
||||
.newSelector(this, new LinkedHashSet<String>(applicationNegotiator.protocols())),
|
||||
"protocolSelector");
|
||||
ALPN.put(engine, new ServerProvider() {
|
||||
@Override
|
||||
public String select(List<String> protocols) throws SSLException {
|
||||
try {
|
||||
return protocolSelector.select(protocols);
|
||||
} catch (SSLHandshakeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
SSLHandshakeException e = new SSLHandshakeException(t.getMessage());
|
||||
e.initCause(t);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
protocolSelector.unsupported();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final ProtocolSelectionListener protocolListener = checkNotNull(applicationNegotiator
|
||||
.protocolListenerFactory().newListener(this, applicationNegotiator.protocols()),
|
||||
"protocolListener");
|
||||
ALPN.put(engine, new ClientProvider() {
|
||||
@Override
|
||||
public List<String> protocols() {
|
||||
return applicationNegotiator.protocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selected(String protocol) throws SSLException {
|
||||
try {
|
||||
protocolListener.selected(protocol);
|
||||
} catch (SSLHandshakeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
SSLHandshakeException e = new SSLHandshakeException(t.getMessage());
|
||||
e.initCause(t);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
protocolListener.unsupported();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeInbound() throws SSLException {
|
||||
ALPN.remove(getWrappedEngine());
|
||||
super.closeInbound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeOutbound() {
|
||||
ALPN.remove(getWrappedEngine());
|
||||
super.closeOutbound();
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ class JdkBaseApplicationProtocolNegotiator implements JdkApplicationProtocolNego
|
||||
* @param listenerFactory How the peer being notified of the selected protocol should behave.
|
||||
* @param protocols The order of iteration determines the preference of support for protocols.
|
||||
*/
|
||||
protected JdkBaseApplicationProtocolNegotiator(SslEngineWrapperFactory wrapperFactory,
|
||||
JdkBaseApplicationProtocolNegotiator(SslEngineWrapperFactory wrapperFactory,
|
||||
ProtocolSelectorFactory selectorFactory, ProtocolSelectionListenerFactory listenerFactory,
|
||||
Iterable<String> protocols) {
|
||||
this(wrapperFactory, selectorFactory, listenerFactory, toList(protocols));
|
||||
@ -54,7 +54,7 @@ class JdkBaseApplicationProtocolNegotiator implements JdkApplicationProtocolNego
|
||||
* @param listenerFactory How the peer being notified of the selected protocol should behave.
|
||||
* @param protocols The order of iteration determines the preference of support for protocols.
|
||||
*/
|
||||
protected JdkBaseApplicationProtocolNegotiator(SslEngineWrapperFactory wrapperFactory,
|
||||
JdkBaseApplicationProtocolNegotiator(SslEngineWrapperFactory wrapperFactory,
|
||||
ProtocolSelectorFactory selectorFactory, ProtocolSelectionListenerFactory listenerFactory,
|
||||
String... protocols) {
|
||||
this(wrapperFactory, selectorFactory, listenerFactory, toList(protocols));
|
||||
@ -126,25 +126,25 @@ class JdkBaseApplicationProtocolNegotiator implements JdkApplicationProtocolNego
|
||||
}
|
||||
};
|
||||
|
||||
protected static class NoFailProtocolSelector implements ProtocolSelector {
|
||||
private final JdkSslEngine jettyWrapper;
|
||||
static class NoFailProtocolSelector implements ProtocolSelector {
|
||||
private final JdkSslEngine engineWrapper;
|
||||
private final Set<String> supportedProtocols;
|
||||
|
||||
public NoFailProtocolSelector(JdkSslEngine jettyWrapper, Set<String> supportedProtocols) {
|
||||
this.jettyWrapper = jettyWrapper;
|
||||
NoFailProtocolSelector(JdkSslEngine engineWrapper, Set<String> supportedProtocols) {
|
||||
this.engineWrapper = engineWrapper;
|
||||
this.supportedProtocols = supportedProtocols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
jettyWrapper.getSession().setApplicationProtocol(null);
|
||||
engineWrapper.getSession().setApplicationProtocol(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String select(List<String> protocols) throws Exception {
|
||||
for (String p : supportedProtocols) {
|
||||
if (protocols.contains(p)) {
|
||||
jettyWrapper.getSession().setApplicationProtocol(p);
|
||||
engineWrapper.getSession().setApplicationProtocol(p);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@ -152,14 +152,14 @@ class JdkBaseApplicationProtocolNegotiator implements JdkApplicationProtocolNego
|
||||
}
|
||||
|
||||
public String noSelectMatchFound() throws Exception {
|
||||
jettyWrapper.getSession().setApplicationProtocol(null);
|
||||
engineWrapper.getSession().setApplicationProtocol(null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final class FailProtocolSelector extends NoFailProtocolSelector {
|
||||
public FailProtocolSelector(JdkSslEngine jettyWrapper, Set<String> supportedProtocols) {
|
||||
super(jettyWrapper, supportedProtocols);
|
||||
private static final class FailProtocolSelector extends NoFailProtocolSelector {
|
||||
FailProtocolSelector(JdkSslEngine engineWrapper, Set<String> supportedProtocols) {
|
||||
super(engineWrapper, supportedProtocols);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -168,40 +168,41 @@ class JdkBaseApplicationProtocolNegotiator implements JdkApplicationProtocolNego
|
||||
}
|
||||
}
|
||||
|
||||
protected static class NoFailProtocolSelectionListener implements ProtocolSelectionListener {
|
||||
private final JdkSslEngine jettyWrapper;
|
||||
private static class NoFailProtocolSelectionListener implements ProtocolSelectionListener {
|
||||
private final JdkSslEngine engineWrapper;
|
||||
private final List<String> supportedProtocols;
|
||||
|
||||
public NoFailProtocolSelectionListener(JdkSslEngine jettyWrapper, List<String> supportedProtocols) {
|
||||
this.jettyWrapper = jettyWrapper;
|
||||
NoFailProtocolSelectionListener(JdkSslEngine engineWrapper, List<String> supportedProtocols) {
|
||||
this.engineWrapper = engineWrapper;
|
||||
this.supportedProtocols = supportedProtocols;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
jettyWrapper.getSession().setApplicationProtocol(null);
|
||||
engineWrapper.getSession().setApplicationProtocol(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selected(String protocol) throws Exception {
|
||||
if (supportedProtocols.contains(protocol)) {
|
||||
jettyWrapper.getSession().setApplicationProtocol(protocol);
|
||||
engineWrapper.getSession().setApplicationProtocol(protocol);
|
||||
} else {
|
||||
noSelectedMatchFound(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
public void noSelectedMatchFound(String protocol) throws Exception {
|
||||
protected void noSelectedMatchFound(String protocol) throws Exception {
|
||||
// Will never be called.
|
||||
}
|
||||
}
|
||||
|
||||
protected static final class FailProtocolSelectionListener extends NoFailProtocolSelectionListener {
|
||||
public FailProtocolSelectionListener(JdkSslEngine jettyWrapper, List<String> supportedProtocols) {
|
||||
super(jettyWrapper, supportedProtocols);
|
||||
private static final class FailProtocolSelectionListener extends NoFailProtocolSelectionListener {
|
||||
FailProtocolSelectionListener(JdkSslEngine engineWrapper, List<String> supportedProtocols) {
|
||||
super(engineWrapper, supportedProtocols);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noSelectedMatchFound(String protocol) throws Exception {
|
||||
protected void noSelectedMatchFound(String protocol) throws Exception {
|
||||
throw new SSLHandshakeException("No compatible protocols found");
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import javax.net.ssl.SSLEngine;
|
||||
public final class JdkNpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator {
|
||||
private static final SslEngineWrapperFactory NPN_WRAPPER = new SslEngineWrapperFactory() {
|
||||
{
|
||||
if (!JdkNpnSslEngine.isAvailable()) {
|
||||
if (!JettyNpnSslEngine.isAvailable()) {
|
||||
throw new RuntimeException("NPN unsupported. Is your classpatch configured correctly?"
|
||||
+ " See https://wiki.eclipse.org/Jetty/Feature/NPN");
|
||||
}
|
||||
@ -32,7 +32,7 @@ public final class JdkNpnApplicationProtocolNegotiator extends JdkBaseApplicatio
|
||||
@Override
|
||||
public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator,
|
||||
boolean isServer) {
|
||||
return new JdkNpnSslEngine(engine, applicationNegotiator, isServer);
|
||||
return new JettyNpnSslEngine(engine, applicationNegotiator, isServer);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import java.security.Provider;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@ -164,8 +165,17 @@ public final class JdkSslClientContext extends JdkSslContext {
|
||||
File certChainFile, TrustManagerFactory trustManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
this(certChainFile, trustManagerFactory, null, null, null, null,
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
this(null, certChainFile, trustManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
}
|
||||
|
||||
JdkSslClientContext(Provider provider,
|
||||
File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
super(newSSLContext(provider, toX509CertificatesInternal(trustCertCollectionFile),
|
||||
trustManagerFactory, null, null,
|
||||
null, null, sessionCacheSize, sessionTimeout), true,
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -244,24 +254,26 @@ public final class JdkSslClientContext extends JdkSslContext {
|
||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
super(newSSLContext(toX509CertificatesInternal(
|
||||
super(newSSLContext(null, toX509CertificatesInternal(
|
||||
trustCertCollectionFile), trustManagerFactory,
|
||||
toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout), true,
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
JdkSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
JdkSslClientContext(Provider sslContextProvider,
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
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, protocols, false);
|
||||
super(newSSLContext(sslContextProvider, trustCertCollection, trustManagerFactory,
|
||||
keyCertChain, key, keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout),
|
||||
true, ciphers, cipherFilter, toNegotiator(apn, false), ClientAuth.NONE, protocols, false);
|
||||
}
|
||||
|
||||
private static SSLContext newSSLContext(X509Certificate[] trustCertCollection,
|
||||
private static SSLContext newSSLContext(Provider sslContextProvider,
|
||||
X509Certificate[] trustCertCollection,
|
||||
TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain,
|
||||
PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
@ -272,7 +284,8 @@ public final class JdkSslClientContext extends JdkSslContext {
|
||||
if (keyCertChain != null) {
|
||||
keyManagerFactory = buildKeyManagerFactory(keyCertChain, key, keyPassword, keyManagerFactory);
|
||||
}
|
||||
SSLContext ctx = SSLContext.getInstance(PROTOCOL);
|
||||
SSLContext ctx = sslContextProvider == null ? SSLContext.getInstance(PROTOCOL)
|
||||
: SSLContext.getInstance(PROTOCOL, sslContextProvider);
|
||||
ctx.init(keyManagerFactory == null ? null : keyManagerFactory.getKeyManagers(),
|
||||
trustManagerFactory == null ? null : trustManagerFactory.getTrustManagers(),
|
||||
null);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import java.security.Provider;
|
||||
import javax.net.ssl.KeyManager;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
@ -138,8 +139,17 @@ public final class JdkSslServerContext extends JdkSslContext {
|
||||
File certChainFile, File keyFile, String keyPassword,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
this(null, null, certChainFile, keyFile, keyPassword, null,
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
this(null, certChainFile, keyFile, keyPassword, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||
}
|
||||
|
||||
JdkSslServerContext(Provider provider,
|
||||
File certChainFile, File keyFile, String keyPassword,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
super(newSSLContext(provider, null, null,
|
||||
toX509CertificatesInternal(certChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, null, sessionCacheSize, sessionTimeout), false,
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -212,23 +222,24 @@ public final class JdkSslServerContext extends JdkSslContext {
|
||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
super(newSSLContext(toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
|
||||
super(newSSLContext(null, toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout), false,
|
||||
ciphers, cipherFilter, apn, ClientAuth.NONE, null, false);
|
||||
}
|
||||
|
||||
JdkSslServerContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
JdkSslServerContext(Provider provider,
|
||||
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, String[] protocols, boolean startTls) throws SSLException {
|
||||
super(newSSLContext(trustCertCollection, trustManagerFactory, keyCertChain, key,
|
||||
super(newSSLContext(provider, trustCertCollection, trustManagerFactory, keyCertChain, key,
|
||||
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout), false,
|
||||
ciphers, cipherFilter, toNegotiator(apn, true), clientAuth, protocols, startTls);
|
||||
}
|
||||
|
||||
private static SSLContext newSSLContext(X509Certificate[] trustCertCollection,
|
||||
private static SSLContext newSSLContext(Provider sslContextProvider, X509Certificate[] trustCertCollection,
|
||||
TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain,
|
||||
PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
long sessionCacheSize, long sessionTimeout)
|
||||
@ -246,7 +257,8 @@ public final class JdkSslServerContext extends JdkSslContext {
|
||||
}
|
||||
|
||||
// Initialize the SSLContext to work with our key managers.
|
||||
SSLContext ctx = SSLContext.getInstance(PROTOCOL);
|
||||
SSLContext ctx = sslContextProvider == null ? SSLContext.getInstance(PROTOCOL)
|
||||
: SSLContext.getInstance(PROTOCOL, sslContextProvider);
|
||||
ctx.init(keyManagerFactory.getKeyManagers(),
|
||||
trustManagerFactory == null ? null : trustManagerFactory.getTrustManagers(),
|
||||
null);
|
||||
|
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2014 The Netty Project
|
||||
*
|
||||
* The Netty Project 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.
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import static io.netty.handler.ssl.SslUtils.toSSLHandshakeException;
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener;
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
|
||||
abstract class JettyAlpnSslEngine extends JdkSslEngine {
|
||||
private static final boolean available = initAvailable();
|
||||
|
||||
static boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
private static boolean initAvailable() {
|
||||
// TODO: Add support for ALPN when using Java9 and still be able to configure it the Netty way.
|
||||
if (PlatformDependent.javaVersion() <= 8) {
|
||||
try {
|
||||
// Always use bootstrap class loader.
|
||||
Class.forName("sun.security.ssl.ALPNExtension", true, null);
|
||||
return true;
|
||||
} catch (Throwable ignore) {
|
||||
// alpn-boot was not loaded.
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static JettyAlpnSslEngine newClientEngine(SSLEngine engine,
|
||||
JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
return new ClientEngine(engine, applicationNegotiator);
|
||||
}
|
||||
|
||||
static JettyAlpnSslEngine newServerEngine(SSLEngine engine,
|
||||
JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
return new ServerEngine(engine, applicationNegotiator);
|
||||
}
|
||||
|
||||
private JettyAlpnSslEngine(SSLEngine engine) {
|
||||
super(engine);
|
||||
}
|
||||
|
||||
private static final class ClientEngine extends JettyAlpnSslEngine {
|
||||
ClientEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
super(engine);
|
||||
checkNotNull(applicationNegotiator, "applicationNegotiator");
|
||||
final ProtocolSelectionListener protocolListener = checkNotNull(applicationNegotiator
|
||||
.protocolListenerFactory().newListener(this, applicationNegotiator.protocols()),
|
||||
"protocolListener");
|
||||
ALPN.put(engine, new ALPN.ClientProvider() {
|
||||
@Override
|
||||
public List<String> protocols() {
|
||||
return applicationNegotiator.protocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selected(String protocol) throws SSLException {
|
||||
try {
|
||||
protocolListener.selected(protocol);
|
||||
} catch (Throwable t) {
|
||||
throw toSSLHandshakeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
protocolListener.unsupported();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeInbound() throws SSLException {
|
||||
try {
|
||||
ALPN.remove(getWrappedEngine());
|
||||
} finally {
|
||||
super.closeInbound();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeOutbound() {
|
||||
try {
|
||||
ALPN.remove(getWrappedEngine());
|
||||
} finally {
|
||||
super.closeOutbound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ServerEngine extends JettyAlpnSslEngine {
|
||||
ServerEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator) {
|
||||
super(engine);
|
||||
checkNotNull(applicationNegotiator, "applicationNegotiator");
|
||||
final ProtocolSelector protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory()
|
||||
.newSelector(this, new LinkedHashSet<String>(applicationNegotiator.protocols())),
|
||||
"protocolSelector");
|
||||
ALPN.put(engine, new ALPN.ServerProvider() {
|
||||
@Override
|
||||
public String select(List<String> protocols) throws SSLException {
|
||||
try {
|
||||
return protocolSelector.select(protocols);
|
||||
} catch (Throwable t) {
|
||||
throw toSSLHandshakeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported() {
|
||||
protocolSelector.unsupported();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeInbound() throws SSLException {
|
||||
try {
|
||||
ALPN.remove(getWrappedEngine());
|
||||
} finally {
|
||||
super.closeInbound();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeOutbound() {
|
||||
try {
|
||||
ALPN.remove(getWrappedEngine());
|
||||
} finally {
|
||||
super.closeOutbound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ import org.eclipse.jetty.npn.NextProtoNego;
|
||||
import org.eclipse.jetty.npn.NextProtoNego.ClientProvider;
|
||||
import org.eclipse.jetty.npn.NextProtoNego.ServerProvider;
|
||||
|
||||
final class JdkNpnSslEngine extends JdkSslEngine {
|
||||
final class JettyNpnSslEngine extends JdkSslEngine {
|
||||
private static boolean available;
|
||||
|
||||
static boolean isAvailable() {
|
||||
@ -52,7 +52,7 @@ final class JdkNpnSslEngine extends JdkSslEngine {
|
||||
}
|
||||
}
|
||||
|
||||
JdkNpnSslEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator, boolean server) {
|
||||
JettyNpnSslEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator, boolean server) {
|
||||
super(engine);
|
||||
checkNotNull(applicationNegotiator, "applicationNegotiator");
|
||||
|
@ -26,6 +26,7 @@ import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBeh
|
||||
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
|
||||
import io.netty.util.internal.EmptyArrays;
|
||||
|
||||
import java.security.Provider;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.crypto.Cipher;
|
||||
@ -380,8 +381,8 @@ public abstract class SslContext {
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
try {
|
||||
return newServerContextInternal(provider, toX509Certificates(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509Certificates(keyCertChainFile),
|
||||
return newServerContextInternal(provider, null, toX509Certificates(trustCertCollectionFile),
|
||||
trustManagerFactory, toX509Certificates(keyCertChainFile),
|
||||
toPrivateKey(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter, apn,
|
||||
sessionCacheSize, sessionTimeout, ClientAuth.NONE, null, false);
|
||||
@ -395,6 +396,7 @@ public abstract class SslContext {
|
||||
|
||||
static SslContext newServerContextInternal(
|
||||
SslProvider provider,
|
||||
Provider sslContextProvider,
|
||||
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
@ -407,16 +409,18 @@ public abstract class SslContext {
|
||||
|
||||
switch (provider) {
|
||||
case JDK:
|
||||
return new JdkSslServerContext(
|
||||
return new JdkSslServerContext(sslContextProvider,
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, protocols, startTls);
|
||||
case OPENSSL:
|
||||
verifyNullSslContextProvider(provider, sslContextProvider);
|
||||
return new OpenSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, protocols, startTls);
|
||||
case OPENSSL_REFCNT:
|
||||
verifyNullSslContextProvider(provider, sslContextProvider);
|
||||
return new ReferenceCountedOpenSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
@ -426,6 +430,12 @@ public abstract class SslContext {
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyNullSslContextProvider(SslProvider provider, Provider sslContextProvider) {
|
||||
if (sslContextProvider != null) {
|
||||
throw new IllegalArgumentException("Java Security Provider unsupported for SslProvider: " + provider);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new client-side {@link SslContext}.
|
||||
*
|
||||
@ -721,11 +731,13 @@ public abstract class SslContext {
|
||||
public static SslContext newClientContext(
|
||||
SslProvider provider,
|
||||
File trustCertCollectionFile, TrustManagerFactory trustManagerFactory,
|
||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
File keyCertChainFile, File keyFile, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||
try {
|
||||
return newClientContextInternal(provider, toX509Certificates(trustCertCollectionFile), trustManagerFactory,
|
||||
return newClientContextInternal(provider, null,
|
||||
toX509Certificates(trustCertCollectionFile), trustManagerFactory,
|
||||
toX509Certificates(keyCertChainFile), toPrivateKey(keyFile, keyPassword),
|
||||
keyPassword, keyManagerFactory, ciphers, cipherFilter,
|
||||
apn, null, sessionCacheSize, sessionTimeout);
|
||||
@ -739,6 +751,7 @@ public abstract class SslContext {
|
||||
|
||||
static SslContext newClientContextInternal(
|
||||
SslProvider provider,
|
||||
Provider sslContextProvider,
|
||||
X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
|
||||
@ -748,14 +761,16 @@ public abstract class SslContext {
|
||||
}
|
||||
switch (provider) {
|
||||
case JDK:
|
||||
return new JdkSslClientContext(
|
||||
return new JdkSslClientContext(sslContextProvider,
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
case OPENSSL:
|
||||
verifyNullSslContextProvider(provider, sslContextProvider);
|
||||
return new OpenSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
case OPENSSL_REFCNT:
|
||||
verifyNullSslContextProvider(provider, sslContextProvider);
|
||||
return new ReferenceCountedOpenSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
|
@ -16,16 +16,17 @@
|
||||
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
import java.security.Provider;
|
||||
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.
|
||||
@ -126,6 +127,7 @@ public final class SslContextBuilder {
|
||||
|
||||
private final boolean forServer;
|
||||
private SslProvider provider;
|
||||
private Provider sslContextProvider;
|
||||
private X509Certificate[] trustCertCollection;
|
||||
private TrustManagerFactory trustManagerFactory;
|
||||
private X509Certificate[] keyCertChain;
|
||||
@ -153,6 +155,15 @@ public final class SslContextBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The SSLContext {@link Provider} to use. {@code null} uses the default one. This is only
|
||||
* used with {@link SslProvider#JDK}.
|
||||
*/
|
||||
public SslContextBuilder sslContextProvider(Provider sslContextProvider) {
|
||||
this.sslContextProvider = sslContextProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trusted certificates for verifying the remote endpoint's certificate. The file should
|
||||
* contain an X.509 certificate collection in PEM format. {@code null} uses the system default.
|
||||
@ -411,11 +422,11 @@ public final class SslContextBuilder {
|
||||
*/
|
||||
public SslContext build() throws SSLException {
|
||||
if (forServer) {
|
||||
return SslContext.newServerContextInternal(provider, trustCertCollection,
|
||||
return SslContext.newServerContextInternal(provider, sslContextProvider, trustCertCollection,
|
||||
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls);
|
||||
} else {
|
||||
return SslContext.newClientContextInternal(provider, trustCertCollection,
|
||||
return SslContext.newClientContextInternal(provider, sslContextProvider, trustCertCollection,
|
||||
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||
ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout);
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
|
||||
int writerIndex = out.writerIndex();
|
||||
final SSLEngineResult result;
|
||||
if (nioBufferCount > 1) {
|
||||
/**
|
||||
/*
|
||||
* If {@link OpenSslEngine} is in use,
|
||||
* we can use a special {@link OpenSslEngine#unwrap(ByteBuffer[], ByteBuffer[])} method
|
||||
* that accepts multiple {@link ByteBuffer}s without additional memory copies.
|
||||
@ -214,6 +214,38 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
|
||||
return ReferenceCountedOpenSslEngine.calculateOutNetBufSize(pendingBytes, numComponents);
|
||||
}
|
||||
},
|
||||
CONSCRYPT(true, COMPOSITE_CUMULATOR) {
|
||||
@Override
|
||||
SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int readerIndex, int len, ByteBuf out)
|
||||
throws SSLException {
|
||||
int nioBufferCount = in.nioBufferCount();
|
||||
int writerIndex = out.writerIndex();
|
||||
final SSLEngineResult result;
|
||||
if (nioBufferCount > 1) {
|
||||
/*
|
||||
* Use a special unwrap method without additional memory copies.
|
||||
*/
|
||||
try {
|
||||
handler.singleBuffer[0] = toByteBuffer(out, writerIndex, out.writableBytes());
|
||||
result = ((ConscryptAlpnSslEngine) handler.engine).unwrap(
|
||||
in.nioBuffers(readerIndex, len),
|
||||
handler.singleBuffer);
|
||||
} finally {
|
||||
handler.singleBuffer[0] = null;
|
||||
}
|
||||
} else {
|
||||
result = handler.engine.unwrap(toByteBuffer(in, readerIndex, len),
|
||||
toByteBuffer(out, writerIndex, out.writableBytes()));
|
||||
}
|
||||
out.writerIndex(writerIndex + result.bytesProduced());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
int calculateOutNetBufSize(SslHandler handler, int pendingBytes, int numComponents) {
|
||||
return ((ConscryptAlpnSslEngine) handler.engine).calculateOutNetBufSize(pendingBytes, numComponents);
|
||||
}
|
||||
},
|
||||
JDK(false, MERGE_CUMULATOR) {
|
||||
@Override
|
||||
SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int readerIndex, int len, ByteBuf out)
|
||||
@ -232,7 +264,13 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
|
||||
};
|
||||
|
||||
static SslEngineType forEngine(SSLEngine engine) {
|
||||
return engine instanceof ReferenceCountedOpenSslEngine ? TCNATIVE : JDK;
|
||||
if (engine instanceof ReferenceCountedOpenSslEngine) {
|
||||
return TCNATIVE;
|
||||
}
|
||||
if (engine instanceof ConscryptAlpnSslEngine) {
|
||||
return CONSCRYPT;
|
||||
}
|
||||
return JDK;
|
||||
}
|
||||
|
||||
SslEngineType(boolean wantsDirectBuffer, Cumulator cumulator) {
|
||||
|
@ -22,6 +22,7 @@ import io.netty.handler.codec.base64.Base64;
|
||||
import io.netty.handler.codec.base64.Base64Dialect;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
/**
|
||||
* Constants for SSL packets.
|
||||
@ -68,6 +69,17 @@ final class SslUtils {
|
||||
*/
|
||||
static final int NOT_ENCRYPTED = -2;
|
||||
|
||||
/**
|
||||
* Converts the given exception to a {@link SSLHandshakeException}, if it isn't already.
|
||||
*/
|
||||
static SSLHandshakeException toSSLHandshakeException(Throwable e) {
|
||||
if (e instanceof SSLHandshakeException) {
|
||||
return (SSLHandshakeException) e;
|
||||
}
|
||||
|
||||
return (SSLHandshakeException) new SSLHandshakeException(e.getMessage()).initCause(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how much bytes can be read out of the encrypted data. Be aware that this method will not increase
|
||||
* the readerIndex of the given {@link ByteBuf}.
|
||||
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2016 The Netty Project
|
||||
*
|
||||
* The Netty Project 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.
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import java.security.Provider;
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class ConscryptJdkSslEngineInteropTest extends SSLEngineTest {
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
||||
public static Collection<Object> data() {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
for (BufferType type: BufferType.values()) {
|
||||
params.add(type);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public ConscryptJdkSslEngineInteropTest(BufferType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void checkConscrypt() {
|
||||
assumeTrue(ConscryptAlpnSslEngine.isAvailable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SslProvider sslClientProvider() {
|
||||
return SslProvider.JDK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SslProvider sslServerProvider() {
|
||||
return SslProvider.JDK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider clientSslContextProvider() {
|
||||
return new OpenSSLProvider();
|
||||
}
|
||||
|
||||
@Ignore /* Does the JDK support a "max certificate chain length"? */
|
||||
@Override
|
||||
public void testMutualAuthValidClientCertChainTooLongFailOptionalClientAuth() throws Exception {
|
||||
}
|
||||
|
||||
@Ignore /* Does the JDK support a "max certificate chain length"? */
|
||||
@Override
|
||||
public void testMutualAuthValidClientCertChainTooLongFailRequireClientAuth() throws Exception {
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2017 The Netty Project
|
||||
*
|
||||
* The Netty Project 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.
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import java.security.Provider;
|
||||
import org.conscrypt.OpenSSLProvider;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class JdkConscryptSslEngineInteropTest extends SSLEngineTest {
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
||||
public static Collection<Object> data() {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
for (BufferType type: BufferType.values()) {
|
||||
params.add(type);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public JdkConscryptSslEngineInteropTest(BufferType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void checkConscrypt() {
|
||||
assumeTrue(ConscryptAlpnSslEngine.isAvailable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SslProvider sslClientProvider() {
|
||||
return SslProvider.JDK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SslProvider sslServerProvider() {
|
||||
return SslProvider.JDK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider serverSslContextProvider() {
|
||||
return new OpenSSLProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
@Ignore("TODO: Make this work with Conscrypt")
|
||||
public void testMutualAuthValidClientCertChainTooLongFailOptionalClientAuth() throws Exception {
|
||||
super.testMutualAuthValidClientCertChainTooLongFailOptionalClientAuth();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
@Ignore("TODO: Make this work with Conscrypt")
|
||||
public void testMutualAuthValidClientCertChainTooLongFailRequireClientAuth() throws Exception {
|
||||
super.testMutualAuthValidClientCertChainTooLongFailRequireClientAuth();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mySetupMutualAuthServerIsValidClientException(Throwable cause) {
|
||||
// TODO(scott): work around for a JDK issue. The exception should be SSLHandshakeException.
|
||||
return super.mySetupMutualAuthServerIsValidClientException(cause) || causedBySSLException(cause);
|
||||
}
|
||||
}
|
@ -17,15 +17,29 @@ package io.netty.handler.ssl;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.handler.ssl.OpenSslTestUtils.checkShouldUseKeyManagerFactory;
|
||||
import static io.netty.internal.tcnative.SSL.SSL_CVERIFY_IGNORED;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class JdkOpenSslEngineInteroptTest extends SSLEngineTest {
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
||||
public static Collection<Object> data() {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
for (BufferType type: BufferType.values()) {
|
||||
params.add(type);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public JdkOpenSslEngineInteroptTest(BufferType type) {
|
||||
super(type);
|
||||
}
|
||||
|
@ -22,61 +22,148 @@ import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
|
||||
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import java.security.Provider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class JdkSslEngineTest extends SSLEngineTest {
|
||||
public enum ProviderType {
|
||||
NPN_DEFAULT {
|
||||
@Override
|
||||
boolean isAvailable() {
|
||||
return JettyNpnSslEngine.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
Protocol protocol() {
|
||||
return Protocol.NPN;
|
||||
}
|
||||
|
||||
@Override
|
||||
Provider provider() {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
ALPN_DEFAULT {
|
||||
@Override
|
||||
boolean isAvailable() {
|
||||
return JettyAlpnSslEngine.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
Protocol protocol() {
|
||||
return Protocol.ALPN;
|
||||
}
|
||||
|
||||
@Override
|
||||
Provider provider() {
|
||||
// Use the default provider.
|
||||
return null;
|
||||
}
|
||||
},
|
||||
ALPN_CONSCRYPT {
|
||||
private Provider provider;
|
||||
|
||||
@Override
|
||||
boolean isAvailable() {
|
||||
return ConscryptAlpnSslEngine.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
Protocol protocol() {
|
||||
return Protocol.ALPN;
|
||||
}
|
||||
|
||||
@Override
|
||||
Provider provider() {
|
||||
try {
|
||||
if (provider == null) {
|
||||
provider = (Provider) Class.forName("org.conscrypt.OpenSSLProvider")
|
||||
.getConstructor().newInstance();
|
||||
}
|
||||
return provider;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
abstract boolean isAvailable();
|
||||
abstract Protocol protocol();
|
||||
abstract Provider provider();
|
||||
|
||||
final void activate(JdkSslEngineTest instance) {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!isAvailable()) {
|
||||
throw tlsExtensionNotFound(protocol());
|
||||
}
|
||||
instance.provider = provider();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2";
|
||||
private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
|
||||
private static final String APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE = "my-protocol-FOO";
|
||||
|
||||
public JdkSslEngineTest(BufferType type) {
|
||||
super(type);
|
||||
@Parameterized.Parameters(name = "{index}: providerType = {0}, bufferType = {1}")
|
||||
public static Collection<Object[]> data() {
|
||||
List<Object[]> params = new ArrayList<Object[]>();
|
||||
for (ProviderType providerType : ProviderType.values()) {
|
||||
for (BufferType bufferType : BufferType.values()) {
|
||||
params.add(new Object[]{providerType, bufferType});
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
private final ProviderType providerType;
|
||||
|
||||
private Provider provider;
|
||||
|
||||
public JdkSslEngineTest(ProviderType providerType, BufferType bufferType) {
|
||||
super(bufferType);
|
||||
this.providerType = providerType;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNpn() throws Exception {
|
||||
public void testTlsExtension() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkNpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.NPN);
|
||||
}
|
||||
ApplicationProtocolConfig apn = failingNegotiator(Protocol.NPN,
|
||||
providerType.activate(this);
|
||||
ApplicationProtocolConfig apn = failingNegotiator(providerType.protocol(),
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
setupHandlers(apn);
|
||||
runTest();
|
||||
} catch (SkipTestException e) {
|
||||
// NPN availability is dependent on the java version. If NPN is not available because of
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNpnNoCompatibleProtocolsNoHandshakeFailure() throws Exception {
|
||||
public void testTlsExtensionNoCompatibleProtocolsNoHandshakeFailure() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkNpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.NPN);
|
||||
}
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
|
||||
providerType.activate(this);
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(providerType.protocol(),
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
|
||||
ApplicationProtocolConfig serverApn = acceptingNegotiator(providerType.protocol(),
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
runTest(null);
|
||||
@ -88,150 +175,19 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNpnNoCompatibleProtocolsClientHandshakeFailure() throws Exception {
|
||||
public void testTlsExtensionNoCompatibleProtocolsClientHandshakeFailure() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkNpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.NPN);
|
||||
}
|
||||
ApplicationProtocolConfig clientApn = failingNegotiator(Protocol.NPN,
|
||||
providerType.activate(this);
|
||||
if (providerType == ProviderType.NPN_DEFAULT) {
|
||||
ApplicationProtocolConfig clientApn = failingNegotiator(providerType.protocol(),
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
|
||||
ApplicationProtocolConfig serverApn = acceptingNegotiator(providerType.protocol(),
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
|
||||
assertTrue(clientException instanceof SSLHandshakeException);
|
||||
} catch (SkipTestException e) {
|
||||
// NPN availability is dependent on the java version. If NPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNpnNoCompatibleProtocolsServerHandshakeFailure() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkNpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.NPN);
|
||||
}
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.NPN,
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
|
||||
assertTrue(serverException instanceof SSLHandshakeException);
|
||||
} catch (SkipTestException e) {
|
||||
// NPN availability is dependent on the java version. If NPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpn() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkAlpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.ALPN);
|
||||
}
|
||||
ApplicationProtocolConfig apn = failingNegotiator(Protocol.ALPN,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
setupHandlers(apn);
|
||||
runTest();
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpnNoCompatibleProtocolsNoHandshakeFailure() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkAlpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.ALPN);
|
||||
}
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.ALPN,
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
runTest(null);
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpnNoCompatibleProtocolsServerHandshakeFailure() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkAlpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.ALPN);
|
||||
}
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
|
||||
assertTrue(serverException instanceof SSLHandshakeException);
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpnCompatibleProtocolsDifferentClientOrder() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkAlpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.ALPN);
|
||||
}
|
||||
// Even the preferred application protocol appears second in the client's list, it will be picked
|
||||
// because it's the first one on server's list.
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
|
||||
FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
assertNull(serverException);
|
||||
runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpnNoCompatibleProtocolsClientHandshakeFailure() throws Exception {
|
||||
try {
|
||||
// Typical code will not have to check this, but will get a initialization error on class load.
|
||||
// Check in this test just in case we have multiple tests that just the class and we already ignored the
|
||||
// initialization error.
|
||||
if (!JdkAlpnSslEngine.isAvailable()) {
|
||||
throw tlsExtensionNotFound(Protocol.ALPN);
|
||||
}
|
||||
} else {
|
||||
// ALPN
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
@ -253,14 +209,59 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
||||
}, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY,
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
|
||||
SslContext serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
|
||||
SslContext serverSslCtx = new JdkSslServerContext(providerType.provider(),
|
||||
ssc.certificate(), ssc.privateKey(), null, null,
|
||||
IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0);
|
||||
SslContext clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null,
|
||||
SslContext clientSslCtx = new JdkSslClientContext(providerType.provider(), null,
|
||||
InsecureTrustManagerFactory.INSTANCE, null,
|
||||
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);
|
||||
|
||||
setupHandlers(serverSslCtx, clientSslCtx);
|
||||
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
|
||||
assertTrue(clientException instanceof SSLHandshakeException);
|
||||
}
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTlsExtensionNoCompatibleProtocolsServerHandshakeFailure() throws Exception {
|
||||
try {
|
||||
providerType.activate(this);
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(providerType.protocol(),
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = failingNegotiator(providerType.protocol(),
|
||||
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
|
||||
assertTrue(serverException instanceof SSLHandshakeException);
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlpnCompatibleProtocolsDifferentClientOrder() throws Exception {
|
||||
try {
|
||||
providerType.activate(this);
|
||||
if (providerType == ProviderType.NPN_DEFAULT) {
|
||||
// This test only applies to ALPN.
|
||||
throw tlsExtensionNotFound(providerType.protocol());
|
||||
}
|
||||
// Even the preferred application protocol appears second in the client's list, it will be picked
|
||||
// because it's the first one on server's list.
|
||||
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
|
||||
FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
|
||||
PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL);
|
||||
setupHandlers(serverApn, clientApn);
|
||||
assertNull(serverException);
|
||||
runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
|
||||
} catch (SkipTestException e) {
|
||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||
// java version incompatibility don't fail the test, but instead just skip the test
|
||||
@ -303,6 +304,16 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
||||
return SslProvider.JDK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider clientSslContextProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider serverSslContextProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
private ApplicationProtocolConfig failingNegotiator(Protocol protocol,
|
||||
String... supportedProtocols) {
|
||||
return new ApplicationProtocolConfig(protocol,
|
||||
@ -319,12 +330,12 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
||||
supportedProtocols);
|
||||
}
|
||||
|
||||
private SkipTestException tlsExtensionNotFound(Protocol protocol) {
|
||||
private static SkipTestException tlsExtensionNotFound(Protocol protocol) {
|
||||
throw new SkipTestException(protocol + " not on classpath");
|
||||
}
|
||||
|
||||
private static final class SkipTestException extends RuntimeException {
|
||||
public SkipTestException(String message) {
|
||||
SkipTestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import io.netty.util.internal.PlatformDependent;
|
||||
import org.junit.Assume;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.AlgorithmConstraints;
|
||||
@ -32,6 +34,7 @@ import java.security.AlgorithmParameters;
|
||||
import java.security.CryptoPrimitive;
|
||||
import java.security.Key;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
@ -52,10 +55,20 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class OpenSslEngineTest extends SSLEngineTest {
|
||||
private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2";
|
||||
private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
||||
public static Collection<Object> data() {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
for (BufferType type: BufferType.values()) {
|
||||
params.add(type);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public OpenSslEngineTest(BufferType type) {
|
||||
super(type);
|
||||
}
|
||||
|
@ -20,12 +20,28 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.handler.ssl.OpenSslTestUtils.checkShouldUseKeyManagerFactory;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
||||
public static Collection<Object> data() {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
for (BufferType type: BufferType.values()) {
|
||||
params.add(type);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public OpenSslJdkSslEngineInteroptTest(BufferType type) {
|
||||
super(type);
|
||||
}
|
||||
|
@ -45,8 +45,6 @@ import io.netty.util.internal.PlatformDependent;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
@ -61,8 +59,7 @@ import java.nio.channels.ClosedChannelException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.security.Provider;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -86,7 +83,6 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public abstract class SSLEngineTest {
|
||||
|
||||
private static final String X509_CERT_PEM =
|
||||
@ -202,15 +198,6 @@ public abstract class SSLEngineTest {
|
||||
Mixed
|
||||
}
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
||||
public static Collection<Object> data() {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
for (BufferType type: BufferType.values()) {
|
||||
params.add(type);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
private final BufferType type;
|
||||
|
||||
protected SSLEngineTest(BufferType type) {
|
||||
@ -624,6 +611,7 @@ public abstract class SSLEngineTest {
|
||||
throws SSLException, InterruptedException {
|
||||
serverSslCtx = SslContextBuilder.forServer(serverKMF)
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.trustManager(serverTrustManager)
|
||||
.clientAuth(clientAuth)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
@ -633,6 +621,7 @@ public abstract class SSLEngineTest {
|
||||
|
||||
clientSslCtx = SslContextBuilder.forClient()
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider())
|
||||
.trustManager(clientTrustManager)
|
||||
.keyManager(clientKMF)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
@ -765,6 +754,7 @@ public abstract class SSLEngineTest {
|
||||
final String expectedHost = "localhost";
|
||||
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, null)
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
.sessionCacheSize(0)
|
||||
@ -773,6 +763,7 @@ public abstract class SSLEngineTest {
|
||||
|
||||
clientSslCtx = SslContextBuilder.forClient()
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider())
|
||||
.trustManager(clientTrustCrtFile)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
.sessionCacheSize(0)
|
||||
@ -882,6 +873,7 @@ public abstract class SSLEngineTest {
|
||||
throws InterruptedException, SSLException {
|
||||
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword)
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.trustManager(servertTrustCrtFile)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
.sessionCacheSize(0)
|
||||
@ -890,6 +882,7 @@ public abstract class SSLEngineTest {
|
||||
|
||||
clientSslCtx = SslContextBuilder.forClient()
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider())
|
||||
.trustManager(clientTrustCrtFile)
|
||||
.keyManager(clientCrtFile, clientKeyFile, clientKeyPassword)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
@ -1038,7 +1031,9 @@ public abstract class SSLEngineTest {
|
||||
|
||||
@Test
|
||||
public void testGetCreationTime() throws Exception {
|
||||
clientSslCtx = SslContextBuilder.forClient().sslProvider(sslClientProvider()).build();
|
||||
clientSslCtx = SslContextBuilder.forClient()
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider()).build();
|
||||
SSLEngine engine = null;
|
||||
try {
|
||||
engine = clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||
@ -1053,10 +1048,12 @@ public abstract class SSLEngineTest {
|
||||
clientSslCtx = SslContextBuilder.forClient()
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider())
|
||||
.build();
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.build();
|
||||
SSLEngine clientEngine = null;
|
||||
SSLEngine serverEngine = null;
|
||||
@ -1080,10 +1077,12 @@ public abstract class SSLEngineTest {
|
||||
clientSslCtx = SslContextBuilder.forClient()
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider())
|
||||
.build();
|
||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.build();
|
||||
SSLEngine clientEngine = null;
|
||||
SSLEngine serverEngine = null;
|
||||
@ -1112,7 +1111,8 @@ public abstract class SSLEngineTest {
|
||||
throws CertificateException, SSLException, InterruptedException, ExecutionException {
|
||||
final SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||
.sslProvider(sslServerProvider()).build();
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider()).build();
|
||||
sb = new ServerBootstrap()
|
||||
.group(new NioEventLoopGroup(1))
|
||||
.channel(NioServerSocketChannel.class)
|
||||
@ -1223,6 +1223,7 @@ public abstract class SSLEngineTest {
|
||||
File serverCrtFile = new File(getClass().getResource("test.crt").getFile());
|
||||
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile)
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.build();
|
||||
|
||||
sslEngine = serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||
@ -1356,6 +1357,13 @@ public abstract class SSLEngineTest {
|
||||
|
||||
protected abstract SslProvider sslServerProvider();
|
||||
|
||||
protected Provider clientSslContextProvider() {
|
||||
return null;
|
||||
}
|
||||
protected Provider serverSslContextProvider() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the test cleanup code and can be used to release the {@code ctx} if it must be done manually.
|
||||
*/
|
||||
@ -1391,6 +1399,7 @@ public abstract class SSLEngineTest {
|
||||
|
||||
setupHandlers(SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null)
|
||||
.sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider())
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
.applicationProtocolConfig(serverApn)
|
||||
.sessionCacheSize(0)
|
||||
@ -1399,6 +1408,7 @@ public abstract class SSLEngineTest {
|
||||
|
||||
SslContextBuilder.forClient()
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider())
|
||||
.applicationProtocolConfig(clientApn)
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||
@ -1479,7 +1489,8 @@ public abstract class SSLEngineTest {
|
||||
new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)),
|
||||
new ByteArrayInputStream(PRIVATE_KEY_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||
.trustManager(new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||
.clientAuth(ClientAuth.REQUIRE).sslProvider(sslServerProvider()).build();
|
||||
.clientAuth(ClientAuth.REQUIRE).sslProvider(sslServerProvider())
|
||||
.sslContextProvider(serverSslContextProvider()).build();
|
||||
|
||||
sb = new ServerBootstrap();
|
||||
sb.group(new NioEventLoopGroup(), new NioEventLoopGroup());
|
||||
@ -1535,7 +1546,8 @@ public abstract class SSLEngineTest {
|
||||
new ByteArrayInputStream(CLIENT_X509_CERT_CHAIN_PEM.getBytes(CharsetUtil.UTF_8)),
|
||||
new ByteArrayInputStream(CLIENT_PRIVATE_KEY_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||
.trustManager(new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||
.sslProvider(sslClientProvider()).build();
|
||||
.sslProvider(sslClientProvider())
|
||||
.sslContextProvider(clientSslContextProvider()).build();
|
||||
cb = new Bootstrap();
|
||||
cb.group(new NioEventLoopGroup());
|
||||
cb.channel(NioSocketChannel.class);
|
||||
|
@ -87,7 +87,7 @@ public class SniHandlerTest {
|
||||
assumeTrue(OpenSsl.isAlpnSupported());
|
||||
break;
|
||||
case JDK:
|
||||
assumeTrue(JdkAlpnSslEngine.isAvailable());
|
||||
assumeTrue(JettyAlpnSslEngine.isAvailable());
|
||||
break;
|
||||
default:
|
||||
throw new Error();
|
||||
|
14
pom.xml
14
pom.xml
@ -244,6 +244,10 @@
|
||||
<tcnative.artifactId>netty-tcnative</tcnative.artifactId>
|
||||
<tcnative.version>2.0.0.Final</tcnative.version>
|
||||
<tcnative.classifier>${os.detected.classifier}</tcnative.classifier>
|
||||
<conscrypt.groupId>org.conscrypt</conscrypt.groupId>
|
||||
<conscrypt.artifactId>conscrypt-openjdk-uber</conscrypt.artifactId>
|
||||
<conscrypt.version>1.0.0.RC7</conscrypt.version>
|
||||
<conscrypt.classifier></conscrypt.classifier>
|
||||
<epoll.classifier>${os.detected.name}-${os.detected.arch}</epoll.classifier>
|
||||
<logging.config>${project.basedir}/../common/src/test/resources/logback-test.xml</logging.config>
|
||||
<logging.logLevel>debug</logging.logLevel>
|
||||
@ -343,6 +347,16 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Conscrypt - needed for running tests, used for acclerating SSL with OpenSSL. -->
|
||||
<dependency>
|
||||
<groupId>${conscrypt.groupId}</groupId>
|
||||
<artifactId>${conscrypt.artifactId}</artifactId>
|
||||
<classifier>${conscrypt.classifier}</classifier>
|
||||
<version>${conscrypt.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Bouncy Castle - completely optional, only needed when:
|
||||
- you generate a temporary self-signed certificate using SelfSignedCertificate, and
|
||||
|
Loading…
Reference in New Issue
Block a user