You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2019/07/25 20:12:13 UTC

[httpcomponents-core] 02/02: TLS integration tests

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch fix-backport
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 305a443b72c60e420b4bd99c30433262c8724136
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Thu Jul 25 22:11:27 2019 +0200

    TLS integration tests
---
 .../apache/http/nio/integration/TestCustomSSL.java | 157 --------
 .../http/nio/integration/TestTLSIntegration.java   | 404 +++++++++++++++++++++
 2 files changed, 404 insertions(+), 157 deletions(-)

diff --git a/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestCustomSSL.java b/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestCustomSSL.java
deleted file mode 100644
index a1caec4..0000000
--- a/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestCustomSSL.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.http.nio.integration;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSession;
-
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.impl.nio.pool.BasicNIOConnFactory;
-import org.apache.http.message.BasicHttpRequest;
-import org.apache.http.nio.NHttpConnection;
-import org.apache.http.nio.protocol.BasicAsyncRequestHandler;
-import org.apache.http.nio.reactor.IOSession;
-import org.apache.http.nio.reactor.ListenerEndpoint;
-import org.apache.http.nio.reactor.ssl.SSLSetupHandler;
-import org.apache.http.nio.testserver.ClientConnectionFactory;
-import org.apache.http.nio.testserver.HttpClientNio;
-import org.apache.http.nio.testserver.HttpServerNio;
-import org.apache.http.nio.testserver.ServerConnectionFactory;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.HttpCoreContext;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.apache.http.ssl.SSLContextBuilder;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestCustomSSL {
-
-    private final static long RESULT_TIMEOUT_SEC = 30;
-
-    protected HttpServerNio server;
-    protected HttpClientNio client;
-
-    @After
-    public void shutDownClient() throws Exception {
-        if (this.client != null) {
-            this.client.shutdown();
-            this.client = null;
-        }
-    }
-
-    @After
-    public void shutDownServer() throws Exception {
-        if (this.server != null) {
-            this.server.shutdown();
-            this.server = null;
-        }
-    }
-
-    @Test
-    public void testCustomSSLContext() throws Exception {
-        final SSLSetupHandler sslSetupHandler = new SSLSetupHandler() {
-
-            @Override
-            public void initalize(
-                    final SSLEngine sslengine) throws SSLException {
-            }
-
-            @Override
-            public void verify(
-                    final IOSession ioSession, final SSLSession sslsession) throws SSLException {
-                final BigInteger sslid = new BigInteger(sslsession.getId());
-                ioSession.setAttribute("ssl-id", sslid);
-            }
-
-        };
-
-        final HttpRequestHandler requestHandler = new HttpRequestHandler() {
-
-            @Override
-            public void handle(
-                    final HttpRequest request,
-                    final HttpResponse response,
-                    final HttpContext context) throws HttpException, IOException {
-                final NHttpConnection conn = (NHttpConnection) context.getAttribute(
-                        HttpCoreContext.HTTP_CONNECTION);
-                final BigInteger sslid = (BigInteger) conn.getContext().getAttribute(
-                        "ssl-id");
-                Assert.assertNotNull(sslid);
-            }
-
-        };
-
-        final URL keyStoreURL = getClass().getResource("/test.keystore");
-        final String storePassword = "nopassword";
-        final SSLContext serverSSLContext = SSLContextBuilder.create()
-                .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
-                .loadKeyMaterial(keyStoreURL, storePassword.toCharArray(), storePassword.toCharArray())
-                .build();
-        this.server = new HttpServerNio();
-        this.server.setConnectionFactory(new ServerConnectionFactory(serverSSLContext, sslSetupHandler));
-        this.server.setTimeout(5000);
-
-        final SSLContext clientSSLContext = SSLContextBuilder.create()
-                .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
-                .build();
-
-        this.client = new HttpClientNio(new BasicNIOConnFactory(new ClientConnectionFactory(clientSSLContext), null));
-        this.client.setTimeout(5000);
-
-        this.server.registerHandler("*", new BasicAsyncRequestHandler(requestHandler));
-
-        this.server.start();
-        this.client.start();
-
-        final ListenerEndpoint endpoint = this.server.getListenerEndpoint();
-        endpoint.waitFor();
-
-        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
-
-        final HttpHost target = new HttpHost("localhost", address.getPort());
-        final BasicHttpRequest request = new BasicHttpRequest("GET", "/");
-        final Future<HttpResponse> future = this.client.execute(target, request);
-        final HttpResponse response = future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
-        Assert.assertNotNull(response);
-        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
-    }
-
-}
diff --git a/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestTLSIntegration.java b/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestTLSIntegration.java
new file mode 100644
index 0000000..3d74797
--- /dev/null
+++ b/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestTLSIntegration.java
@@ -0,0 +1,404 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.nio.integration;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLSession;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.config.ConnectionConfig;
+import org.apache.http.impl.nio.pool.BasicNIOConnFactory;
+import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.nio.NHttpConnection;
+import org.apache.http.nio.protocol.BasicAsyncRequestHandler;
+import org.apache.http.nio.reactor.IOSession;
+import org.apache.http.nio.reactor.ListenerEndpoint;
+import org.apache.http.nio.reactor.ssl.SSLSetupHandler;
+import org.apache.http.nio.testserver.ClientConnectionFactory;
+import org.apache.http.nio.testserver.HttpClientNio;
+import org.apache.http.nio.testserver.HttpServerNio;
+import org.apache.http.nio.testserver.ServerConnectionFactory;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpCoreContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+
+public class TestTLSIntegration {
+
+    private final static long RESULT_TIMEOUT_SEC = 30;
+
+    private HttpServerNio server;
+
+    @Rule
+    public ExternalResource serverResource = new ExternalResource() {
+
+        @Override
+        protected void after() {
+            if (server != null) {
+                try {
+                    server.shutdown();
+                } catch (final Exception ignore) {
+                }
+            }
+        }
+
+    };
+
+    private HttpClientNio client;
+
+    @Rule
+    public ExternalResource clientResource = new ExternalResource() {
+
+        @Override
+        protected void after() {
+            if (client != null) {
+                try {
+                    client.shutdown();
+                } catch (final Exception ignore) {
+                }
+            }
+        }
+
+    };
+
+    private static SSLContext createServerSSLContext() throws Exception {
+        final URL keyStoreURL = TestTLSIntegration.class.getResource("/test.keystore");
+        final String storePassword = "nopassword";
+        return SSLContextBuilder.create()
+                .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
+                .loadKeyMaterial(keyStoreURL, storePassword.toCharArray(), storePassword.toCharArray())
+                .build();
+
+    }
+
+    private static SSLContext createClientSSLContext() throws Exception {
+        final URL keyStoreURL = TestTLSIntegration.class.getResource("/test.keystore");
+        final String storePassword = "nopassword";
+        return SSLContextBuilder.create()
+                .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
+                .build();
+    }
+
+    @Test
+    public void testTLSSuccess() throws Exception {
+        server = new HttpServerNio();
+        server.setConnectionFactory(new ServerConnectionFactory(createServerSSLContext(), null));
+        server.setTimeout(5000);
+        server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
+        server.start();
+
+        final AtomicReference<SSLSession> sslSessionRef = new AtomicReference<SSLSession>(null);
+
+        this.client = new HttpClientNio(new BasicNIOConnFactory(createClientSSLContext(), new SSLSetupHandler() {
+
+            @Override
+            public void initalize(final SSLEngine sslEngine) throws SSLException {
+
+            }
+
+            @Override
+            public void verify(final IOSession ioSession, final SSLSession sslSession) throws SSLException {
+                sslSessionRef.set(sslSession);
+            }
+
+        }, ConnectionConfig.DEFAULT));
+        client.setTimeout(5000);
+        client.start();
+
+        final ListenerEndpoint endpoint = server.getListenerEndpoint();
+        endpoint.waitFor();
+
+        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
+
+        final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+
+        final BasicHttpRequest request = new BasicHttpRequest("GET", "BLAHx200");
+        final Future<HttpResponse> future = client.execute(target, request);
+        final HttpResponse response = future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
+        Assert.assertThat(response, CoreMatchers.notNullValue());
+        Assert.assertThat(response.getStatusLine().getStatusCode(), CoreMatchers.equalTo(200));
+
+        final SSLSession sslSession = sslSessionRef.getAndSet(null);
+        Assert.assertThat(sslSession.getPeerPrincipal().getName(),
+                CoreMatchers.equalTo("CN=localhost,OU=Apache HttpComponents,O=Apache Software Foundation"));
+    }
+
+    @Test
+    public void testTLSTrustFailure() throws Exception {
+        server = new HttpServerNio();
+        server.setConnectionFactory(new ServerConnectionFactory(createServerSSLContext(), null));
+        server.setTimeout(5000);
+        server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
+        server.start();
+
+        this.client = new HttpClientNio(new BasicNIOConnFactory(SSLContexts.createDefault(), null, ConnectionConfig.DEFAULT));
+        client.setTimeout(5000);
+        client.start();
+
+        final ListenerEndpoint endpoint = server.getListenerEndpoint();
+        endpoint.waitFor();
+
+        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
+
+        final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+
+        final BasicHttpRequest request = new BasicHttpRequest("GET", "BLAHx200");
+        final Future<HttpResponse> future = client.execute(target, request);
+        try {
+            future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
+            Assert.fail("ExecutionException expected");
+        } catch (final ExecutionException ex) {
+            final Throwable cause = ex.getCause();
+            Assert.assertThat(cause, CoreMatchers.<Throwable>instanceOf(SSLHandshakeException.class));
+        }
+    }
+
+    @Test
+    public void testTLSClientAuthFailure() throws Exception {
+        server = new HttpServerNio();
+        server.setConnectionFactory(new ServerConnectionFactory(createServerSSLContext(), new SSLSetupHandler() {
+
+            @Override
+            public void initalize(final SSLEngine sslEngine) throws SSLException {
+                sslEngine.setNeedClientAuth(true);
+            }
+
+            @Override
+            public void verify(final IOSession ioSession, final SSLSession sslSession) throws SSLException {
+            }
+
+        }));
+        server.setTimeout(5000);
+        server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
+        server.start();
+
+        this.client = new HttpClientNio(new BasicNIOConnFactory(createClientSSLContext(), null, ConnectionConfig.DEFAULT));
+        client.setTimeout(5000);
+        client.start();
+
+        final ListenerEndpoint endpoint = server.getListenerEndpoint();
+        endpoint.waitFor();
+
+        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
+
+        final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+
+        final BasicHttpRequest request = new BasicHttpRequest("GET", "BLAHx200");
+        final Future<HttpResponse> future = client.execute(target, request);
+        try {
+            future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
+            Assert.fail("ExecutionException expected");
+        } catch (final ExecutionException ex) {
+            final Throwable cause = ex.getCause();
+            Assert.assertThat(cause, CoreMatchers.<Throwable>instanceOf(IOException.class));
+        }
+    }
+
+    @Test
+    public void testTLSProtocolMismatch() throws Exception {
+        server = new HttpServerNio();
+        server.setConnectionFactory(new ServerConnectionFactory(createServerSSLContext(), new SSLSetupHandler() {
+
+            @Override
+            public void initalize(final SSLEngine sslEngine) throws SSLException {
+                sslEngine.setEnabledProtocols(new String[]{"TLSv1.2"});
+            }
+
+            @Override
+            public void verify(final IOSession ioSession, final SSLSession sslSession) throws SSLException {
+            }
+
+        }));
+        server.setTimeout(5000);
+        server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
+        server.start();
+
+        this.client = new HttpClientNio(new BasicNIOConnFactory(createClientSSLContext(), new SSLSetupHandler() {
+
+            @Override
+            public void initalize(final SSLEngine sslEngine) throws SSLException {
+                sslEngine.setEnabledProtocols(new String[]{"SSLv3"});
+            }
+
+            @Override
+            public void verify(final IOSession ioSession, final SSLSession sslSession) throws SSLException {
+            }
+
+        }, ConnectionConfig.DEFAULT));
+        client.setTimeout(5000);
+        client.start();
+
+        final ListenerEndpoint endpoint = server.getListenerEndpoint();
+        endpoint.waitFor();
+
+        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
+
+        final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+
+        final BasicHttpRequest request = new BasicHttpRequest("GET", "BLAHx200");
+        final Future<HttpResponse> future = client.execute(target, request);
+        try {
+            future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
+            Assert.fail("ExecutionException expected");
+        } catch (final ExecutionException ex) {
+            final Throwable cause = ex.getCause();
+            Assert.assertThat(cause, CoreMatchers.<Throwable>instanceOf(SSLHandshakeException.class));
+        }
+    }
+
+    @Test
+    public void testTLSCipherMismatch() throws Exception {
+        server = new HttpServerNio();
+        server.setConnectionFactory(new ServerConnectionFactory(createServerSSLContext(), new SSLSetupHandler() {
+
+            @Override
+            public void initalize(final SSLEngine sslEngine) throws SSLException {
+                sslEngine.setEnabledCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+            }
+
+            @Override
+            public void verify(final IOSession ioSession, final SSLSession sslSession) throws SSLException {
+            }
+
+        }));
+        server.setTimeout(5000);
+        server.registerHandler("*", new BasicAsyncRequestHandler(new SimpleRequestHandler()));
+        server.start();
+
+        this.client = new HttpClientNio(new BasicNIOConnFactory(createClientSSLContext(), new SSLSetupHandler() {
+
+            @Override
+            public void initalize(final SSLEngine sslEngine) throws SSLException {
+                sslEngine.setEnabledCipherSuites(new String[]{"SSL_RSA_EXPORT_WITH_RC4_40_MD5"});
+            }
+
+            @Override
+            public void verify(final IOSession ioSession, final SSLSession sslSession) throws SSLException {
+            }
+
+        }, ConnectionConfig.DEFAULT));
+        client.setTimeout(5000);
+        client.start();
+
+        final ListenerEndpoint endpoint = server.getListenerEndpoint();
+        endpoint.waitFor();
+
+        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
+
+        final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+
+        final BasicHttpRequest request = new BasicHttpRequest("GET", "BLAHx200");
+        final Future<HttpResponse> future = client.execute(target, request);
+        try {
+            future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
+            Assert.fail("ExecutionException expected");
+        } catch (final ExecutionException ex) {
+            final Throwable cause = ex.getCause();
+            Assert.assertThat(cause, CoreMatchers.<Throwable>instanceOf(IOException.class));
+        }
+    }
+
+    @Test
+    public void testCustomSSLContext() throws Exception {
+        final SSLSetupHandler sslSetupHandler = new SSLSetupHandler() {
+
+            @Override
+            public void initalize(
+                    final SSLEngine sslengine) throws SSLException {
+            }
+
+            @Override
+            public void verify(
+                    final IOSession ioSession, final SSLSession sslsession) throws SSLException {
+                final BigInteger sslid = new BigInteger(sslsession.getId());
+                ioSession.setAttribute("ssl-id", sslid);
+            }
+
+        };
+
+        final HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+            @Override
+            public void handle(
+                    final HttpRequest request,
+                    final HttpResponse response,
+                    final HttpContext context) throws HttpException, IOException {
+                final NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        HttpCoreContext.HTTP_CONNECTION);
+                final BigInteger sslid = (BigInteger) conn.getContext().getAttribute(
+                        "ssl-id");
+                Assert.assertNotNull(sslid);
+            }
+
+        };
+
+        this.server = new HttpServerNio();
+        this.server.setConnectionFactory(new ServerConnectionFactory(createServerSSLContext(), sslSetupHandler));
+        this.server.setTimeout(5000);
+        this.server.registerHandler("*", new BasicAsyncRequestHandler(requestHandler));
+        this.server.start();
+
+        this.client = new HttpClientNio(new BasicNIOConnFactory(new ClientConnectionFactory(createClientSSLContext()), null));
+        this.client.setTimeout(5000);
+        this.client.start();
+
+        final ListenerEndpoint endpoint = this.server.getListenerEndpoint();
+        endpoint.waitFor();
+
+        final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress();
+
+        final HttpHost target = new HttpHost("localhost", address.getPort());
+        final BasicHttpRequest request = new BasicHttpRequest("GET", "/");
+        final Future<HttpResponse> future = this.client.execute(target, request);
+        final HttpResponse response = future.get(RESULT_TIMEOUT_SEC, TimeUnit.SECONDS);
+        Assert.assertNotNull(response);
+        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+    }
+
+}