From e2a79312fc4bd3ad2a85f1252d2db66fcbaa73a7 Mon Sep 17 00:00:00 2001 From: Ola Johnsson Date: Tue, 19 Jan 2016 13:14:22 +0100 Subject: [PATCH 01/11] Fix for vulnerability https://github.com/notnoop/java-apns/issues/286 The old commons httpclient library is exchanged with latest version of apache httpclient which does not have any known security issues. The previous test case has been updated to automatically setup proxy with auth and a basic http server to test the tunnel (it can still be reconfigured to test your local proxy/server combo) The new httpclient does not allow the same way of figuring out which credential protocol is used, but I think that the functionality is basically the same. Implementing the change described in https://github.com/notnoop/java-apns/issues/287 will improve the credentials support further. --- pom.xml | 12 +- .../apns/internal/TlsTunnelBuilder.java | 77 ++++------- .../apns/internal/TlsTunnelBuilderTest.java | 122 +++++++++++++----- 3 files changed, 128 insertions(+), 83 deletions(-) diff --git a/pom.xml b/pom.xml index 84646588..01bb99c0 100644 --- a/pom.xml +++ b/pom.xml @@ -260,9 +260,9 @@ --> - commons-httpclient - commons-httpclient - 3.1 + org.apache.httpcomponents + httpclient + 4.5.1 @@ -307,6 +307,12 @@ jar compile + + org.littleshoot + littleproxy + 1.1.0-beta1 + test + diff --git a/src/main/java/com/notnoop/apns/internal/TlsTunnelBuilder.java b/src/main/java/com/notnoop/apns/internal/TlsTunnelBuilder.java index 5e0d68cf..b84d0b07 100644 --- a/src/main/java/com/notnoop/apns/internal/TlsTunnelBuilder.java +++ b/src/main/java/com/notnoop/apns/internal/TlsTunnelBuilder.java @@ -35,16 +35,19 @@ import java.net.ProtocolException; import java.net.Proxy; import java.net.Socket; + import javax.net.ssl.SSLSocketFactory; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.apache.commons.httpclient.ConnectMethod; -import org.apache.commons.httpclient.NTCredentials; -import org.apache.commons.httpclient.ProxyClient; -import org.apache.commons.httpclient.UsernamePasswordCredentials; -import org.apache.commons.httpclient.auth.AuthScope; + +import org.apache.http.HttpHost; +import org.apache.http.auth.NTCredentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.ProxyClient; +import org.apache.http.impl.execchain.TunnelRefusedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * Establishes a TLS connection using an HTTP proxy. See RFC 2817 5.2. This class does @@ -87,27 +90,26 @@ Socket makeTunnel(String host, int port, String proxyUsername, logger.debug("Creating socket for Proxy : " + proxyAddress.getAddress() + ":" + proxyAddress.getPort()); Socket socket; try { - ProxyClient client = new ProxyClient(); - client.getParams().setParameter("http.useragent", "java-apns"); - client.getHostConfiguration().setHost(host, port); String proxyHost = proxyAddress.getAddress().toString().substring(0, proxyAddress.getAddress().toString().indexOf("/")); - client.getHostConfiguration().setProxy(proxyHost, proxyAddress.getPort()); + + HttpHost proxyHttpHost = new HttpHost(proxyHost, proxyAddress.getPort()); + HttpHost destHttpHost = new HttpHost(host, port); + ProxyClient proxyClient = new ProxyClient(); - - ProxyClient.ConnectResponse response = client.connect(); - socket = response.getSocket(); - if (socket == null) { - ConnectMethod method = response.getConnectMethod(); - // Read the proxy's HTTP response. - if(method.getStatusLine().getStatusCode() == 407) { - // Proxy server returned 407. We will now try to connect with auth Header - if(proxyUsername != null && proxyPassword != null) { - socket = AuthenticateProxy(method, client,proxyHost, proxyAddress.getPort(), - proxyUsername, proxyPassword); - } else { - throw new ProtocolException("Socket not created: " + method.getStatusLine()); - } - } + if (proxyUsername == null || proxyPassword == null) { + // Empty credentials created to fulfill api contract in case of proxy without credentials + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("", ""); + socket = proxyClient.tunnel(proxyHttpHost, destHttpHost, credentials); + } else { + try { + UsernamePasswordCredentials cred = new UsernamePasswordCredentials(proxyUsername, proxyPassword); + socket = proxyClient.tunnel(proxyHttpHost, destHttpHost, cred); + } catch (TunnelRefusedException e) { + // To support NT credentials we try to connect once more + // Would be nicer to move the decision of which credentials to use + NTCredentials credentials = new NTCredentials(proxyUsername, proxyPassword, null, null); + socket = proxyClient.tunnel(proxyHttpHost, destHttpHost, credentials); + } } } catch (Exception e) { @@ -119,29 +121,4 @@ Socket makeTunnel(String host, int port, String proxyUsername, return socket; } - private Socket AuthenticateProxy(ConnectMethod method, ProxyClient client, - String proxyHost, int proxyPort, - String proxyUsername, String proxyPassword) throws IOException { - if("ntlm".equalsIgnoreCase(method.getProxyAuthState().getAuthScheme().getSchemeName())) { - // If Auth scheme is NTLM, set NT credentials with blank host and domain name - client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort), - new NTCredentials(proxyUsername, proxyPassword,"","")); - } else { - // If Auth scheme is Basic/Digest, set regular Credentials - client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort), - new UsernamePasswordCredentials(proxyUsername, proxyPassword)); - } - - ProxyClient.ConnectResponse response = client.connect(); - Socket socket = response.getSocket(); - - if (socket == null) { - method = response.getConnectMethod(); - throw new ProtocolException("Proxy Authentication failed. Socket not created: " - + method.getStatusLine()); - } - return socket; - } - } - diff --git a/src/test/java/com/notnoop/apns/internal/TlsTunnelBuilderTest.java b/src/test/java/com/notnoop/apns/internal/TlsTunnelBuilderTest.java index 833bed55..8d1796a6 100644 --- a/src/test/java/com/notnoop/apns/internal/TlsTunnelBuilderTest.java +++ b/src/test/java/com/notnoop/apns/internal/TlsTunnelBuilderTest.java @@ -30,48 +30,110 @@ */ package com.notnoop.apns.internal; -import java.io.ByteArrayInputStream; +import static org.junit.Assert.assertNotNull; + +import com.sun.net.httpserver.HttpServer; + import java.io.IOException; -import java.io.InputStream; -//import java.net.InetSocketAddress; -//import java.net.Proxy; -//import java.net.Socket; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.fail; +import org.littleshoot.proxy.HttpProxyServer; +import org.littleshoot.proxy.ProxyAuthenticator; +import org.littleshoot.proxy.impl.DefaultHttpProxyServer; public class TlsTunnelBuilderTest { + private static final String PROXY_USERNAME = "proxy-username"; + private static final String PROXY_PASSWORD = "proxy-password"; + private TestHttpService testHttpService; + private String remoteHost; + private int remoteport = 9999; + private int localport = 8888; + private HttpProxyServer server; + + @Before + public void setUp() throws UnknownHostException { + + InetSocketAddress address = new InetSocketAddress(remoteport); + testHttpService = new TestHttpService(address); + remoteHost = address.getHostName(); + + server = DefaultHttpProxyServer.bootstrap() + .withProxyAuthenticator(new ProxyAuthenticator() { + @Override + public boolean authenticate(String userName, String password) { + return PROXY_USERNAME.equals(userName) && PROXY_PASSWORD.equals(password); + } + }) + .withPort(localport) + .start(); + } + + @After + public void tearDown() { + testHttpService.stop(); + server.stop(); + } + @Test public void makeTunnelSuccess() throws IOException { - /* Uncomment this test to verify with your proxy settings */ - /*try { - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.mydomain.com", 8080)); - - InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address(); - Socket proxySocket = new Socket(proxyAddress.getAddress(), proxyAddress.getPort()); - InetSocketAddress destAddress = new InetSocketAddress("myhost.com", 2195); - - new TlsTunnelBuilder().makeTunnel(destAddress.getAddress().toString(), - destAddress.getPort(), - "proxy-username", "proxy-password", - proxyAddress); - } catch (IOException ex){ - fail(); - }*/ + /* Change host in this test to verify with your proxy settings */ + + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", localport)); + + InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address(); + Socket proxySocket = new Socket(proxyAddress.getAddress(), proxyAddress.getPort()); + assertNotNull(proxySocket); + proxySocket.close(); + + InetSocketAddress destAddress = new InetSocketAddress(remoteHost, remoteport); + + Socket remoteAddress = new Socket(destAddress.getAddress(), destAddress.getPort()); + assertNotNull(remoteAddress); + remoteAddress.close(); + + Socket socket = new TlsTunnelBuilder() + .makeTunnel( + remoteHost, + remoteport, + PROXY_USERNAME, + PROXY_PASSWORD, + proxyAddress); + assertNotNull(socket); } - @Test + @Test(expected = IOException.class) public void invalidProxyParams() throws IOException { - try { - new TlsTunnelBuilder().makeTunnel("origin.example.com", 9876, null, null, null); - fail(); - } catch (IOException expected) { - // No operation - } + new TlsTunnelBuilder().makeTunnel("origin.example.com", 9876, null, null, null); } - private InputStream inputStream(String content) throws IOException { - return new ByteArrayInputStream(content.getBytes("UTF-8")); + + public class TestHttpService { + + private HttpServer server; + + public TestHttpService(InetSocketAddress inetSocketAddress) { + try { + server = HttpServer.create(inetSocketAddress, 0); + server.createContext("/"); + server.setExecutor(null); + server.start(); + } catch (IOException e) { + throw new IllegalStateException("Could not get ip to localhost", e); + } + } + + public void stop() { + server.stop(0); + } + } + } From f1dc0221232199307ed60825a01405f3a2ea4fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 12:57:59 +0200 Subject: [PATCH 02/11] [maven-release-plugin] prepare release apns-1.0.0.Beta7-EC-3.2.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 01bb99c0..4954bb4e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.0.Beta7-SNAPSHOT + 1.0.0.Beta7-EC-3.2.0 jar Java Apple Push Notification Service Library @@ -17,7 +17,7 @@ scm:git:git://github.com/notnoop/java-apns.git scm:git:git@github.com:notnoop/java-apns.git http://github.com/notnoop/java-apns - HEAD + apns-1.0.0.Beta7-EC-3.2.0 From 4bd9815737b90a2bcb55fde2ea0e58ec0e07f336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:00:16 +0200 Subject: [PATCH 03/11] [maven-release-plugin] prepare release apns-1.0.0.Beta7-EC-3.2.0 --- pom.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 4954bb4e..cbb1ddb4 100644 --- a/pom.xml +++ b/pom.xml @@ -14,9 +14,9 @@ - scm:git:git://github.com/notnoop/java-apns.git - scm:git:git@github.com:notnoop/java-apns.git - http://github.com/notnoop/java-apns + scm:git:git://github.com/encapsecurity/java-apns.git + scm:git:git@github.com:encapsecurity/java-apns.git + http://github.com/encapsecurity/java-apns apns-1.0.0.Beta7-EC-3.2.0 @@ -66,7 +66,7 @@ maven-jar-plugin 2.4 - + ${project.build.outputDirectory}/META-INF/MANIFEST.MF @@ -78,14 +78,14 @@ - + maven-javadoc-plugin 2.9.1 - + generate-javadoc @@ -125,9 +125,9 @@ bundle-manifest process-classes - + manifest - + From 1dc7d4926e2eebfda0cbaa40b945acab4e15c314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:04:14 +0200 Subject: [PATCH 04/11] REL: Prepare for release --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cbb1ddb4..3e17ac04 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.0.Beta7-EC-3.2.0 + 1.0.0.Beta7-EC-3.2.0-SNAPSHOT jar Java Apple Push Notification Service Library From 20e8751fd1ea85023227c27a10c13e1ee88debeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:06:08 +0200 Subject: [PATCH 05/11] [maven-release-plugin] prepare release apns-1.0.0.Beta7-EC-3.2.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3e17ac04..3460bd4e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.0.Beta7-EC-3.2.0-SNAPSHOT + 1.0.0.Beta7-EC-3.2.1 jar Java Apple Push Notification Service Library @@ -17,7 +17,7 @@ scm:git:git://github.com/encapsecurity/java-apns.git scm:git:git@github.com:encapsecurity/java-apns.git http://github.com/encapsecurity/java-apns - apns-1.0.0.Beta7-EC-3.2.0 + apns-1.0.0.Beta7-EC-3.2.1 From 63b68b4d46237f69643d93b683ab999d9c57af75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:06:14 +0200 Subject: [PATCH 06/11] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3460bd4e..1c665c5d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.0.Beta7-EC-3.2.1 + 1.0.1.Beta7-EC-3.2.1-SNAPSHOT jar Java Apple Push Notification Service Library @@ -17,7 +17,7 @@ scm:git:git://github.com/encapsecurity/java-apns.git scm:git:git@github.com:encapsecurity/java-apns.git http://github.com/encapsecurity/java-apns - apns-1.0.0.Beta7-EC-3.2.1 + apns-1.0.0.Beta7-EC-3.2.0 From ea8e0663ca403c1912c4000d3ab161b4a7cf96d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:19:04 +0200 Subject: [PATCH 07/11] [maven-release-plugin] rollback the release of apns-1.0.0.Beta7-EC-3.2.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1c665c5d..3e17ac04 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.1.Beta7-EC-3.2.1-SNAPSHOT + 1.0.0.Beta7-EC-3.2.0-SNAPSHOT jar Java Apple Push Notification Service Library From 0f630debd0cc6e7cd945ef669a7fea555ac94c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:20:48 +0200 Subject: [PATCH 08/11] REL: Prepare for release --- pom.xml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 3e17ac04..5842519b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,13 +6,6 @@ jar Java Apple Push Notification Service Library - - - org.sonatype.oss - oss-parent - 9 - - scm:git:git://github.com/encapsecurity/java-apns.git scm:git:git@github.com:encapsecurity/java-apns.git @@ -20,6 +13,20 @@ apns-1.0.0.Beta7-EC-3.2.0 + + + + encap-release-repo + https://test.encap.no/repository/content/repositories/releases + true + + + encap-snapshot-repo + https://test.encap.no/repository/content/repositories/snapshots + true + + + UTF-8 From 6bf8b306c375e36e5de89c5c1fbe854636da55b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:22:59 +0200 Subject: [PATCH 09/11] [maven-release-plugin] prepare release apns-1.0.0.Beta7-EC-3.2.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5842519b..9bb554e8 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.0.Beta7-EC-3.2.0-SNAPSHOT + 1.0.0.Beta7-EC-3.2.2 jar Java Apple Push Notification Service Library @@ -10,7 +10,7 @@ scm:git:git://github.com/encapsecurity/java-apns.git scm:git:git@github.com:encapsecurity/java-apns.git http://github.com/encapsecurity/java-apns - apns-1.0.0.Beta7-EC-3.2.0 + apns-1.0.0.Beta7-EC-3.2.2 From 0825f7506bbef6e8c67c3e82c06fe3775926112a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 13:23:07 +0200 Subject: [PATCH 10/11] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9bb554e8..d8815fcb 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.0.Beta7-EC-3.2.2 + 1.0.1.Beta7-EC-3.2.2-SNAPSHOT jar Java Apple Push Notification Service Library @@ -10,7 +10,7 @@ scm:git:git://github.com/encapsecurity/java-apns.git scm:git:git@github.com:encapsecurity/java-apns.git http://github.com/encapsecurity/java-apns - apns-1.0.0.Beta7-EC-3.2.2 + apns-1.0.0.Beta7-EC-3.2.0 From 5067cd7df81048ed23e9f70bbb7f6c454d8f5c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Werup?= Date: Fri, 3 Jun 2016 14:00:50 +0200 Subject: [PATCH 11/11] Fixed version number of development version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d8815fcb..84e5e02b 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.notnoop.apns apns - 1.0.1.Beta7-EC-3.2.2-SNAPSHOT + 1.0.0.Beta7-EC-3.2.2-SNAPSHOT jar Java Apple Push Notification Service Library