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.
This commit is contained in:
parent
cd3bf3df58
commit
fdcad3150e
@ -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) {
|
||||
|
@ -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 <a href="https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html">SSL_set_verify</a> 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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
@ -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<Channel>() {
|
||||
@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<Channel>() {
|
||||
@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);
|
||||
|
37
handler/src/test/resources/io/netty/handler/ssl/generate-certs.sh
Executable file
37
handler/src/test/resources/io/netty/handler/ssl/generate-certs.sh
Executable file
@ -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
|
@ -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-----
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
123
handler/src/test/resources/io/netty/handler/ssl/openssl.cnf
Normal file
123
handler/src/test/resources/io/netty/handler/ssl/openssl.cnf
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user