From fdcad3150efde5676a4b895236703710ae15e9e4 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Tue, 7 Feb 2017 20:37:51 -0800 Subject: [PATCH] Use tcnative's new setVerify modes Modifications: tcnative made some fixes and API changes related to setVerify. We should absorb these changes in Netty. Modifications: - Use tcnatives updated APIs - Add unit tests to demonstrate correct behavior Result: Updated to latest tcnative code and more unit tests to verify expected behavior. --- .../ReferenceCountedOpenSslClientContext.java | 2 +- .../ssl/ReferenceCountedOpenSslEngine.java | 12 +- .../ssl/JdkOpenSslEngineInteroptTest.java | 15 ++ .../netty/handler/ssl/JdkSslEngineTest.java | 22 +- .../netty/handler/ssl/OpenSslEngineTest.java | 26 +++ .../ssl/OpenSslJdkSslEngineInteroptTest.java | 11 + .../io/netty/handler/ssl/SSLEngineTest.java | 205 +++++++++++++++++- .../io/netty/handler/ssl/generate-certs.sh | 37 ++++ .../io/netty/handler/ssl/mutual_auth_ca.pem | 19 ++ .../netty/handler/ssl/mutual_auth_client.p12 | Bin 0 -> 3997 bytes .../ssl/mutual_auth_invalid_client.p12 | Bin 0 -> 3949 bytes .../netty/handler/ssl/mutual_auth_server.p12 | Bin 0 -> 3141 bytes .../io/netty/handler/ssl/openssl.cnf | 123 +++++++++++ 13 files changed, 467 insertions(+), 5 deletions(-) create mode 100755 handler/src/test/resources/io/netty/handler/ssl/generate-certs.sh create mode 100644 handler/src/test/resources/io/netty/handler/ssl/mutual_auth_ca.pem create mode 100644 handler/src/test/resources/io/netty/handler/ssl/mutual_auth_client.p12 create mode 100644 handler/src/test/resources/io/netty/handler/ssl/mutual_auth_invalid_client.p12 create mode 100644 handler/src/test/resources/io/netty/handler/ssl/mutual_auth_server.p12 create mode 100644 handler/src/test/resources/io/netty/handler/ssl/openssl.cnf diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java index 06c80eabb4..2ad1be62bd 100644 --- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java @@ -121,7 +121,7 @@ public final class ReferenceCountedOpenSslClientContext extends ReferenceCounted throw new SSLException("failed to set certificate and key", e); } - SSLContext.setVerify(ctx, SSL.SSL_VERIFY_NONE, VERIFY_DEPTH); + SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, VERIFY_DEPTH); try { if (trustCertCollection != null) { diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java index f37660e167..c4b5321dd2 100644 --- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java +++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java @@ -28,6 +28,7 @@ import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.StringUtil; import io.netty.util.internal.ThrowableUtil; +import io.netty.util.internal.UnstableApi; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -1461,6 +1462,15 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc return clientAuth == ClientAuth.OPTIONAL; } + /** + * See SSL_set_verify and + * {@link SSL#setVerify(long, int, int)}. + */ + @UnstableApi + public synchronized final void setVerify(int verifyMode, int depth) { + SSL.setVerify(ssl, verifyMode, depth); + } + private void setClientAuth(ClientAuth mode) { if (clientMode) { return; @@ -1475,7 +1485,7 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH); break; case REQUIRE: - SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRE, ReferenceCountedOpenSslContext.VERIFY_DEPTH); + SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH); break; case OPTIONAL: SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH); diff --git a/handler/src/test/java/io/netty/handler/ssl/JdkOpenSslEngineInteroptTest.java b/handler/src/test/java/io/netty/handler/ssl/JdkOpenSslEngineInteroptTest.java index 716379fc67..a916430769 100644 --- a/handler/src/test/java/io/netty/handler/ssl/JdkOpenSslEngineInteroptTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/JdkOpenSslEngineInteroptTest.java @@ -17,6 +17,9 @@ package io.netty.handler.ssl; import org.junit.BeforeClass; +import javax.net.ssl.SSLException; + +import static io.netty.tcnative.jni.SSL.SSL_CVERIFY_IGNORED; import static org.junit.Assume.assumeTrue; public class JdkOpenSslEngineInteroptTest extends SSLEngineTest { @@ -39,4 +42,16 @@ public class JdkOpenSslEngineInteroptTest extends SSLEngineTest { protected SslProvider sslServerProvider() { return SslProvider.OPENSSL; } + + @Override + protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) { + ReferenceCountedOpenSslEngine engine = (ReferenceCountedOpenSslEngine) handler.engine(); + engine.setVerify(SSL_CVERIFY_IGNORED, 1); + } + + @Override + protected boolean mySetupMutualAuthServerIsValidClientException(Throwable cause) { + // TODO(scott): work around for a JDK issue. The exception should be SSLHandshakeException. + return super.mySetupMutualAuthServerIsValidException(cause) || cause instanceof SSLException; + } } diff --git a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java index 5856fee1c2..640823ade8 100644 --- a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java @@ -22,13 +22,15 @@ import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector; import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.SelfSignedCertificate; +import org.junit.Ignore; import org.junit.Test; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLHandshakeException; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -271,6 +273,22 @@ public class JdkSslEngineTest extends SSLEngineTest { testEnablingAnAlreadyDisabledSslProtocol(new String[]{}, new String[]{PROTOCOL_TLS_V1_2}); } + @Ignore /* Does the JDK support a "max certificate chain length"? */ + @Override + public void testMutualAuthValidClientCertChainTooLongFailOptionalClientAuth() throws Exception { + } + + @Ignore /* Does the JDK support a "max certificate chain length"? */ + @Override + public void testMutualAuthValidClientCertChainTooLongFailRequireClientAuth() throws Exception { + } + + @Override + protected boolean mySetupMutualAuthServerIsValidException(Throwable cause) { + // TODO(scott): work around for a JDK issue. The exception should be SSLHandshakeException. + return super.mySetupMutualAuthServerIsValidException(cause) || cause instanceof SSLException; + } + private void runTest() throws Exception { runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL); } diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java index da8018386a..659a623c44 100644 --- a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java @@ -15,25 +15,45 @@ */ package io.netty.handler.ssl; +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.UnpooledByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol; import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.util.NetUtil; import io.netty.util.internal.ThreadLocalRandom; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; +import java.io.File; +import java.net.InetSocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.security.KeyStore; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; +import static io.netty.tcnative.jni.SSL.SSL_CVERIFY_IGNORED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -268,6 +288,12 @@ public class OpenSslEngineTest extends SSLEngineTest { ReferenceCountedOpenSslEngine.calculateOutNetBufSize(0)); } + @Override + protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) { + ReferenceCountedOpenSslEngine engine = (ReferenceCountedOpenSslEngine) handler.engine(); + engine.setVerify(SSL_CVERIFY_IGNORED, 1); + } + @Test public void testWrapWithDifferentSizesTLSv1() throws Exception { clientSslCtx = SslContextBuilder.forClient() diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslJdkSslEngineInteroptTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslJdkSslEngineInteroptTest.java index 7cba76ffc5..8d6f56dc6e 100644 --- a/handler/src/test/java/io/netty/handler/ssl/OpenSslJdkSslEngineInteroptTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslJdkSslEngineInteroptTest.java @@ -16,6 +16,7 @@ package io.netty.handler.ssl; import org.junit.BeforeClass; +import org.junit.Ignore; import static org.junit.Assume.assumeTrue; @@ -39,4 +40,14 @@ public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest { protected SslProvider sslServerProvider() { return SslProvider.JDK; } + + @Ignore /* Does the JDK support a "max certificate chain length"? */ + @Override + public void testMutualAuthValidClientCertChainTooLongFailOptionalClientAuth() throws Exception { + } + + @Ignore /* Does the JDK support a "max certificate chain length"? */ + @Override + public void testMutualAuthValidClientCertChainTooLongFailRequireClientAuth() throws Exception { + } } diff --git a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java index 3ee3b8219b..63daef6b90 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java @@ -57,6 +57,8 @@ import java.io.FileInputStream; import java.io.InputStream; import java.net.InetSocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.ArrayList; @@ -65,7 +67,7 @@ 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.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; @@ -512,6 +514,207 @@ public abstract class SSLEngineTest { assertTrue(clientException instanceof SSLHandshakeException); } + @Test + public void testMutualAuthInvalidIntermediateCASucceedWithOptionalClientAuth() throws Exception { + testMutualAuthInvalidClientCertSucceed(ClientAuth.NONE); + } + + @Test + public void testMutualAuthInvalidIntermediateCAFailWithOptionalClientAuth() throws Exception { + testMutualAuthClientCertFail(ClientAuth.OPTIONAL); + } + + @Test + public void testMutualAuthInvalidIntermediateCAFailWithRequiredClientAuth() throws Exception { + testMutualAuthClientCertFail(ClientAuth.REQUIRE); + } + + @Test + public void testMutualAuthValidClientCertChainTooLongFailOptionalClientAuth() throws Exception { + testMutualAuthClientCertFail(ClientAuth.OPTIONAL, "mutual_auth_client.p12", true); + } + + @Test + public void testMutualAuthValidClientCertChainTooLongFailRequireClientAuth() throws Exception { + testMutualAuthClientCertFail(ClientAuth.REQUIRE, "mutual_auth_client.p12", true); + } + + private void testMutualAuthInvalidClientCertSucceed(ClientAuth auth) throws Exception { + char[] password = "example".toCharArray(); + final KeyStore serverKeyStore = KeyStore.getInstance("PKCS12"); + serverKeyStore.load(getClass().getResourceAsStream("mutual_auth_server.p12"), password); + final KeyStore clientKeyStore = KeyStore.getInstance("PKCS12"); + clientKeyStore.load(getClass().getResourceAsStream("mutual_auth_invalid_client.p12"), password); + final KeyManagerFactory serverKeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + serverKeyManagerFactory.init(serverKeyStore, password); + final KeyManagerFactory clientKeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + clientKeyManagerFactory.init(clientKeyStore, password); + File commonCertChain = new File(getClass().getResource("mutual_auth_ca.pem").getFile()); + + mySetupMutualAuth(serverKeyManagerFactory, commonCertChain, clientKeyManagerFactory, commonCertChain, + auth, false, false); + assertTrue(clientLatch.await(5, TimeUnit.SECONDS)); + assertNull(clientException); + assertTrue(serverLatch.await(5, TimeUnit.SECONDS)); + assertNull(serverException); + } + + private void testMutualAuthClientCertFail(ClientAuth auth) throws Exception { + testMutualAuthClientCertFail(auth, "mutual_auth_invalid_client.p12", false); + } + + private void testMutualAuthClientCertFail(ClientAuth auth, String clientCert, boolean serverInitEngine) throws Exception { + char[] password = "example".toCharArray(); + final KeyStore serverKeyStore = KeyStore.getInstance("PKCS12"); + serverKeyStore.load(getClass().getResourceAsStream("mutual_auth_server.p12"), password); + final KeyStore clientKeyStore = KeyStore.getInstance("PKCS12"); + clientKeyStore.load(getClass().getResourceAsStream(clientCert), password); + final KeyManagerFactory serverKeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + serverKeyManagerFactory.init(serverKeyStore, password); + final KeyManagerFactory clientKeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + clientKeyManagerFactory.init(clientKeyStore, password); + File commonCertChain = new File(getClass().getResource("mutual_auth_ca.pem").getFile()); + + mySetupMutualAuth(serverKeyManagerFactory, commonCertChain, clientKeyManagerFactory, commonCertChain, + auth, true, serverInitEngine); + assertTrue(clientLatch.await(5, TimeUnit.SECONDS)); + assertTrue("unexpected exception: " + clientException, + mySetupMutualAuthServerIsValidClientException(clientException)); + assertTrue(serverLatch.await(5, TimeUnit.SECONDS)); + assertTrue("unexpected exception: " + serverException, + mySetupMutualAuthServerIsValidServerException(serverException)); + } + + protected boolean mySetupMutualAuthServerIsValidServerException(Throwable cause) { + return mySetupMutualAuthServerIsValidException(cause); + } + + protected boolean mySetupMutualAuthServerIsValidClientException(Throwable cause) { + return mySetupMutualAuthServerIsValidException(cause); + } + + protected boolean mySetupMutualAuthServerIsValidException(Throwable cause) { + return cause instanceof SSLHandshakeException || cause instanceof ClosedChannelException; + } + + protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) { + } + + private void mySetupMutualAuth(KeyManagerFactory serverKMF, final File serverTrustManager, + KeyManagerFactory clientKMF, File clientTrustManager, + ClientAuth clientAuth, final boolean failureExpected, + final boolean serverInitEngine) + throws SSLException, InterruptedException { + serverSslCtx = SslContextBuilder.forServer(serverKMF) + .sslProvider(sslServerProvider()) + .trustManager(serverTrustManager) + .clientAuth(clientAuth) + .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) + .sessionCacheSize(0) + .sessionTimeout(0) + .build(); + + clientSslCtx = SslContextBuilder.forClient() + .sslProvider(sslClientProvider()) + .trustManager(clientTrustManager) + .keyManager(clientKMF) + .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() { + @Override + protected void initChannel(Channel ch) throws Exception { + ch.config().setAllocator(new TestByteBufAllocator(ch.config().getAllocator(), type)); + + ChannelPipeline p = ch.pipeline(); + SslHandler handler = serverSslCtx.newHandler(ch.alloc()); + if (serverInitEngine) { + mySetupMutualAuthServerInitSslHandler(handler); + } + p.addLast(handler); + 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() { + @Override + protected void initChannel(Channel ch) throws Exception { + ch.config().setAllocator(new TestByteBufAllocator(ch.config().getAllocator(), type)); + ChannelPipeline p = ch.pipeline(); + p.addLast(clientSslCtx.newHandler(ch.alloc())); + 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(9999)).sync().channel(); + int port = ((InetSocketAddress) serverChannel.localAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(NetUtil.LOCALHOST, 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); diff --git a/handler/src/test/resources/io/netty/handler/ssl/generate-certs.sh b/handler/src/test/resources/io/netty/handler/ssl/generate-certs.sh new file mode 100755 index 0000000000..34ecb442af --- /dev/null +++ b/handler/src/test/resources/io/netty/handler/ssl/generate-certs.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# Generate a new, self-signed root CA +openssl req -extensions v3_ca -new -x509 -days 30 -nodes -subj "/CN=NettyTestRoot" -newkey rsa:2048 -sha512 -out mutual_auth_ca.pem -keyout mutual_auth_ca.key + +# Generate a certificate/key for the server +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 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 + +# Generate a client certificate signed by the invalid intermediate CA +openssl req -new -keyout mutual_auth_invalid_client.key -nodes -newkey rsa:2048 -subj "/CN=NettyTestInvalidClient/UID=ClientWithInvalidCa" | \ + openssl x509 -req -CAkey mutual_auth_invalid_intermediate_ca.key -CA mutual_auth_invalid_intermediate_ca.pem -days 36500 -set_serial $RANDOM -sha512 -out mutual_auth_invalid_client.pem + +# Generate a valid intermediate CA which will be used to sign the client certificate +openssl req -new -keyout mutual_auth_intermediate_ca.key -nodes -newkey rsa:2048 -out mutual_auth_intermediate_ca.key +openssl req -new -sha512 -key mutual_auth_intermediate_ca.key -subj "/CN=NettyTestIntermediate" -out intermediate.csr +openssl x509 -req -days 1825 -in intermediate.csr -extfile openssl.cnf -extensions v3_ca -CA mutual_auth_ca.pem -CAkey mutual_auth_ca.key -set_serial $RANDOM -out mutual_auth_intermediate_ca.pem + +# Generate a client certificate signed by the intermediate CA +openssl req -new -keyout mutual_auth_client.key -nodes -newkey rsa:2048 -subj "/CN=NettyTestClient/UID=Client" | \ + openssl x509 -req -CAkey mutual_auth_intermediate_ca.key -CA mutual_auth_intermediate_ca.pem -days 36500 -set_serial $RANDOM -sha512 -out mutual_auth_client.pem + +# For simplicity, squish everything down into PKCS#12 keystores +cat mutual_auth_invalid_intermediate_ca.pem mutual_auth_ca.pem > mutual_auth_invalid_client_cert_chain.pem +cat mutual_auth_intermediate_ca.pem mutual_auth_ca.pem > mutual_auth_client_cert_chain.pem +openssl pkcs12 -export -in mutual_auth_server.pem -inkey mutual_auth_server.key -certfile mutual_auth_ca.pem -out mutual_auth_server.p12 -password pass:example +openssl pkcs12 -export -in mutual_auth_invalid_client.pem -inkey mutual_auth_invalid_client.key -certfile mutual_auth_invalid_client_cert_chain.pem -out mutual_auth_invalid_client.p12 -password pass:example +openssl pkcs12 -export -in mutual_auth_client.pem -inkey mutual_auth_client.key -certfile mutual_auth_client_cert_chain.pem -out mutual_auth_client.p12 -password pass:example + +# Clean up intermediate files +rm intermediate.csr +rm mutual_auth_ca.key mutual_auth_invalid_client.key mutual_auth_client.key mutual_auth_server.key mutual_auth_invalid_intermediate_ca.key mutual_auth_intermediate_ca.key +rm mutual_auth_invalid_client.pem mutual_auth_client.pem mutual_auth_server.pem mutual_auth_client_cert_chain.pem mutual_auth_invalid_intermediate_ca.pem mutual_auth_intermediate_ca.pem mutual_auth_invalid_client_cert_chain.pem diff --git a/handler/src/test/resources/io/netty/handler/ssl/mutual_auth_ca.pem b/handler/src/test/resources/io/netty/handler/ssl/mutual_auth_ca.pem new file mode 100644 index 0000000000..6b523e9862 --- /dev/null +++ b/handler/src/test/resources/io/netty/handler/ssl/mutual_auth_ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDLDCCAhSgAwIBAgIJANb6te+x5bB3MA0GCSqGSIb3DQEBDQUAMBgxFjAUBgNV +BAMTDU5ldHR5VGVzdFJvb3QwHhcNMTcwMjA4MjI1NDU2WhcNMTcwMzEwMjI1NDU2 +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 +-----END CERTIFICATE----- diff --git a/handler/src/test/resources/io/netty/handler/ssl/mutual_auth_client.p12 b/handler/src/test/resources/io/netty/handler/ssl/mutual_auth_client.p12 new file mode 100644 index 0000000000000000000000000000000000000000..94c105cc35c3a44c7a124518b0c02d2eacd6e51c GIT binary patch literal 3997 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 #GVw}dx#GLiO3MLYm+Q(7@4Fe3&DDuzgg z_YDCF6)_eB6py!GFmK#n2hmF8U;G#kp}8ghCNMEDAutIB1uG5%0vZJX1QfMN4Qm8J f0}zEfeVn--%Y@x0o}~l`SbqF5r&Dd`0s;sC{9^Ch literal 0 HcmV?d00001 diff --git a/handler/src/test/resources/io/netty/handler/ssl/openssl.cnf b/handler/src/test/resources/io/netty/handler/ssl/openssl.cnf new file mode 100644 index 0000000000..74fee1590d --- /dev/null +++ b/handler/src/test/resources/io/netty/handler/ssl/openssl.cnf @@ -0,0 +1,123 @@ +# +# This OpenSSL configuration file is necessary to generate an Intermediate CA +# which is capable of signing other certificates. The most important part is +# the [ v3_ca ] profile and the "basicConstraints = CA:true" value +# + +# This definition stops the following lines choking if HOME isn't +# defined. +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true