OpenSslEngine should respect hostname verification

Motivation:
OpenSSL doesn't automatically verify hostnames and requires extract method calls to enable this feature [1]. We should allow this to be configured.

Modifications:
- SSLParamaters#getEndpointIdentificationAlgorithm() should be respected and configured via tcnative interfaces.

Result:
OpenSslEngine respects hostname verification.

[1] https://wiki.openssl.org/index.php/Hostname_validation
This commit is contained in:
Scott Mitchell 2017-02-16 20:25:25 -08:00
parent 67be7c5b9f
commit d8e6fbb9c3
16 changed files with 337 additions and 21 deletions

View File

@ -19,6 +19,7 @@ import javax.net.ssl.SNIHostName;
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLParameters;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
final class Java8SslParametersUtils {
@ -27,6 +28,9 @@ final class Java8SslParametersUtils {
static List<String> getSniHostNames(SSLParameters sslParameters) {
List<SNIServerName> names = sslParameters.getServerNames();
if (names == null || names.isEmpty()) {
return Collections.emptyList();
}
List<String> strings = new ArrayList<String>(names.size());
for (SNIServerName serverName : names) {

View File

@ -51,6 +51,7 @@ public final class OpenSsl {
private static final Set<String> AVAILABLE_OPENSSL_CIPHER_SUITES;
private static final Set<String> AVAILABLE_JAVA_CIPHER_SUITES;
private static final boolean SUPPORTS_KEYMANAGER_FACTORY;
private static final boolean SUPPORTS_HOSTNAME_VALIDATION;
private static final boolean USE_KEYMANAGER_FACTORY;
// Protocols
@ -114,6 +115,7 @@ public final class OpenSsl {
final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128);
boolean supportsKeyManagerFactory = false;
boolean useKeyManagerFactory = false;
boolean supportsHostNameValidation = false;
try {
final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
long privateKeyBio = 0;
@ -129,6 +131,12 @@ public final class OpenSsl {
}
availableOpenSslCipherSuites.add(c);
}
try {
SSL.setHostNameValidation(ssl, 0, "netty.io");
supportsHostNameValidation = true;
} catch (Throwable ignore) {
logger.debug("Hostname Verification not supported.");
}
try {
SelfSignedCertificate cert = new SelfSignedCertificate();
certBio = ReferenceCountedOpenSslContext.toBIO(cert.cert());
@ -180,6 +188,7 @@ public final class OpenSsl {
}
AVAILABLE_CIPHER_SUITES = availableCipherSuites;
SUPPORTS_KEYMANAGER_FACTORY = supportsKeyManagerFactory;
SUPPORTS_HOSTNAME_VALIDATION = supportsHostNameValidation;
USE_KEYMANAGER_FACTORY = useKeyManagerFactory;
Set<String> protocols = new LinkedHashSet<String>(6);
@ -207,6 +216,7 @@ public final class OpenSsl {
AVAILABLE_JAVA_CIPHER_SUITES = Collections.emptySet();
AVAILABLE_CIPHER_SUITES = Collections.emptySet();
SUPPORTS_KEYMANAGER_FACTORY = false;
SUPPORTS_HOSTNAME_VALIDATION = false;
USE_KEYMANAGER_FACTORY = false;
SUPPORTED_PROTOCOLS_SET = Collections.emptySet();
}
@ -331,6 +341,14 @@ public final class OpenSsl {
return SUPPORTS_KEYMANAGER_FACTORY;
}
/**
* Returns {@code true} if <a href="https://wiki.openssl.org/index.php/Hostname_validation">Hostname Validation</a>
* is supported when using OpenSSL.
*/
public static boolean supportsHostnameValidation() {
return SUPPORTS_HOSTNAME_VALIDATION;
}
static boolean useKeyManagerFactory() {
return USE_KEYMANAGER_FACTORY;
}

View File

@ -87,10 +87,12 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "handshake()");
private static final SSLException RENEGOTIATION_UNSUPPORTED = ThrowableUtil.unknownStackTrace(
new SSLException("renegotiation unsupported"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
private static final SSLException ENCRYPTED_PACKET_OVERSIZED = ThrowableUtil.unknownStackTrace(
new SSLException("encrypted packet oversized"), ReferenceCountedOpenSslEngine.class, "unwrap(...)");
private static final ResourceLeakDetector<ReferenceCountedOpenSslEngine> leakDetector =
ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class);
/**
* <a href="https://www.openssl.org/docs/man1.0.2/crypto/X509_check_host.html">The flags argument is usually 0</a>.
*/
private static final int DEFAULT_HOSTNAME_VALIDATION_FLAGS = 0;
static final int MAX_PLAINTEXT_LENGTH = 16 * 1024; // 2^14
@ -1557,14 +1559,26 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
int version = PlatformDependent.javaVersion();
if (version >= 7) {
endPointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
final String endPointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
final boolean endPointVerificationEnabled = endPointIdentificationAlgorithm != null &&
!endPointIdentificationAlgorithm.isEmpty();
SSL.setHostNameValidation(ssl, DEFAULT_HOSTNAME_VALIDATION_FLAGS,
endPointVerificationEnabled ? getPeerHost() : null);
// If the user asks for hostname verification we must ensure we verify the peer.
// If the user disables hostname verification we leave it up to the user to change the mode manually.
if (clientMode && endPointVerificationEnabled) {
SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
}
this.endPointIdentificationAlgorithm = endPointIdentificationAlgorithm;
algorithmConstraints = sslParameters.getAlgorithmConstraints();
if (version >= 8 && !isDestroyed()) {
if (clientMode) {
sniHostNames = Java8SslParametersUtils.getSniHostNames(sslParameters);
final List<String> sniHostNames = Java8SslParametersUtils.getSniHostNames(sslParameters);
for (String name: sniHostNames) {
SSL.setTlsExtHostName(ssl, name);
}
this.sniHostNames = sniHostNames;
}
if (Java8SslParametersUtils.getUseCipherSuitesOrder(sslParameters)) {
SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);

View File

@ -89,6 +89,20 @@ public class OpenSslEngineTest extends SSLEngineTest {
super.testMutualAuthValidClientCertChainTooLongFailRequireClientAuth();
}
@Override
@Test
public void testClientHostnameValidationSuccess() throws InterruptedException, SSLException {
assumeTrue(OpenSsl.supportsHostnameValidation());
super.testClientHostnameValidationSuccess();
}
@Override
@Test
public void testClientHostnameValidationFail() throws InterruptedException, SSLException {
assumeTrue(OpenSsl.supportsHostnameValidation());
super.testClientHostnameValidationFail();
}
@Test
public void testNpn() throws Exception {
ApplicationProtocolConfig apn = acceptingNegotiator(Protocol.NPN,

View File

@ -19,6 +19,8 @@ import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import javax.net.ssl.SSLException;
import static org.junit.Assume.assumeTrue;
public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
@ -72,4 +74,24 @@ public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
assumeTrue(OpenSsl.supportsKeyManagerFactory());
super.testMutualAuthInvalidIntermediateCAFailWithRequiredClientAuth();
}
@Override
@Test
public void testClientHostnameValidationSuccess() throws InterruptedException, SSLException {
assumeTrue(OpenSsl.supportsHostnameValidation());
super.testClientHostnameValidationSuccess();
}
@Override
@Test
public void testClientHostnameValidationFail() throws InterruptedException, SSLException {
assumeTrue(OpenSsl.supportsHostnameValidation());
super.testClientHostnameValidationFail();
}
@Override
protected boolean mySetupMutualAuthServerIsValidServerException(Throwable cause) {
// TODO(scott): work around for a JDK issue. The exception should be SSLHandshakeException.
return super.mySetupMutualAuthServerIsValidServerException(cause) || cause instanceof SSLException;
}
}

View File

@ -63,15 +63,18 @@ import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
import javax.security.cert.X509Certificate;
@ -720,6 +723,145 @@ public abstract class SSLEngineTest {
clientChannel = ccf.channel();
}
@Test
public void testClientHostnameValidationSuccess() throws InterruptedException, SSLException {
mySetupClientHostnameValidation(new File(getClass().getResource("localhost_server.pem").getFile()),
new File(getClass().getResource("localhost_server.key").getFile()),
new File(getClass().getResource("mutual_auth_ca.pem").getFile()),
false);
assertTrue(clientLatch.await(5, TimeUnit.SECONDS));
assertNull(clientException);
assertTrue(serverLatch.await(5, TimeUnit.SECONDS));
assertNull(serverException);
}
@Test
public void testClientHostnameValidationFail() throws InterruptedException, SSLException {
mySetupClientHostnameValidation(new File(getClass().getResource("notlocalhost_server.pem").getFile()),
new File(getClass().getResource("notlocalhost_server.key").getFile()),
new File(getClass().getResource("mutual_auth_ca.pem").getFile()),
true);
assertTrue(clientLatch.await(5, TimeUnit.SECONDS));
assertTrue("unexpected exception: " + clientException,
mySetupMutualAuthServerIsValidClientException(clientException));
assertTrue(serverLatch.await(5, TimeUnit.SECONDS));
assertTrue("unexpected exception: " + serverException,
mySetupMutualAuthServerIsValidServerException(serverException));
}
private void mySetupClientHostnameValidation(File serverCrtFile, File serverKeyFile,
File clientTrustCrtFile,
final boolean failureExpected)
throws SSLException, InterruptedException {
final String expectedHost = "localhost";
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, null)
.sslProvider(sslServerProvider())
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build();
clientSslCtx = SslContextBuilder.forClient()
.sslProvider(sslClientProvider())
.trustManager(clientTrustCrtFile)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build();
serverConnectedChannel = null;
sb = new ServerBootstrap();
cb = new Bootstrap();
sb.group(new NioEventLoopGroup(), new NioEventLoopGroup());
sb.channel(NioServerSocketChannel.class);
sb.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.config().setAllocator(new TestByteBufAllocator(ch.config().getAllocator(), type));
ChannelPipeline p = ch.pipeline();
p.addLast(serverSslCtx.newHandler(ch.alloc()));
p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch));
p.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt == SslHandshakeCompletionEvent.SUCCESS) {
if (failureExpected) {
serverException = new IllegalStateException("handshake complete. expected failure");
}
serverLatch.countDown();
} else if (evt instanceof SslHandshakeCompletionEvent) {
serverException = ((SslHandshakeCompletionEvent) evt).cause();
serverLatch.countDown();
}
ctx.fireUserEventTriggered(evt);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause.getCause() instanceof SSLHandshakeException) {
serverException = cause.getCause();
serverLatch.countDown();
} else {
serverException = cause;
ctx.fireExceptionCaught(cause);
}
}
});
serverConnectedChannel = ch;
}
});
cb.group(new NioEventLoopGroup());
cb.channel(NioSocketChannel.class);
cb.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.config().setAllocator(new TestByteBufAllocator(ch.config().getAllocator(), type));
ChannelPipeline p = ch.pipeline();
InetSocketAddress remoteAddress = (InetSocketAddress) serverChannel.localAddress();
SslHandler sslHandler = clientSslCtx.newHandler(ch.alloc(), expectedHost, 0);
SSLParameters parameters = sslHandler.engine().getSSLParameters();
parameters.setEndpointIdentificationAlgorithm("HTTPS");
sslHandler.engine().setSSLParameters(parameters);
p.addLast(sslHandler);
p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch));
p.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt == SslHandshakeCompletionEvent.SUCCESS) {
if (failureExpected) {
clientException = new IllegalStateException("handshake complete. expected failure");
}
clientLatch.countDown();
} else if (evt instanceof SslHandshakeCompletionEvent) {
clientException = ((SslHandshakeCompletionEvent) evt).cause();
clientLatch.countDown();
}
ctx.fireUserEventTriggered(evt);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause.getCause() instanceof SSLHandshakeException) {
clientException = cause.getCause();
clientLatch.countDown();
} else {
ctx.fireExceptionCaught(cause);
}
}
});
}
});
serverChannel = sb.bind(new InetSocketAddress(expectedHost, 0)).sync().channel();
final int port = ((InetSocketAddress) serverChannel.localAddress()).getPort();
ChannelFuture ccf = cb.connect(new InetSocketAddress(expectedHost, port));
assertTrue(ccf.awaitUninterruptibly().isSuccess());
clientChannel = ccf.channel();
}
private void mySetupMutualAuth(File keyFile, File crtFile, String keyPassword)
throws SSLException, InterruptedException {
mySetupMutualAuth(crtFile, keyFile, crtFile, keyPassword, crtFile, keyFile, crtFile, keyPassword);

View File

@ -7,6 +7,18 @@ openssl req -extensions v3_ca -new -x509 -days 30 -nodes -subj "/CN=NettyTestRoo
openssl req -new -keyout mutual_auth_server.key -nodes -newkey rsa:2048 -subj "/CN=NettyTestServer" | \
openssl x509 -req -CAkey mutual_auth_ca.key -CA mutual_auth_ca.pem -days 36500 -set_serial $RANDOM -sha512 -out mutual_auth_server.pem
# Generate a certificate/key for the server to use for Hostname Verification via localhost
openssl req -new -keyout localhost_server_rsa.key -nodes -newkey rsa:2048 -subj "/CN=localhost" | \
openssl x509 -req -CAkey mutual_auth_ca.key -CA mutual_auth_ca.pem -days 36500 -set_serial $RANDOM -sha512 -out localhost_server.pem
openssl pkcs8 -topk8 -inform PEM -outform PEM -in localhost_server_rsa.key -out localhost_server.key -nocrypt
rm localhost_server_rsa.key
# Generate a certificate/key for the server to fail for Hostname Verification via localhost
openssl req -new -keyout notlocalhost_server_rsa.key -nodes -newkey rsa:2048 -subj "/CN=NOTlocalhost" | \
openssl x509 -req -CAkey mutual_auth_ca.key -CA mutual_auth_ca.pem -days 36500 -set_serial $RANDOM -sha512 -out notlocalhost_server.pem
openssl pkcs8 -topk8 -inform PEM -outform PEM -in notlocalhost_server_rsa.key -out notlocalhost_server.key -nocrypt
rm notlocalhost_server_rsa.key
# Generate an invalid intermediate CA which will be used to sign the client certificate
openssl req -new -keyout mutual_auth_invalid_intermediate_ca.key -nodes -newkey rsa:2048 -subj "/CN=NettyTestInvalidIntermediate" | \
openssl x509 -req -CAkey mutual_auth_ca.key -CA mutual_auth_ca.pem -days 36500 -set_serial $RANDOM -sha512 -out mutual_auth_invalid_intermediate_ca.pem

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDYrLtMlZzoe2BP
iCURF3So5XNLfsOLcAVERXXjnxqX6Mex55WdJiy6uWTFKbRHWJdbWELdZxVl5+GX
pMv3OdkKZt+19ZdSfByv6bB5RNdZOEGnKOHSY2XdnzYnF5JBaWEx0fvtvIPZOUlW
DWgsQzJk1UQhu+XnBc7P1hHYNvwsVNOR+HD9LGebDy+UcfiL34XwAyBdHUsbcIr8
hltABcj6vNbqOLndpU86DxU9z9b1PDmkFVfisElhpDEhpxmTCwI22Us1GC8D81LM
ZzMlbWSzTfNPEuqNzJYGiFt/XPwPkPPyVvti0XWPBQpwzJFFUX5xKsOGERolELRT
0yNQYznFAgMBAAECggEAOFR/xSNITbB1k3ejm1PrwlUUqlXkZIXU+LDOO0UL1t5v
vDKm1Not2sWECzYSZlID132UtJauG3YzUgdH95gUcv3XvyiAFLOriZhJht181vcn
KlwYiWfJ/dn8bCFWpqbM2/TpeB8AcCLSjAqkQI2ftlMziUmeNXdvEt1mej2hRay1
ULfoxlC0mftNRQptD5gBFzrc47O4mVpVEQt4yS3Qyzp2/9ds9UkhaCIFpXPVCalZ
ds7R+bDDP+wiYTkUcd8fvelaMkD3Wcy8DedGRShhILZvBYTDdWcpJ7+e5EkNlEq4
+Ys4Y/u6aFDJD53g3zCaJhatmdAZcct2MMmWH1vewQKBgQD3Y2S245cad1D9AqYD
ChZGp95EfRo3EzXk4VkE50bjZXjHq9fD8T0CWEZGWQZrXJCR+vBpEURy0mrPD8se
QQ0Q5+I27RadtfPnMd6ry9nDGMPxyd/10vzU6LazzLNE+uf9ljF1RHZu1iDAvInR
r1cQGbn/wKBF6BurPPIXABZEuQKBgQDgN6JHbIfDzHKhwEoUTvRrYJsTXqplD+h0
Whg+kSQyhtKdlpINFOoEj8FUNJvTjG8les1aoajyWIqikVdvHto/mrxrSIeRkEmt
X+KG+5ld2n466tzv1DmVcIGXSrBrH3lA0i6R8Ly26FLSqw0Z12fx5GUUa1qaVRqo
rwcrIZovbQKBgHa2mojs9AC+Sv3uvG1u9LuZKJ7jDaZqMI2R2d7xgOH0Op5Ohy6+
39D1PVvasqroc3Op4J36rEcRVDHi2Uy+WJ/JNpO2+AhcXRuPodP88ZWel8C6aB+V
zL/6oFntnAU5BgR5g2hLny2W0YbLsrMNmhDe15O0AvUo6cYla+K/pu/5AoGACr/g
EdiMMcDthf+4DX0zjqpVBPq25J18oYdoPierOpjoJBIB8oqcJZfWxvi2t8+1zHA0
xDGX7fZ8vwqEzJkIEaCTg/k4NqxaO+uq6pnJYoyFHMIB0aW1FQsNy3kTOC+MGqV5
Ahoukf5VajA1MpX3L8upZO84qsmFu6yYhWLZB4kCgYBlgSD5G4q6rX4ELa3XG61h
fDtu75IYEsjWm4vgJzHjeYT2xPIm9OFFYXjPghto0f1oH37ODD3DoXmsnmddgpmn
tH7aRWWHsSpB5zVgftV4urNCIsm87LWw8mvUGgCwYV1CtCX8warKokfeoA2ltz4u
oeuUzo98hN+aKRU5RO6Bmg==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICozCCAYsCAnS/MA0GCSqGSIb3DQEBDQUAMBgxFjAUBgNVBAMTDU5ldHR5VGVz
dFJvb3QwIBcNMTcwMjE3MDMzMzQ0WhgPMjExNzAxMjQwMzMzNDRaMBQxEjAQBgNV
BAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANis
u0yVnOh7YE+IJREXdKjlc0t+w4twBURFdeOfGpfox7HnlZ0mLLq5ZMUptEdYl1tY
Qt1nFWXn4Zeky/c52Qpm37X1l1J8HK/psHlE11k4Qaco4dJjZd2fNicXkkFpYTHR
++28g9k5SVYNaCxDMmTVRCG75ecFzs/WEdg2/CxU05H4cP0sZ5sPL5Rx+IvfhfAD
IF0dSxtwivyGW0AFyPq81uo4ud2lTzoPFT3P1vU8OaQVV+KwSWGkMSGnGZMLAjbZ
SzUYLwPzUsxnMyVtZLNN808S6o3MlgaIW39c/A+Q8/JW+2LRdY8FCnDMkUVRfnEq
w4YRGiUQtFPTI1BjOcUCAwEAATANBgkqhkiG9w0BAQ0FAAOCAQEAQNXnwE2MJFy5
ti07xyi8h/mY0Kl1dwZUqx4F9D9eoxLCq2/p3h/Z18AlOmjdW06pvC2sGtQtyEqL
YjuQFbMjXRo9c+6+d+xwdDKTu7+XOTHvznJ8xJpKnFOlohGq/n3efBIJSsaeasTU
slFzmdKYABDZzbsQ4X6YCIOF4XVdEQqmXpS+uEbn5C2sVtG+LXI8srmkVGpCcRew
SuTGanwxLparhBBeN1ARjKzNxXUWuK2UKZ9p8c7n7TXGhd12ZNTcLhk4rCnOFq1J
ySFvP5YL2q29fpEt+Tq0zm3V7An2qtaNDp26cEdevtKPjRyOLkCJx8OlZxc9DZvJ
HjalFDoRUw==
-----END CERTIFICATE-----

View File

@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDLDCCAhSgAwIBAgIJANb6te+x5bB3MA0GCSqGSIb3DQEBDQUAMBgxFjAUBgNV
BAMTDU5ldHR5VGVzdFJvb3QwHhcNMTcwMjA4MjI1NDU2WhcNMTcwMzEwMjI1NDU2
MIIDLDCCAhSgAwIBAgIJAO1m5pioZhLLMA0GCSqGSIb3DQEBDQUAMBgxFjAUBgNV
BAMTDU5ldHR5VGVzdFJvb3QwHhcNMTcwMjE3MDMzMzQ0WhcNMTcwMzE5MDMzMzQ0
WjAYMRYwFAYDVQQDEw1OZXR0eVRlc3RSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEApkpHDf3/7RighRTV0aphCJDOs+TnTW3Ui76Uu7Sfhesljwze
ROuAfZaaZqV6NN/3wyX7fQdGh6BF2Y+926twyTXWgrQB1IW5bHaezTwWWraOwF9w
d1mtioDoTw9L2ZO++EOXhi13uO8YGNzA5RDuwLQ4aHam0S31s4EJREuH7YjzHLKY
0wlGrCQln++2jMe7y82xSe3Zgu7kKvtN277voiW6zyeYiZXdLzvCY6iu+3hr5D3Y
qMNEJecRmUJdlL53yDlGhXjnTRHvHZdrPIk5zMiN9yqFBza709fJLUYVB0qJNLxT
Jt2mnHEguYQZpVlJL9E5l3yuJxV+aEU14MlpCQIDAQABo3kwdzAdBgNVHQ4EFgQU
5jOdBEbyH76T4YMWlP1Ex6NrBxwwSAYDVR0jBEEwP4AU5jOdBEbyH76T4YMWlP1E
x6NrBxyhHKQaMBgxFjAUBgNVBAMTDU5ldHR5VGVzdFJvb3SCCQDW+rXvseWwdzAM
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQA5+VDgVgj2OQHzUNHmiK/L
Awq2/vZx6SttwMSBpPHTuI6V1rp/2DNZSEJ5OJtY8FXLHvXRidr7I5HyGM5N86K8
ptxTyd/0A3y8FKS09HPx4KTMOQhZViErbj4jTdDT0D750w99O6Wnh7tGR5nWBmKC
WjaKT8hVdspvTGhINZPFNHN2PrGBoz+9+2+SzbuG60f3NB/Bn2Zq8xCD/e9lOvHJ
wPVvlbfw9Gz05yCk/7kpDY/6+X7G2FSVSOldM5rGTDFtXB69IPYXgcynX28PvnhW
07yh7aayPOZ05mlB6S9RyLNhWwJoASqYIh4EbXlpvrY6AukOBrjhlTKQvaFtrfs4
AQ8AMIIBCgKCAQEAnC7Y/p/TSWI1KxBKETfFKaRWCPEkoYn5G973WbCF0VDT90PX
xK6yHvhqNdDQZPmddgfDAQfjekHeeIFkjCKlvQu0js0G4Bubz4NffNumd/Mgsix8
SWJ13lPk+Ly4PDv0bK1zB6BxP1qQm1qxVwsPy9zNP8ylJrM0Div4TXHmnWOfc0JD
4/XPpfeUHH1tt/GMtsS2Gx6EpTVPD2w7LDKUza1/rQ7d9sqmFpgsNcI9Db/sAtFP
lK2iJku5WIXQkmHimn4bqZ9wkiXJ85pm5ggGQqGMPSbe+2Lh24AvZMIBiwPbkjEU
EDFXEJfKOC3Dl71JgWOthtHZ9vcCRDQ3Sky6AQIDAQABo3kwdzAdBgNVHQ4EFgQU
qT+cH8qrebiVPpKCBQDB6At2iOAwSAYDVR0jBEEwP4AUqT+cH8qrebiVPpKCBQDB
6At2iOChHKQaMBgxFjAUBgNVBAMTDU5ldHR5VGVzdFJvb3SCCQDtZuaYqGYSyzAM
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQCEemXTIew4pR2cHEFpVsW2
bLHXLAnC23wBMT46D3tqyxscukMYjFuWosCdEsgRW8d50BXy9o4dHWeg94+aDo3A
DX4OTRN/veQGIG7dgM6poDzFuVJlSN0ubKKg6gpDD60IhopZpMviFAOsmzr7OXwS
9hjbTqUWujMIEHQ95sPlQFdSaavYSFfqhSltWmVCPSbArxrw0lZ2QcnUqGN47EFp
whc5wFB+rSw/ojU1jBLMvgvgzf/8V8zr1IBTDSiHNlknGqGpOOaookzUh95YRiAT
hH82y9bBeflqroOeztqMpONpWoZjlz0sWbJNvXztXINL7LaNmVYOcoUrCcxPS54T
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDEkT/UNROZLBfR
LvmGv6TmP7IftPH3P2KQ16sCBEzsISy51kA7IdIEBsAEho3gTgqRsJwNpGQeRJTD
PFDEDDB5MJnxKsUkN2PAEC1VF5CD0E7grqrUXOn/sqNbE9jDe7sziVaZmV35EnNj
f+RW55mHtoFNW8pDb35v14oKiB4mp31fkFn84xeAwG+stAhY50qcmcSQ9woAx7vK
vv8CTZhEYeHrnd8FkLYF1RZkn2tvcLvS7RIUQOBIY9IZa+hf3AMJE0khJsQgO1Z3
eOLIlq2tOW4VVzb84M/9te9L/KXQcjWkEhX0qbITSRLd7Oqgs8/bUMY9oq7gMWSj
IXkzMGiLAgMBAAECggEAPlEyJCujh/bzogy7bN3LAHgHF4g9Ab6ll/fXri8A2Ad4
b34eJOEG/OHK9GRYDFmRfji4cJbCatohM3gmvtCCeZlP5KZDk8S/qf827/glh7R9
nTuiyuqeAMN4iIJVQTwz0BXlT5LQuQsBa/T6xhZslRrmCUllaVWqhviVOduHe4cl
ftK5D1IlsBElxeWSXy5Cbu7FhWz4dbJjduuXKfbEPpoHxk/Nsg7bhDh86kOablUG
FraqvMg9GfeOcFlP+PJV4Xlu02GmY7mYBgRnlccErDSFd6QvZIFcUW5hca+B937i
FiToQ+uvYaNeD3IZ/t8PDKIb2APxzRrwj3J5j+fcYQKBgQDtk95rH2xdncYlqYsg
3Lbvo/HZUv38uqjgUofMV87ijcRpKc8l7pbeg/xG5IIYwICaIVuc5idHJGpc63GC
ZZSxwPPfREU+9cZsf3Fn2pTP1Knf9gfjLW7UZi5SdJ7F6S6zMQawlTjKsvvvXTvE
vIeO5BU07jhhEE5W4W+aJ5AycQKBgQDTz0pJn5VkzigdMvyki+QKuF+DZUWUuesL
TzjPm6xblBARUL1vpOLUsm4IR7anOH/6UWQY7+ojTyo1S3QqfLVP4SMkqAEaP8j8
Qixy9KD0Ma2vUF2FaE55lHcnJbGjo8gd4elry1oLRsl26HKi8/fXAZfMkwASYr92
KaY6PjyQuwKBgCXs+w6iv4vaSe1tOVaPpWxwAYWt5/nWWmslAaSvR8mG1BntoLHv
eoofC8DNba9B28W/GX7chtymhYw70az9RlVx9fxoS52XYoujdJkdna/nxQ6Jmgy8
Dfs+LJrhHw99AAV/CBBcYeqJ1AoMGiR37DP1WSVP+hQUpEzeRBCZzD0hAoGAJHS5
RJLDE+an4N61vVyWk4HIbsUvhLm7SucH0DPrJpgFa/WJpX2rzRApACPXvFBtNphr
sh8ZHZqymRmzlNyCGI2XjuebyPjRjxmUrPSN/3nNey9J6XxahXKYT5SdTp0SBJKt
qnAFv4sfgefgU0vKjKcpiXyDtqZobd4dTkkIA6ECgYB2QkGweLbB+Auus5KcuWt1
iG1qJIv5cna0VGaUkhwYDsCBgTM5i8wpdl1UvCVWuETU8+FO19jBx5X/Gv6TwKE8
vWY83HzGvoIcHpXOHlfMFlZnY1Fl6RO5V1XlbzJzjButqdiGEG1oqygVbpn8ui9i
c0AdsCH2P2Ef28bVgiwYBA==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICpjCCAY4CAnvYMA0GCSqGSIb3DQEBDQUAMBgxFjAUBgNVBAMTDU5ldHR5VGVz
dFJvb3QwIBcNMTcwMjE3MDMzMzQ1WhgPMjExNzAxMjQwMzMzNDVaMBcxFTATBgNV
BAMTDE5PVGxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AMSRP9Q1E5ksF9Eu+Ya/pOY/sh+08fc/YpDXqwIETOwhLLnWQDsh0gQGwASGjeBO
CpGwnA2kZB5ElMM8UMQMMHkwmfEqxSQ3Y8AQLVUXkIPQTuCuqtRc6f+yo1sT2MN7
uzOJVpmZXfkSc2N/5FbnmYe2gU1bykNvfm/XigqIHianfV+QWfzjF4DAb6y0CFjn
SpyZxJD3CgDHu8q+/wJNmERh4eud3wWQtgXVFmSfa29wu9LtEhRA4Ehj0hlr6F/c
AwkTSSEmxCA7Vnd44siWra05bhVXNvzgz/2170v8pdByNaQSFfSpshNJEt3s6qCz
z9tQxj2iruAxZKMheTMwaIsCAwEAATANBgkqhkiG9w0BAQ0FAAOCAQEAbYBv+biZ
9wr8LIBKkUp+gMRlPj3YHEbMqSjDpDmtgE9/rYWwrrWbC3Nux6Otwm8lCuofxdZ0
HcpMzj6npOzyW+r21Xhdnwd8b4GclPXJHUP09TxzV6yS+8t6pHVvzVGFGKMPUSt2
L7sKz6/BZFZqynZxoh5LPmdxoFVfFY/05tLCazzz8SWBjzO6kfVLL2RJKIXKeBYm
ipRvCi2YWoHivfg1D+kjVCk42F148R53HQURHiBUMkTLuUzgTnUpg6TKRIJXGsz3
onXWJ1k9a27vGvLMxS5EGtcZRKFOAq0pZ5JJg5E/DkGiFAZb2BonvVHtITU9RqaS
Uvf16yaUsKDHFA==
-----END CERTIFICATE-----

View File

@ -244,7 +244,7 @@
<!-- Fedora-"like" systems. This is currently only used for the netty-tcnative dependency -->
<os.detection.classifierWithLikes>fedora</os.detection.classifierWithLikes>
<tcnative.artifactId>netty-tcnative</tcnative.artifactId>
<tcnative.version>2.0.0.Beta4</tcnative.version>
<tcnative.version>2.0.0.Beta5</tcnative.version>
<tcnative.classifier>${os.detected.classifier}</tcnative.classifier>
<epoll.classifier>${os.detected.name}-${os.detected.arch}</epoll.classifier>
<logging.config>${project.basedir}/../common/src/test/resources/logback-test.xml</logging.config>