Introduce SslContextOption which can be used for "optional" features … (#10981)
Motivation: Some of the features we want to support can only be supported by some of the SslContext implementations. We should allow to configure these in a consistent way the same way as we do it with Channel / ChannelOption Modifications: - Add SslContextOption and add builder methods that take these - Add OpenSslContextOption and define two options there which are specific to openssl Result: More flexible configuration and implementation of SslContext
This commit is contained in:
parent
a9a3e2cef1
commit
ab8b8ae81b
@ -21,6 +21,7 @@ import java.io.File;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLException;
|
||||
@ -184,10 +185,11 @@ public final class OpenSslClientContext extends OpenSslContext {
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
||||
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
|
||||
long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStore)
|
||||
long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStore,
|
||||
Map.Entry<SslContextOption<?>, Object>... options)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain,
|
||||
ClientAuth.NONE, protocols, false, enableOcsp);
|
||||
ClientAuth.NONE, protocols, false, enableOcsp, options);
|
||||
boolean success = false;
|
||||
try {
|
||||
OpenSslKeyMaterialProvider.validateKeyMaterialSupported(keyCertChain, key, keyPassword);
|
||||
|
@ -18,6 +18,7 @@ package io.netty.handler.ssl;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
@ -29,19 +30,20 @@ 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, String[] protocols, boolean startTls, boolean enableOcsp)
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp,
|
||||
Map.Entry<SslContextOption<?>, Object>... options)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apnCfg, sessionCacheSize, sessionTimeout, mode, keyCertChain,
|
||||
clientAuth, protocols, startTls, enableOcsp, false);
|
||||
super(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode, keyCertChain,
|
||||
clientAuth, protocols, startTls, enableOcsp, false, options);
|
||||
}
|
||||
|
||||
OpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize,
|
||||
long sessionTimeout, int mode, Certificate[] keyCertChain,
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls,
|
||||
boolean enableOcsp) throws SSLException {
|
||||
boolean enableOcsp, Map.Entry<SslContextOption<?>, Object>... options) throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, mode, keyCertChain, clientAuth, protocols,
|
||||
startTls, enableOcsp, false);
|
||||
startTls, enableOcsp, false, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2021 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:
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* {@link SslContextOption}s that are specific to the {@link SslProvider#OPENSSL} / {@link SslProvider#OPENSSL_REFCNT}.
|
||||
*
|
||||
* @param <T> the type of the value.
|
||||
*/
|
||||
public final class OpenSslContextOption<T> extends SslContextOption<T> {
|
||||
|
||||
private OpenSslContextOption(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* If enabled heavy-operations may be offloaded from the {@link io.netty.channel.EventLoop} if possible.
|
||||
*/
|
||||
public static final OpenSslContextOption<Boolean> USE_TASKS =
|
||||
new OpenSslContextOption<Boolean>("USE_TASKS");
|
||||
/**
|
||||
* If enabled <a href="https://tools.ietf.org/html/rfc7918">TLS false start</a> will be enabled if supported.
|
||||
* When TLS false start is enabled the flow of {@link SslHandshakeCompletionEvent}s may be different compared when,
|
||||
* not enabled.
|
||||
*
|
||||
* This is currently only supported when {@code BoringSSL} and ALPN is used.
|
||||
*/
|
||||
public static final OpenSslContextOption<Boolean> TLS_FALSE_START =
|
||||
new OpenSslContextOption<Boolean>("TLS_FALSE_START");
|
||||
|
||||
/**
|
||||
* Set the {@link OpenSslPrivateKeyMethod} to use. This allows to offload private-key operations
|
||||
* if needed.
|
||||
*
|
||||
* This is currently only supported when {@code BoringSSL} is used.
|
||||
*/
|
||||
public static final OpenSslContextOption<OpenSslPrivateKeyMethod> PRIVATE_KEY_METHOD =
|
||||
new OpenSslContextOption<OpenSslPrivateKeyMethod>("PRIVATE_KEY_METHOD");
|
||||
}
|
@ -21,6 +21,7 @@ import java.io.File;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
@ -330,10 +331,11 @@ public final class OpenSslServerContext extends OpenSslContext {
|
||||
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,
|
||||
boolean enableOcsp, String keyStore) throws SSLException {
|
||||
boolean enableOcsp, String keyStore, Map.Entry<SslContextOption<?>, Object>... options)
|
||||
throws SSLException {
|
||||
this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
|
||||
cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls,
|
||||
enableOcsp, keyStore);
|
||||
enableOcsp, keyStore, options);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@ -342,9 +344,10 @@ public final class OpenSslServerContext extends OpenSslContext {
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
|
||||
boolean enableOcsp, String keyStore) throws SSLException {
|
||||
boolean enableOcsp, String keyStore, Map.Entry<SslContextOption<?>, Object>... options)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
|
||||
clientAuth, protocols, startTls, enableOcsp);
|
||||
clientAuth, protocols, startTls, enableOcsp, options);
|
||||
|
||||
// Create a new SSL_CTX and configure it.
|
||||
boolean success = false;
|
||||
|
@ -18,8 +18,6 @@ package io.netty.handler.ssl;
|
||||
import io.netty.internal.tcnative.CertificateCallback;
|
||||
import io.netty.util.internal.SuppressJava6Requirement;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
import io.netty.internal.tcnative.SSL;
|
||||
import io.netty.internal.tcnative.SSLContext;
|
||||
|
||||
@ -31,6 +29,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
@ -65,9 +64,10 @@ public final class ReferenceCountedOpenSslClientContext extends ReferenceCounted
|
||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
||||
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||
String[] protocols, long sessionCacheSize, long sessionTimeout,
|
||||
boolean enableOcsp, String keyStore) throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain,
|
||||
ClientAuth.NONE, protocols, false, enableOcsp, true);
|
||||
boolean enableOcsp, String keyStore,
|
||||
Map.Entry<SslContextOption<?>, Object>... options) throws SSLException {
|
||||
super(ciphers, cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT,
|
||||
keyCertChain, ClientAuth.NONE, protocols, false, enableOcsp, true, options);
|
||||
boolean success = false;
|
||||
try {
|
||||
sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
|
||||
|
@ -179,19 +179,14 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
DH_KEY_LENGTH = dhLen;
|
||||
}
|
||||
|
||||
ReferenceCountedOpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
ApplicationProtocolConfig apnCfg, long sessionCacheSize, long sessionTimeout,
|
||||
int mode, Certificate[] keyCertChain, ClientAuth clientAuth, String[] protocols,
|
||||
boolean startTls, boolean enableOcsp, boolean leakDetection) throws SSLException {
|
||||
this(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode, keyCertChain,
|
||||
clientAuth, protocols, startTls, enableOcsp, leakDetection);
|
||||
}
|
||||
final boolean tlsFalseStart;
|
||||
|
||||
ReferenceCountedOpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||
OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize,
|
||||
long sessionTimeout, int mode, Certificate[] keyCertChain,
|
||||
ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp,
|
||||
boolean leakDetection) throws SSLException {
|
||||
boolean leakDetection, Map.Entry<SslContextOption<?>, Object>... ctxOptions)
|
||||
throws SSLException {
|
||||
super(startTls);
|
||||
|
||||
OpenSsl.ensureAvailability();
|
||||
@ -203,6 +198,29 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
if (mode != SSL.SSL_MODE_SERVER && mode != SSL.SSL_MODE_CLIENT) {
|
||||
throw new IllegalArgumentException("mode most be either SSL.SSL_MODE_SERVER or SSL.SSL_MODE_CLIENT");
|
||||
}
|
||||
|
||||
boolean tlsFalseStart = false;
|
||||
boolean useTasks = USE_TASKS;
|
||||
OpenSslPrivateKeyMethod privateKeyMethod = null;
|
||||
|
||||
if (ctxOptions != null) {
|
||||
for (Map.Entry<SslContextOption<?>, Object> ctxOpt : ctxOptions) {
|
||||
SslContextOption<?> option = ctxOpt.getKey();
|
||||
|
||||
if (option == OpenSslContextOption.TLS_FALSE_START) {
|
||||
tlsFalseStart = (Boolean) ctxOpt.getValue();
|
||||
} else if (option == OpenSslContextOption.USE_TASKS) {
|
||||
useTasks = (Boolean) ctxOpt.getValue();
|
||||
} else if (option == OpenSslContextOption.PRIVATE_KEY_METHOD) {
|
||||
privateKeyMethod = (OpenSslPrivateKeyMethod) ctxOpt.getValue();
|
||||
} else {
|
||||
logger.debug("Skipping unsupported " + SslContextOption.class.getSimpleName()
|
||||
+ ": " + ctxOpt.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tlsFalseStart = tlsFalseStart;
|
||||
|
||||
leak = leakDetection ? leakDetector.track(this) : null;
|
||||
this.mode = mode;
|
||||
this.clientAuth = isServer() ? checkNotNull(clientAuth, "clientAuth") : ClientAuth.NONE;
|
||||
@ -335,7 +353,10 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
SSLContext.enableOcsp(ctx, isClient());
|
||||
}
|
||||
|
||||
SSLContext.setUseTasks(ctx, USE_TASKS);
|
||||
SSLContext.setUseTasks(ctx, useTasks);
|
||||
if (privateKeyMethod != null) {
|
||||
SSLContext.setPrivateKeyMethod(ctx, new PrivateKeyMethod(engineMap, privateKeyMethod));
|
||||
}
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
@ -514,8 +535,11 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
*
|
||||
* This method is currently only supported when {@code BoringSSL} is used.
|
||||
*
|
||||
* @param method method to use.
|
||||
* @param method method to use.
|
||||
* @deprecated use {@link SslContextBuilder#option(SslContextOption, Object)} with
|
||||
* {@link OpenSslContextOption#PRIVATE_KEY_METHOD}.
|
||||
*/
|
||||
@Deprecated
|
||||
@UnstableApi
|
||||
public final void setPrivateKeyMethod(OpenSslPrivateKeyMethod method) {
|
||||
ObjectUtil.checkNotNull(method, "method");
|
||||
@ -528,6 +552,11 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link SslContextBuilder#option(SslContextOption, Object)} with
|
||||
* {@link OpenSslContextOption#USE_TASKS}.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void setUseTasks(boolean useTasks) {
|
||||
Lock writerLock = ctxLock.writeLock();
|
||||
writerLock.lock();
|
||||
|
@ -357,10 +357,16 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
||||
SSL.enableOcsp(ssl);
|
||||
}
|
||||
|
||||
if (!jdkCompatibilityMode) {
|
||||
SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
int mode = SSL.getMode(ssl);
|
||||
if (context.tlsFalseStart) {
|
||||
mode |= SSL.SSL_MODE_ENABLE_FALSE_START;
|
||||
}
|
||||
|
||||
if (!jdkCompatibilityMode) {
|
||||
mode |= SSL.SSL_MODE_ENABLE_PARTIAL_WRITE;
|
||||
}
|
||||
SSL.setMode(ssl, mode);
|
||||
|
||||
// setMode may impact the overhead.
|
||||
calculateMaxWrapOverhead();
|
||||
} catch (Throwable cause) {
|
||||
|
@ -30,6 +30,7 @@ import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Map;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
@ -60,10 +61,11 @@ public final class ReferenceCountedOpenSslServerContext extends ReferenceCounted
|
||||
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,
|
||||
boolean enableOcsp, String keyStore) throws SSLException {
|
||||
boolean enableOcsp, String keyStore, Map.Entry<SslContextOption<?>, Object>... options)
|
||||
throws SSLException {
|
||||
this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
|
||||
cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls,
|
||||
enableOcsp, keyStore);
|
||||
enableOcsp, keyStore, options);
|
||||
}
|
||||
|
||||
ReferenceCountedOpenSslServerContext(
|
||||
@ -71,9 +73,10 @@ public final class ReferenceCountedOpenSslServerContext extends ReferenceCounted
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
|
||||
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
|
||||
boolean enableOcsp, String keyStore) throws SSLException {
|
||||
boolean enableOcsp, String keyStore, Map.Entry<SslContextOption<?>, Object>... options)
|
||||
throws SSLException {
|
||||
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
|
||||
clientAuth, protocols, startTls, enableOcsp, true);
|
||||
clientAuth, protocols, startTls, enableOcsp, true, options);
|
||||
// Create a new SSL_CTX and configure it.
|
||||
boolean success = false;
|
||||
try {
|
||||
|
@ -62,6 +62,7 @@ import java.security.cert.X509Certificate;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
@ -451,7 +452,8 @@ public abstract class SslContext {
|
||||
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,
|
||||
boolean enableOcsp, String keyStoreType) throws SSLException {
|
||||
boolean enableOcsp, String keyStoreType, Map.Entry<SslContextOption<?>, Object>... ctxOptions)
|
||||
throws SSLException {
|
||||
|
||||
if (provider == null) {
|
||||
provider = defaultServerProvider();
|
||||
@ -471,13 +473,13 @@ public abstract class SslContext {
|
||||
return new OpenSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, protocols, startTls, enableOcsp, keyStoreType);
|
||||
clientAuth, protocols, startTls, enableOcsp, keyStoreType, ctxOptions);
|
||||
case OPENSSL_REFCNT:
|
||||
verifyNullSslContextProvider(provider, sslContextProvider);
|
||||
return new ReferenceCountedOpenSslServerContext(
|
||||
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
|
||||
clientAuth, protocols, startTls, enableOcsp, keyStoreType);
|
||||
clientAuth, protocols, startTls, enableOcsp, keyStoreType, ctxOptions);
|
||||
default:
|
||||
throw new Error(provider.toString());
|
||||
}
|
||||
@ -809,7 +811,8 @@ public abstract class SslContext {
|
||||
X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory,
|
||||
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
|
||||
long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStoreType) throws SSLException {
|
||||
long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStoreType,
|
||||
Map.Entry<SslContextOption<?>, Object>... options) throws SSLException {
|
||||
if (provider == null) {
|
||||
provider = defaultClientProvider();
|
||||
}
|
||||
@ -827,13 +830,13 @@ public abstract class SslContext {
|
||||
return new OpenSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout,
|
||||
enableOcsp, keyStoreType);
|
||||
enableOcsp, keyStoreType, options);
|
||||
case OPENSSL_REFCNT:
|
||||
verifyNullSslContextProvider(provider, sslContextProvider);
|
||||
return new ReferenceCountedOpenSslClientContext(
|
||||
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout,
|
||||
enableOcsp, keyStoreType);
|
||||
enableOcsp, keyStoreType, options);
|
||||
default:
|
||||
throw new Error(provider.toString());
|
||||
}
|
||||
|
@ -33,7 +33,9 @@ import java.security.PrivateKey;
|
||||
import java.security.Provider;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.netty.util.internal.EmptyArrays.EMPTY_STRINGS;
|
||||
import static io.netty.util.internal.EmptyArrays.EMPTY_X509_CERTIFICATES;
|
||||
@ -43,6 +45,8 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
* Builder for configuring a new SslContext for creation.
|
||||
*/
|
||||
public final class SslContextBuilder {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final Map.Entry[] EMPTY_ENTRIES = new Map.Entry[0];
|
||||
|
||||
/**
|
||||
* Creates a builder for new client-side {@link SslContext}.
|
||||
@ -201,11 +205,24 @@ public final class SslContextBuilder {
|
||||
private boolean startTls;
|
||||
private boolean enableOcsp;
|
||||
private String keyStoreType = KeyStore.getDefaultType();
|
||||
private final Map<SslContextOption<?>, Object> options = new HashMap<SslContextOption<?>, Object>();
|
||||
|
||||
private SslContextBuilder(boolean forServer) {
|
||||
this.forServer = forServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a {@link SslContextOption}.
|
||||
*/
|
||||
public <T> SslContextBuilder option(SslContextOption<T> option, T value) {
|
||||
if (value == null) {
|
||||
options.remove(option);
|
||||
} else {
|
||||
options.put(option, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link SslContext} implementation to use. {@code null} uses the default one.
|
||||
*/
|
||||
@ -592,11 +609,12 @@ public final class SslContextBuilder {
|
||||
return SslContext.newServerContextInternal(provider, sslContextProvider, trustCertCollection,
|
||||
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls,
|
||||
enableOcsp, keyStoreType);
|
||||
enableOcsp, keyStoreType, toArray(options.entrySet(), EMPTY_ENTRIES));
|
||||
} else {
|
||||
return SslContext.newClientContextInternal(provider, sslContextProvider, trustCertCollection,
|
||||
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||
ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout, enableOcsp, keyStoreType);
|
||||
ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout, enableOcsp, keyStoreType,
|
||||
toArray(options.entrySet(), EMPTY_ENTRIES));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2021 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:
|
||||
*
|
||||
* https://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 io.netty.util.AbstractConstant;
|
||||
import io.netty.util.ConstantPool;
|
||||
import io.netty.util.internal.ObjectUtil;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link SslContextOption} allows to configure a {@link SslContext} in a type-safe
|
||||
* way. Which {@link SslContextOption} is supported depends on the actual implementation
|
||||
* of {@link SslContext} and may depend on the nature of the SSL implementation it belongs
|
||||
* to.
|
||||
*
|
||||
* @param <T> the type of the value which is valid for the {@link SslContextOption}
|
||||
*/
|
||||
public class SslContextOption<T> extends AbstractConstant<SslContextOption<T>> {
|
||||
|
||||
private static final ConstantPool<SslContextOption<Object>> pool = new ConstantPool<SslContextOption<Object>>() {
|
||||
@Override
|
||||
protected SslContextOption<Object> newConstant(int id, String name) {
|
||||
return new SslContextOption<Object>(id, name);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the {@link SslContextOption} of the specified name.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> SslContextOption<T> valueOf(String name) {
|
||||
return (SslContextOption<T>) pool.valueOf(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut of {@link #valueOf(String) valueOf(firstNameComponent.getName() + "#" + secondNameComponent)}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> SslContextOption<T> valueOf(Class<?> firstNameComponent, String secondNameComponent) {
|
||||
return (SslContextOption<T>) pool.valueOf(firstNameComponent, secondNameComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if a {@link SslContextOption} exists for the given {@code name}.
|
||||
*/
|
||||
public static boolean exists(String name) {
|
||||
return pool.exists(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SslContextOption} with the specified unique {@code name}.
|
||||
*/
|
||||
private SslContextOption(int id, String name) {
|
||||
super(id, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be used by sub-classes.
|
||||
*
|
||||
* @param name the name of the option
|
||||
*/
|
||||
protected SslContextOption(String name) {
|
||||
this(pool.nextId(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the value which is set for the {@link SslContextOption}. Sub-classes
|
||||
* may override this for special checks.
|
||||
*/
|
||||
public void validate(T value) {
|
||||
ObjectUtil.checkNotNull(value, "value");
|
||||
}
|
||||
}
|
@ -155,6 +155,7 @@ public class ConscryptOpenSslEngineInteropTest extends ConscryptSslEngineTest {
|
||||
return Java8SslTestUtils.wrapSSLEngineForTesting(engine);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected SslContext wrapContext(SslContext context) {
|
||||
if (context instanceof OpenSslContext) {
|
||||
|
@ -162,6 +162,7 @@ public class JdkOpenSslEngineInteroptTest extends SSLEngineTest {
|
||||
return Java8SslTestUtils.wrapSSLEngineForTesting(engine);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected SslContext wrapContext(SslContext context) {
|
||||
if (context instanceof OpenSslContext) {
|
||||
|
@ -147,6 +147,7 @@ public class OpenSslConscryptSslEngineInteropTest extends ConscryptSslEngineTest
|
||||
return Java8SslTestUtils.wrapSSLEngineForTesting(engine);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected SslContext wrapContext(SslContext context) {
|
||||
if (context instanceof OpenSslContext) {
|
||||
|
@ -1414,6 +1414,7 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
||||
return (ReferenceCountedOpenSslEngine) engine;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected SslContext wrapContext(SslContext context) {
|
||||
if (context instanceof OpenSslContext) {
|
||||
|
@ -148,6 +148,7 @@ public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
|
||||
return Java8SslTestUtils.wrapSSLEngineForTesting(engine);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected SslContext wrapContext(SslContext context) {
|
||||
if (context instanceof OpenSslContext) {
|
||||
|
@ -151,15 +151,13 @@ public class OpenSslPrivateKeyMethodTest {
|
||||
|
||||
final KeyManagerFactory kmf = OpenSslX509KeyManagerFactory.newKeyless(CERT.cert());
|
||||
|
||||
final SslContext sslServerContext = SslContextBuilder.forServer(kmf)
|
||||
return SslContextBuilder.forServer(kmf)
|
||||
.sslProvider(SslProvider.OPENSSL)
|
||||
.ciphers(ciphers)
|
||||
// As this is not a TLSv1.3 cipher we should ensure we talk something else.
|
||||
.protocols(SslUtils.PROTOCOL_TLS_V1_2)
|
||||
.option(OpenSslContextOption.PRIVATE_KEY_METHOD, method)
|
||||
.build();
|
||||
|
||||
((OpenSslContext) sslServerContext).setPrivateKeyMethod(method);
|
||||
return sslServerContext;
|
||||
}
|
||||
|
||||
private SslContext buildClientContext() throws Exception {
|
||||
|
@ -73,6 +73,7 @@ public class ReferenceCountedOpenSslEngineTest extends OpenSslEngineTest {
|
||||
clientSslCtx.newEngine(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected SslContext wrapContext(SslContext context) {
|
||||
if (context instanceof ReferenceCountedOpenSslContext) {
|
||||
|
Loading…
Reference in New Issue
Block a user