From 43ebbc3fa065155fa67732b0cbd7c12843b0f3f7 Mon Sep 17 00:00:00 2001 From: Alex Petrov Date: Thu, 26 Nov 2015 08:45:56 +0100 Subject: [PATCH] Update JDK SSL Tests to use SSL Context Builder. Motivation: Use new / non-deprecated APIs for creating SSL Context in tests, in order to be able to implement OpenSsl tests with maximum code reuse. Modifications: Use `SslContextBuilder.(forServer|forClient)` instead of deprecated `JdkSslServerContext` constructor. Use `ApplicationProtocolConfig` instead of Protocol Negotiator. Use custom exception type for skipping tests to avoid swallowing exceptions arising from tests. Result: Exceptions from tests aren't swallowed. Using new APIs allows reusing same test code for OpenSsl tests. --- .../netty/handler/ssl/JdkSslEngineTest.java | 134 +++++++++++++----- .../io/netty/handler/ssl/SSLEngineTest.java | 23 ++- .../io/netty/handler/ssl/SniHandlerTest.java | 2 +- 3 files changed, 112 insertions(+), 47 deletions(-) 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 9482f2b445..4dda2c6eca 100644 --- a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java @@ -31,6 +31,9 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector; import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory; +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; @@ -59,13 +62,13 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkNpnSslEngine.isAvailable()) { - throw new RuntimeException("NPN not on classpath"); + throw tlsExtensionNotFound(Protocol.NPN); } - JdkApplicationProtocolNegotiator apn = new JdkNpnApplicationProtocolNegotiator(true, true, + ApplicationProtocolConfig apn = failingNegotiator(Protocol.NPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); mySetup(apn); runTest(); - } catch (RuntimeException e) { + } catch (SkipTestException e) { // NPN availability is dependent on the java version. If NPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -79,15 +82,15 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkNpnSslEngine.isAvailable()) { - throw new RuntimeException("NPN not on classpath"); + throw tlsExtensionNotFound(Protocol.NPN); } - JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); - JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); mySetup(serverApn, clientApn); runTest(null); - } catch (Exception e) { + } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -101,16 +104,16 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkNpnSslEngine.isAvailable()) { - throw new RuntimeException("NPN not on classpath"); + throw tlsExtensionNotFound(Protocol.NPN); } - JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(true, true, + ApplicationProtocolConfig clientApn = failingNegotiator(Protocol.NPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); - JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); mySetup(serverApn, clientApn); assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); assertTrue(clientException instanceof SSLHandshakeException); - } catch (RuntimeException e) { + } catch (SkipTestException e) { // NPN availability is dependent on the java version. If NPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -124,16 +127,16 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkNpnSslEngine.isAvailable()) { - throw new RuntimeException("NPN not on classpath"); + throw tlsExtensionNotFound(Protocol.NPN); } - JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); - JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(true, true, + ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.NPN, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); mySetup(serverApn, clientApn); assertTrue(serverLatch.await(2, TimeUnit.SECONDS)); assertTrue(serverException instanceof SSLHandshakeException); - } catch (RuntimeException e) { + } catch (SkipTestException e) { // NPN availability is dependent on the java version. If NPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -147,13 +150,13 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkAlpnSslEngine.isAvailable()) { - throw new RuntimeException("ALPN not on classpath"); + throw tlsExtensionNotFound(Protocol.ALPN); } - JdkApplicationProtocolNegotiator apn = new JdkAlpnApplicationProtocolNegotiator(true, true, + ApplicationProtocolConfig apn = failingNegotiator(Protocol.ALPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); mySetup(apn); runTest(); - } catch (Exception e) { + } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -167,15 +170,15 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkAlpnSslEngine.isAvailable()) { - throw new RuntimeException("ALPN not on classpath"); + throw tlsExtensionNotFound(Protocol.ALPN); } - JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); - JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.ALPN, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); mySetup(serverApn, clientApn); runTest(null); - } catch (Exception e) { + } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -189,16 +192,16 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkAlpnSslEngine.isAvailable()) { - throw new RuntimeException("ALPN not on classpath"); + throw tlsExtensionNotFound(Protocol.ALPN); } - JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL); - JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true, + ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); mySetup(serverApn, clientApn); assertTrue(serverLatch.await(2, TimeUnit.SECONDS)); assertTrue(serverException instanceof SSLHandshakeException); - } catch (Exception e) { + } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -212,18 +215,18 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkAlpnSslEngine.isAvailable()) { - throw new RuntimeException("ALPN not on classpath"); + throw tlsExtensionNotFound(Protocol.ALPN); } // Even the preferred application protocol appears second in the client's list, it will be picked // because it's the first one on server's list. - JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, + ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN, FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL); - JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true, + ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN, PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL); mySetup(serverApn, clientApn); assertNull(serverException); runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL); - } catch (Exception e) { + } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); @@ -237,8 +240,9 @@ public class JdkSslEngineTest extends SSLEngineTest { // Check in this test just in case we have multiple tests that just the class and we already ignored the // initialization error. if (!JdkAlpnSslEngine.isAvailable()) { - throw new RuntimeException("ALPN not on classpath"); + throw tlsExtensionNotFound(Protocol.ALPN); } + SelfSignedCertificate ssc = new SelfSignedCertificate(); JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true, PREFERRED_APPLICATION_LEVEL_PROTOCOL); JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator( @@ -258,28 +262,54 @@ public class JdkSslEngineTest extends SSLEngineTest { } }, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY, APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); - mySetup(serverApn, clientApn); + + SslContext serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null, + IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0); + SslContext clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null, + IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0); + + mySetup(serverSslCtx, clientSslCtx); assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); assertTrue(clientException instanceof SSLHandshakeException); - } catch (Exception e) { + } catch (SkipTestException e) { // ALPN availability is dependent on the java version. If ALPN is not available because of // java version incompatibility don't fail the test, but instead just skip the test assumeNoException(e); } } - private void mySetup(JdkApplicationProtocolNegotiator apn) throws InterruptedException, SSLException, + private void mySetup(ApplicationProtocolConfig apn) throws InterruptedException, SSLException, CertificateException { mySetup(apn, apn); } - private void mySetup(JdkApplicationProtocolNegotiator serverApn, JdkApplicationProtocolNegotiator clientApn) + private void mySetup(ApplicationProtocolConfig serverApn, ApplicationProtocolConfig clientApn) throws InterruptedException, SSLException, CertificateException { SelfSignedCertificate ssc = new SelfSignedCertificate(); - serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null, - IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0); - clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null, - IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0); + + mySetup(SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null) + .sslProvider(sslProvider()) + .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) + .applicationProtocolConfig(serverApn) + .sessionCacheSize(0) + .sessionTimeout(0) + .build(), + + SslContextBuilder.forClient() + .sslProvider(sslProvider()) + .applicationProtocolConfig(clientApn) + .trustManager(InsecureTrustManagerFactory.INSTANCE) + .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) + .sessionCacheSize(0) + .sessionTimeout(0) + .build()); + } + + private void mySetup(SslContext serverCtx, SslContext clientCtx) + throws InterruptedException, SSLException, CertificateException { + + serverSslCtx = serverCtx; + clientSslCtx = clientCtx; serverConnectedChannel = null; sb = new ServerBootstrap(); @@ -346,4 +376,30 @@ public class JdkSslEngineTest extends SSLEngineTest { protected SslProvider sslProvider() { return SslProvider.JDK; } + + private ApplicationProtocolConfig failingNegotiator(Protocol protocol, + String... supportedProtocols) { + return new ApplicationProtocolConfig(protocol, + SelectorFailureBehavior.FATAL_ALERT, + SelectedListenerFailureBehavior.FATAL_ALERT, + supportedProtocols); + } + + private ApplicationProtocolConfig acceptingNegotiator(Protocol protocol, + String... supportedProtocols) { + return new ApplicationProtocolConfig(protocol, + SelectorFailureBehavior.NO_ADVERTISE, + SelectedListenerFailureBehavior.ACCEPT, + supportedProtocols); + } + + private SkipTestException tlsExtensionNotFound(Protocol protocol) { + throw new SkipTestException(protocol + " not on classpath"); + } + + private static final class SkipTestException extends RuntimeException { + public SkipTestException(String message) { + super(message); + } + } } 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 e712fb34dc..e5575b2edb 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java @@ -180,13 +180,22 @@ public abstract class SSLEngineTest { File servertTrustCrtFile, File serverKeyFile, File serverCrtFile, String serverKeyPassword, File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword) throws InterruptedException, SSLException { - serverSslCtx = SslContext.newServerContext(sslProvider(), servertTrustCrtFile, null, - serverCrtFile, serverKeyFile, serverKeyPassword, null, - null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0); - clientSslCtx = SslContext.newClientContext(sslProvider(), clientTrustCrtFile, null, - clientCrtFile, clientKeyFile, clientKeyPassword, null, - null, IdentityCipherSuiteFilter.INSTANCE, - null, 0, 0); + serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword) + .sslProvider(sslProvider()) + .trustManager(servertTrustCrtFile) + .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) + .sessionCacheSize(0) + .sessionTimeout(0) + .build(); + + clientSslCtx = SslContextBuilder.forClient() + .sslProvider(sslProvider()) + .trustManager(clientTrustCrtFile) + .keyManager(clientCrtFile, clientKeyFile, clientKeyPassword) + .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) + .sessionCacheSize(0) + .sessionTimeout(0) + .build(); serverConnectedChannel = null; sb = new ServerBootstrap(); diff --git a/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java b/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java index 1171bf08c6..ea28b412b5 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java @@ -34,7 +34,7 @@ public class SniHandlerTest { File keyFile = new File(SniHandlerTest.class.getResource("test_encrypted.pem").getFile()); File crtFile = new File(SniHandlerTest.class.getResource("test.crt").getFile()); - return new JdkSslServerContext(crtFile, keyFile, "12345"); + return SslContextBuilder.forServer(crtFile, keyFile, "12345").build(); } @Test