Allow to create SslContext from existing PrivateKey / X509Certificate
Motivation: Sometimes the user already has a PrivateKey / X509Certificate which should be used to create a new SslContext. At the moment we only allow to construct it via Files. Modifications: - Add new methods to the SslContextBuilder to allow creating a SslContext from PrivateKey / X509Certificate - Mark all public constructors of *SslContext as @Deprecated, the user should use SslContextBuilder - Update tests to us SslContextBuilder. Result: Creating of SslContext is possible with PrivateKay/X509Certificate
This commit is contained in:
parent
9d417c1626
commit
5ac84760c4
@ -24,6 +24,8 @@ import javax.net.ssl.SSLSessionContext;
|
|||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client-side {@link SslContext} which uses JDK's SSL/TLS implementation.
|
* A client-side {@link SslContext} which uses JDK's SSL/TLS implementation.
|
||||||
@ -34,7 +36,10 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
|
*
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext() throws SSLException {
|
public JdkSslClientContext() throws SSLException {
|
||||||
this(null, null);
|
this(null, null);
|
||||||
}
|
}
|
||||||
@ -44,7 +49,9 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format.
|
* @param certChainFile an X.509 certificate chain file in PEM format.
|
||||||
* {@code null} to use the system default
|
* {@code null} to use the system default
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(File certChainFile) throws SSLException {
|
public JdkSslClientContext(File certChainFile) throws SSLException {
|
||||||
this(certChainFile, null);
|
this(certChainFile, null);
|
||||||
}
|
}
|
||||||
@ -55,7 +62,9 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
||||||
* that verifies the certificates sent from servers.
|
* that verifies the certificates sent from servers.
|
||||||
* {@code null} to use the default.
|
* {@code null} to use the default.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException {
|
public JdkSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException {
|
||||||
this(null, trustManagerFactory);
|
this(null, trustManagerFactory);
|
||||||
}
|
}
|
||||||
@ -68,7 +77,9 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
||||||
* that verifies the certificates sent from servers.
|
* that verifies the certificates sent from servers.
|
||||||
* {@code null} to use the default.
|
* {@code null} to use the default.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException {
|
public JdkSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException {
|
||||||
this(certChainFile, trustManagerFactory, null, IdentityCipherSuiteFilter.INSTANCE,
|
this(certChainFile, trustManagerFactory, null, IdentityCipherSuiteFilter.INSTANCE,
|
||||||
JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0);
|
JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0);
|
||||||
@ -93,6 +104,7 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public JdkSslClientContext(
|
public JdkSslClientContext(
|
||||||
@ -119,7 +131,9 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(
|
public JdkSslClientContext(
|
||||||
File certChainFile, TrustManagerFactory trustManagerFactory,
|
File certChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
@ -144,7 +158,9 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(
|
public JdkSslClientContext(
|
||||||
File certChainFile, TrustManagerFactory trustManagerFactory,
|
File certChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||||
@ -181,7 +197,9 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
public JdkSslClientContext(File trustCertChainFile, 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,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
@ -218,21 +236,47 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslClientContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
public JdkSslClientContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
super(ciphers, cipherFilter, apn);
|
super(ciphers, cipherFilter, apn);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (trustCertChainFile != null) {
|
ctx = newSSLContext(toX509Certificates(trustCertChainFile), trustManagerFactory,
|
||||||
trustManagerFactory = buildTrustManagerFactory(trustCertChainFile, trustManagerFactory);
|
toX509Certificates(keyCertChainFile), toPrivateKey(keyFile, keyPassword),
|
||||||
|
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
throw (SSLException) e;
|
||||||
}
|
}
|
||||||
if (keyFile != null) {
|
throw new SSLException("failed to initialize the client-side SSL context", e);
|
||||||
keyManagerFactory = buildKeyManagerFactory(keyCertChainFile, keyFile, keyPassword, keyManagerFactory);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JdkSslClientContext(X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||||
|
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||||
|
ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
|
super(ciphers, cipherFilter, toNegotiator(apn, false));
|
||||||
|
ctx = newSSLContext(trustCertChain, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||||
|
keyManagerFactory, sessionCacheSize, sessionTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SSLContext newSSLContext(X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||||
|
KeyManagerFactory keyManagerFactory, long sessionCacheSize,
|
||||||
|
long sessionTimeout) throws SSLException {
|
||||||
|
try {
|
||||||
|
if (trustCertChain != null) {
|
||||||
|
trustManagerFactory = buildTrustManagerFactory(trustCertChain, trustManagerFactory);
|
||||||
}
|
}
|
||||||
ctx = SSLContext.getInstance(PROTOCOL);
|
if (keyCertChain != null) {
|
||||||
|
keyManagerFactory = buildKeyManagerFactory(keyCertChain, key, keyPassword, keyManagerFactory);
|
||||||
|
}
|
||||||
|
SSLContext ctx = SSLContext.getInstance(PROTOCOL);
|
||||||
ctx.init(keyManagerFactory == null ? null : keyManagerFactory.getKeyManagers(),
|
ctx.init(keyManagerFactory == null ? null : keyManagerFactory.getKeyManagers(),
|
||||||
trustManagerFactory == null ? null : trustManagerFactory.getTrustManagers(),
|
trustManagerFactory == null ? null : trustManagerFactory.getTrustManagers(),
|
||||||
null);
|
null);
|
||||||
@ -244,7 +288,11 @@ public final class JdkSslClientContext extends JdkSslContext {
|
|||||||
if (sessionTimeout > 0) {
|
if (sessionTimeout > 0) {
|
||||||
sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
|
sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
|
||||||
}
|
}
|
||||||
|
return ctx;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
throw (SSLException) e;
|
||||||
|
}
|
||||||
throw new SSLException("failed to initialize the client-side SSL context", e);
|
throw new SSLException("failed to initialize the client-side SSL context", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,11 @@ import java.security.KeyException;
|
|||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -281,7 +283,9 @@ public abstract class JdkSslContext extends SslContext {
|
|||||||
* {@code null} if it's not password-protected.
|
* {@code null} if it's not password-protected.
|
||||||
* @param kmf The existing {@link KeyManagerFactory} that will be used if not {@code null}
|
* @param kmf The existing {@link KeyManagerFactory} that will be used if not {@code null}
|
||||||
* @return A {@link KeyManagerFactory} based upon a key file, key file password, and a certificate chain.
|
* @return A {@link KeyManagerFactory} based upon a key file, key file password, and a certificate chain.
|
||||||
|
* @deprecated will be removed.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
protected static KeyManagerFactory buildKeyManagerFactory(File certChainFile, File keyFile, String keyPassword,
|
protected static KeyManagerFactory buildKeyManagerFactory(File certChainFile, File keyFile, String keyPassword,
|
||||||
KeyManagerFactory kmf)
|
KeyManagerFactory kmf)
|
||||||
throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException,
|
throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException,
|
||||||
@ -294,6 +298,17 @@ public abstract class JdkSslContext extends SslContext {
|
|||||||
return buildKeyManagerFactory(certChainFile, algorithm, keyFile, keyPassword, kmf);
|
return buildKeyManagerFactory(certChainFile, algorithm, keyFile, keyPassword, kmf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static KeyManagerFactory buildKeyManagerFactory(X509Certificate[] certChain, PrivateKey key, String keyPassword,
|
||||||
|
KeyManagerFactory kmf)
|
||||||
|
throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException,
|
||||||
|
CertificateException, IOException {
|
||||||
|
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
|
||||||
|
if (algorithm == null) {
|
||||||
|
algorithm = "SunX509";
|
||||||
|
}
|
||||||
|
return buildKeyManagerFactory(certChain, algorithm, key, keyPassword, kmf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a {@link KeyManagerFactory} based upon a key algorithm, key file, key file password,
|
* Build a {@link KeyManagerFactory} based upon a key algorithm, key file, key file password,
|
||||||
* and a certificate chain.
|
* and a certificate chain.
|
||||||
@ -306,14 +321,25 @@ public abstract class JdkSslContext extends SslContext {
|
|||||||
* @param kmf The existing {@link KeyManagerFactory} that will be used if not {@code null}
|
* @param kmf The existing {@link KeyManagerFactory} that will be used if not {@code null}
|
||||||
* @return A {@link KeyManagerFactory} based upon a key algorithm, key file, key file password,
|
* @return A {@link KeyManagerFactory} based upon a key algorithm, key file, key file password,
|
||||||
* and a certificate chain.
|
* and a certificate chain.
|
||||||
|
* @deprecated will be removed.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
protected static KeyManagerFactory buildKeyManagerFactory(File certChainFile,
|
protected static KeyManagerFactory buildKeyManagerFactory(File certChainFile,
|
||||||
String keyAlgorithm, File keyFile, String keyPassword, KeyManagerFactory kmf)
|
String keyAlgorithm, File keyFile, String keyPassword, KeyManagerFactory kmf)
|
||||||
throws KeyStoreException, NoSuchAlgorithmException, NoSuchPaddingException,
|
throws KeyStoreException, NoSuchAlgorithmException, NoSuchPaddingException,
|
||||||
InvalidKeySpecException, InvalidAlgorithmParameterException, IOException,
|
InvalidKeySpecException, InvalidAlgorithmParameterException, IOException,
|
||||||
CertificateException, KeyException, UnrecoverableKeyException {
|
CertificateException, KeyException, UnrecoverableKeyException {
|
||||||
|
return buildKeyManagerFactory(toX509Certificates(certChainFile), keyAlgorithm,
|
||||||
|
toPrivateKey(keyFile, keyPassword), keyPassword, kmf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static KeyManagerFactory buildKeyManagerFactory(X509Certificate[] certChainFile,
|
||||||
|
String keyAlgorithm, PrivateKey key,
|
||||||
|
String keyPassword, KeyManagerFactory kmf)
|
||||||
|
throws KeyStoreException, NoSuchAlgorithmException, IOException,
|
||||||
|
CertificateException, UnrecoverableKeyException {
|
||||||
char[] keyPasswordChars = keyPassword == null ? EmptyArrays.EMPTY_CHARS : keyPassword.toCharArray();
|
char[] keyPasswordChars = keyPassword == null ? EmptyArrays.EMPTY_CHARS : keyPassword.toCharArray();
|
||||||
KeyStore ks = buildKeyStore(certChainFile, keyFile, keyPasswordChars);
|
KeyStore ks = buildKeyStore(certChainFile, key, keyPasswordChars);
|
||||||
// Set up key manager factory to use our key store
|
// Set up key manager factory to use our key store
|
||||||
if (kmf == null) {
|
if (kmf == null) {
|
||||||
kmf = KeyManagerFactory.getInstance(keyAlgorithm);
|
kmf = KeyManagerFactory.getInstance(keyAlgorithm);
|
||||||
|
@ -25,6 +25,8 @@ import javax.net.ssl.SSLSessionContext;
|
|||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A server-side {@link SslContext} which uses JDK's SSL/TLS implementation.
|
* A server-side {@link SslContext} which uses JDK's SSL/TLS implementation.
|
||||||
@ -38,7 +40,9 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
* @param keyFile a PKCS#8 private key file in PEM format
|
* @param keyFile a PKCS#8 private key file in PEM format
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(File certChainFile, File keyFile) throws SSLException {
|
public JdkSslServerContext(File certChainFile, File keyFile) throws SSLException {
|
||||||
this(certChainFile, keyFile, null);
|
this(certChainFile, keyFile, null);
|
||||||
}
|
}
|
||||||
@ -50,7 +54,9 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
* @param keyFile a PKCS#8 private key file in PEM format
|
* @param keyFile a PKCS#8 private key file in PEM format
|
||||||
* @param keyPassword the password of the {@code keyFile}.
|
* @param keyPassword the password of the {@code keyFile}.
|
||||||
* {@code null} if it's not password-protected.
|
* {@code null} if it's not password-protected.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException {
|
public JdkSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException {
|
||||||
this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE,
|
this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE,
|
||||||
JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0);
|
JdkDefaultApplicationProtocolNegotiator.INSTANCE, 0, 0);
|
||||||
@ -71,7 +77,9 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(
|
public JdkSslServerContext(
|
||||||
File certChainFile, File keyFile, String keyPassword,
|
File certChainFile, File keyFile, String keyPassword,
|
||||||
Iterable<String> ciphers, Iterable<String> nextProtocols,
|
Iterable<String> ciphers, Iterable<String> nextProtocols,
|
||||||
@ -95,7 +103,9 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(
|
public JdkSslServerContext(
|
||||||
File certChainFile, File keyFile, String keyPassword,
|
File certChainFile, File keyFile, String keyPassword,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
@ -119,7 +129,9 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(
|
public JdkSslServerContext(
|
||||||
File certChainFile, File keyFile, String keyPassword,
|
File certChainFile, File keyFile, String keyPassword,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||||
@ -153,7 +165,9 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
public JdkSslServerContext(File trustCertChainFile, 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,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
@ -187,26 +201,53 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JdkSslServerContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
public JdkSslServerContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, JdkApplicationProtocolNegotiator apn,
|
||||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
super(ciphers, cipherFilter, apn);
|
super(ciphers, cipherFilter, apn);
|
||||||
if (keyFile == null && keyManagerFactory == null) {
|
try {
|
||||||
throw new NullPointerException("keyFile, keyManagerFactory");
|
ctx = newSSLContext(toX509Certificates(trustCertChainFile), trustManagerFactory,
|
||||||
|
toX509Certificates(keyCertChainFile), toPrivateKey(keyFile, keyPassword),
|
||||||
|
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
throw (SSLException) e;
|
||||||
|
}
|
||||||
|
throw new SSLException("failed to initialize the server-side SSL context", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JdkSslServerContext(X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||||
|
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
|
||||||
|
ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
|
super(ciphers, cipherFilter, toNegotiator(apn, true));
|
||||||
|
ctx = newSSLContext(trustCertChain, trustManagerFactory, keyCertChain, key,
|
||||||
|
keyPassword, keyManagerFactory, sessionCacheSize, sessionTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SSLContext newSSLContext(X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||||
|
KeyManagerFactory keyManagerFactory, long sessionCacheSize, long sessionTimeout)
|
||||||
|
throws SSLException {
|
||||||
|
if (key == null && keyManagerFactory == null) {
|
||||||
|
throw new NullPointerException("key, keyManagerFactory");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (trustCertChainFile != null) {
|
if (trustCertChain != null) {
|
||||||
trustManagerFactory = buildTrustManagerFactory(trustCertChainFile, trustManagerFactory);
|
trustManagerFactory = buildTrustManagerFactory(trustCertChain, trustManagerFactory);
|
||||||
}
|
}
|
||||||
if (keyFile != null) {
|
if (key != null) {
|
||||||
keyManagerFactory = buildKeyManagerFactory(keyCertChainFile, keyFile, keyPassword, keyManagerFactory);
|
keyManagerFactory = buildKeyManagerFactory(keyCertChain, key, keyPassword, keyManagerFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the SSLContext to work with our key managers.
|
// Initialize the SSLContext to work with our key managers.
|
||||||
ctx = SSLContext.getInstance(PROTOCOL);
|
SSLContext ctx = SSLContext.getInstance(PROTOCOL);
|
||||||
ctx.init(keyManagerFactory.getKeyManagers(),
|
ctx.init(keyManagerFactory.getKeyManagers(),
|
||||||
trustManagerFactory == null ? null : trustManagerFactory.getTrustManagers(),
|
trustManagerFactory == null ? null : trustManagerFactory.getTrustManagers(),
|
||||||
null);
|
null);
|
||||||
@ -218,7 +259,11 @@ public final class JdkSslServerContext extends JdkSslContext {
|
|||||||
if (sessionTimeout > 0) {
|
if (sessionTimeout > 0) {
|
||||||
sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
|
sessCtx.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE));
|
||||||
}
|
}
|
||||||
|
return ctx;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
throw (SSLException) e;
|
||||||
|
}
|
||||||
throw new SSLException("failed to initialize the server-side SSL context", e);
|
throw new SSLException("failed to initialize the server-side SSL context", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import javax.net.ssl.X509ExtendedTrustManager;
|
|||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,9 +37,11 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslClientContext() throws SSLException {
|
public OpenSslClientContext() throws SSLException {
|
||||||
this(null, null, null, null, null, null, null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0);
|
this((File) null, null, null, null, null, null, null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,7 +49,9 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format.
|
* @param certChainFile an X.509 certificate chain file in PEM format.
|
||||||
* {@code null} to use the system default
|
* {@code null} to use the system default
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslClientContext(File certChainFile) throws SSLException {
|
public OpenSslClientContext(File certChainFile) throws SSLException {
|
||||||
this(certChainFile, null);
|
this(certChainFile, null);
|
||||||
}
|
}
|
||||||
@ -57,7 +62,9 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
||||||
* that verifies the certificates sent from servers.
|
* that verifies the certificates sent from servers.
|
||||||
* {@code null} to use the default.
|
* {@code null} to use the default.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException {
|
public OpenSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException {
|
||||||
this(null, trustManagerFactory);
|
this(null, trustManagerFactory);
|
||||||
}
|
}
|
||||||
@ -70,16 +77,15 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
* @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s
|
||||||
* that verifies the certificates sent from servers.
|
* that verifies the certificates sent from servers.
|
||||||
* {@code null} to use the default.
|
* {@code null} to use the default.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException {
|
public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException {
|
||||||
this(certChainFile, trustManagerFactory, null, null, null, null, null,
|
this(certChainFile, trustManagerFactory, null, null, null, null, null,
|
||||||
IdentityCipherSuiteFilter.INSTANCE, null, 0, 0);
|
IdentityCipherSuiteFilter.INSTANCE, null, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #OpenSslClientContext(File, TrustManagerFactory, Iterable,
|
|
||||||
* CipherSuiteFilter, ApplicationProtocolConfig, long, long)}
|
|
||||||
*
|
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
@ -93,6 +99,7 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers,
|
public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers,
|
||||||
@ -103,9 +110,6 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #OpenSslClientContext(File, TrustManagerFactory, File, File, String,
|
|
||||||
* KeyManagerFactory, Iterable, CipherSuiteFilter, ApplicationProtocolConfig,long, long)}
|
|
||||||
*
|
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
@ -120,6 +124,7 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers,
|
public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers,
|
||||||
@ -157,7 +162,9 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslClientContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
public OpenSslClientContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword,
|
File keyCertChainFile, File keyFile, String keyPassword,
|
||||||
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
||||||
@ -257,6 +264,119 @@ public final class OpenSslClientContext extends OpenSslContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
OpenSslClientContext(X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
|
||||||
|
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
|
||||||
|
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
|
long sessionCacheSize, long sessionTimeout)
|
||||||
|
throws SSLException {
|
||||||
|
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT);
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
if (key == null && keyCertChain != null || key != null && keyCertChain == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Either both keyCertChain and key needs to be null or none of them");
|
||||||
|
}
|
||||||
|
synchronized (OpenSslContext.class) {
|
||||||
|
if (trustCertChain != null) {
|
||||||
|
long trustCertChainBio = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
trustCertChainBio = toBIO(trustCertChain);
|
||||||
|
/* Load the certificate chain. We must NOT skip the first cert when client mode */
|
||||||
|
if (!SSLContext.setCertificateChainBio(ctx, trustCertChainBio, false)) {
|
||||||
|
long error = SSL.getLastErrorNumber();
|
||||||
|
if (OpenSsl.isError(error)) {
|
||||||
|
throw new SSLException(
|
||||||
|
"failed to set certificate chain: " + SSL.getErrorString(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException(
|
||||||
|
"failed to set certificate chain", e);
|
||||||
|
} finally {
|
||||||
|
if (trustCertChainBio != 0) {
|
||||||
|
SSL.freeBIO(trustCertChainBio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyCertChain != null && key != null) {
|
||||||
|
/* Load the certificate file and private key. */
|
||||||
|
long keyBio = 0;
|
||||||
|
long keyCertChainBio = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
keyCertChainBio = toBIO(keyCertChain);
|
||||||
|
|
||||||
|
keyBio = toBIO(key);
|
||||||
|
|
||||||
|
if (!SSLContext.setCertificateBio(
|
||||||
|
ctx, keyCertChainBio, keyBio, keyPassword, SSL.SSL_AIDX_RSA)) {
|
||||||
|
long error = SSL.getLastErrorNumber();
|
||||||
|
if (OpenSsl.isError(error)) {
|
||||||
|
throw new SSLException("failed to set certificate and key: "
|
||||||
|
+ SSL.getErrorString(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SSLException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException("failed to set certificate and key", e);
|
||||||
|
} finally {
|
||||||
|
if (keyBio != 0) {
|
||||||
|
SSL.freeBIO(keyBio);
|
||||||
|
}
|
||||||
|
if (keyCertChainBio != 0) {
|
||||||
|
SSL.freeBIO(keyCertChainBio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLContext.setVerify(ctx, SSL.SSL_VERIFY_NONE, VERIFY_DEPTH);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (trustCertChain != null) {
|
||||||
|
trustManagerFactory = buildTrustManagerFactory(trustCertChain, trustManagerFactory);
|
||||||
|
} else if (trustManagerFactory == null) {
|
||||||
|
trustManagerFactory = TrustManagerFactory.getInstance(
|
||||||
|
TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
trustManagerFactory.init((KeyStore) null);
|
||||||
|
}
|
||||||
|
final X509TrustManager manager = chooseTrustManager(trustManagerFactory.getTrustManagers());
|
||||||
|
|
||||||
|
// Use this to prevent an error when running on java < 7
|
||||||
|
if (useExtendedTrustManager(manager)) {
|
||||||
|
final X509ExtendedTrustManager extendedManager = (X509ExtendedTrustManager) manager;
|
||||||
|
SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() {
|
||||||
|
@Override
|
||||||
|
void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth)
|
||||||
|
throws Exception {
|
||||||
|
extendedManager.checkServerTrusted(peerCerts, auth, engine);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() {
|
||||||
|
@Override
|
||||||
|
void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth)
|
||||||
|
throws Exception {
|
||||||
|
manager.checkServerTrusted(peerCerts, auth);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException("unable to setup trustmanager", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessionContext = new OpenSslClientSessionContext(ctx);
|
||||||
|
success = true;
|
||||||
|
} finally {
|
||||||
|
if (!success) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenSslSessionContext sessionContext() {
|
public OpenSslSessionContext sessionContext() {
|
||||||
return sessionContext;
|
return sessionContext;
|
||||||
|
@ -15,7 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.handler.codec.base64.Base64;
|
||||||
|
import io.netty.util.CharsetUtil;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import io.netty.util.internal.SystemPropertyUtil;
|
import io.netty.util.internal.SystemPropertyUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
@ -31,6 +35,7 @@ import javax.net.ssl.SSLHandshakeException;
|
|||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.X509ExtendedTrustManager;
|
import javax.net.ssl.X509ExtendedTrustManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -43,6 +48,10 @@ import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBeha
|
|||||||
import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
|
import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
|
||||||
|
|
||||||
public abstract class OpenSslContext extends SslContext {
|
public abstract class OpenSslContext extends SslContext {
|
||||||
|
private static final byte[] BEGIN_CERT = "-----BEGIN CERTIFICATE-----\n".getBytes(CharsetUtil.US_ASCII);
|
||||||
|
private static final byte[] END_CERT = "\n-----END CERTIFICATE-----\n".getBytes(CharsetUtil.US_ASCII);
|
||||||
|
private static final byte[] BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n".getBytes(CharsetUtil.US_ASCII);
|
||||||
|
private static final byte[] END_PRIVATE_KEY = "\n-----END PRIVATE KEY-----\n".getBytes(CharsetUtil.US_ASCII);
|
||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSslContext.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSslContext.class);
|
||||||
/**
|
/**
|
||||||
@ -62,7 +71,7 @@ public abstract class OpenSslContext extends SslContext {
|
|||||||
|
|
||||||
/** The OpenSSL SSL_CTX object */
|
/** The OpenSSL SSL_CTX object */
|
||||||
protected volatile long ctx;
|
protected volatile long ctx;
|
||||||
private long aprPool;
|
long aprPool;
|
||||||
@SuppressWarnings({ "unused", "FieldMayBeFinal" })
|
@SuppressWarnings({ "unused", "FieldMayBeFinal" })
|
||||||
private volatile int aprPoolDestroyed;
|
private volatile int aprPoolDestroyed;
|
||||||
private volatile boolean rejectRemoteInitiatedRenegotiation;
|
private volatile boolean rejectRemoteInitiatedRenegotiation;
|
||||||
@ -458,4 +467,54 @@ public abstract class OpenSslContext extends SslContext {
|
|||||||
engines.put(engine.sslPointer(), engine);
|
engines.put(engine.sslPointer(), engine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pointer to a <a href="https://www.openssl.org/docs/crypto/BIO_get_mem_ptr.html">in-memory BIO</a>
|
||||||
|
* or {@code 0} if the {@code key} is {@code null}. The BIO contains the content of the {@code key}.
|
||||||
|
*/
|
||||||
|
static long toBIO(PrivateKey key) throws Exception {
|
||||||
|
if (key == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ByteBuf buffer = Unpooled.directBuffer();
|
||||||
|
try {
|
||||||
|
buffer.writeBytes(BEGIN_PRIVATE_KEY);
|
||||||
|
buffer.writeBytes(Base64.encode(Unpooled.wrappedBuffer(key.getEncoded()), true));
|
||||||
|
buffer.writeBytes(END_PRIVATE_KEY);
|
||||||
|
return newBIO(buffer);
|
||||||
|
} finally {
|
||||||
|
buffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pointer to a <a href="https://www.openssl.org/docs/crypto/BIO_get_mem_ptr.html">in-memory BIO</a>
|
||||||
|
* or {@code 0} if the {@code certChain} is {@code null}. The BIO contains the content of the {@code certChain}.
|
||||||
|
*/
|
||||||
|
static long toBIO(X509Certificate[] certChain) throws Exception {
|
||||||
|
if (certChain == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ByteBuf buffer = Unpooled.directBuffer();
|
||||||
|
try {
|
||||||
|
for (X509Certificate cert: certChain) {
|
||||||
|
buffer.writeBytes(BEGIN_CERT);
|
||||||
|
buffer.writeBytes(Base64.encode(Unpooled.wrappedBuffer(cert.getEncoded()), true));
|
||||||
|
buffer.writeBytes(END_CERT);
|
||||||
|
}
|
||||||
|
return newBIO(buffer);
|
||||||
|
} finally {
|
||||||
|
buffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long newBIO(ByteBuf buffer) throws Exception {
|
||||||
|
long bio = SSL.newMemBIO();
|
||||||
|
int readable = buffer.readableBytes();
|
||||||
|
if (SSL.writeToBIO(bio, buffer.memoryAddress(), readable) != readable) {
|
||||||
|
SSL.freeBIO(bio);
|
||||||
|
throw new IllegalStateException("Could not write data to memory BIO");
|
||||||
|
}
|
||||||
|
return bio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
import io.netty.util.internal.EmptyArrays;
|
|
||||||
import org.apache.tomcat.jni.SSL;
|
import org.apache.tomcat.jni.SSL;
|
||||||
import org.apache.tomcat.jni.SSLContext;
|
import org.apache.tomcat.jni.SSLContext;
|
||||||
|
|
||||||
@ -28,6 +27,7 @@ import javax.net.ssl.X509ExtendedTrustManager;
|
|||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import static io.netty.util.internal.ObjectUtil.*;
|
import static io.netty.util.internal.ObjectUtil.*;
|
||||||
@ -43,7 +43,9 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
* @param keyFile a PKCS#8 private key file in PEM format
|
* @param keyFile a PKCS#8 private key file in PEM format
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslServerContext(File certChainFile, File keyFile) throws SSLException {
|
public OpenSslServerContext(File certChainFile, File keyFile) throws SSLException {
|
||||||
this(certChainFile, keyFile, null);
|
this(certChainFile, keyFile, null);
|
||||||
}
|
}
|
||||||
@ -55,16 +57,15 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* @param keyFile a PKCS#8 private key file in PEM format
|
* @param keyFile a PKCS#8 private key file in PEM format
|
||||||
* @param keyPassword the password of the {@code keyFile}.
|
* @param keyPassword the password of the {@code keyFile}.
|
||||||
* {@code null} if it's not password-protected.
|
* {@code null} if it's not password-protected.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException {
|
public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException {
|
||||||
this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE,
|
this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE,
|
||||||
ApplicationProtocolConfig.DISABLED, 0, 0);
|
ApplicationProtocolConfig.DISABLED, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #OpenSslServerContext(
|
|
||||||
* File, File, String, Iterable, CipherSuiteFilter, ApplicationProtocolConfig, long, long)}
|
|
||||||
*
|
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
@ -78,6 +79,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
@ -89,9 +91,6 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the constructors that accepts {@link ApplicationProtocolConfig} or
|
|
||||||
* {@link ApplicationProtocolNegotiator} instead.
|
|
||||||
*
|
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
@ -106,6 +105,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
@ -130,8 +130,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @deprecated use {@link #OpenSslServerContext(File, TrustManagerFactory, File, File, String, KeyManagerFactory,
|
* @deprecated use {@link SslContextBuilder}
|
||||||
* Iterable, CipherSuiteFilter, ApplicationProtocolConfig, long, long)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
@ -156,8 +155,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @deprecated use {@link #OpenSslServerContext(File, TrustManagerFactory, File, File, String, KeyManagerFactory,
|
* @deprecated use {@link SslContextBuilder}
|
||||||
* Iterable, CipherSuiteFilter, ApplicationProtocolConfig, long, long)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
@ -183,7 +181,9 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
File certChainFile, File keyFile, String keyPassword,
|
File certChainFile, File keyFile, String keyPassword,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
@ -218,7 +218,9 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
@ -243,6 +245,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword,
|
public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword,
|
||||||
@ -268,8 +271,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @deprecated use {@link #OpenSslServerContext(File, TrustManagerFactory, File, File, String, KeyManagerFactory,
|
* @deprecated use {@link SslContextBuilder}}
|
||||||
* Iterable, CipherSuiteFilter, OpenSslApplicationProtocolNegotiator, long, long)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
@ -307,7 +309,9 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
* @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
|
||||||
* {@code 0} to use the default value.
|
* {@code 0} to use the default value.
|
||||||
|
* @deprecated use {@link SslContextBuilder}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public OpenSslServerContext(
|
public OpenSslServerContext(
|
||||||
File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
@ -370,10 +374,123 @@ public final class OpenSslServerContext extends OpenSslContext {
|
|||||||
if (trustCertChainFile != null) {
|
if (trustCertChainFile != null) {
|
||||||
trustManagerFactory = buildTrustManagerFactory(trustCertChainFile, trustManagerFactory);
|
trustManagerFactory = buildTrustManagerFactory(trustCertChainFile, trustManagerFactory);
|
||||||
} else {
|
} else {
|
||||||
char[] keyPasswordChars =
|
KeyStore ks = buildKeyStore(keyCertChainFile, keyFile, keyPassword);
|
||||||
keyPassword == null ? EmptyArrays.EMPTY_CHARS : keyPassword.toCharArray();
|
trustManagerFactory.init(ks);
|
||||||
|
}
|
||||||
|
|
||||||
KeyStore ks = buildKeyStore(keyCertChainFile, keyFile, keyPasswordChars);
|
final X509TrustManager manager = chooseTrustManager(trustManagerFactory.getTrustManagers());
|
||||||
|
|
||||||
|
// Use this to prevent an error when running on java < 7
|
||||||
|
if (useExtendedTrustManager(manager)) {
|
||||||
|
final X509ExtendedTrustManager extendedManager = (X509ExtendedTrustManager) manager;
|
||||||
|
SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() {
|
||||||
|
@Override
|
||||||
|
void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth)
|
||||||
|
throws Exception {
|
||||||
|
extendedManager.checkClientTrusted(peerCerts, auth, engine);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() {
|
||||||
|
@Override
|
||||||
|
void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth)
|
||||||
|
throws Exception {
|
||||||
|
manager.checkClientTrusted(peerCerts, auth);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException("unable to setup trustmanager", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessionContext = new OpenSslServerSessionContext(ctx);
|
||||||
|
success = true;
|
||||||
|
} finally {
|
||||||
|
if (!success) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
OpenSslServerContext(
|
||||||
|
X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
|
super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER);
|
||||||
|
OpenSsl.ensureAvailability();
|
||||||
|
|
||||||
|
checkNotNull(keyCertChain, "keyCertChainFile");
|
||||||
|
checkNotNull(key, "keyFile");
|
||||||
|
|
||||||
|
if (keyPassword == null) {
|
||||||
|
keyPassword = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new SSL_CTX and configure it.
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
synchronized (OpenSslContext.class) {
|
||||||
|
/* Set certificate verification policy. */
|
||||||
|
SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, VERIFY_DEPTH);
|
||||||
|
long keyCertChainBio = 0;
|
||||||
|
try {
|
||||||
|
keyCertChainBio = toBIO(keyCertChain);
|
||||||
|
/* Load the certificate chain. We must skip the first cert when server mode */
|
||||||
|
if (!SSLContext.setCertificateChainBio(ctx, keyCertChainBio, true)) {
|
||||||
|
long error = SSL.getLastErrorNumber();
|
||||||
|
if (OpenSsl.isError(error)) {
|
||||||
|
String err = SSL.getErrorString(error);
|
||||||
|
throw new SSLException(
|
||||||
|
"failed to set certificate chain: " + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException(
|
||||||
|
"failed to set certificate chain", e);
|
||||||
|
} finally {
|
||||||
|
if (keyCertChainBio != 0) {
|
||||||
|
SSL.freeBIO(keyCertChainBio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the certificate file and private key. */
|
||||||
|
long keyBio = 0;
|
||||||
|
keyCertChainBio = 0;
|
||||||
|
try {
|
||||||
|
keyBio = toBIO(key);
|
||||||
|
keyCertChainBio = toBIO(keyCertChain);
|
||||||
|
if (!SSLContext.setCertificateBio(
|
||||||
|
ctx, keyCertChainBio, keyBio, keyPassword, SSL.SSL_AIDX_RSA)) {
|
||||||
|
long error = SSL.getLastErrorNumber();
|
||||||
|
if (OpenSsl.isError(error)) {
|
||||||
|
String err = SSL.getErrorString(error);
|
||||||
|
throw new SSLException("failed to set certificate and key: " + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SSLException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException("failed to set certificate and key", e);
|
||||||
|
} finally {
|
||||||
|
if (keyBio != 0) {
|
||||||
|
SSL.freeBIO(keyBio);
|
||||||
|
}
|
||||||
|
if (keyCertChainBio != 0) {
|
||||||
|
SSL.freeBIO(keyCertChainBio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (trustManagerFactory == null) {
|
||||||
|
// Mimic the way SSLContext.getInstance(KeyManager[], null, null) works
|
||||||
|
trustManagerFactory = TrustManagerFactory.getInstance(
|
||||||
|
TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
}
|
||||||
|
if (trustCertChain != null) {
|
||||||
|
trustManagerFactory = buildTrustManagerFactory(trustCertChain, trustManagerFactory);
|
||||||
|
} else {
|
||||||
|
KeyStore ks = buildKeyStore(keyCertChain, key, keyPassword.toCharArray());
|
||||||
trustManagerFactory.init(ks);
|
trustManagerFactory.init(ks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +50,11 @@ import java.security.KeyStore;
|
|||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,8 +145,6 @@ public abstract class SslContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig} instead.
|
|
||||||
*
|
|
||||||
* Creates a new server-side {@link SslContext}.
|
* Creates a new server-side {@link SslContext}.
|
||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format
|
* @param certChainFile an X.509 certificate chain file in PEM format
|
||||||
@ -241,8 +237,6 @@ public abstract class SslContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig} instead.
|
|
||||||
*
|
|
||||||
* Creates a new server-side {@link SslContext}.
|
* Creates a new server-side {@link SslContext}.
|
||||||
*
|
*
|
||||||
* @param provider the {@link SslContext} implementation to use.
|
* @param provider the {@link SslContext} implementation to use.
|
||||||
@ -378,15 +372,24 @@ public abstract class SslContext {
|
|||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
return newServerContextInternal(provider, trustCertChainFile, trustManagerFactory, keyCertChainFile,
|
try {
|
||||||
keyFile, keyPassword, keyManagerFactory, ciphers, cipherFilter, apn,
|
return newServerContextInternal(provider, toX509Certificates(trustCertChainFile), trustManagerFactory,
|
||||||
sessionCacheSize, sessionTimeout);
|
toX509Certificates(keyCertChainFile),
|
||||||
|
toPrivateKey(keyFile, keyPassword),
|
||||||
|
keyPassword, keyManagerFactory, ciphers, cipherFilter, apn,
|
||||||
|
sessionCacheSize, sessionTimeout);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
throw (SSLException) e;
|
||||||
|
}
|
||||||
|
throw new SSLException("failed to initialize the server-side SSL context", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SslContext newServerContextInternal(
|
static SslContext newServerContextInternal(
|
||||||
SslProvider provider,
|
SslProvider provider,
|
||||||
File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
X509Certificate[] trustCertChain, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
|
|
||||||
@ -397,11 +400,11 @@ public abstract class SslContext {
|
|||||||
switch (provider) {
|
switch (provider) {
|
||||||
case JDK:
|
case JDK:
|
||||||
return new JdkSslServerContext(
|
return new JdkSslServerContext(
|
||||||
trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword,
|
trustCertChain, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||||
case OPENSSL:
|
case OPENSSL:
|
||||||
return new OpenSslServerContext(
|
return new OpenSslServerContext(
|
||||||
trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword,
|
trustCertChain, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||||
default:
|
default:
|
||||||
throw new Error(provider.toString());
|
throw new Error(provider.toString());
|
||||||
@ -466,8 +469,6 @@ public abstract class SslContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig} instead.
|
|
||||||
*
|
|
||||||
* Creates a new client-side {@link SslContext}.
|
* Creates a new client-side {@link SslContext}.
|
||||||
*
|
*
|
||||||
* @param certChainFile an X.509 certificate chain file in PEM format.
|
* @param certChainFile an X.509 certificate chain file in PEM format.
|
||||||
@ -597,8 +598,6 @@ public abstract class SslContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig}.
|
|
||||||
*
|
|
||||||
* Creates a new client-side {@link SslContext}.
|
* Creates a new client-side {@link SslContext}.
|
||||||
*
|
*
|
||||||
* @param provider the {@link SslContext} implementation to use.
|
* @param provider the {@link SslContext} implementation to use.
|
||||||
@ -709,16 +708,24 @@ public abstract class SslContext {
|
|||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
return newClientContextInternal(provider, trustCertChainFile, trustManagerFactory,
|
try {
|
||||||
keyCertChainFile, keyFile, keyPassword, keyManagerFactory, ciphers, cipherFilter,
|
return newClientContextInternal(provider, toX509Certificates(trustCertChainFile), trustManagerFactory,
|
||||||
apn,
|
toX509Certificates(keyCertChainFile), toPrivateKey(keyFile, keyPassword),
|
||||||
sessionCacheSize, sessionTimeout);
|
keyPassword, keyManagerFactory, ciphers, cipherFilter,
|
||||||
|
apn,
|
||||||
|
sessionCacheSize, sessionTimeout);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
throw (SSLException) e;
|
||||||
|
}
|
||||||
|
throw new SSLException("failed to initialize the client-side SSL context", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SslContext newClientContextInternal(
|
static SslContext newClientContextInternal(
|
||||||
SslProvider provider,
|
SslProvider provider,
|
||||||
File trustCertChainFile, TrustManagerFactory trustManagerFactory,
|
X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory,
|
||||||
File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory,
|
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
|
||||||
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
|
||||||
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
long sessionCacheSize, long sessionTimeout) throws SSLException {
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
@ -727,11 +734,11 @@ public abstract class SslContext {
|
|||||||
switch (provider) {
|
switch (provider) {
|
||||||
case JDK:
|
case JDK:
|
||||||
return new JdkSslClientContext(
|
return new JdkSslClientContext(
|
||||||
trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword,
|
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||||
case OPENSSL:
|
case OPENSSL:
|
||||||
return new OpenSslClientContext(
|
return new OpenSslClientContext(
|
||||||
trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword,
|
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
|
||||||
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||||
}
|
}
|
||||||
// Should never happen!!
|
// Should never happen!!
|
||||||
@ -877,21 +884,45 @@ public abstract class SslContext {
|
|||||||
/**
|
/**
|
||||||
* Generates a new {@link KeyStore}.
|
* Generates a new {@link KeyStore}.
|
||||||
*
|
*
|
||||||
* @param certChainFile a X.509 certificate chain file in PEM format,
|
* @param certChain a X.509 certificate chain
|
||||||
* @param keyFile a PKCS#8 private key file in PEM format,
|
* @param key a PKCS#8 private key
|
||||||
* @param keyPasswordChars the password of the {@code keyFile}.
|
* @param keyPasswordChars the password of the {@code keyFile}.
|
||||||
* {@code null} if it's not password-protected.
|
* {@code null} if it's not password-protected.
|
||||||
* @return generated {@link KeyStore}.
|
* @return generated {@link KeyStore}.
|
||||||
*/
|
*/
|
||||||
static KeyStore buildKeyStore(File certChainFile, File keyFile, char[] keyPasswordChars)
|
static KeyStore buildKeyStore(X509Certificate[] certChain, PrivateKey key, char[] keyPasswordChars)
|
||||||
throws KeyStoreException, NoSuchAlgorithmException,
|
throws KeyStoreException, NoSuchAlgorithmException,
|
||||||
NoSuchPaddingException, InvalidKeySpecException, InvalidAlgorithmParameterException,
|
CertificateException, IOException {
|
||||||
CertificateException, KeyException, IOException {
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
ks.load(null, null);
|
||||||
|
ks.setKeyEntry("key", key, keyPasswordChars, certChain);
|
||||||
|
return ks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static KeyStore buildKeyStore(File certChainFile, File keyFile, String keyPassword)
|
||||||
|
throws KeyStoreException, NoSuchAlgorithmException,
|
||||||
|
CertificateException, NoSuchPaddingException, InvalidKeySpecException,
|
||||||
|
InvalidAlgorithmParameterException, KeyException, IOException {
|
||||||
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
ks.load(null, null);
|
||||||
|
ks.setKeyEntry("key", toPrivateKey(keyFile, keyPassword),
|
||||||
|
keyPassword == null ? null : keyPassword.toCharArray(), toX509Certificates(certChainFile));
|
||||||
|
return ks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PrivateKey toPrivateKey(File keyFile, String keyPassword) throws NoSuchAlgorithmException,
|
||||||
|
NoSuchPaddingException, InvalidKeySpecException,
|
||||||
|
InvalidAlgorithmParameterException,
|
||||||
|
KeyException, IOException {
|
||||||
|
if (keyFile == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
ByteBuf encodedKeyBuf = PemReader.readPrivateKey(keyFile);
|
ByteBuf encodedKeyBuf = PemReader.readPrivateKey(keyFile);
|
||||||
byte[] encodedKey = new byte[encodedKeyBuf.readableBytes()];
|
byte[] encodedKey = new byte[encodedKeyBuf.readableBytes()];
|
||||||
encodedKeyBuf.readBytes(encodedKey).release();
|
encodedKeyBuf.readBytes(encodedKey).release();
|
||||||
|
|
||||||
PKCS8EncodedKeySpec encodedKeySpec = generateKeySpec(keyPasswordChars, encodedKey);
|
PKCS8EncodedKeySpec encodedKeySpec = generateKeySpec(keyPassword == null ? null : keyPassword.toCharArray(),
|
||||||
|
encodedKey);
|
||||||
|
|
||||||
PrivateKey key;
|
PrivateKey key;
|
||||||
try {
|
try {
|
||||||
@ -907,25 +938,7 @@ public abstract class SslContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return key;
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
ByteBuf[] certs = PemReader.readCertificates(certChainFile);
|
|
||||||
List<Certificate> certChain = new ArrayList<Certificate>(certs.length);
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (ByteBuf buf: certs) {
|
|
||||||
certChain.add(cf.generateCertificate(new ByteBufInputStream(buf)));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
for (ByteBuf buf: certs) {
|
|
||||||
buf.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyStore ks = KeyStore.getInstance("JKS");
|
|
||||||
ks.load(null, null);
|
|
||||||
ks.setKeyEntry("key", key, keyPasswordChars, certChain.toArray(new Certificate[certChain.size()]));
|
|
||||||
return ks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -934,25 +947,45 @@ public abstract class SslContext {
|
|||||||
* @param trustManagerFactory The existing {@link TrustManagerFactory} that will be used if not {@code null}.
|
* @param trustManagerFactory The existing {@link TrustManagerFactory} that will be used if not {@code null}.
|
||||||
* @return A {@link TrustManagerFactory} which contains the certificates in {@code certChainFile}
|
* @return A {@link TrustManagerFactory} which contains the certificates in {@code certChainFile}
|
||||||
*/
|
*/
|
||||||
protected static TrustManagerFactory buildTrustManagerFactory(File certChainFile,
|
@Deprecated
|
||||||
TrustManagerFactory trustManagerFactory)
|
protected static TrustManagerFactory buildTrustManagerFactory(
|
||||||
|
File certChainFile, TrustManagerFactory trustManagerFactory)
|
||||||
throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException {
|
throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException {
|
||||||
KeyStore ks = KeyStore.getInstance("JKS");
|
X509Certificate[] x509Certs = toX509Certificates(certChainFile);
|
||||||
ks.load(null, null);
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
return buildTrustManagerFactory(x509Certs, trustManagerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
static X509Certificate[] toX509Certificates(File file) throws CertificateException {
|
||||||
|
if (file == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
|
ByteBuf[] certs = PemReader.readCertificates(file);
|
||||||
|
X509Certificate[] x509Certs = new X509Certificate[certs.length];
|
||||||
|
|
||||||
ByteBuf[] certs = PemReader.readCertificates(certChainFile);
|
|
||||||
try {
|
try {
|
||||||
for (ByteBuf buf: certs) {
|
for (int i = 0; i < certs.length; i++) {
|
||||||
X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteBufInputStream(buf));
|
x509Certs[i] = (X509Certificate) cf.generateCertificate(new ByteBufInputStream(certs[i]));
|
||||||
X500Principal principal = cert.getSubjectX500Principal();
|
|
||||||
ks.setCertificateEntry(principal.getName("RFC2253"), cert);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
for (ByteBuf buf: certs) {
|
for (ByteBuf buf: certs) {
|
||||||
buf.release();
|
buf.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return x509Certs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TrustManagerFactory buildTrustManagerFactory(
|
||||||
|
X509Certificate[] certChain, TrustManagerFactory trustManagerFactory)
|
||||||
|
throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException {
|
||||||
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
|
ks.load(null, null);
|
||||||
|
|
||||||
|
for (X509Certificate cert: certChain) {
|
||||||
|
X500Principal principal = cert.getSubjectX500Principal();
|
||||||
|
ks.setCertificateEntry(principal.getName("RFC2253"), cert);
|
||||||
|
}
|
||||||
|
|
||||||
// Set up trust manager factory to use our key store.
|
// Set up trust manager factory to use our key store.
|
||||||
if (trustManagerFactory == null) {
|
if (trustManagerFactory == null) {
|
||||||
|
@ -22,11 +22,14 @@ import javax.net.ssl.KeyManagerFactory;
|
|||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for configuring a new SslContext for creation.
|
* Builder for configuring a new SslContext for creation.
|
||||||
*/
|
*/
|
||||||
public final class SslContextBuilder {
|
public final class SslContextBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a builder for new client-side {@link SslContext}.
|
* Creates a builder for new client-side {@link SslContext}.
|
||||||
*/
|
*/
|
||||||
@ -45,6 +48,17 @@ public final class SslContextBuilder {
|
|||||||
return new SslContextBuilder(true).keyManager(keyCertChainFile, keyFile);
|
return new SslContextBuilder(true).keyManager(keyCertChainFile, keyFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a builder for new server-side {@link SslContext}.
|
||||||
|
*
|
||||||
|
* @param key a PKCS#8 private key
|
||||||
|
* @param keyCertChain the X.509 certificate chain
|
||||||
|
* @see #keyManager(PrivateKey, X509Certificate[])
|
||||||
|
*/
|
||||||
|
public static SslContextBuilder forServer(PrivateKey key, X509Certificate... keyCertChain) {
|
||||||
|
return new SslContextBuilder(true).keyManager(key, keyCertChain);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a builder for new server-side {@link SslContext}.
|
* Creates a builder for new server-side {@link SslContext}.
|
||||||
*
|
*
|
||||||
@ -59,6 +73,20 @@ public final class SslContextBuilder {
|
|||||||
return new SslContextBuilder(true).keyManager(keyCertChainFile, keyFile, keyPassword);
|
return new SslContextBuilder(true).keyManager(keyCertChainFile, keyFile, keyPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a builder for new server-side {@link SslContext}.
|
||||||
|
*
|
||||||
|
* @param key a PKCS#8 private key
|
||||||
|
* @param keyCertChain the X.509 certificate chain
|
||||||
|
* @param keyPassword the password of the {@code keyFile}, or {@code null} if it's not
|
||||||
|
* password-protected
|
||||||
|
* @see #keyManager(File, File, String)
|
||||||
|
*/
|
||||||
|
public static SslContextBuilder forServer(
|
||||||
|
PrivateKey key, String keyPassword, X509Certificate... keyCertChain) {
|
||||||
|
return new SslContextBuilder(true).keyManager(key, keyPassword, keyCertChain);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a builder for new server-side {@link SslContext}.
|
* Creates a builder for new server-side {@link SslContext}.
|
||||||
*
|
*
|
||||||
@ -71,10 +99,10 @@ public final class SslContextBuilder {
|
|||||||
|
|
||||||
private final boolean forServer;
|
private final boolean forServer;
|
||||||
private SslProvider provider;
|
private SslProvider provider;
|
||||||
private File trustCertChainFile;
|
private X509Certificate[] trustCertChain;
|
||||||
private TrustManagerFactory trustManagerFactory;
|
private TrustManagerFactory trustManagerFactory;
|
||||||
private File keyCertChainFile;
|
private X509Certificate[] keyCertChain;
|
||||||
private File keyFile;
|
private PrivateKey key;
|
||||||
private String keyPassword;
|
private String keyPassword;
|
||||||
private KeyManagerFactory keyManagerFactory;
|
private KeyManagerFactory keyManagerFactory;
|
||||||
private Iterable<String> ciphers;
|
private Iterable<String> ciphers;
|
||||||
@ -100,8 +128,19 @@ public final class SslContextBuilder {
|
|||||||
* contain an X.509 certificate chain in PEM format. {@code null} uses the system default.
|
* contain an X.509 certificate chain in PEM format. {@code null} uses the system default.
|
||||||
*/
|
*/
|
||||||
public SslContextBuilder trustManager(File trustCertChainFile) {
|
public SslContextBuilder trustManager(File trustCertChainFile) {
|
||||||
this.trustCertChainFile = trustCertChainFile;
|
try {
|
||||||
this.trustManagerFactory = null;
|
return trustManager(SslContext.toX509Certificates(trustCertChainFile));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("File does not contain valid certificates: " + trustCertChainFile, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trusted certificates for verifying the remote endpoint's certificate, {@code null} uses the system default.
|
||||||
|
*/
|
||||||
|
public SslContextBuilder trustManager(X509Certificate... trustCertChain) {
|
||||||
|
this.trustCertChain = trustCertChain != null ? trustCertChain.clone() : null;
|
||||||
|
trustManagerFactory = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +150,7 @@ public final class SslContextBuilder {
|
|||||||
* you must use {@link #trustManager(File)}. {@code null} uses the system default.
|
* you must use {@link #trustManager(File)}. {@code null} uses the system default.
|
||||||
*/
|
*/
|
||||||
public SslContextBuilder trustManager(TrustManagerFactory trustManagerFactory) {
|
public SslContextBuilder trustManager(TrustManagerFactory trustManagerFactory) {
|
||||||
this.trustCertChainFile = null;
|
trustCertChain = null;
|
||||||
this.trustManagerFactory = trustManagerFactory;
|
this.trustManagerFactory = trustManagerFactory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -127,6 +166,17 @@ public final class SslContextBuilder {
|
|||||||
return keyManager(keyCertChainFile, keyFile, null);
|
return keyManager(keyCertChainFile, keyFile, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifying certificate for this host. {@code keyCertChain} and {@code key} may
|
||||||
|
* be {@code null} for client contexts, which disables mutual authentication.
|
||||||
|
*
|
||||||
|
* @param key a PKCS#8 private key
|
||||||
|
* @param keyCertChain an X.509 certificate chain
|
||||||
|
*/
|
||||||
|
public SslContextBuilder keyManager(PrivateKey key, X509Certificate... keyCertChain) {
|
||||||
|
return keyManager(key, null, keyCertChain);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifying certificate for this host. {@code keyCertChainFile} and {@code keyFile} may
|
* Identifying certificate for this host. {@code keyCertChainFile} and {@code keyFile} may
|
||||||
* be {@code null} for client contexts, which disables mutual authentication.
|
* be {@code null} for client contexts, which disables mutual authentication.
|
||||||
@ -137,14 +187,51 @@ public final class SslContextBuilder {
|
|||||||
* password-protected
|
* password-protected
|
||||||
*/
|
*/
|
||||||
public SslContextBuilder keyManager(File keyCertChainFile, File keyFile, String keyPassword) {
|
public SslContextBuilder keyManager(File keyCertChainFile, File keyFile, String keyPassword) {
|
||||||
if (forServer) {
|
X509Certificate[] keyCertChain;
|
||||||
checkNotNull(keyCertChainFile, "keyCertChainFile required for servers");
|
PrivateKey key;
|
||||||
checkNotNull(keyFile, "keyFile required for servers");
|
try {
|
||||||
|
keyCertChain = SslContext.toX509Certificates(keyCertChainFile);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("File does not contain valid certificates: " + keyCertChainFile, e);
|
||||||
}
|
}
|
||||||
this.keyCertChainFile = keyCertChainFile;
|
try {
|
||||||
this.keyFile = keyFile;
|
key = SslContext.toPrivateKey(keyFile, keyPassword);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("File does not contain valid private key: " + keyFile, e);
|
||||||
|
}
|
||||||
|
return keyManager(key, keyPassword, keyCertChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifying certificate for this host. {@code keyCertChain} and {@code key} may
|
||||||
|
* be {@code null} for client contexts, which disables mutual authentication.
|
||||||
|
*
|
||||||
|
* @param key a PKCS#8 private key file
|
||||||
|
* @param keyPassword the password of the {@code key}, or {@code null} if it's not
|
||||||
|
* password-protected
|
||||||
|
* @param keyCertChain an X.509 certificate chain
|
||||||
|
*/
|
||||||
|
public SslContextBuilder keyManager(PrivateKey key, String keyPassword, X509Certificate... keyCertChain) {
|
||||||
|
if (forServer) {
|
||||||
|
checkNotNull(keyCertChain, "keyCertChain required for servers");
|
||||||
|
if (keyCertChain.length == 0) {
|
||||||
|
throw new IllegalArgumentException("keyCertChain must be non-empty");
|
||||||
|
}
|
||||||
|
checkNotNull(key, "key required for servers");
|
||||||
|
}
|
||||||
|
if (keyCertChain == null || keyCertChain.length == 0) {
|
||||||
|
this.keyCertChain = null;
|
||||||
|
} else {
|
||||||
|
for (X509Certificate cert: keyCertChain) {
|
||||||
|
if (cert == null) {
|
||||||
|
throw new IllegalArgumentException("keyCertChain contains null entry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.keyCertChain = keyCertChain.clone();
|
||||||
|
}
|
||||||
|
this.key = key;
|
||||||
this.keyPassword = keyPassword;
|
this.keyPassword = keyPassword;
|
||||||
this.keyManagerFactory = null;
|
keyManagerFactory = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,9 +245,9 @@ public final class SslContextBuilder {
|
|||||||
if (forServer) {
|
if (forServer) {
|
||||||
checkNotNull(keyManagerFactory, "keyManagerFactory required for servers");
|
checkNotNull(keyManagerFactory, "keyManagerFactory required for servers");
|
||||||
}
|
}
|
||||||
this.keyCertChainFile = null;
|
keyCertChain = null;
|
||||||
this.keyFile = null;
|
key = null;
|
||||||
this.keyPassword = null;
|
keyPassword = null;
|
||||||
this.keyManagerFactory = keyManagerFactory;
|
this.keyManagerFactory = keyManagerFactory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -216,12 +303,12 @@ public final class SslContextBuilder {
|
|||||||
*/
|
*/
|
||||||
public SslContext build() throws SSLException {
|
public SslContext build() throws SSLException {
|
||||||
if (forServer) {
|
if (forServer) {
|
||||||
return SslContext.newServerContextInternal(provider, trustCertChainFile,
|
return SslContext.newServerContextInternal(provider, trustCertChain,
|
||||||
trustManagerFactory, keyCertChainFile, keyFile, keyPassword, keyManagerFactory,
|
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||||
} else {
|
} else {
|
||||||
return SslContext.newClientContextInternal(provider, trustCertChainFile,
|
return SslContext.newClientContextInternal(provider, trustCertChain,
|
||||||
trustManagerFactory, keyCertChainFile, keyFile, keyPassword, keyManagerFactory,
|
trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory,
|
||||||
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import io.netty.util.internal.logging.InternalLogger;
|
|||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -33,6 +34,7 @@ import java.security.PrivateKey;
|
|||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -63,6 +65,8 @@ public final class SelfSignedCertificate {
|
|||||||
|
|
||||||
private final File certificate;
|
private final File certificate;
|
||||||
private final File privateKey;
|
private final File privateKey;
|
||||||
|
private final X509Certificate cert;
|
||||||
|
private final PrivateKey key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
@ -120,6 +124,13 @@ public final class SelfSignedCertificate {
|
|||||||
|
|
||||||
certificate = new File(paths[0]);
|
certificate = new File(paths[0]);
|
||||||
privateKey = new File(paths[1]);
|
privateKey = new File(paths[1]);
|
||||||
|
key = keypair.getPrivate();
|
||||||
|
try {
|
||||||
|
cert = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(
|
||||||
|
new FileInputStream(certificate));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CertificateEncodingException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,6 +147,20 @@ public final class SelfSignedCertificate {
|
|||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the generated X.509 certificate.
|
||||||
|
*/
|
||||||
|
public X509Certificate cert() {
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the generated RSA private key.
|
||||||
|
*/
|
||||||
|
public PrivateKey key() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the generated X.509 certificate file and RSA private key file.
|
* Deletes the generated X.509 certificate file and RSA private key file.
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 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 io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
|
public class SslContextBuilderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientContextFromFileJdk() throws Exception {
|
||||||
|
testClientContextFromFile(SslProvider.JDK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientContextFromFileOpenssl() throws Exception {
|
||||||
|
Assume.assumeTrue(OpenSsl.isAvailable());
|
||||||
|
testClientContextFromFile(SslProvider.OPENSSL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientContextJdk() throws Exception {
|
||||||
|
testClientContext(SslProvider.JDK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientContextOpenssl() throws Exception {
|
||||||
|
Assume.assumeTrue(OpenSsl.isAvailable());
|
||||||
|
testClientContext(SslProvider.OPENSSL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerContextFromFileJdk() throws Exception {
|
||||||
|
testServerContextFromFile(SslProvider.JDK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerContextFromFileOpenssl() throws Exception {
|
||||||
|
Assume.assumeTrue(OpenSsl.isAvailable());
|
||||||
|
testServerContextFromFile(SslProvider.OPENSSL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerContextJdk() throws Exception {
|
||||||
|
testServerContext(SslProvider.JDK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerContextOpenssl() throws Exception {
|
||||||
|
Assume.assumeTrue(OpenSsl.isAvailable());
|
||||||
|
testServerContext(SslProvider.OPENSSL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testClientContextFromFile(SslProvider provider) throws Exception {
|
||||||
|
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||||
|
SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(provider).keyManager(
|
||||||
|
cert.certificate(), cert.privateKey()).trustManager(cert.certificate());
|
||||||
|
SslContext context = builder.build();
|
||||||
|
SSLEngine engine = context.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||||
|
engine.closeInbound();
|
||||||
|
engine.closeOutbound();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testClientContext(SslProvider provider) throws Exception {
|
||||||
|
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||||
|
SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(provider).keyManager(
|
||||||
|
cert.key(), cert.cert()).trustManager(cert.cert());
|
||||||
|
SslContext context = builder.build();
|
||||||
|
SSLEngine engine = context.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||||
|
engine.closeInbound();
|
||||||
|
engine.closeOutbound();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testServerContextFromFile(SslProvider provider) throws Exception {
|
||||||
|
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||||
|
SslContextBuilder builder = SslContextBuilder.forServer(cert.certificate(), cert.privateKey())
|
||||||
|
.sslProvider(provider).trustManager(cert.certificate());
|
||||||
|
SslContext context = builder.build();
|
||||||
|
SSLEngine engine = context.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||||
|
engine.closeInbound();
|
||||||
|
engine.closeOutbound();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testServerContext(SslProvider provider) throws Exception {
|
||||||
|
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||||
|
SslContextBuilder builder = SslContextBuilder.forServer(cert.key(), cert.cert())
|
||||||
|
.sslProvider(provider).trustManager(cert.cert());
|
||||||
|
SslContext context = builder.build();
|
||||||
|
SSLEngine engine = context.newEngine(UnpooledByteBufAllocator.DEFAULT);
|
||||||
|
engine.closeInbound();
|
||||||
|
engine.closeOutbound();
|
||||||
|
}
|
||||||
|
}
|
2
pom.xml
2
pom.xml
@ -686,7 +686,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>netty-tcnative</artifactId>
|
<artifactId>netty-tcnative</artifactId>
|
||||||
<version>1.1.33.Fork3</version>
|
<version>1.1.33.Fork5</version>
|
||||||
<classifier>${os.detected.classifier}</classifier>
|
<classifier>${os.detected.classifier}</classifier>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
|
@ -26,15 +26,13 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.handler.ssl.JdkSslClientContext;
|
|
||||||
import io.netty.handler.ssl.JdkSslServerContext;
|
|
||||||
import io.netty.handler.ssl.OpenSsl;
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
import io.netty.handler.ssl.OpenSslClientContext;
|
|
||||||
import io.netty.handler.ssl.OpenSslContext;
|
import io.netty.handler.ssl.OpenSslContext;
|
||||||
import io.netty.handler.ssl.OpenSslServerContext;
|
|
||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
||||||
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||||
import io.netty.testsuite.util.TestUtils;
|
import io.netty.testsuite.util.TestUtils;
|
||||||
@ -125,15 +123,17 @@ public class SocketSslEchoTest extends AbstractSocketTest {
|
|||||||
"autoRead = {5}, useChunkedWriteHandler = {6}, useCompositeByteBuf = {7}")
|
"autoRead = {5}, useChunkedWriteHandler = {6}, useCompositeByteBuf = {7}")
|
||||||
public static Collection<Object[]> data() throws Exception {
|
public static Collection<Object[]> data() throws Exception {
|
||||||
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
||||||
serverContexts.add(new JdkSslServerContext(CERT_FILE, KEY_FILE));
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE).sslProvider(SslProvider.JDK).build());
|
||||||
|
|
||||||
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
||||||
clientContexts.add(new JdkSslClientContext(CERT_FILE));
|
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.JDK).trustManager(CERT_FILE).build());
|
||||||
|
|
||||||
boolean hasOpenSsl = OpenSsl.isAvailable();
|
boolean hasOpenSsl = OpenSsl.isAvailable();
|
||||||
if (hasOpenSsl) {
|
if (hasOpenSsl) {
|
||||||
serverContexts.add(new OpenSslServerContext(CERT_FILE, KEY_FILE));
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE)
|
||||||
clientContexts.add(new OpenSslClientContext(CERT_FILE));
|
.sslProvider(SslProvider.OPENSSL).build());
|
||||||
|
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.OPENSSL)
|
||||||
|
.trustManager(CERT_FILE).build());
|
||||||
} else {
|
} else {
|
||||||
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,10 @@ import io.netty.channel.ChannelPipeline;
|
|||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.handler.logging.LogLevel;
|
import io.netty.handler.logging.LogLevel;
|
||||||
import io.netty.handler.logging.LoggingHandler;
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
import io.netty.handler.ssl.JdkSslClientContext;
|
|
||||||
import io.netty.handler.ssl.JdkSslServerContext;
|
|
||||||
import io.netty.handler.ssl.OpenSsl;
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
import io.netty.handler.ssl.OpenSslClientContext;
|
|
||||||
import io.netty.handler.ssl.OpenSslServerContext;
|
|
||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||||
import io.netty.util.ReferenceCountUtil;
|
import io.netty.util.ReferenceCountUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
@ -76,15 +74,17 @@ public class SocketSslGreetingTest extends AbstractSocketTest {
|
|||||||
@Parameters(name = "{index}: serverEngine = {0}, clientEngine = {1}")
|
@Parameters(name = "{index}: serverEngine = {0}, clientEngine = {1}")
|
||||||
public static Collection<Object[]> data() throws Exception {
|
public static Collection<Object[]> data() throws Exception {
|
||||||
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
||||||
serverContexts.add(new JdkSslServerContext(CERT_FILE, KEY_FILE));
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE).sslProvider(SslProvider.JDK).build());
|
||||||
|
|
||||||
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
||||||
clientContexts.add(new JdkSslClientContext(CERT_FILE));
|
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.JDK).trustManager(CERT_FILE).build());
|
||||||
|
|
||||||
boolean hasOpenSsl = OpenSsl.isAvailable();
|
boolean hasOpenSsl = OpenSsl.isAvailable();
|
||||||
if (hasOpenSsl) {
|
if (hasOpenSsl) {
|
||||||
serverContexts.add(new OpenSslServerContext(CERT_FILE, KEY_FILE));
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE)
|
||||||
clientContexts.add(new OpenSslClientContext(CERT_FILE));
|
.sslProvider(SslProvider.OPENSSL).build());
|
||||||
|
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.OPENSSL)
|
||||||
|
.trustManager(CERT_FILE).build());
|
||||||
} else {
|
} else {
|
||||||
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,11 @@ import io.netty.handler.codec.string.StringDecoder;
|
|||||||
import io.netty.handler.codec.string.StringEncoder;
|
import io.netty.handler.codec.string.StringEncoder;
|
||||||
import io.netty.handler.logging.LogLevel;
|
import io.netty.handler.logging.LogLevel;
|
||||||
import io.netty.handler.logging.LoggingHandler;
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
import io.netty.handler.ssl.JdkSslClientContext;
|
|
||||||
import io.netty.handler.ssl.JdkSslServerContext;
|
|
||||||
import io.netty.handler.ssl.OpenSsl;
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
import io.netty.handler.ssl.OpenSslClientContext;
|
|
||||||
import io.netty.handler.ssl.OpenSslServerContext;
|
|
||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||||
import io.netty.util.concurrent.DefaultEventExecutorGroup;
|
import io.netty.util.concurrent.DefaultEventExecutorGroup;
|
||||||
import io.netty.util.concurrent.EventExecutorGroup;
|
import io.netty.util.concurrent.EventExecutorGroup;
|
||||||
@ -84,15 +82,17 @@ public class SocketStartTlsTest extends AbstractSocketTest {
|
|||||||
@Parameters(name = "{index}: serverEngine = {0}, clientEngine = {1}")
|
@Parameters(name = "{index}: serverEngine = {0}, clientEngine = {1}")
|
||||||
public static Collection<Object[]> data() throws Exception {
|
public static Collection<Object[]> data() throws Exception {
|
||||||
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
||||||
serverContexts.add(new JdkSslServerContext(CERT_FILE, KEY_FILE));
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE).sslProvider(SslProvider.JDK).build());
|
||||||
|
|
||||||
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
||||||
clientContexts.add(new JdkSslClientContext(CERT_FILE));
|
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.JDK).trustManager(CERT_FILE).build());
|
||||||
|
|
||||||
boolean hasOpenSsl = OpenSsl.isAvailable();
|
boolean hasOpenSsl = OpenSsl.isAvailable();
|
||||||
if (hasOpenSsl) {
|
if (hasOpenSsl) {
|
||||||
serverContexts.add(new OpenSslServerContext(CERT_FILE, KEY_FILE));
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE)
|
||||||
clientContexts.add(new OpenSslClientContext(CERT_FILE));
|
.sslProvider(SslProvider.OPENSSL).build());
|
||||||
|
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.OPENSSL)
|
||||||
|
.trustManager(CERT_FILE).build());
|
||||||
} else {
|
} else {
|
||||||
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user