From 4fb22f26654c9452e5444157ea118be1957361b8 Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Fri, 31 Mar 2017 18:22:59 -0400 Subject: [PATCH 1/3] Updated to Netty 4.1.9/netty-tcnative 2.0.0. --- README.md | 8 ++++---- pom.xml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4169c66eb..6edfe04fd 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,11 @@ If you use [Maven](http://maven.apache.org/), you can add Pushy to your project ``` -It's very important to note that you will also need to have either `netty-tcnative` (1.1.33.Fork24 or newer) or `alpn-boot`, as discussed in the [system requirements](#system-requirements) section below. +It's very important to note that you will also need to have either `netty-tcnative` (2.0.0.Final or newer) or `alpn-boot`, as discussed in the [system requirements](#system-requirements) section below. If you don't use Maven (or something else that understands Maven dependencies, like Gradle), you can [download Pushy as a `.jar` file](https://github.com/relayrides/pushy/releases/download/pushy-0.9.2/pushy-0.9.2.jar) and add it to your project directly. You'll also need to make sure you have Pushy's runtime dependencies on your classpath. They are: -- [netty 4.1.6](http://netty.io/) +- [netty 4.1.9](http://netty.io/) - [gson 2.6](https://github.com/google/gson) - [slf4j 1.7.6](http://www.slf4j.org/) (and possibly an SLF4J binding, as described in the [logging](#logging) section below) - [alpn-api](http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html) if you've opted to use a native SSL provider (`alpn-api` is included in `alpn-boot`); please see the [system requirements](#system-requirements) section for details) @@ -167,13 +167,13 @@ To add the netty-tcnative uber-jar, you'll just need to add the following depend io.netty netty-tcnative-boringssl-static - 1.1.33.Fork24 + 2.0.0.Final ``` Otherwise, you may add the jar to your classpath by the means of your choice. -Please note that Pushy requires netty-tcnative 1.1.33.Fork24 or newer. Additionally, you'll need [`alpn-api`](http://mvnrepository.com/artifact/org.eclipse.jetty.alpn/alpn-api) as a `runtime` dependency for your project. If you're managing dependencies manually, you'll just need to make sure the latest version of `alpn-api` is available on your classpath. +Please note that Pushy requires netty-tcnative 2.0.0.Final or newer. Additionally, you'll need [`alpn-api`](http://mvnrepository.com/artifact/org.eclipse.jetty.alpn/alpn-api) as a `runtime` dependency for your project. If you're managing dependencies manually, you'll just need to make sure the latest version of `alpn-api` is available on your classpath. ### Using Jetty's ALPN implementation diff --git a/pom.xml b/pom.xml index 64160dfc5..a9f489509 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ io.netty netty-tcnative-boringssl-static - 1.1.33.Fork24 + 2.0.0.Final test @@ -82,7 +82,7 @@ - 4.1.6.Final + 4.1.9.Final 1.7.21 UTF-8 From 4ce3b805d8c88213c7f0728d104c576cdc9234f6 Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Fri, 31 Mar 2017 18:31:14 -0400 Subject: [PATCH 2/3] Removed untrusted certificate tests. --- pushy/script/generate-certs.sh | 8 +--- .../pushy/apns/ApnsClientBuilder.java | 38 ++++-------------- .../relayrides/pushy/apns/ApnsClientTest.java | 26 ------------ pushy/src/test/resources/untrusted-client.p12 | Bin 2469 -> 0 bytes 4 files changed, 9 insertions(+), 63 deletions(-) delete mode 100644 pushy/src/test/resources/untrusted-client.p12 diff --git a/pushy/script/generate-certs.sh b/pushy/script/generate-certs.sh index bc8d904b9..358988e38 100755 --- a/pushy/script/generate-certs.sh +++ b/pushy/script/generate-certs.sh @@ -14,15 +14,10 @@ openssl req -new -keyout single-topic-client.key -nodes -newkey rsa:2048 -subj " openssl req -new -keyout multi-topic-client.key -nodes -newkey rsa:2048 -subj "/CN=Apple Push Services: com.relayrides.pushy/UID=com.relayrides.pushy" | \ openssl x509 -extfile ./apns-extensions.cnf -extensions apns_multi_topic_client_extensions -req -CAkey ca.key -CA ca.pem -days 36500 -set_serial $RANDOM -sha512 -out multi-topic-client.pem -# We also want one bogus (self-signed) certificate to make sure the mock server is turning away untrusted clients -openssl req -new -keyout untrusted-client.key -nodes -newkey rsa:2048 -subj "/CN=Apple Push Services: com.relayrides.pushy/UID=com.relayrides.pushy" | \ - openssl x509 -extfile ./apns-extensions.cnf -extensions apns_single_topic_client_extensions -req -days 36500 -set_serial $RANDOM -signkey untrusted-client.key -out untrusted-client.pem - # For simplicity, squish everything down into PKCS#12 keystores openssl pkcs12 -export -in server.pem -inkey server.key -out server.p12 -password pass:pushy-test openssl pkcs12 -export -in single-topic-client.pem -inkey single-topic-client.key -out single-topic-client.p12 -password pass:pushy-test openssl pkcs12 -export -in multi-topic-client.pem -inkey multi-topic-client.key -out multi-topic-client.p12 -password pass:pushy-test -openssl pkcs12 -export -in untrusted-client.pem -inkey untrusted-client.key -out untrusted-client.p12 -password pass:pushy-test # We'll also want one keystore with an unprotected key to make sure no-password constructors behave correctly openssl pkcs12 -export -in single-topic-client.pem -inkey single-topic-client.key -out single-topic-client-unprotected.p12 -nodes -password pass:pushy-test @@ -44,6 +39,5 @@ openssl pkcs12 -export -in ca.pem -nokeys -out no-keys.p12 -password pass:pushy- openssl ecparam -name prime256v1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -out token-auth-private-key.p8 # Clean up intermediate files -rm ca.key multi-topic-client.key single-topic-client.key untrusted-client.key +rm ca.key multi-topic-client.key single-topic-client.key rm multiple-keys.jks -rm untrusted-client.pem diff --git a/pushy/src/main/java/com/relayrides/pushy/apns/ApnsClientBuilder.java b/pushy/src/main/java/com/relayrides/pushy/apns/ApnsClientBuilder.java index 6b94dab8e..3f664d9e8 100644 --- a/pushy/src/main/java/com/relayrides/pushy/apns/ApnsClientBuilder.java +++ b/pushy/src/main/java/com/relayrides/pushy/apns/ApnsClientBuilder.java @@ -71,8 +71,6 @@ public class ApnsClientBuilder { private InputStream trustedServerCertificateInputStream; private X509Certificate[] trustedServerCertificates; - private SslProvider preferredSslProvider; - private EventLoopGroup eventLoopGroup; private ApnsClientMetricsListener metricsListener; @@ -239,22 +237,6 @@ public ApnsClientBuilder setTrustedServerCertificateChain(final X509Certificate. return this; } - /** - * Sets the SSL provider to be used by the client under construction. By default, the client will use a native SSL - * provider if available and fall back to the JDK provider otherwise. - * - * @param sslProvider the SSL provider to be used by the client under construction, or {@code null} to choose a - * provider automatically - * - * @return a reference to this builder - * - * @since 0.9 - */ - public ApnsClientBuilder setSslProvider(final SslProvider sslProvider) { - this.preferredSslProvider = sslProvider; - return this; - } - /** *

Sets the event loop group to be used by the client under construction. If not set (or if {@code null}), the * client will create and manage its own event loop group.

@@ -387,21 +369,17 @@ public ApnsClient build() throws SSLException { { final SslProvider sslProvider; - if (this.preferredSslProvider != null) { - sslProvider = this.preferredSslProvider; - } else { - if (OpenSsl.isAvailable()) { - if (OpenSsl.isAlpnSupported()) { - log.info("Native SSL provider is available and supports ALPN; will use native provider."); - sslProvider = SslProvider.OPENSSL; - } else { - log.info("Native SSL provider is available, but does not support ALPN; will use JDK SSL provider."); - sslProvider = SslProvider.JDK; - } + if (OpenSsl.isAvailable()) { + if (OpenSsl.isAlpnSupported()) { + log.info("Native SSL provider is available and supports ALPN; will use native provider."); + sslProvider = SslProvider.OPENSSL; } else { - log.info("Native SSL provider not available; will use JDK SSL provider."); + log.info("Native SSL provider is available, but does not support ALPN; will use JDK SSL provider."); sslProvider = SslProvider.JDK; } + } else { + log.info("Native SSL provider not available; will use JDK SSL provider."); + sslProvider = SslProvider.JDK; } final SslContextBuilder sslContextBuilder = SslContextBuilder.forClient() diff --git a/pushy/src/test/java/com/relayrides/pushy/apns/ApnsClientTest.java b/pushy/src/test/java/com/relayrides/pushy/apns/ApnsClientTest.java index 2a3722b25..d068bdb47 100644 --- a/pushy/src/test/java/com/relayrides/pushy/apns/ApnsClientTest.java +++ b/pushy/src/test/java/com/relayrides/pushy/apns/ApnsClientTest.java @@ -34,7 +34,6 @@ import com.relayrides.pushy.apns.util.SimpleApnsPushNotification; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.handler.ssl.SslProvider; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; @@ -44,7 +43,6 @@ public class ApnsClientTest { private static final String SINGLE_TOPIC_CLIENT_KEYSTORE_FILENAME = "/single-topic-client.p12"; private static final String MULTI_TOPIC_CLIENT_KEYSTORE_FILENAME = "/multi-topic-client.p12"; - private static final String UNTRUSTED_CLIENT_KEYSTORE_FILENAME = "/untrusted-client.p12"; private static final String CA_CERTIFICATE_FILENAME = "/ca.pem"; private static final String SERVER_KEYSTORE = "/server.p12"; @@ -69,8 +67,6 @@ public class ApnsClientTest { private ApnsClient tlsAuthenticationClient; private ApnsClient tokenAuthenticationClient; - private SslProvider preferredSslProvider; - private static class TestMetricsListener implements ApnsClientMetricsListener { private final List writeFailures = new ArrayList<>(); @@ -227,21 +223,17 @@ public void setUp() throws Exception { this.server.start(PORT).await(); - this.preferredSslProvider = "jdk".equals(System.getenv("PUSHY_SSL_PROVIDER")) ? SslProvider.JDK : null; - try (final InputStream p12InputStream = ApnsClientTest.class.getResourceAsStream(SINGLE_TOPIC_CLIENT_KEYSTORE_FILENAME)) { this.tlsAuthenticationClient = new ApnsClientBuilder() .setClientCredentials(p12InputStream, KEYSTORE_PASSWORD) .setTrustedServerCertificateChain(CA_CERTIFICATE) .setEventLoopGroup(EVENT_LOOP_GROUP) - .setSslProvider(this.preferredSslProvider) .build(); } this.tokenAuthenticationClient = new ApnsClientBuilder() .setTrustedServerCertificateChain(CA_CERTIFICATE) .setEventLoopGroup(EVENT_LOOP_GROUP) - .setSslProvider(this.preferredSslProvider) .build(); this.tlsAuthenticationClient.connect(HOST, PORT).await(); @@ -366,24 +358,6 @@ public void testGetReconnectionFutureWhenNotConnected() throws Exception { assertFalse(reconnectionFuture.isSuccess()); } - @Test - public void testConnectWithUntrustedCertificate() throws Exception { - final ApnsClient untrustedClient; - - try (final InputStream p12InputStream = ApnsClientTest.class.getResourceAsStream(UNTRUSTED_CLIENT_KEYSTORE_FILENAME)) { - untrustedClient = new ApnsClientBuilder() - .setClientCredentials(p12InputStream, KEYSTORE_PASSWORD) - .setTrustedServerCertificateChain(CA_CERTIFICATE) - .setEventLoopGroup(EVENT_LOOP_GROUP) - .build(); - } - - final Future connectFuture = untrustedClient.connect(HOST, PORT).await(); - assertFalse(connectFuture.isSuccess()); - - untrustedClient.disconnect().await(); - } - @Test(expected = IllegalStateException.class) public void testRegisterSigningKeyWithTlsAuthentication() throws Exception { this.tlsAuthenticationClient.registerSigningKey((ECPrivateKey) KeyPairUtil.generateKeyPair().getPrivate(), "team-id", "key-id", "topic"); diff --git a/pushy/src/test/resources/untrusted-client.p12 b/pushy/src/test/resources/untrusted-client.p12 deleted file mode 100644 index 74448f2dc67c2be7d46bfbe14b46a0d56a5ac514..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2469 zcmV;W30n3rf(fAl0Ru3C319_It>=hKrKYtGeEzMStTfZut zqjfKE%%XP6lpuswu0(PEQueIxX$}*7Fue56#`xIx76M=BkE)qUnufiW|6$T7P2~Vt zO&JutfSa{Aq2lDrBqS z9#W9<>NFeYq@%NSbcEZ zR4}+F-cE-l5H8i~3&pN;w)0}oy?k3CPVP`WD)CzWZRny~EOD*ukDPWP zI)hFpv2!&cnG88Zk%gWfC?2gI@4*~uDEE5+=bP=iHMX~y{9~^mCtRc?X(WQs_P>P5 z99Z?HVcU|=6~?dQL$=-4;i4Nx{`%0bN^Yon;k~x{QRvj#=~4e^)1&;mYN(l*?nJ2@ zcj?c<2NM~HT7@cL{@Wlg%)s2@kCeQ-qcXVu=c&2z4Hhaq<7~!(G0V<98Q%${SdvGf zEOXI}D3b-8;QUTR|^ z2qf9JE-=WHvB$M~*lP)@UyEkXB_U0wkOZ8!SPT&SGJl=psdkbagpWv&9{!6?VYMPQ z4)ELV)Zeh0`JT4jS?}!F-0C+tG>1y+Rfjinrx!cnyklp2uwgWnS9AI+1k7D2?uX;n<@HC zleVogA1>WS!vO%M1d|ZXM3LU$(GECXx_cPCoOr~ z8=Y4mh`9`8@%^p9D?posY@Vsbu6UlA9v=!H`EbtDDIB}LoF|-z1{FDoJD*#Pu7WH1 zCihbqJE_jl;Q}OiiOyQ8zh|scbx~@2X3P+0>B00P^?m1+;lTgHt4}hg7InxUA#w9< z6P8s#UhZR6g~Y_h15g9oW!yF;oOmKwN+_&4D4VKY#_v>XFoFd^1_>&LNQUY5=Kk;^v{&_W;d3Q_o)N)zhi=U61*#p&xb=-~ ztiZ?*bzTm!jcvLmDv>N*>0eJ(N?^sJ*gT&pL+Tj)z76(s4Is=PbaCF=ps_d7Z=qhB zugpmY@Ky6#Z4NhkU=#2p4MjC8gT-P@mOt|~x8c2`s_yy}Ge>y?_RPrtnXfnAoaKf0 z(eOLDeR6@5sHs^qM^ZSgF<#sE&4!+T##W}~5GZTZGbS{oR+D#pKrsgN z?CJJaP<+goSpidXaP+C`KiTt2tGk9O7+d)?pLmtGBxBxzfNJNWsDNuDzulbIcsHz0 zG`V9Tq^0$r7ErQ<4E>a*E55N4ar7X&8ePh-+hA@^gpcT`T#tX4eY&~Xb}=yt=K0VU zU_u6@XFqY~aeyNMpg)NM_%XKwTH$>ak>0&FM^UFaWg3l2!}eL@DYf`VL*RvRwCr}^ z7!j*evc!3|l?PG7wejlp&f944`CXsoU%SlBwFpK+MrkW{fCM*r58`!kUFjJyZk&M5 zcM*v!sq%@f9oR}t*~YX0T zrb<%j6OPdJC@?Y>nQQc{3H>g}86)!o-hHixVI9gMmr++Epm8E zFP<4^B%@ql#P%sT|2VsfZW{NL z{6|H}!_260O&l3QoE#^ucRTC=VCGF}yb5ukVBf2M*J#f$? zd~)w@?Z^D4X^f|KJBS?I*>68vx~9mO!Xs&}4f+#XP9RCcx#NqELmit)b{w;#T-$*h zXMckao7(8_{1z?uz{LCu&+23>mtv?&lL9o(+#wv#n(V<-EMCP@eX{6sYp`?5ts5BX zCiBnPcp>{l6mp`O*%+j8bCVi*M82zSqt5BmEF2YU1%rlxVGEoGETF~4Z?G`7IqI?k z%!|DwvjB(gs8%P=ik3-Ox%xmwMtC=4V7;f`4_-+w#zlNJR?VmKZ0r2|-04Ge Date: Mon, 3 Apr 2017 15:42:41 -0400 Subject: [PATCH 3/3] Depend on `netty-tcnative` by default. --- README.md | 38 +++----------------------------------- pom.xml | 11 +++++------ pushy/pom.xml | 8 ++++---- 3 files changed, 12 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 6edfe04fd..fc69419ab 100644 --- a/README.md +++ b/README.md @@ -21,14 +21,13 @@ If you use [Maven](http://maven.apache.org/), you can add Pushy to your project ``` -It's very important to note that you will also need to have either `netty-tcnative` (2.0.0.Final or newer) or `alpn-boot`, as discussed in the [system requirements](#system-requirements) section below. - If you don't use Maven (or something else that understands Maven dependencies, like Gradle), you can [download Pushy as a `.jar` file](https://github.com/relayrides/pushy/releases/download/pushy-0.9.2/pushy-0.9.2.jar) and add it to your project directly. You'll also need to make sure you have Pushy's runtime dependencies on your classpath. They are: - [netty 4.1.9](http://netty.io/) +- [netty-tcnative-2.0.0.Final](http://netty.io/wiki/forked-tomcat-native.html) - [gson 2.6](https://github.com/google/gson) - [slf4j 1.7.6](http://www.slf4j.org/) (and possibly an SLF4J binding, as described in the [logging](#logging) section below) -- [alpn-api](http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html) if you've opted to use a native SSL provider (`alpn-api` is included in `alpn-boot`); please see the [system requirements](#system-requirements) section for details) +- [alpn-api](http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html) Pushy itself requires Java 7 or newer to build and run. @@ -148,38 +147,7 @@ When shutting down, clients will wait for all sent-but-not-acknowledged notifica ## System requirements -Pushy works with Java 7 and newer, but has some additional dependencies depending on the environment in which it is running. - -The APNs protocol is built on top of the [HTTP/2 protocol](https://http2.github.io/). HTTP/2 is a relatively new protocol, and relies on some new developments that aren't yet wide-spread in the Java world. In particular: - -1. HTTP/2 depends on [ALPN](https://tools.ietf.org/html/rfc7301), a TLS extension for protocol negotiation. No version of Java has native ALPN support at this time. The ALPN requirement may be met either by [using a native SSL provider](#using-a-native-ssl-provider) or by [using Jetty's ALPN implementation](#using-jettys-alpn-implementation) under Java 7 or 8. -2. The HTTP/2 specification requires the use of [ciphers](https://httpwg.github.io/specs/rfc7540.html#rfc.section.9.2.2) that weren't introduced in Java until Java 8. Using a native SSL provider is the best way to meet this requirement under Java 7. A native SSL provider isn't a requirement under Java 8, but may still yield performance gains. - -Generally speaking, a native SSL provider is the best way to fulfill the system requirements imposed by HTTP/2 because installation is fairly straightforward, it works for Java 7 onward and generally offers better SSL performance than the JDK SSL provider. - -### Using a native SSL provider - -Using a native SSL provider (like [OpenSSL](https://www.openssl.org/), [BoringSSL](https://boringssl.googlesource.com/boringssl/), or [LibreSSL](http://www.libressl.org/)) via `netty-tcnative` fulfills the ALPN and cipher suite requirements imposed by HTTP/2 under all supported versions of Java. To use a native SSL provider, you'll need to add `netty-tcnative` as a dependency to your project. The `netty-tcnative` wiki provides [detailed instructions](http://netty.io/wiki/forked-tomcat-native.html), but in short, you'll need to add one additional platform-specific dependency to your project; we recommend using a statically-linked "uber jar" flavor for supported operating systems/CPU architectures (currently `linux-x86_64`, `osx-x86_64`, and `windows-x86_64`). This approach will meet all requirements imposed by HTTP/2 under Java 7 and 8. - -To add the netty-tcnative uber-jar, you'll just need to add the following dependency (if you're using Maven): - -```xml - - io.netty - netty-tcnative-boringssl-static - 2.0.0.Final - -``` - -Otherwise, you may add the jar to your classpath by the means of your choice. - -Please note that Pushy requires netty-tcnative 2.0.0.Final or newer. Additionally, you'll need [`alpn-api`](http://mvnrepository.com/artifact/org.eclipse.jetty.alpn/alpn-api) as a `runtime` dependency for your project. If you're managing dependencies manually, you'll just need to make sure the latest version of `alpn-api` is available on your classpath. - -### Using Jetty's ALPN implementation - -As an alternative to a native SSL provider, Jetty's ALPN implementation. Please note that if you're not using Oracle JDK 8 or newer (or if you're using a JDK other than Oracle's), you'll need to meet the cipher suite requirement separately; you may do so either by using a native SSL provider (which also fulfills the ALPN requirement) or by using another cryptography provider (which is beyond the scope of this document). - -Using Jetty's ALPN implementation is somewhat more complicated than using a native SSL provider. You'll need to choose a version of `alpn-boot` specific to the version (down to the update!) of the JDK you're using, and then add it to your *boot* class path (note that this is *not* the same as your regular classpath). [Detailed instructions](http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html) are provided by Jetty. If you choose to use the `alpn-boot` approach instead of a native SSL provider, we strongly recommend using [`jetty-alpn-agent`](https://github.com/jetty-project/jetty-alpn-agent), which will automatically choose the correct version of `alpn-boot` for your JRE. +Pushy works with Java 7 and newer. By default, it depends on `netty-tcnative` and should work "out of the box" for most users. Users who can't (or choose not to) use `netty-tcnative` will need to take extra steps to [configure a JDK SSL provider](https://github.com/relayrides/pushy/wiki/Using-a-JDK-SSL-provider). ## Metrics diff --git a/pom.xml b/pom.xml index a9f489509..2ba78635a 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,11 @@ netty-handler-proxy ${netty.version} + + io.netty + netty-tcnative-boringssl-static + 2.0.0.Final + com.google.code.gson gson @@ -64,12 +69,6 @@ ${slf4j.version} test - - io.netty - netty-tcnative-boringssl-static - 2.0.0.Final - test - diff --git a/pushy/pom.xml b/pushy/pom.xml index 148b6fa12..e21f56ea2 100644 --- a/pushy/pom.xml +++ b/pushy/pom.xml @@ -21,6 +21,10 @@ io.netty netty-handler-proxy + + io.netty + netty-tcnative-boringssl-static + com.google.code.gson gson @@ -42,10 +46,6 @@ org.slf4j slf4j-simple - - io.netty - netty-tcnative-boringssl-static -