diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60a8142 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/netty-4.0.28.Final.tar.gz diff --git a/.rh-java-common-netty.metadata b/.rh-java-common-netty.metadata new file mode 100644 index 0000000..cf488fa --- /dev/null +++ b/.rh-java-common-netty.metadata @@ -0,0 +1 @@ +b2fe0c498f7bb85f5f98c4992ffef082bc62cfc2 SOURCES/netty-4.0.28.Final.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 98f42b4..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/netty-old-jzlib.patch b/SOURCES/netty-old-jzlib.patch new file mode 100644 index 0000000..45db8de --- /dev/null +++ b/SOURCES/netty-old-jzlib.patch @@ -0,0 +1,91 @@ +--- codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java.orig 2015-07-03 11:47:23.545978767 +0100 ++++ codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java 2015-07-03 11:47:33.284855182 +0100 +@@ -140,8 +140,7 @@ + } + + int resultCode = z.init( +- compressionLevel, windowBits, memLevel, +- ZlibUtil.convertWrapperType(wrapper)); ++ compressionLevel, windowBits, memLevel); + if (resultCode != JZlib.Z_OK) { + ZlibUtil.fail(z, "initialization failure", resultCode); + } +@@ -225,8 +225,7 @@ + } + int resultCode; + resultCode = z.deflateInit( +- compressionLevel, windowBits, memLevel, +- JZlib.W_ZLIB); // Default: ZLIB format ++ compressionLevel, windowBits, memLevel); + if (resultCode != JZlib.Z_OK) { + ZlibUtil.fail(z, "initialization failure", resultCode); + } else { +--- codec/src/main/java/io/netty/handler/codec/compression/JZlibDecoder.java.orig 2015-07-03 11:45:12.040647549 +0100 ++++ codec/src/main/java/io/netty/handler/codec/compression/JZlibDecoder.java 2015-07-03 11:45:42.114265920 +0100 +@@ -47,7 +47,7 @@ + throw new NullPointerException("wrapper"); + } + +- int resultCode = z.init(ZlibUtil.convertWrapperType(wrapper)); ++ int resultCode = z.init(); + if (resultCode != JZlib.Z_OK) { + ZlibUtil.fail(z, "initialization failure", resultCode); + } +@@ -67,7 +67,7 @@ + this.dictionary = dictionary; + + int resultCode; +- resultCode = z.inflateInit(JZlib.W_ZLIB); ++ resultCode = z.inflateInit(); + if (resultCode != JZlib.Z_OK) { + ZlibUtil.fail(z, "initialization failure", resultCode); + } +--- codec/src/main/java/io/netty/handler/codec/compression/ZlibUtil.java.orig 2015-07-03 11:51:33.209807700 +0100 ++++ codec/src/main/java/io/netty/handler/codec/compression/ZlibUtil.java 2015-07-03 11:58:07.594767969 +0100 +@@ -17,7 +17,6 @@ + + import com.jcraft.jzlib.Deflater; + import com.jcraft.jzlib.Inflater; +-import com.jcraft.jzlib.JZlib; + + /** + * Utility methods used by {@link JZlibEncoder} and {@link JZlibDecoder}. +@@ -40,27 +39,6 @@ + return new CompressionException(message + " (" + resultCode + ')' + (z.msg != null? ": " + z.msg : "")); + } + +- static JZlib.WrapperType convertWrapperType(ZlibWrapper wrapper) { +- JZlib.WrapperType convertedWrapperType; +- switch (wrapper) { +- case NONE: +- convertedWrapperType = JZlib.W_NONE; +- break; +- case ZLIB: +- convertedWrapperType = JZlib.W_ZLIB; +- break; +- case GZIP: +- convertedWrapperType = JZlib.W_GZIP; +- break; +- case ZLIB_OR_NONE: +- convertedWrapperType = JZlib.W_ANY; +- break; +- default: +- throw new Error(); +- } +- return convertedWrapperType; +- } +- + static int wrapperOverhead(ZlibWrapper wrapper) { + int overhead; + switch (wrapper) { +--- codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockJZlibEncoder.java.orig 2015-07-03 12:04:31.063867729 +0100 ++++ codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockJZlibEncoder.java 2015-07-03 12:04:39.829755712 +0100 +@@ -47,7 +47,7 @@ + } + + int resultCode = z.deflateInit( +- compressionLevel, windowBits, memLevel, JZlib.W_ZLIB); ++ compressionLevel, windowBits, memLevel); + if (resultCode != JZlib.Z_OK) { + throw new CompressionException( + "failed to initialize an SPDY header block deflater: " + resultCode); diff --git a/SOURCES/npn_alpn_ssl_fixes.patch b/SOURCES/npn_alpn_ssl_fixes.patch new file mode 100644 index 0000000..48c4842 --- /dev/null +++ b/SOURCES/npn_alpn_ssl_fixes.patch @@ -0,0 +1,4384 @@ +commit b654e334d8df083dca71f330c6d9d7306ab78649 +Author: Severin Gehwolf +Date: Wed May 20 13:19:37 2015 +0200 + + Remove optional NPN/ALPN/OpenSSL handlers. + +diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java b/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java +deleted file mode 100644 +index aaaf5b7..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java ++++ /dev/null +@@ -1,120 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import javax.net.ssl.SSLEngine; +- +-/** +- * The {@link JdkApplicationProtocolNegotiator} to use if you need ALPN and are using {@link SslProvider#JDK}. +- */ +-public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator { +- private static final SslEngineWrapperFactory ALPN_WRAPPER = new SslEngineWrapperFactory() { +- { +- if (!JdkAlpnSslEngine.isAvailable()) { +- throw new RuntimeException("ALPN unsupported. Is your classpatch configured correctly?" +- + " See http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-starting"); +- } +- } +- +- @Override +- public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator, +- boolean isServer) { +- return new JdkAlpnSslEngine(engine, applicationNegotiator, isServer); +- } +- }; +- +- /** +- * Create a new instance. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(Iterable protocols) { +- this(false, protocols); +- } +- +- /** +- * Create a new instance. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(String... protocols) { +- this(false, protocols); +- } +- +- /** +- * Create a new instance. +- * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, Iterable protocols) { +- this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols); +- } +- +- /** +- * Create a new instance. +- * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, String... protocols) { +- this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols); +- } +- +- /** +- * Create a new instance. +- * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected. +- * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols, +- boolean serverFailIfNoCommonProtocols, Iterable protocols) { +- this(serverFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY, +- clientFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY, +- protocols); +- } +- +- /** +- * Create a new instance. +- * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected. +- * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols, +- boolean serverFailIfNoCommonProtocols, String... protocols) { +- this(serverFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY, +- clientFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY, +- protocols); +- } +- +- /** +- * Create a new instance. +- * @param selectorFactory The factory which provides classes responsible for selecting the protocol. +- * @param listenerFactory The factory which provides to be notified of which protocol was selected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory, +- ProtocolSelectionListenerFactory listenerFactory, Iterable protocols) { +- super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols); +- } +- +- /** +- * Create a new instance. +- * @param selectorFactory The factory which provides classes responsible for selecting the protocol. +- * @param listenerFactory The factory which provides to be notified of which protocol was selected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkAlpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory, +- ProtocolSelectionListenerFactory listenerFactory, String... protocols) { +- super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols); +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkAlpnSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/JdkAlpnSslEngine.java +deleted file mode 100644 +index 6cfacb8..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/JdkAlpnSslEngine.java ++++ /dev/null +@@ -1,117 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import static io.netty.util.internal.ObjectUtil.checkNotNull; +-import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener; +-import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector; +-import io.netty.util.internal.PlatformDependent; +- +-import java.util.LinkedHashSet; +-import java.util.List; +- +-import javax.net.ssl.SSLEngine; +-import javax.net.ssl.SSLException; +- +-import org.eclipse.jetty.alpn.ALPN; +-import org.eclipse.jetty.alpn.ALPN.ClientProvider; +-import org.eclipse.jetty.alpn.ALPN.ServerProvider; +- +-final class JdkAlpnSslEngine extends JdkSslEngine { +- private static boolean available; +- +- static boolean isAvailable() { +- updateAvailability(); +- return available; +- } +- +- private static void updateAvailability() { +- if (available) { +- return; +- } +- +- try { +- // Always use bootstrap class loader. +- Class.forName("sun.security.ssl.ALPNExtension", true, null); +- available = true; +- } catch (Exception ignore) { +- // alpn-boot was not loaded. +- } +- } +- +- JdkAlpnSslEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator, boolean server) { +- super(engine); +- checkNotNull(applicationNegotiator, "applicationNegotiator"); +- +- if (server) { +- final ProtocolSelector protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory() +- .newSelector(this, new LinkedHashSet(applicationNegotiator.protocols())), +- "protocolSelector"); +- ALPN.put(engine, new ServerProvider() { +- @Override +- public String select(List protocols) { +- try { +- return protocolSelector.select(protocols); +- } catch (Throwable t) { +- PlatformDependent.throwException(t); +- return null; +- } +- } +- +- @Override +- public void unsupported() { +- protocolSelector.unsupported(); +- } +- }); +- } else { +- final ProtocolSelectionListener protocolListener = checkNotNull(applicationNegotiator +- .protocolListenerFactory().newListener(this, applicationNegotiator.protocols()), +- "protocolListener"); +- ALPN.put(engine, new ClientProvider() { +- @Override +- public List protocols() { +- return applicationNegotiator.protocols(); +- } +- +- @Override +- public void selected(String protocol) { +- try { +- protocolListener.selected(protocol); +- } catch (Throwable t) { +- PlatformDependent.throwException(t); +- } +- } +- +- @Override +- public void unsupported() { +- protocolListener.unsupported(); +- } +- }); +- } +- } +- +- @Override +- public void closeInbound() throws SSLException { +- ALPN.remove(getWrappedEngine()); +- super.closeInbound(); +- } +- +- @Override +- public void closeOutbound() { +- ALPN.remove(getWrappedEngine()); +- super.closeOutbound(); +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkNpnApplicationProtocolNegotiator.java b/handler/src/main/java/io/netty/handler/ssl/JdkNpnApplicationProtocolNegotiator.java +deleted file mode 100644 +index c893f05..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/JdkNpnApplicationProtocolNegotiator.java ++++ /dev/null +@@ -1,120 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import javax.net.ssl.SSLEngine; +- +-/** +- * The {@link JdkApplicationProtocolNegotiator} to use if you need NPN and are using {@link SslProvider#JDK}. +- */ +-public final class JdkNpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator { +- private static final SslEngineWrapperFactory NPN_WRAPPER = new SslEngineWrapperFactory() { +- { +- if (!JdkNpnSslEngine.isAvailable()) { +- throw new RuntimeException("NPN unsupported. Is your classpatch configured correctly?" +- + " See http://www.eclipse.org/jetty/documentation/current/npn-chapter.html#npn-starting"); +- } +- } +- +- @Override +- public SSLEngine wrapSslEngine(SSLEngine engine, JdkApplicationProtocolNegotiator applicationNegotiator, +- boolean isServer) { +- return new JdkNpnSslEngine(engine, applicationNegotiator, isServer); +- } +- }; +- +- /** +- * Create a new instance. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(Iterable protocols) { +- this(false, protocols); +- } +- +- /** +- * Create a new instance. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(String... protocols) { +- this(false, protocols); +- } +- +- /** +- * Create a new instance. +- * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, Iterable protocols) { +- this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols); +- } +- +- /** +- * Create a new instance. +- * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, String... protocols) { +- this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols); +- } +- +- /** +- * Create a new instance. +- * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected. +- * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols, +- boolean serverFailIfNoCommonProtocols, Iterable protocols) { +- this(clientFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY, +- serverFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY, +- protocols); +- } +- +- /** +- * Create a new instance. +- * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected. +- * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols, +- boolean serverFailIfNoCommonProtocols, String... protocols) { +- this(clientFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY, +- serverFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY, +- protocols); +- } +- +- /** +- * Create a new instance. +- * @param selectorFactory The factory which provides classes responsible for selecting the protocol. +- * @param listenerFactory The factory which provides to be notified of which protocol was selected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory, +- ProtocolSelectionListenerFactory listenerFactory, Iterable protocols) { +- super(NPN_WRAPPER, selectorFactory, listenerFactory, protocols); +- } +- +- /** +- * Create a new instance. +- * @param selectorFactory The factory which provides classes responsible for selecting the protocol. +- * @param listenerFactory The factory which provides to be notified of which protocol was selected. +- * @param protocols The order of iteration determines the preference of support for protocols. +- */ +- public JdkNpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory, +- ProtocolSelectionListenerFactory listenerFactory, String... protocols) { +- super(NPN_WRAPPER, selectorFactory, listenerFactory, protocols); +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkNpnSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/JdkNpnSslEngine.java +deleted file mode 100644 +index 422727a..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/JdkNpnSslEngine.java ++++ /dev/null +@@ -1,122 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +- +-package io.netty.handler.ssl; +- +-import static io.netty.util.internal.ObjectUtil.checkNotNull; +-import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectionListener; +-import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector; +-import io.netty.util.internal.PlatformDependent; +- +-import java.util.LinkedHashSet; +-import java.util.List; +- +-import javax.net.ssl.SSLEngine; +-import javax.net.ssl.SSLException; +- +-import org.eclipse.jetty.npn.NextProtoNego; +-import org.eclipse.jetty.npn.NextProtoNego.ClientProvider; +-import org.eclipse.jetty.npn.NextProtoNego.ServerProvider; +- +-final class JdkNpnSslEngine extends JdkSslEngine { +- private static boolean available; +- +- static boolean isAvailable() { +- updateAvailability(); +- return available; +- } +- +- private static void updateAvailability() { +- if (available) { +- return; +- } +- try { +- // Always use bootstrap class loader. +- Class.forName("sun.security.ssl.NextProtoNegoExtension", true, null); +- available = true; +- } catch (Exception ignore) { +- // npn-boot was not loaded. +- } +- } +- +- JdkNpnSslEngine(SSLEngine engine, final JdkApplicationProtocolNegotiator applicationNegotiator, boolean server) { +- super(engine); +- checkNotNull(applicationNegotiator, "applicationNegotiator"); +- +- if (server) { +- final ProtocolSelectionListener protocolListener = checkNotNull(applicationNegotiator +- .protocolListenerFactory().newListener(this, applicationNegotiator.protocols()), +- "protocolListener"); +- NextProtoNego.put(engine, new ServerProvider() { +- @Override +- public void unsupported() { +- protocolListener.unsupported(); +- } +- +- @Override +- public List protocols() { +- return applicationNegotiator.protocols(); +- } +- +- @Override +- public void protocolSelected(String protocol) { +- try { +- protocolListener.selected(protocol); +- } catch (Throwable t) { +- PlatformDependent.throwException(t); +- } +- } +- }); +- } else { +- final ProtocolSelector protocolSelector = checkNotNull(applicationNegotiator.protocolSelectorFactory() +- .newSelector(this, new LinkedHashSet(applicationNegotiator.protocols())), +- "protocolSelector"); +- NextProtoNego.put(engine, new ClientProvider() { +- @Override +- public boolean supports() { +- return true; +- } +- +- @Override +- public void unsupported() { +- protocolSelector.unsupported(); +- } +- +- @Override +- public String selectProtocol(List protocols) { +- try { +- return protocolSelector.select(protocols); +- } catch (Throwable t) { +- PlatformDependent.throwException(t); +- return null; +- } +- } +- }); +- } +- } +- +- @Override +- public void closeInbound() throws SSLException { +- NextProtoNego.remove(getWrappedEngine()); +- super.closeInbound(); +- } +- +- @Override +- public void closeOutbound() { +- NextProtoNego.remove(getWrappedEngine()); +- super.closeOutbound(); +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java +index 54ee2be..e3ffb67 100644 +--- a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java ++++ b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java +@@ -220,50 +220,6 @@ public abstract class JdkSslContext extends SslContext { + switch(config.protocol()) { + case NONE: + return JdkDefaultApplicationProtocolNegotiator.INSTANCE; +- case ALPN: +- if (isServer) { +- switch(config.selectorFailureBehavior()) { +- case FATAL_ALERT: +- return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols()); +- case NO_ADVERTISE: +- return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols()); +- default: +- throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") +- .append(config.selectorFailureBehavior()).append(" failure behavior").toString()); +- } +- } else { +- switch(config.selectedListenerFailureBehavior()) { +- case ACCEPT: +- return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols()); +- case FATAL_ALERT: +- return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols()); +- default: +- throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") +- .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString()); +- } +- } +- case NPN: +- if (isServer) { +- switch(config.selectedListenerFailureBehavior()) { +- case ACCEPT: +- return new JdkNpnApplicationProtocolNegotiator(false, config.supportedProtocols()); +- case FATAL_ALERT: +- return new JdkNpnApplicationProtocolNegotiator(true, config.supportedProtocols()); +- default: +- throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") +- .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString()); +- } +- } else { +- switch(config.selectorFailureBehavior()) { +- case FATAL_ALERT: +- return new JdkNpnApplicationProtocolNegotiator(true, config.supportedProtocols()); +- case NO_ADVERTISE: +- return new JdkNpnApplicationProtocolNegotiator(false, config.supportedProtocols()); +- default: +- throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") +- .append(config.selectorFailureBehavior()).append(" failure behavior").toString()); +- } +- } + default: + throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") + .append(config.protocol()).append(" protocol").toString()); +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java +deleted file mode 100644 +index 619768a..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java ++++ /dev/null +@@ -1,194 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +- +-package io.netty.handler.ssl; +- +-import io.netty.util.internal.NativeLibraryLoader; +-import io.netty.util.internal.logging.InternalLogger; +-import io.netty.util.internal.logging.InternalLoggerFactory; +-import org.apache.tomcat.jni.Library; +-import org.apache.tomcat.jni.Pool; +-import org.apache.tomcat.jni.SSL; +-import org.apache.tomcat.jni.SSLContext; +- +-import java.util.Collections; +-import java.util.LinkedHashSet; +-import java.util.Set; +- +-/** +- * Tells if {@code netty-tcnative} and its OpenSSL support +- * are available. +- */ +-public final class OpenSsl { +- +- private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSsl.class); +- private static final Throwable UNAVAILABILITY_CAUSE; +- +- private static final Set AVAILABLE_CIPHER_SUITES; +- +- static { +- Throwable cause = null; +- +- // Test if netty-tcnative is in the classpath first. +- try { +- Class.forName("org.apache.tomcat.jni.SSL", false, OpenSsl.class.getClassLoader()); +- } catch (ClassNotFoundException t) { +- cause = t; +- logger.debug( +- "netty-tcnative not in the classpath; " + +- OpenSslEngine.class.getSimpleName() + " will be unavailable."); +- } +- +- // If in the classpath, try to load the native library and initialize netty-tcnative. +- if (cause == null) { +- try { +- NativeLibraryLoader.load("netty-tcnative", SSL.class.getClassLoader()); +- Library.initialize("provided"); +- SSL.initialize(null); +- } catch (Throwable t) { +- cause = t; +- logger.debug( +- "Failed to load netty-tcnative; " + +- OpenSslEngine.class.getSimpleName() + " will be unavailable. " + +- "See http://netty.io/wiki/forked-tomcat-native.html for more information.", t); +- } +- } +- +- UNAVAILABILITY_CAUSE = cause; +- +- if (cause == null) { +- final Set availableCipherSuites = new LinkedHashSet(128); +- final long aprPool = Pool.create(0); +- try { +- final long sslCtx = SSLContext.make(aprPool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER); +- try { +- SSLContext.setOptions(sslCtx, SSL.SSL_OP_ALL); +- SSLContext.setCipherSuite(sslCtx, "ALL"); +- final long ssl = SSL.newSSL(sslCtx, true); +- try { +- for (String c: SSL.getCiphers(ssl)) { +- // Filter out bad input. +- if (c == null || c.length() == 0 || availableCipherSuites.contains(c)) { +- continue; +- } +- availableCipherSuites.add(c); +- } +- } finally { +- SSL.freeSSL(ssl); +- } +- } finally { +- SSLContext.free(sslCtx); +- } +- } catch (Exception e) { +- logger.warn("Failed to get the list of available OpenSSL cipher suites.", e); +- } finally { +- Pool.destroy(aprPool); +- } +- +- AVAILABLE_CIPHER_SUITES = Collections.unmodifiableSet(availableCipherSuites); +- } else { +- AVAILABLE_CIPHER_SUITES = Collections.emptySet(); +- } +- } +- +- /** +- * Returns {@code true} if and only if +- * {@code netty-tcnative} and its OpenSSL support +- * are available. +- */ +- public static boolean isAvailable() { +- return UNAVAILABILITY_CAUSE == null; +- } +- +- /** +- * Returns {@code true} if the used version of openssl supports +- * ALPN. +- */ +- public static boolean isAlpnSupported() { +- return version() >= 0x10002000L; +- } +- +- /** +- * Returns the version of the used available OpenSSL library or {@code -1} if {@link #isAvailable()} +- * returns {@code false}. +- */ +- public static int version() { +- if (isAvailable()) { +- return SSL.version(); +- } +- return -1; +- } +- +- /** +- * Returns the version string of the used available OpenSSL library or {@code null} if {@link #isAvailable()} +- * returns {@code false}. +- */ +- public static String versionString() { +- if (isAvailable()) { +- return SSL.versionString(); +- } +- return null; +- } +- +- /** +- * Ensure that {@code netty-tcnative} and +- * its OpenSSL support are available. +- * +- * @throws UnsatisfiedLinkError if unavailable +- */ +- public static void ensureAvailability() { +- if (UNAVAILABILITY_CAUSE != null) { +- throw (Error) new UnsatisfiedLinkError( +- "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE); +- } +- } +- +- /** +- * Returns the cause of unavailability of +- * {@code netty-tcnative} and its OpenSSL support. +- * +- * @return the cause if unavailable. {@code null} if available. +- */ +- public static Throwable unavailabilityCause() { +- return UNAVAILABILITY_CAUSE; +- } +- +- /** +- * Returns all the available OpenSSL cipher suites. +- * Please note that the returned array may include the cipher suites that are insecure or non-functional. +- */ +- public static Set availableCipherSuites() { +- return AVAILABLE_CIPHER_SUITES; +- } +- +- /** +- * Returns {@code true} if and only if the specified cipher suite is available in OpenSSL. +- * Both Java-style cipher suite and OpenSSL-style cipher suite are accepted. +- */ +- public static boolean isCipherSuiteAvailable(String cipherSuite) { +- String converted = CipherSuiteConverter.toOpenSsl(cipherSuite); +- if (converted != null) { +- cipherSuite = converted; +- } +- return AVAILABLE_CIPHER_SUITES.contains(cipherSuite); +- } +- +- static boolean isError(long errorCode) { +- return errorCode != SSL.SSL_ERROR_NONE; +- } +- +- private OpenSsl() { } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java +deleted file mode 100644 +index 85f15d1..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java ++++ /dev/null +@@ -1,333 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import io.netty.buffer.ByteBuf; +-import io.netty.buffer.ByteBufInputStream; +-import org.apache.tomcat.jni.SSL; +-import org.apache.tomcat.jni.SSLContext; +- +-import javax.net.ssl.KeyManagerFactory; +-import javax.net.ssl.SSLException; +-import javax.net.ssl.TrustManager; +-import javax.net.ssl.TrustManagerFactory; +-import javax.net.ssl.X509ExtendedTrustManager; +-import javax.net.ssl.X509TrustManager; +-import javax.security.auth.x500.X500Principal; +-import java.io.File; +-import java.io.IOException; +-import java.security.KeyStore; +-import java.security.KeyStoreException; +-import java.security.NoSuchAlgorithmException; +-import java.security.cert.CertificateException; +-import java.security.cert.X509Certificate; +- +-/** +- * A client-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation. +- */ +-public final class OpenSslClientContext extends OpenSslContext { +- private final OpenSslSessionContext sessionContext; +- +- /** +- * Creates a new instance. +- */ +- public OpenSslClientContext() throws SSLException { +- this(null, null, null, null, null, null, null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format. +- * {@code null} to use the system default +- */ +- public OpenSslClientContext(File certChainFile) throws SSLException { +- this(certChainFile, null); +- } +- +- /** +- * Creates a new instance. +- * +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from servers. +- * {@code null} to use the default. +- */ +- public OpenSslClientContext(TrustManagerFactory trustManagerFactory) throws SSLException { +- this(null, trustManagerFactory); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format. +- * {@code null} to use the system default +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from servers. +- * {@code null} to use the default. +- */ +- public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException { +- this(certChainFile, trustManagerFactory, null, null, null, null, null, +- IdentityCipherSuiteFilter.INSTANCE, null, 0, 0); +- } +- +- /** +- * @deprecated use {@link #OpenSslClientContext(File, TrustManagerFactory, Iterable, +- * CipherSuiteFilter, ApplicationProtocolConfig, long, long)} +- * +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from servers. +- * {@code null} to use the default.. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param apn Provides a means to configure parameters related to application protocol negotiation. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- @Deprecated +- public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory, Iterable ciphers, +- ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) +- throws SSLException { +- this(certChainFile, trustManagerFactory, null, null, null, null, ciphers, IdentityCipherSuiteFilter.INSTANCE, +- apn, sessionCacheSize, sessionTimeout); +- } +- +- /** +- * @deprecated use {@link #OpenSslClientContext(File, TrustManagerFactory, File, File, String, +- * KeyManagerFactory, Iterable, CipherSuiteFilter, ApplicationProtocolConfig,long, long)} +- * +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from servers. +- * {@code null} to use the default.. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * @param apn Provides a means to configure parameters related to application protocol negotiation. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- @Deprecated +- public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory, Iterable ciphers, +- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(certChainFile, trustManagerFactory, null, null, null, null, +- ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * @param trustCertChainFile an X.509 certificate chain file in PEM format. +- * {@code null} to use the system default +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from servers. +- * {@code null} to use the default or the results of parsing {@code trustCertChainFile} +- * @param keyCertChainFile an X.509 certificate chain file in PEM format. +- * This provides the public key for mutual authentication. +- * {@code null} to use the system default +- * @param keyFile a PKCS#8 private key file in PEM format. +- * This provides the private key for mutual authentication. +- * {@code null} for no mutual authentication. +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * Ignored if {@code keyFile} is {@code null}. +- * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link javax.net.ssl.KeyManager}s +- * that is used to encrypt data being sent to servers. +- * {@code null} to use the default or the results of parsing +- * {@code keyCertChainFile} and {@code keyFile}. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * @param apn Application Protocol Negotiator object. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- public OpenSslClientContext(File trustCertChainFile, TrustManagerFactory trustManagerFactory, +- File keyCertChainFile, File keyFile, String keyPassword, +- KeyManagerFactory keyManagerFactory, Iterable ciphers, +- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, +- long sessionCacheSize, long sessionTimeout) +- throws SSLException { +- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT); +- boolean success = false; +- try { +- if (trustCertChainFile != null && !trustCertChainFile.isFile()) { +- throw new IllegalArgumentException("trustCertChainFile is not a file: " + trustCertChainFile); +- } +- +- if (keyCertChainFile != null && !keyCertChainFile.isFile()) { +- throw new IllegalArgumentException("keyCertChainFile is not a file: " + keyCertChainFile); +- } +- +- if (keyFile != null && !keyFile.isFile()) { +- throw new IllegalArgumentException("keyFile is not a file: " + keyFile); +- } +- if (keyFile == null && keyCertChainFile != null || keyFile != null && keyCertChainFile == null) { +- throw new IllegalArgumentException( +- "Either both keyCertChainFile and keyFile needs to be null or none of them"); +- } +- synchronized (OpenSslContext.class) { +- if (trustCertChainFile != null) { +- /* Load the certificate chain. We must skip the first cert when server mode */ +- if (!SSLContext.setCertificateChainFile(ctx, trustCertChainFile.getPath(), true)) { +- long error = SSL.getLastErrorNumber(); +- if (OpenSsl.isError(error)) { +- throw new SSLException( +- "failed to set certificate chain: " +- + trustCertChainFile + " (" + SSL.getErrorString(error) + ')'); +- } +- } +- } +- if (keyCertChainFile != null && keyFile != null) { +- /* Load the certificate file and private key. */ +- try { +- if (!SSLContext.setCertificate( +- ctx, keyCertChainFile.getPath(), keyFile.getPath(), keyPassword, SSL.SSL_AIDX_RSA)) { +- long error = SSL.getLastErrorNumber(); +- if (OpenSsl.isError(error)) { +- throw new SSLException("failed to set certificate: " + +- keyCertChainFile + " and " + keyFile + +- " (" + SSL.getErrorString(error) + ')'); +- } +- } +- } catch (SSLException e) { +- throw e; +- } catch (Exception e) { +- throw new SSLException("failed to set certificate: " + keyCertChainFile + " and " + keyFile, e); +- } +- } +- +- SSLContext.setVerify(ctx, SSL.SSL_VERIFY_NONE, VERIFY_DEPTH); +- +- try { +- // Set up trust manager factory to use our key store. +- if (trustManagerFactory == null) { +- trustManagerFactory = TrustManagerFactory.getInstance( +- TrustManagerFactory.getDefaultAlgorithm()); +- } +- initTrustManagerFactory(trustCertChainFile, trustManagerFactory); +- final X509TrustManager manager = chooseTrustManager(trustManagerFactory.getTrustManagers()); +- +- // Use this to prevent an error when running on java < 7 +- if (useExtendedTrustManager(manager)) { +- final X509ExtendedTrustManager extendedManager = (X509ExtendedTrustManager) manager; +- SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() { +- @Override +- void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth) +- throws Exception { +- extendedManager.checkServerTrusted(peerCerts, auth, engine); +- } +- }); +- } else { +- SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() { +- @Override +- void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth) +- throws Exception { +- manager.checkServerTrusted(peerCerts, auth); +- } +- }); +- } +- } catch (Exception e) { +- throw new SSLException("unable to setup trustmanager", e); +- } +- } +- sessionContext = new OpenSslClientSessionContext(ctx); +- success = true; +- } finally { +- if (!success) { +- destroyPools(); +- } +- } +- } +- +- private static void initTrustManagerFactory(File certChainFile, TrustManagerFactory trustManagerFactory) +- throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { +- KeyStore ks = KeyStore.getInstance("JKS"); +- ks.load(null, null); +- if (certChainFile != null) { +- ByteBuf[] certs = PemReader.readCertificates(certChainFile); +- try { +- for (ByteBuf buf: certs) { +- X509Certificate cert = (X509Certificate) X509_CERT_FACTORY.generateCertificate( +- new ByteBufInputStream(buf)); +- X500Principal principal = cert.getSubjectX500Principal(); +- ks.setCertificateEntry(principal.getName("RFC2253"), cert); +- } +- } finally { +- for (ByteBuf buf: certs) { +- buf.release(); +- } +- } +- } +- trustManagerFactory.init(ks); +- } +- +- @Override +- public OpenSslSessionContext sessionContext() { +- return sessionContext; +- } +- +- // No cache is currently supported for client side mode. +- private static final class OpenSslClientSessionContext extends OpenSslSessionContext { +- private OpenSslClientSessionContext(long context) { +- super(context); +- } +- +- @Override +- public void setSessionTimeout(int seconds) { +- if (seconds < 0) { +- throw new IllegalArgumentException(); +- } +- } +- +- @Override +- public int getSessionTimeout() { +- return 0; +- } +- +- @Override +- public void setSessionCacheSize(int size) { +- if (size < 0) { +- throw new IllegalArgumentException(); +- } +- } +- +- @Override +- public int getSessionCacheSize() { +- return 0; +- } +- +- @Override +- public void setSessionCacheEnabled(boolean enabled) { +- // ignored +- } +- +- @Override +- public boolean isSessionCacheEnabled() { +- return false; +- } +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java +deleted file mode 100644 +index 6cfdc57..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java ++++ /dev/null +@@ -1,456 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import io.netty.buffer.ByteBufAllocator; +-import io.netty.util.internal.PlatformDependent; +-import io.netty.util.internal.SystemPropertyUtil; +-import io.netty.util.internal.logging.InternalLogger; +-import io.netty.util.internal.logging.InternalLoggerFactory; +-import org.apache.tomcat.jni.CertificateVerifier; +-import org.apache.tomcat.jni.Pool; +-import org.apache.tomcat.jni.SSL; +-import org.apache.tomcat.jni.SSLContext; +- +-import javax.net.ssl.SSLEngine; +-import javax.net.ssl.SSLException; +-import javax.net.ssl.SSLHandshakeException; +-import javax.net.ssl.TrustManager; +-import javax.net.ssl.X509ExtendedTrustManager; +-import javax.net.ssl.X509TrustManager; +-import java.security.cert.X509Certificate; +-import java.util.ArrayList; +-import java.util.Arrays; +-import java.util.Collections; +-import java.util.List; +-import java.util.Map; +-import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +- +-import static io.netty.util.internal.ObjectUtil.checkNotNull; +-import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; +-import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; +- +-public abstract class OpenSslContext extends SslContext { +- +- private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSslContext.class); +- /** +- * To make it easier for users to replace JDK implemention with OpenSsl version we also use +- * {@code jdk.tls.rejectClientInitiatedRenegotiation} to allow disabling client initiated renegotiation. +- * Java8+ uses this system property as well. +- * +- * See also +- * Significant SSL/TLS improvements in Java 8 +- */ +- private static final boolean JDK_REJECT_CLIENT_INITIATED_RENEGOTIATION = +- SystemPropertyUtil.getBoolean("jdk.tls.rejectClientInitiatedRenegotiation", false); +- private static final List DEFAULT_CIPHERS; +- private static final AtomicIntegerFieldUpdater DESTROY_UPDATER; +- +- // TODO: Maybe make configurable ? +- protected static final int VERIFY_DEPTH = 10; +- +- private final long aprPool; +- @SuppressWarnings({ "unused", "FieldMayBeFinal" }) +- private volatile int aprPoolDestroyed; +- private volatile boolean rejectRemoteInitiatedRenegotiation; +- private final List unmodifiableCiphers; +- private final long sessionCacheSize; +- private final long sessionTimeout; +- private final OpenSslEngineMap engineMap = new DefaultOpenSslEngineMap(); +- +- private final OpenSslApplicationProtocolNegotiator apn; +- /** The OpenSSL SSL_CTX object */ +- protected final long ctx; +- private final int mode; +- +- static final OpenSslApplicationProtocolNegotiator NONE_PROTOCOL_NEGOTIATOR = +- new OpenSslApplicationProtocolNegotiator() { +- @Override +- public ApplicationProtocolConfig.Protocol protocol() { +- return ApplicationProtocolConfig.Protocol.NONE; +- } +- +- @Override +- public List protocols() { +- return Collections.emptyList(); +- } +- +- @Override +- public SelectorFailureBehavior selectorFailureBehavior() { +- return SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL; +- } +- +- @Override +- public SelectedListenerFailureBehavior selectedListenerFailureBehavior() { +- return SelectedListenerFailureBehavior.ACCEPT; +- } +- }; +- +- static { +- List ciphers = new ArrayList(); +- // XXX: Make sure to sync this list with JdkSslEngineFactory. +- Collections.addAll( +- ciphers, +- "ECDHE-RSA-AES128-GCM-SHA256", +- "ECDHE-RSA-AES128-SHA", +- "ECDHE-RSA-AES256-SHA", +- "AES128-GCM-SHA256", +- "AES128-SHA", +- "AES256-SHA", +- "DES-CBC3-SHA", +- "RC4-SHA"); +- DEFAULT_CIPHERS = Collections.unmodifiableList(ciphers); +- +- if (logger.isDebugEnabled()) { +- logger.debug("Default cipher suite (OpenSSL): " + ciphers); +- } +- +- AtomicIntegerFieldUpdater updater = +- PlatformDependent.newAtomicIntegerFieldUpdater(OpenSslContext.class, "aprPoolDestroyed"); +- if (updater == null) { +- updater = AtomicIntegerFieldUpdater.newUpdater(OpenSslContext.class, "aprPoolDestroyed"); +- } +- DESTROY_UPDATER = updater; +- } +- +- OpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apnCfg, +- long sessionCacheSize, long sessionTimeout, int mode) throws SSLException { +- this(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode); +- } +- +- OpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, +- OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize, +- long sessionTimeout, int mode) throws SSLException { +- OpenSsl.ensureAvailability(); +- +- if (mode != SSL.SSL_MODE_SERVER && mode != SSL.SSL_MODE_CLIENT) { +- throw new IllegalArgumentException("mode most be either SSL.SSL_MODE_SERVER or SSL.SSL_MODE_CLIENT"); +- } +- this.mode = mode; +- +- if (mode == SSL.SSL_MODE_SERVER) { +- rejectRemoteInitiatedRenegotiation = +- JDK_REJECT_CLIENT_INITIATED_RENEGOTIATION; +- } +- final List convertedCiphers; +- if (ciphers == null) { +- convertedCiphers = null; +- } else { +- convertedCiphers = new ArrayList(); +- for (String c: ciphers) { +- if (c == null) { +- break; +- } +- +- String converted = CipherSuiteConverter.toOpenSsl(c); +- if (converted != null) { +- c = converted; +- } +- convertedCiphers.add(c); +- } +- } +- +- unmodifiableCiphers = Arrays.asList(checkNotNull(cipherFilter, "cipherFilter").filterCipherSuites( +- convertedCiphers, DEFAULT_CIPHERS, OpenSsl.availableCipherSuites())); +- +- this.apn = checkNotNull(apn, "apn"); +- +- // Allocate a new APR pool. +- aprPool = Pool.create(0); +- +- // Create a new SSL_CTX and configure it. +- boolean success = false; +- try { +- synchronized (OpenSslContext.class) { +- try { +- ctx = SSLContext.make(aprPool, SSL.SSL_PROTOCOL_ALL, mode); +- } catch (Exception e) { +- throw new SSLException("failed to create an SSL_CTX", e); +- } +- +- SSLContext.setOptions(ctx, SSL.SSL_OP_ALL); +- SSLContext.setOptions(ctx, SSL.SSL_OP_NO_SSLv2); +- SSLContext.setOptions(ctx, SSL.SSL_OP_NO_SSLv3); +- SSLContext.setOptions(ctx, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); +- SSLContext.setOptions(ctx, SSL.SSL_OP_SINGLE_ECDH_USE); +- SSLContext.setOptions(ctx, SSL.SSL_OP_SINGLE_DH_USE); +- SSLContext.setOptions(ctx, SSL.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); +- +- /* List the ciphers that are permitted to negotiate. */ +- try { +- SSLContext.setCipherSuite(ctx, CipherSuiteConverter.toOpenSsl(unmodifiableCiphers)); +- } catch (SSLException e) { +- throw e; +- } catch (Exception e) { +- throw new SSLException("failed to set cipher suite: " + unmodifiableCiphers, e); +- } +- +- List nextProtoList = apn.protocols(); +- /* Set next protocols for next protocol negotiation extension, if specified */ +- if (!nextProtoList.isEmpty()) { +- String[] protocols = nextProtoList.toArray(new String[nextProtoList.size()]); +- int selectorBehavior = opensslSelectorFailureBehavior(apn.selectorFailureBehavior()); +- +- switch (apn.protocol()) { +- case NPN: +- SSLContext.setNpnProtos(ctx, protocols, selectorBehavior); +- break; +- case ALPN: +- SSLContext.setAlpnProtos(ctx, protocols, selectorBehavior); +- break; +- case NPN_AND_ALPN: +- SSLContext.setNpnProtos(ctx, protocols, selectorBehavior); +- SSLContext.setAlpnProtos(ctx, protocols, selectorBehavior); +- break; +- default: +- throw new Error(); +- } +- } +- +- /* Set session cache size, if specified */ +- if (sessionCacheSize > 0) { +- this.sessionCacheSize = sessionCacheSize; +- SSLContext.setSessionCacheSize(ctx, sessionCacheSize); +- } else { +- // Get the default session cache size using SSLContext.setSessionCacheSize() +- this.sessionCacheSize = sessionCacheSize = SSLContext.setSessionCacheSize(ctx, 20480); +- // Revert the session cache size to the default value. +- SSLContext.setSessionCacheSize(ctx, sessionCacheSize); +- } +- +- /* Set session timeout, if specified */ +- if (sessionTimeout > 0) { +- this.sessionTimeout = sessionTimeout; +- SSLContext.setSessionCacheTimeout(ctx, sessionTimeout); +- } else { +- // Get the default session timeout using SSLContext.setSessionCacheTimeout() +- this.sessionTimeout = sessionTimeout = SSLContext.setSessionCacheTimeout(ctx, 300); +- // Revert the session timeout to the default value. +- SSLContext.setSessionCacheTimeout(ctx, sessionTimeout); +- } +- } +- success = true; +- } finally { +- if (!success) { +- destroyPools(); +- } +- } +- } +- +- private static int opensslSelectorFailureBehavior(SelectorFailureBehavior behavior) { +- switch (behavior) { +- case NO_ADVERTISE: +- return SSL.SSL_SELECTOR_FAILURE_NO_ADVERTISE; +- case CHOOSE_MY_LAST_PROTOCOL: +- return SSL.SSL_SELECTOR_FAILURE_CHOOSE_MY_LAST_PROTOCOL; +- default: +- throw new Error(); +- } +- } +- +- @Override +- public final List cipherSuites() { +- return unmodifiableCiphers; +- } +- +- @Override +- public final long sessionCacheSize() { +- return sessionCacheSize; +- } +- +- @Override +- public final long sessionTimeout() { +- return sessionTimeout; +- } +- +- @Override +- public ApplicationProtocolNegotiator applicationProtocolNegotiator() { +- return apn; +- } +- +- @Override +- public final boolean isClient() { +- return mode == SSL.SSL_MODE_CLIENT; +- } +- +- @Override +- public final SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) { +- throw new UnsupportedOperationException(); +- } +- +- /** +- * Returns a new server-side {@link javax.net.ssl.SSLEngine} with the current configuration. +- */ +- @Override +- public final SSLEngine newEngine(ByteBufAllocator alloc) { +- final OpenSslEngine engine = new OpenSslEngine( +- ctx, alloc, isClient(), sessionContext(), apn, engineMap, rejectRemoteInitiatedRenegotiation); +- engineMap.add(engine); +- return engine; +- } +- +- /** +- * Returns the {@code SSL_CTX} object of this context. +- */ +- public final long context() { +- return ctx; +- } +- +- /** +- * Returns the stats of this context. +- * @deprecated use {@link #sessionContext#stats()} +- */ +- @Deprecated +- public final OpenSslSessionStats stats() { +- return sessionContext().stats(); +- } +- +- /** +- * Specify if remote initiated renegotiation is supported or not. If not supported and the remote side tries +- * to initiate a renegotiation a {@link SSLHandshakeException} will be thrown during decoding. +- */ +- public void setRejectRemoteInitiatedRenegotiation(boolean rejectRemoteInitiatedRenegotiation) { +- this.rejectRemoteInitiatedRenegotiation = rejectRemoteInitiatedRenegotiation; +- } +- +- @Override +- @SuppressWarnings("FinalizeDeclaration") +- protected final void finalize() throws Throwable { +- super.finalize(); +- synchronized (OpenSslContext.class) { +- if (ctx != 0) { +- SSLContext.free(ctx); +- } +- } +- +- destroyPools(); +- } +- +- /** +- * Sets the SSL session ticket keys of this context. +- * @deprecated use {@link OpenSslSessionContext#setTicketKeys(byte[])} +- */ +- @Deprecated +- public final void setTicketKeys(byte[] keys) { +- sessionContext().setTicketKeys(keys); +- } +- +- @Override +- public abstract OpenSslSessionContext sessionContext(); +- +- protected final void destroyPools() { +- // Guard against multiple destroyPools() calls triggered by construction exception and finalize() later +- if (aprPool != 0 && DESTROY_UPDATER.compareAndSet(this, 0, 1)) { +- Pool.destroy(aprPool); +- } +- } +- +- protected static X509Certificate[] certificates(byte[][] chain) { +- X509Certificate[] peerCerts = new X509Certificate[chain.length]; +- for (int i = 0; i < peerCerts.length; i++) { +- peerCerts[i] = new OpenSslX509Certificate(chain[i]); +- } +- return peerCerts; +- } +- +- protected static X509TrustManager chooseTrustManager(TrustManager[] managers) { +- for (TrustManager m : managers) { +- if (m instanceof X509TrustManager) { +- return (X509TrustManager) m; +- } +- } +- throw new IllegalStateException("no X509TrustManager found"); +- } +- +- /** +- * Translate a {@link ApplicationProtocolConfig} object to a +- * {@link OpenSslApplicationProtocolNegotiator} object. +- * @param config The configuration which defines the translation +- * @return The results of the translation +- */ +- static OpenSslApplicationProtocolNegotiator toNegotiator(ApplicationProtocolConfig config) { +- if (config == null) { +- return NONE_PROTOCOL_NEGOTIATOR; +- } +- +- switch (config.protocol()) { +- case NONE: +- return NONE_PROTOCOL_NEGOTIATOR; +- case ALPN: +- case NPN: +- case NPN_AND_ALPN: +- switch (config.selectedListenerFailureBehavior()) { +- case CHOOSE_MY_LAST_PROTOCOL: +- case ACCEPT: +- switch (config.selectorFailureBehavior()) { +- case CHOOSE_MY_LAST_PROTOCOL: +- case NO_ADVERTISE: +- return new OpenSslDefaultApplicationProtocolNegotiator( +- config); +- default: +- throw new UnsupportedOperationException( +- new StringBuilder("OpenSSL provider does not support ") +- .append(config.selectorFailureBehavior()) +- .append(" behavior").toString()); +- } +- default: +- throw new UnsupportedOperationException( +- new StringBuilder("OpenSSL provider does not support ") +- .append(config.selectedListenerFailureBehavior()) +- .append(" behavior").toString()); +- } +- default: +- throw new Error(); +- } +- } +- +- static boolean useExtendedTrustManager(X509TrustManager trustManager) { +- return PlatformDependent.javaVersion() >= 7 && trustManager instanceof X509ExtendedTrustManager; +- } +- +- abstract class AbstractCertificateVerifier implements CertificateVerifier { +- @Override +- public final boolean verify(long ssl, byte[][] chain, String auth) { +- X509Certificate[] peerCerts = certificates(chain); +- final OpenSslEngine engine = engineMap.remove(ssl); +- try { +- verify(engine, peerCerts, auth); +- return true; +- } catch (Throwable cause) { +- logger.debug("verification of certificate failed", cause); +- SSLHandshakeException e = new SSLHandshakeException("General OpenSslEngine problem"); +- e.initCause(cause); +- engine.handshakeException = e; +- } +- return false; +- } +- +- abstract void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth) throws Exception; +- } +- +- private static final class DefaultOpenSslEngineMap implements OpenSslEngineMap { +- private final Map engines = PlatformDependent.newConcurrentHashMap(); +- @Override +- public OpenSslEngine remove(long ssl) { +- return engines.remove(ssl); +- } +- +- @Override +- public void add(OpenSslEngine engine) { +- engines.put(engine.ssl(), engine); +- } +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java +deleted file mode 100644 +index b5c8e6c..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java ++++ /dev/null +@@ -1,1525 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import io.netty.buffer.ByteBuf; +-import io.netty.buffer.ByteBufAllocator; +-import io.netty.buffer.Unpooled; +-import io.netty.util.internal.EmptyArrays; +-import io.netty.util.internal.PlatformDependent; +-import io.netty.util.internal.StringUtil; +-import io.netty.util.internal.logging.InternalLogger; +-import io.netty.util.internal.logging.InternalLoggerFactory; +-import org.apache.tomcat.jni.Buffer; +-import org.apache.tomcat.jni.SSL; +- +-import javax.net.ssl.SSLEngine; +-import javax.net.ssl.SSLEngineResult; +-import javax.net.ssl.SSLException; +-import javax.net.ssl.SSLHandshakeException; +-import javax.net.ssl.SSLPeerUnverifiedException; +-import javax.net.ssl.SSLSession; +-import javax.net.ssl.SSLSessionBindingEvent; +-import javax.net.ssl.SSLSessionBindingListener; +-import javax.net.ssl.SSLSessionContext; +-import javax.security.cert.CertificateException; +-import javax.security.cert.X509Certificate; +-import java.nio.ByteBuffer; +-import java.nio.ReadOnlyBufferException; +-import java.security.Principal; +-import java.security.cert.Certificate; +-import java.util.ArrayList; +-import java.util.Arrays; +-import java.util.HashMap; +-import java.util.HashSet; +-import java.util.List; +-import java.util.Map; +-import java.util.Set; +-import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +- +-import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; +-import static io.netty.util.internal.ObjectUtil.checkNotNull; +-import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; +-import static javax.net.ssl.SSLEngineResult.Status.*; +- +-/** +- * Implements a {@link SSLEngine} using +- * OpenSSL BIO abstractions. +- */ +-public final class OpenSslEngine extends SSLEngine { +- +- private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSslEngine.class); +- +- private static final Certificate[] EMPTY_CERTIFICATES = EmptyArrays.EMPTY_CERTIFICATES; +- private static final X509Certificate[] EMPTY_X509_CERTIFICATES = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES; +- +- private static final SSLException ENGINE_CLOSED = new SSLException("engine closed"); +- private static final SSLException RENEGOTIATION_UNSUPPORTED = new SSLException("renegotiation unsupported"); +- private static final SSLException ENCRYPTED_PACKET_OVERSIZED = new SSLException("encrypted packet oversized"); +- static { +- ENGINE_CLOSED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); +- RENEGOTIATION_UNSUPPORTED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); +- ENCRYPTED_PACKET_OVERSIZED.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE); +- +- AtomicIntegerFieldUpdater destroyedUpdater = +- PlatformDependent.newAtomicIntegerFieldUpdater(OpenSslEngine.class, "destroyed"); +- if (destroyedUpdater == null) { +- destroyedUpdater = AtomicIntegerFieldUpdater.newUpdater(OpenSslEngine.class, "destroyed"); +- } +- DESTROYED_UPDATER = destroyedUpdater; +- } +- +- private static final int MAX_PLAINTEXT_LENGTH = 16 * 1024; // 2^14 +- private static final int MAX_COMPRESSED_LENGTH = MAX_PLAINTEXT_LENGTH + 1024; +- private static final int MAX_CIPHERTEXT_LENGTH = MAX_COMPRESSED_LENGTH + 1024; +- +- // Protocols +- private static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello"; +- private static final String PROTOCOL_SSL_V2 = "SSLv2"; +- private static final String PROTOCOL_SSL_V3 = "SSLv3"; +- private static final String PROTOCOL_TLS_V1 = "TLSv1"; +- private static final String PROTOCOL_TLS_V1_1 = "TLSv1.1"; +- private static final String PROTOCOL_TLS_V1_2 = "TLSv1.2"; +- +- private static final String[] SUPPORTED_PROTOCOLS = { +- PROTOCOL_SSL_V2_HELLO, +- PROTOCOL_SSL_V2, +- PROTOCOL_SSL_V3, +- PROTOCOL_TLS_V1, +- PROTOCOL_TLS_V1_1, +- PROTOCOL_TLS_V1_2 +- }; +- private static final Set SUPPORTED_PROTOCOLS_SET = new HashSet(Arrays.asList(SUPPORTED_PROTOCOLS)); +- +- // Header (5) + Data (2^14) + Compression (1024) + Encryption (1024) + MAC (20) + Padding (256) +- static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 20 + 256; +- +- static final int MAX_ENCRYPTION_OVERHEAD_LENGTH = MAX_ENCRYPTED_PACKET_LENGTH - MAX_PLAINTEXT_LENGTH; +- +- enum ClientAuthMode { +- NONE, +- OPTIONAL, +- REQUIRE, +- } +- +- private static final AtomicIntegerFieldUpdater DESTROYED_UPDATER; +- +- private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL"; +- +- private static final long EMPTY_ADDR = Buffer.address(Unpooled.EMPTY_BUFFER.nioBuffer()); +- +- private static final SSLEngineResult NEED_UNWRAP_OK = new SSLEngineResult(OK, NEED_UNWRAP, 0, 0); +- private static final SSLEngineResult NEED_UNWRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0); +- private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0); +- private static final SSLEngineResult NEED_WRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0); +- private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0); +- +- // OpenSSL state +- private long ssl; +- private long networkBIO; +- +- /** +- * 0 - not accepted, 1 - accepted implicitly via wrap()/unwrap(), 2 - accepted explicitly via beginHandshake() call +- */ +- private int accepted; +- private boolean handshakeFinished; +- private boolean receivedShutdown; +- @SuppressWarnings("UnusedDeclaration") +- private volatile int destroyed; +- +- // Use an invalid cipherSuite until the handshake is completed +- // See http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html#getSession() +- private volatile String cipher; +- private volatile String applicationProtocol; +- +- // We store this outside of the SslSession so we not need to create an instance during verifyCertificates(...) +- private volatile Certificate[] peerCerts; +- private volatile ClientAuthMode clientAuth = ClientAuthMode.NONE; +- +- // SSL Engine status variables +- private boolean isInboundDone; +- private boolean isOutboundDone; +- private boolean engineClosed; +- +- private final boolean clientMode; +- private final ByteBufAllocator alloc; +- private final OpenSslSessionContext sessionContext; +- private final OpenSslEngineMap engineMap; +- private final OpenSslApplicationProtocolNegotiator apn; +- private final boolean rejectRemoteInitiatedRenegation; +- private final SSLSession session = new OpenSslSession(); +- +- // This is package-private as we set it from OpenSslContext if an exception is thrown during +- // the verification step. +- SSLHandshakeException handshakeException; +- +- /** +- * Creates a new instance +- * +- * @param sslCtx an OpenSSL {@code SSL_CTX} object +- * @param alloc the {@link ByteBufAllocator} that will be used by this engine +- */ +- @Deprecated +- public OpenSslEngine(long sslCtx, ByteBufAllocator alloc, +- @SuppressWarnings("unused") String fallbackApplicationProtocol) { +- this(sslCtx, alloc, false, null, OpenSslContext.NONE_PROTOCOL_NEGOTIATOR, OpenSslEngineMap.EMPTY, false); +- } +- +- /** +- * Creates a new instance +- * +- * @param sslCtx an OpenSSL {@code SSL_CTX} object +- * @param alloc the {@link ByteBufAllocator} that will be used by this engine +- * @param clientMode {@code true} if this is used for clients, {@code false} otherwise +- * @param sessionContext the {@link OpenSslSessionContext} this {@link SSLEngine} belongs to. +- */ +- OpenSslEngine(long sslCtx, ByteBufAllocator alloc, +- boolean clientMode, OpenSslSessionContext sessionContext, +- OpenSslApplicationProtocolNegotiator apn, OpenSslEngineMap engineMap, +- boolean rejectRemoteInitiatedRenegation) { +- OpenSsl.ensureAvailability(); +- if (sslCtx == 0) { +- throw new NullPointerException("sslCtx"); +- } +- +- this.alloc = checkNotNull(alloc, "alloc"); +- this.apn = checkNotNull(apn, "apn"); +- ssl = SSL.newSSL(sslCtx, !clientMode); +- networkBIO = SSL.makeNetworkBIO(ssl); +- this.clientMode = clientMode; +- this.sessionContext = sessionContext; +- this.engineMap = engineMap; +- this.rejectRemoteInitiatedRenegation = rejectRemoteInitiatedRenegation; +- } +- +- @Override +- public SSLSession getHandshakeSession() { +- if (accepted > 0) { +- // handshake started we are able to return the session. +- return session; +- } +- // As stated by the javadocs of getHandshakeSession() we should return null if the handshake not started yet. +- return null; +- } +- +- long ssl() { +- return ssl; +- } +- +- /** +- * Destroys this engine. +- */ +- public synchronized void shutdown() { +- if (DESTROYED_UPDATER.compareAndSet(this, 0, 1)) { +- engineMap.remove(ssl); +- SSL.freeSSL(ssl); +- SSL.freeBIO(networkBIO); +- ssl = networkBIO = 0; +- +- // internal errors can cause shutdown without marking the engine closed +- isInboundDone = isOutboundDone = engineClosed = true; +- } +- } +- +- /** +- * Write plaintext data to the OpenSSL internal BIO +- * +- * Calling this function with src.remaining == 0 is undefined. +- */ +- private int writePlaintextData(final ByteBuffer src) { +- final int pos = src.position(); +- final int limit = src.limit(); +- final int len = Math.min(limit - pos, MAX_PLAINTEXT_LENGTH); +- final int sslWrote; +- +- if (src.isDirect()) { +- final long addr = Buffer.address(src) + pos; +- sslWrote = SSL.writeToSSL(ssl, addr, len); +- if (sslWrote > 0) { +- src.position(pos + sslWrote); +- return sslWrote; +- } +- } else { +- ByteBuf buf = alloc.directBuffer(len); +- try { +- final long addr = memoryAddress(buf); +- +- src.limit(pos + len); +- +- buf.setBytes(0, src); +- src.limit(limit); +- +- sslWrote = SSL.writeToSSL(ssl, addr, len); +- if (sslWrote > 0) { +- src.position(pos + sslWrote); +- return sslWrote; +- } else { +- src.position(pos); +- } +- } finally { +- buf.release(); +- } +- } +- +- throw new IllegalStateException("SSL.writeToSSL() returned a non-positive value: " + sslWrote); +- } +- +- /** +- * Write encrypted data to the OpenSSL network BIO. +- */ +- private int writeEncryptedData(final ByteBuffer src) { +- final int pos = src.position(); +- final int len = src.remaining(); +- if (src.isDirect()) { +- final long addr = Buffer.address(src) + pos; +- final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +- if (netWrote >= 0) { +- src.position(pos + netWrote); +- return netWrote; +- } +- } else { +- final ByteBuf buf = alloc.directBuffer(len); +- try { +- final long addr = memoryAddress(buf); +- +- buf.setBytes(0, src); +- +- final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +- if (netWrote >= 0) { +- src.position(pos + netWrote); +- return netWrote; +- } else { +- src.position(pos); +- } +- } finally { +- buf.release(); +- } +- } +- +- return -1; +- } +- +- /** +- * Read plaintext data from the OpenSSL internal BIO +- */ +- private int readPlaintextData(final ByteBuffer dst) { +- if (dst.isDirect()) { +- final int pos = dst.position(); +- final long addr = Buffer.address(dst) + pos; +- final int len = dst.limit() - pos; +- final int sslRead = SSL.readFromSSL(ssl, addr, len); +- if (sslRead > 0) { +- dst.position(pos + sslRead); +- return sslRead; +- } +- } else { +- final int pos = dst.position(); +- final int limit = dst.limit(); +- final int len = Math.min(MAX_ENCRYPTED_PACKET_LENGTH, limit - pos); +- final ByteBuf buf = alloc.directBuffer(len); +- try { +- final long addr = memoryAddress(buf); +- +- final int sslRead = SSL.readFromSSL(ssl, addr, len); +- if (sslRead > 0) { +- dst.limit(pos + sslRead); +- buf.getBytes(0, dst); +- dst.limit(limit); +- return sslRead; +- } +- } finally { +- buf.release(); +- } +- } +- +- return 0; +- } +- +- /** +- * Read encrypted data from the OpenSSL network BIO +- */ +- private int readEncryptedData(final ByteBuffer dst, final int pending) { +- if (dst.isDirect() && dst.remaining() >= pending) { +- final int pos = dst.position(); +- final long addr = Buffer.address(dst) + pos; +- final int bioRead = SSL.readFromBIO(networkBIO, addr, pending); +- if (bioRead > 0) { +- dst.position(pos + bioRead); +- return bioRead; +- } +- } else { +- final ByteBuf buf = alloc.directBuffer(pending); +- try { +- final long addr = memoryAddress(buf); +- +- final int bioRead = SSL.readFromBIO(networkBIO, addr, pending); +- if (bioRead > 0) { +- int oldLimit = dst.limit(); +- dst.limit(dst.position() + bioRead); +- buf.getBytes(0, dst); +- dst.limit(oldLimit); +- return bioRead; +- } +- } finally { +- buf.release(); +- } +- } +- +- return 0; +- } +- +- @Override +- public synchronized SSLEngineResult wrap( +- final ByteBuffer[] srcs, final int offset, final int length, final ByteBuffer dst) throws SSLException { +- +- // Check to make sure the engine has not been closed +- if (destroyed != 0) { +- return CLOSED_NOT_HANDSHAKING; +- } +- +- // Throw required runtime exceptions +- if (srcs == null) { +- throw new IllegalArgumentException("srcs is null"); +- } +- if (dst == null) { +- throw new IllegalArgumentException("dst is null"); +- } +- +- if (offset >= srcs.length || offset + length > srcs.length) { +- throw new IndexOutOfBoundsException( +- "offset: " + offset + ", length: " + length + +- " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))"); +- } +- +- if (dst.isReadOnly()) { +- throw new ReadOnlyBufferException(); +- } +- +- // Prepare OpenSSL to work in server mode and receive handshake +- if (accepted == 0) { +- beginHandshakeImplicitly(); +- } +- +- // In handshake or close_notify stages, check if call to wrap was made +- // without regard to the handshake status. +- SSLEngineResult.HandshakeStatus handshakeStatus = handshakeStatus0(); +- +- if (handshakeStatus == NEED_UNWRAP) { +- if (!handshakeFinished) { +- return NEED_UNWRAP_OK; +- } +- if (engineClosed) { +- return NEED_UNWRAP_CLOSED; +- } +- } +- +- int bytesProduced = 0; +- int pendingNet; +- +- // Check for pending data in the network BIO +- pendingNet = SSL.pendingWrittenBytesInBIO(networkBIO); +- if (pendingNet > 0) { +- // Do we have enough room in dst to write encrypted data? +- int capacity = dst.remaining(); +- if (capacity < pendingNet) { +- return new SSLEngineResult(BUFFER_OVERFLOW, handshakeStatus, 0, bytesProduced); +- } +- +- // Write the pending data from the network BIO into the dst buffer +- try { +- bytesProduced += readEncryptedData(dst, pendingNet); +- } catch (Exception e) { +- throw new SSLException(e); +- } +- +- // If isOuboundDone is set, then the data from the network BIO +- // was the close_notify message -- we are not required to wait +- // for the receipt the peer's close_notify message -- shutdown. +- if (isOutboundDone) { +- shutdown(); +- } +- +- return new SSLEngineResult(getEngineStatus(), handshakeStatus0(), 0, bytesProduced); +- } +- +- // There was no pending data in the network BIO -- encrypt any application data +- int bytesConsumed = 0; +- int endOffset = offset + length; +- for (int i = offset; i < endOffset; ++ i) { +- final ByteBuffer src = srcs[i]; +- if (src == null) { +- throw new IllegalArgumentException("srcs[" + i + "] is null"); +- } +- while (src.hasRemaining()) { +- +- // Write plaintext application data to the SSL engine +- try { +- bytesConsumed += writePlaintextData(src); +- } catch (Exception e) { +- throw new SSLException(e); +- } +- +- // Check to see if the engine wrote data into the network BIO +- pendingNet = SSL.pendingWrittenBytesInBIO(networkBIO); +- if (pendingNet > 0) { +- // Do we have enough room in dst to write encrypted data? +- int capacity = dst.remaining(); +- if (capacity < pendingNet) { +- return new SSLEngineResult( +- BUFFER_OVERFLOW, handshakeStatus0(), bytesConsumed, bytesProduced); +- } +- +- // Write the pending data from the network BIO into the dst buffer +- try { +- bytesProduced += readEncryptedData(dst, pendingNet); +- } catch (Exception e) { +- throw new SSLException(e); +- } +- +- return new SSLEngineResult(getEngineStatus(), handshakeStatus0(), bytesConsumed, bytesProduced); +- } +- } +- } +- +- return new SSLEngineResult(getEngineStatus(), handshakeStatus0(), bytesConsumed, bytesProduced); +- } +- +- private SSLException newSSLException(String msg) { +- if (!handshakeFinished) { +- return new SSLHandshakeException(msg); +- } +- return new SSLException(msg); +- } +- +- private void checkPendingHandshakeException() throws SSLHandshakeException { +- if (handshakeException != null) { +- SSLHandshakeException exception = handshakeException; +- handshakeException = null; +- shutdown(); +- throw exception; +- } +- } +- +- public synchronized SSLEngineResult unwrap( +- final ByteBuffer[] srcs, int srcsOffset, final int srcsLength, +- final ByteBuffer[] dsts, final int dstsOffset, final int dstsLength) throws SSLException { +- +- // Check to make sure the engine has not been closed +- if (destroyed != 0) { +- return CLOSED_NOT_HANDSHAKING; +- } +- +- // Throw requried runtime exceptions +- if (srcs == null) { +- throw new NullPointerException("srcs"); +- } +- if (srcsOffset >= srcs.length +- || srcsOffset + srcsLength > srcs.length) { +- throw new IndexOutOfBoundsException( +- "offset: " + srcsOffset + ", length: " + srcsLength + +- " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))"); +- } +- if (dsts == null) { +- throw new IllegalArgumentException("dsts is null"); +- } +- if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) { +- throw new IndexOutOfBoundsException( +- "offset: " + dstsOffset + ", length: " + dstsLength + +- " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))"); +- } +- int capacity = 0; +- final int endOffset = dstsOffset + dstsLength; +- for (int i = dstsOffset; i < endOffset; i ++) { +- ByteBuffer dst = dsts[i]; +- if (dst == null) { +- throw new IllegalArgumentException("dsts[" + i + "] is null"); +- } +- if (dst.isReadOnly()) { +- throw new ReadOnlyBufferException(); +- } +- capacity += dst.remaining(); +- } +- +- // Prepare OpenSSL to work in server mode and receive handshake +- if (accepted == 0) { +- beginHandshakeImplicitly(); +- } +- +- // In handshake or close_notify stages, check if call to unwrap was made +- // without regard to the handshake status. +- SSLEngineResult.HandshakeStatus handshakeStatus = handshakeStatus0(); +- if (handshakeStatus == NEED_WRAP) { +- if (!handshakeFinished) { +- return NEED_WRAP_OK; +- } +- if (engineClosed) { +- return NEED_WRAP_CLOSED; +- } +- } +- +- final int srcsEndOffset = srcsOffset + srcsLength; +- int len = 0; +- for (int i = srcsOffset; i < srcsEndOffset; i++) { +- ByteBuffer src = srcs[i]; +- if (src == null) { +- throw new IllegalArgumentException("srcs[" + i + "] is null"); +- } +- len += src.remaining(); +- } +- +- // protect against protocol overflow attack vector +- if (len > MAX_ENCRYPTED_PACKET_LENGTH) { +- isInboundDone = true; +- isOutboundDone = true; +- engineClosed = true; +- shutdown(); +- throw ENCRYPTED_PACKET_OVERSIZED; +- } +- +- // Write encrypted data to network BIO +- int bytesConsumed = -1; +- try { +- while (srcsOffset < srcsEndOffset) { +- ByteBuffer src = srcs[srcsOffset]; +- int remaining = src.remaining(); +- int written = writeEncryptedData(src); +- if (written >= 0) { +- if (bytesConsumed == -1) { +- bytesConsumed = written; +- } else { +- bytesConsumed += written; +- } +- if (written == remaining) { +- srcsOffset ++; +- } else if (written == 0) { +- break; +- } +- } else { +- break; +- } +- } +- } catch (Exception e) { +- throw new SSLException(e); +- } +- if (bytesConsumed >= 0) { +- int lastPrimingReadResult = SSL.readFromSSL(ssl, EMPTY_ADDR, 0); // priming read +- +- // check if SSL_read returned <= 0. In this case we need to check the error and see if it was something +- // fatal. +- if (lastPrimingReadResult <= 0) { +- // Check for OpenSSL errors caused by the priming read +- long error = SSL.getLastErrorNumber(); +- if (OpenSsl.isError(error)) { +- String err = SSL.getErrorString(error); +- if (logger.isDebugEnabled()) { +- logger.debug( +- "SSL_read failed: primingReadResult: " + lastPrimingReadResult + +- "; OpenSSL error: '" + err + '\''); +- } +- +- // There was an internal error -- shutdown +- shutdown(); +- throw newSSLException(err); +- } else { +- checkPendingHandshakeException(); +- } +- } +- +- rejectRemoteInitiatedRenegation(); +- } else { +- // Reset to 0 as -1 is used to signal that nothing was written and no priming read needs to be done +- bytesConsumed = 0; +- } +- +- // There won't be any application data until we're done handshaking +- // +- // We first check handshakeFinished to eliminate the overhead of extra JNI call if possible. +- int pendingApp = (handshakeFinished || SSL.isInInit(ssl) == 0) ? SSL.pendingReadableBytesInSSL(ssl) : 0; +- int bytesProduced = 0; +- +- if (pendingApp > 0) { +- // Do we have enough room in dsts to write decrypted data? +- if (capacity < pendingApp) { +- return new SSLEngineResult(BUFFER_OVERFLOW, handshakeStatus0(), bytesConsumed, 0); +- } +- +- // Write decrypted data to dsts buffers +- int idx = dstsOffset; +- while (idx < endOffset) { +- ByteBuffer dst = dsts[idx]; +- if (!dst.hasRemaining()) { +- idx ++; +- continue; +- } +- +- if (pendingApp <= 0) { +- break; +- } +- +- int bytesRead; +- try { +- bytesRead = readPlaintextData(dst); +- } catch (Exception e) { +- throw new SSLException(e); +- } +- +- rejectRemoteInitiatedRenegation(); +- +- if (bytesRead == 0) { +- break; +- } +- bytesProduced += bytesRead; +- pendingApp -= bytesRead; +- +- if (!dst.hasRemaining()) { +- idx ++; +- } +- } +- } +- +- // Check to see if we received a close_notify message from the peer +- if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) { +- receivedShutdown = true; +- closeOutbound(); +- closeInbound(); +- } +- +- return new SSLEngineResult(getEngineStatus(), handshakeStatus0(), bytesConsumed, bytesProduced); +- } +- +- private void rejectRemoteInitiatedRenegation() throws SSLHandshakeException { +- if (rejectRemoteInitiatedRenegation && SSL.getHandshakeCount(ssl) > 1) { +- // TODO: In future versions me may also want to send a fatal_alert to the client and so notify it +- // that the renegotiation failed. +- shutdown(); +- throw new SSLHandshakeException("remote-initiated renegotation not allowed"); +- } +- } +- +- public SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException { +- return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length); +- } +- +- @Override +- public SSLEngineResult unwrap( +- final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException { +- return unwrap(new ByteBuffer[] { src }, 0, 1, dsts, offset, length); +- } +- +- @Override +- public Runnable getDelegatedTask() { +- // Currently, we do not delegate SSL computation tasks +- // TODO: in the future, possibly create tasks to do encrypt / decrypt async +- +- return null; +- } +- +- @Override +- public synchronized void closeInbound() throws SSLException { +- if (isInboundDone) { +- return; +- } +- +- isInboundDone = true; +- engineClosed = true; +- +- shutdown(); +- +- if (accepted != 0 && !receivedShutdown) { +- throw new SSLException( +- "Inbound closed before receiving peer's close_notify: possible truncation attack?"); +- } +- } +- +- @Override +- public synchronized boolean isInboundDone() { +- return isInboundDone || engineClosed; +- } +- +- @Override +- public synchronized void closeOutbound() { +- if (isOutboundDone) { +- return; +- } +- +- isOutboundDone = true; +- engineClosed = true; +- +- if (accepted != 0 && destroyed == 0) { +- int mode = SSL.getShutdown(ssl); +- if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) { +- SSL.shutdownSSL(ssl); +- } +- } else { +- // engine closing before initial handshake +- shutdown(); +- } +- } +- +- @Override +- public synchronized boolean isOutboundDone() { +- return isOutboundDone; +- } +- +- @Override +- public String[] getSupportedCipherSuites() { +- Set availableCipherSuites = OpenSsl.availableCipherSuites(); +- return availableCipherSuites.toArray(new String[availableCipherSuites.size()]); +- } +- +- @Override +- public String[] getEnabledCipherSuites() { +- final String[] enabled; +- synchronized (this) { +- if (destroyed == 0) { +- enabled = SSL.getCiphers(ssl); +- } else { +- return EmptyArrays.EMPTY_STRINGS; +- } +- } +- if (enabled == null) { +- return EmptyArrays.EMPTY_STRINGS; +- } else { +- for (int i = 0; i < enabled.length; i++) { +- String mapped = toJavaCipherSuite(enabled[i]); +- if (mapped != null) { +- enabled[i] = mapped; +- } +- } +- return enabled; +- } +- } +- +- @Override +- public void setEnabledCipherSuites(String[] cipherSuites) { +- checkNotNull(cipherSuites, "cipherSuites"); +- +- final StringBuilder buf = new StringBuilder(); +- for (String c: cipherSuites) { +- if (c == null) { +- break; +- } +- +- String converted = CipherSuiteConverter.toOpenSsl(c); +- if (converted == null) { +- converted = c; +- } +- +- if (!OpenSsl.isCipherSuiteAvailable(converted)) { +- throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')'); +- } +- +- buf.append(converted); +- buf.append(':'); +- } +- +- if (buf.length() == 0) { +- throw new IllegalArgumentException("empty cipher suites"); +- } +- buf.setLength(buf.length() - 1); +- +- final String cipherSuiteSpec = buf.toString(); +- +- synchronized (this) { +- if (destroyed == 0) { +- try { +- SSL.setCipherSuites(ssl, cipherSuiteSpec); +- } catch (Exception e) { +- throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e); +- } +- } else { +- throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec); +- } +- } +- } +- +- @Override +- public String[] getSupportedProtocols() { +- return SUPPORTED_PROTOCOLS.clone(); +- } +- +- @Override +- public String[] getEnabledProtocols() { +- List enabled = new ArrayList(); +- // Seems like there is no way to explict disable SSLv2Hello in openssl so it is always enabled +- enabled.add(PROTOCOL_SSL_V2_HELLO); +- +- int opts; +- synchronized (this) { +- if (destroyed == 0) { +- opts = SSL.getOptions(ssl); +- } else { +- return enabled.toArray(new String[1]); +- } +- } +- if ((opts & SSL.SSL_OP_NO_TLSv1) == 0) { +- enabled.add(PROTOCOL_TLS_V1); +- } +- if ((opts & SSL.SSL_OP_NO_TLSv1_1) == 0) { +- enabled.add(PROTOCOL_TLS_V1_1); +- } +- if ((opts & SSL.SSL_OP_NO_TLSv1_2) == 0) { +- enabled.add(PROTOCOL_TLS_V1_2); +- } +- if ((opts & SSL.SSL_OP_NO_SSLv2) == 0) { +- enabled.add(PROTOCOL_SSL_V2); +- } +- if ((opts & SSL.SSL_OP_NO_SSLv3) == 0) { +- enabled.add(PROTOCOL_SSL_V3); +- } +- return enabled.toArray(new String[enabled.size()]); +- } +- +- @Override +- public void setEnabledProtocols(String[] protocols) { +- if (protocols == null) { +- // This is correct from the API docs +- throw new IllegalArgumentException(); +- } +- boolean sslv2 = false; +- boolean sslv3 = false; +- boolean tlsv1 = false; +- boolean tlsv1_1 = false; +- boolean tlsv1_2 = false; +- for (String p: protocols) { +- if (!SUPPORTED_PROTOCOLS_SET.contains(p)) { +- throw new IllegalArgumentException("Protocol " + p + " is not supported."); +- } +- if (p.equals(PROTOCOL_SSL_V2)) { +- sslv2 = true; +- } else if (p.equals(PROTOCOL_SSL_V3)) { +- sslv3 = true; +- } else if (p.equals(PROTOCOL_TLS_V1)) { +- tlsv1 = true; +- } else if (p.equals(PROTOCOL_TLS_V1_1)) { +- tlsv1_1 = true; +- } else if (p.equals(PROTOCOL_TLS_V1_2)) { +- tlsv1_2 = true; +- } +- } +- synchronized (this) { +- if (destroyed == 0) { +- // Enable all and then disable what we not want +- SSL.setOptions(ssl, SSL.SSL_OP_ALL); +- +- if (!sslv2) { +- SSL.setOptions(ssl, SSL.SSL_OP_NO_SSLv2); +- } +- if (!sslv3) { +- SSL.setOptions(ssl, SSL.SSL_OP_NO_SSLv3); +- } +- if (!tlsv1) { +- SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1); +- } +- if (!tlsv1_1) { +- SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1_1); +- } +- if (!tlsv1_2) { +- SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1_2); +- } +- } else { +- throw new IllegalStateException("failed to enable protocols: " + protocols); +- } +- } +- } +- +- @Override +- public SSLSession getSession() { +- return session; +- } +- +- @Override +- public synchronized void beginHandshake() throws SSLException { +- if (engineClosed || destroyed != 0) { +- throw ENGINE_CLOSED; +- } +- switch (accepted) { +- case 0: +- handshake(); +- accepted = 2; +- break; +- case 1: +- // A user did not start handshake by calling this method by him/herself, +- // but handshake has been started already by wrap() or unwrap() implicitly. +- // Because it's the user's first time to call this method, it is unfair to +- // raise an exception. From the user's standpoint, he or she never asked +- // for renegotiation. +- +- accepted = 2; // Next time this method is invoked by the user, we should raise an exception. +- break; +- case 2: +- throw RENEGOTIATION_UNSUPPORTED; +- default: +- throw new Error(); +- } +- } +- +- private void beginHandshakeImplicitly() throws SSLException { +- if (engineClosed || destroyed != 0) { +- throw ENGINE_CLOSED; +- } +- +- if (accepted == 0) { +- handshake(); +- accepted = 1; +- } +- } +- +- private void handshake() throws SSLException { +- int code = SSL.doHandshake(ssl); +- if (code <= 0) { +- // Check for OpenSSL errors caused by the handshake +- long error = SSL.getLastErrorNumber(); +- if (OpenSsl.isError(error)) { +- String err = SSL.getErrorString(error); +- if (logger.isDebugEnabled()) { +- logger.debug( +- "SSL_do_handshake failed: OpenSSL error: '" + err + '\''); +- } +- +- // There was an internal error -- shutdown +- shutdown(); +- throw newSSLException(err); +- } +- checkPendingHandshakeException(); +- } else { +- // if SSL_do_handshake returns > 0 it means the handshake was finished. This means we can update +- // handshakeFinished directly and so eliminate uncessary calls to SSL.isInInit(...) +- handshakeFinished(); +- } +- } +- +- private static long memoryAddress(ByteBuf buf) { +- if (buf.hasMemoryAddress()) { +- return buf.memoryAddress(); +- } else { +- return Buffer.address(buf.nioBuffer()); +- } +- } +- +- private void handshakeFinished() throws SSLException { +- SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior(); +- List protocols = apn.protocols(); +- String applicationProtocol; +- switch (apn.protocol()) { +- case NONE: +- break; +- // We always need to check for applicationProtocol == null as the remote peer may not support +- // the TLS extension or may have returned an empty selection. +- case ALPN: +- applicationProtocol = SSL.getAlpnSelected(ssl); +- if (applicationProtocol != null) { +- this.applicationProtocol = selectApplicationProtocol(protocols, behavior, applicationProtocol); +- } +- break; +- case NPN: +- applicationProtocol = SSL.getNextProtoNegotiated(ssl); +- if (applicationProtocol != null) { +- this.applicationProtocol = selectApplicationProtocol(protocols, behavior, applicationProtocol); +- } +- break; +- case NPN_AND_ALPN: +- applicationProtocol = SSL.getAlpnSelected(ssl); +- if (applicationProtocol == null) { +- applicationProtocol = SSL.getNextProtoNegotiated(ssl); +- } +- if (applicationProtocol != null) { +- this.applicationProtocol = selectApplicationProtocol(protocols, behavior, applicationProtocol); +- } +- break; +- default: +- throw new Error(); +- } +- handshakeFinished = true; +- } +- +- private static String selectApplicationProtocol(List protocols, +- SelectedListenerFailureBehavior behavior, +- String applicationProtocol) throws SSLException { +- applicationProtocol = applicationProtocol.replace(':', '_'); +- if (behavior == SelectedListenerFailureBehavior.ACCEPT) { +- return applicationProtocol; +- } else { +- int size = protocols.size(); +- assert size > 0; +- if (protocols.contains(applicationProtocol)) { +- return applicationProtocol; +- } else { +- if (behavior == SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) { +- return protocols.get(size - 1); +- } else { +- throw new SSLException("Unknown protocol " + applicationProtocol); +- } +- } +- } +- } +- +- private SSLEngineResult.Status getEngineStatus() { +- return engineClosed? CLOSED : OK; +- } +- +- private SSLEngineResult.HandshakeStatus handshakeStatus0() throws SSLException { +- SSLEngineResult.HandshakeStatus status = getHandshakeStatus(); +- if (status == FINISHED) { +- handshakeFinished(); +- } +- checkPendingHandshakeException(); +- +- return status; +- } +- +- @Override +- public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() { +- if (accepted == 0 || destroyed != 0) { +- return NOT_HANDSHAKING; +- } +- +- // Check if we are in the initial handshake phase +- if (!handshakeFinished) { +- // There is pending data in the network BIO -- call wrap +- if (SSL.pendingWrittenBytesInBIO(networkBIO) != 0) { +- return NEED_WRAP; +- } +- +- // No pending data to be sent to the peer +- // Check to see if we have finished handshaking +- if (SSL.isInInit(ssl) == 0) { +- return FINISHED; +- } +- +- // No pending data and still handshaking +- // Must be waiting on the peer to send more data +- return NEED_UNWRAP; +- } +- +- // Check if we are in the shutdown phase +- if (engineClosed) { +- // Waiting to send the close_notify message +- if (SSL.pendingWrittenBytesInBIO(networkBIO) != 0) { +- return NEED_WRAP; +- } +- +- // Must be waiting to receive the close_notify message +- return NEED_UNWRAP; +- } +- +- return NOT_HANDSHAKING; +- } +- +- /** +- * Converts the specified OpenSSL cipher suite to the Java cipher suite. +- */ +- private String toJavaCipherSuite(String openSslCipherSuite) { +- if (openSslCipherSuite == null) { +- return null; +- } +- +- String prefix = toJavaCipherSuitePrefix(SSL.getVersion(ssl)); +- return CipherSuiteConverter.toJava(openSslCipherSuite, prefix); +- } +- +- /** +- * Converts the protocol version string returned by {@link SSL#getVersion(long)} to protocol family string. +- */ +- private static String toJavaCipherSuitePrefix(String protocolVersion) { +- final char c; +- if (protocolVersion == null || protocolVersion.length() == 0) { +- c = 0; +- } else { +- c = protocolVersion.charAt(0); +- } +- +- switch (c) { +- case 'T': +- return "TLS"; +- case 'S': +- return "SSL"; +- default: +- return "UNKNOWN"; +- } +- } +- +- @Override +- public void setUseClientMode(boolean clientMode) { +- if (clientMode != this.clientMode) { +- throw new UnsupportedOperationException(); +- } +- } +- +- @Override +- public boolean getUseClientMode() { +- return clientMode; +- } +- +- @Override +- public void setNeedClientAuth(boolean b) { +- setClientAuth(b ? ClientAuthMode.REQUIRE : ClientAuthMode.NONE); +- } +- +- @Override +- public boolean getNeedClientAuth() { +- return clientAuth == ClientAuthMode.REQUIRE; +- } +- +- @Override +- public void setWantClientAuth(boolean b) { +- setClientAuth(b ? ClientAuthMode.OPTIONAL : ClientAuthMode.NONE); +- } +- +- @Override +- public boolean getWantClientAuth() { +- return clientAuth == ClientAuthMode.OPTIONAL; +- } +- +- private void setClientAuth(ClientAuthMode mode) { +- if (clientMode) { +- return; +- } +- synchronized (this) { +- if (clientAuth == mode) { +- // No need to issue any JNI calls if the mode is the same +- return; +- } +- switch (mode) { +- case NONE: +- SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, OpenSslContext.VERIFY_DEPTH); +- break; +- case REQUIRE: +- SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRE, OpenSslContext.VERIFY_DEPTH); +- break; +- case OPTIONAL: +- SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, OpenSslContext.VERIFY_DEPTH); +- break; +- } +- clientAuth = mode; +- } +- } +- +- @Override +- public void setEnableSessionCreation(boolean b) { +- if (b) { +- throw new UnsupportedOperationException(); +- } +- } +- +- @Override +- public boolean getEnableSessionCreation() { +- return false; +- } +- +- @Override +- @SuppressWarnings("FinalizeDeclaration") +- protected void finalize() throws Throwable { +- super.finalize(); +- // Call shutdown as the user may have created the OpenSslEngine and not used it at all. +- shutdown(); +- } +- +- private final class OpenSslSession implements SSLSession { +- // SSLSession implementation seems to not need to be thread-safe so no need for volatile etc. +- private X509Certificate[] x509PeerCerts; +- +- // lazy init for memory reasons +- private Map values; +- +- @Override +- public byte[] getId() { +- final byte[] id; +- synchronized (OpenSslEngine.this) { +- if (destroyed == 0) { +- id = SSL.getSessionId(ssl); +- } else { +- id = EmptyArrays.EMPTY_BYTES; +- } +- } +- // We don't cache that to keep memory usage to a minimum. +- if (id == null) { +- // The id should never be null, if it was null then the SESSION itself was not valid. +- throw new IllegalStateException("SSL session ID not available"); +- } +- return id; +- } +- +- @Override +- public SSLSessionContext getSessionContext() { +- return sessionContext; +- } +- +- @Override +- public long getCreationTime() { +- synchronized (OpenSslEngine.this) { +- if (destroyed == 0) { +- // We need ot multiple by 1000 as openssl uses seconds and we need milli-seconds. +- return SSL.getTime(ssl) * 1000L; +- } +- return 0; +- } +- } +- +- @Override +- public long getLastAccessedTime() { +- // TODO: Add proper implementation +- return getCreationTime(); +- } +- +- @Override +- public void invalidate() { +- // NOOP +- } +- +- @Override +- public boolean isValid() { +- return false; +- } +- +- @Override +- public void putValue(String name, Object value) { +- if (name == null) { +- throw new NullPointerException("name"); +- } +- if (value == null) { +- throw new NullPointerException("value"); +- } +- Map values = this.values; +- if (values == null) { +- // Use size of 2 to keep the memory overhead small +- values = this.values = new HashMap(2); +- } +- Object old = values.put(name, value); +- if (value instanceof SSLSessionBindingListener) { +- ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name)); +- } +- notifyUnbound(old, name); +- } +- +- @Override +- public Object getValue(String name) { +- if (name == null) { +- throw new NullPointerException("name"); +- } +- if (values == null) { +- return null; +- } +- return values.get(name); +- } +- +- @Override +- public void removeValue(String name) { +- if (name == null) { +- throw new NullPointerException("name"); +- } +- Map values = this.values; +- if (values == null) { +- return; +- } +- Object old = values.remove(name); +- notifyUnbound(old, name); +- } +- +- @Override +- public String[] getValueNames() { +- Map values = this.values; +- if (values == null || values.isEmpty()) { +- return EmptyArrays.EMPTY_STRINGS; +- } +- return values.keySet().toArray(new String[values.size()]); +- } +- +- private void notifyUnbound(Object value, String name) { +- if (value instanceof SSLSessionBindingListener) { +- ((SSLSessionBindingListener) value).valueUnbound(new SSLSessionBindingEvent(this, name)); +- } +- } +- +- @Override +- public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { +- // these are lazy created to reduce memory overhead +- Certificate[] c = peerCerts; +- if (c == null) { +- synchronized (OpenSslEngine.this) { +- if (destroyed == 0) { +- if (SSL.isInInit(ssl) != 0) { +- throw new SSLPeerUnverifiedException("peer not verified"); +- } +- c = peerCerts = initPeerCertChain(); +- } else { +- c = peerCerts = EMPTY_CERTIFICATES; +- } +- } +- } +- return c; +- } +- +- @Override +- public Certificate[] getLocalCertificates() { +- // TODO: Find out how to get these +- return EMPTY_CERTIFICATES; +- } +- +- @Override +- public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { +- // these are lazy created to reduce memory overhead +- X509Certificate[] c = x509PeerCerts; +- if (c == null) { +- final byte[][] chain; +- synchronized (OpenSslEngine.this) { +- if (destroyed == 0) { +- if (SSL.isInInit(ssl) != 0) { +- throw new SSLPeerUnverifiedException("peer not verified"); +- } +- chain = SSL.getPeerCertChain(ssl); +- } else { +- c = x509PeerCerts = EMPTY_X509_CERTIFICATES; +- return c; +- } +- } +- if (chain == null) { +- throw new SSLPeerUnverifiedException("peer not verified"); +- } +- X509Certificate[] peerCerts = new X509Certificate[chain.length]; +- for (int i = 0; i < peerCerts.length; i++) { +- try { +- peerCerts[i] = X509Certificate.getInstance(chain[i]); +- } catch (CertificateException e) { +- throw new IllegalStateException(e); +- } +- } +- c = x509PeerCerts = peerCerts; +- } +- return c; +- } +- +- @Override +- public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { +- Certificate[] peer = getPeerCertificates(); +- if (peer == null || peer.length == 0) { +- return null; +- } +- return principal(peer); +- } +- +- @Override +- public Principal getLocalPrincipal() { +- Certificate[] local = getLocalCertificates(); +- if (local == null || local.length == 0) { +- return null; +- } +- return principal(local); +- } +- +- private Principal principal(Certificate[] certs) { +- return ((java.security.cert.X509Certificate) certs[0]).getIssuerX500Principal(); +- } +- +- @Override +- public String getCipherSuite() { +- if (!handshakeFinished) { +- return INVALID_CIPHER; +- } +- if (cipher == null) { +- final String c; +- synchronized (OpenSslEngine.this) { +- if (destroyed == 0) { +- c = toJavaCipherSuite(SSL.getCipherForSSL(ssl)); +- } else { +- c = INVALID_CIPHER; +- } +- } +- if (c != null) { +- cipher = c; +- } +- } +- return cipher; +- } +- +- @Override +- public String getProtocol() { +- String applicationProtocol = OpenSslEngine.this.applicationProtocol; +- final String version; +- synchronized (OpenSslEngine.this) { +- if (destroyed == 0) { +- version = SSL.getVersion(ssl); +- } else { +- return StringUtil.EMPTY_STRING; +- } +- } +- if (applicationProtocol == null || applicationProtocol.isEmpty()) { +- return version; +- } else { +- return version + ':' + applicationProtocol; +- } +- } +- +- @Override +- public String getPeerHost() { +- return null; +- } +- +- @Override +- public int getPeerPort() { +- return 0; +- } +- +- @Override +- public int getPacketBufferSize() { +- return MAX_ENCRYPTED_PACKET_LENGTH; +- } +- +- @Override +- public int getApplicationBufferSize() { +- return MAX_PLAINTEXT_LENGTH; +- } +- +- private Certificate[] initPeerCertChain() throws SSLPeerUnverifiedException { +- byte[][] chain = SSL.getPeerCertChain(ssl); +- final byte[] clientCert; +- if (!clientMode) { +- // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. +- // We use SSL_get_peer_certificate to get it in this case and add it to our array later. +- // +- // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html +- clientCert = SSL.getPeerCertificate(ssl); +- } else { +- clientCert = null; +- } +- +- if (chain == null && clientCert == null) { +- throw new SSLPeerUnverifiedException("peer not verified"); +- } +- int len = 0; +- if (chain != null) { +- len += chain.length; +- } +- +- int i = 0; +- Certificate[] peerCerts; +- if (clientCert != null) { +- len++; +- peerCerts = new Certificate[len]; +- peerCerts[i++] = new OpenSslX509Certificate(clientCert); +- } else { +- peerCerts = new Certificate[len]; +- } +- if (chain != null) { +- int a = 0; +- for (; i < peerCerts.length; i++) { +- peerCerts[i] = new OpenSslX509Certificate(chain[a++]); +- } +- } +- return peerCerts; +- } +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngineMap.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngineMap.java +deleted file mode 100644 +index 382a28d..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngineMap.java ++++ /dev/null +@@ -1,42 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-interface OpenSslEngineMap { +- +- OpenSslEngineMap EMPTY = new OpenSslEngineMap() { +- @Override +- public OpenSslEngine remove(long ssl) { +- return null; +- } +- +- @Override +- public void add(OpenSslEngine engine) { +- // NOOP +- } +- }; +- +- /** +- * Remove the {@link OpenSslEngine} with the given {@code ssl} address and +- * return it. +- */ +- OpenSslEngine remove(long ssl); +- +- /** +- * Add a {@link OpenSslEngine} to this {@link OpenSslEngineMap}. +- */ +- void add(OpenSslEngine engine); +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java +deleted file mode 100644 +index 83ee505..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java ++++ /dev/null +@@ -1,418 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import io.netty.util.internal.EmptyArrays; +-import org.apache.tomcat.jni.SSL; +-import org.apache.tomcat.jni.SSLContext; +- +-import javax.net.ssl.KeyManager; +-import javax.net.ssl.KeyManagerFactory; +-import javax.net.ssl.SSLException; +-import javax.net.ssl.TrustManager; +-import javax.net.ssl.TrustManagerFactory; +-import javax.net.ssl.X509ExtendedTrustManager; +-import javax.net.ssl.X509TrustManager; +-import java.io.File; +-import java.security.KeyStore; +-import java.security.cert.X509Certificate; +- +-import static io.netty.util.internal.ObjectUtil.*; +- +-/** +- * A server-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation. +- */ +-public final class OpenSslServerContext extends OpenSslContext { +- private final OpenSslServerSessionContext sessionContext; +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- */ +- public OpenSslServerContext(File certChainFile, File keyFile) throws SSLException { +- this(certChainFile, keyFile, null); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- */ +- public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException { +- this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE, +- ApplicationProtocolConfig.DISABLED, 0, 0); +- } +- +- /** +- * @deprecated use {@link #OpenSslServerContext( +- * File, File, String, Iterable, CipherSuiteFilter, ApplicationProtocolConfig, long, long)} +- * +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param apn Provides a means to configure parameters related to application protocol negotiation. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- @Deprecated +- public OpenSslServerContext( +- File certChainFile, File keyFile, String keyPassword, +- Iterable ciphers, ApplicationProtocolConfig apn, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(certChainFile, keyFile, keyPassword, ciphers, IdentityCipherSuiteFilter.INSTANCE, +- apn, sessionCacheSize, sessionTimeout); +- } +- +- /** +- * @deprecated Use the constructors that accepts {@link ApplicationProtocolConfig} or +- * {@link ApplicationProtocolNegotiator} instead. +- * +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param nextProtocols the application layer protocols to accept, in the order of preference. +- * {@code null} to disable TLS NPN/ALPN extension. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- @Deprecated +- public OpenSslServerContext( +- File certChainFile, File keyFile, String keyPassword, +- Iterable ciphers, Iterable nextProtocols, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(certChainFile, keyFile, keyPassword, ciphers, +- toApplicationProtocolConfig(nextProtocols), sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param config Application protocol config. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- * @deprecated use {@link #OpenSslServerContext(File, TrustManagerFactory, File, File, String, KeyManagerFactory, +- * Iterable, CipherSuiteFilter, ApplicationProtocolConfig, long, long)} +- */ +- @Deprecated +- public OpenSslServerContext( +- File certChainFile, File keyFile, String keyPassword, TrustManagerFactory trustManagerFactory, +- Iterable ciphers, ApplicationProtocolConfig config, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(certChainFile, keyFile, keyPassword, trustManagerFactory, ciphers, +- toNegotiator(config), sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param apn Application protocol negotiator. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- * @deprecated use {@link #OpenSslServerContext(File, TrustManagerFactory, File, File, String, KeyManagerFactory, +- * Iterable, CipherSuiteFilter, ApplicationProtocolConfig, long, long)} +- */ +- @Deprecated +- public OpenSslServerContext( +- File certChainFile, File keyFile, String keyPassword, TrustManagerFactory trustManagerFactory, +- Iterable ciphers, OpenSslApplicationProtocolNegotiator apn, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(null, trustManagerFactory, certChainFile, keyFile, keyPassword, null, +- ciphers, null, apn, sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * @param apn Provides a means to configure parameters related to application protocol negotiation. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- public OpenSslServerContext( +- File certChainFile, File keyFile, String keyPassword, +- Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(null, null, certChainFile, keyFile, keyPassword, null, +- ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * @param trustCertChainFile an X.509 certificate chain file in PEM format. +- * This provides the certificate chains used for mutual authentication. +- * {@code null} to use the system default +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from clients. +- * {@code null} to use the default or the results of parsing {@code trustCertChainFile}. +- * @param keyCertChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s +- * that is used to encrypt data being sent to clients. +- * {@code null} to use the default or the results of parsing +- * {@code keyCertChainFile} and {@code keyFile}. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * Only required if {@code provider} is {@link SslProvider#JDK} +- * @param config Provides a means to configure parameters related to application protocol negotiation. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- public OpenSslServerContext( +- File trustCertChainFile, TrustManagerFactory trustManagerFactory, +- File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, +- Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig config, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, keyManagerFactory, +- ciphers, cipherFilter, toNegotiator(config), sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * @param config Application protocol config. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- @Deprecated +- public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword, +- TrustManagerFactory trustManagerFactory, Iterable ciphers, +- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig config, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(null, trustManagerFactory, certChainFile, keyFile, keyPassword, null, ciphers, cipherFilter, +- toNegotiator(config), sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * @param certChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * @param apn Application protocol negotiator. +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- * @deprecated use {@link #OpenSslServerContext(File, TrustManagerFactory, File, File, String, KeyManagerFactory, +- * Iterable, CipherSuiteFilter, OpenSslApplicationProtocolNegotiator, long, long)} +- */ +- @Deprecated +- public OpenSslServerContext( +- File certChainFile, File keyFile, String keyPassword, TrustManagerFactory trustManagerFactory, +- Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- this(null, trustManagerFactory, certChainFile, keyFile, keyPassword, null, ciphers, cipherFilter, +- apn, sessionCacheSize, sessionTimeout); +- } +- +- /** +- * Creates a new instance. +- * +- * +- * @param trustCertChainFile an X.509 certificate chain file in PEM format. +- * This provides the certificate chains used for mutual authentication. +- * {@code null} to use the system default +- * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s +- * that verifies the certificates sent from clients. +- * {@code null} to use the default or the results of parsing {@code trustCertChainFile}. +- * @param keyCertChainFile an X.509 certificate chain file in PEM format +- * @param keyFile a PKCS#8 private key file in PEM format +- * @param keyPassword the password of the {@code keyFile}. +- * {@code null} if it's not password-protected. +- * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s +- * that is used to encrypt data being sent to clients. +- * {@code null} to use the default or the results of parsing +- * {@code keyCertChainFile} and {@code keyFile}. +- * @param ciphers the cipher suites to enable, in the order of preference. +- * {@code null} to use the default cipher suites. +- * @param cipherFilter a filter to apply over the supplied list of ciphers +- * Only required if {@code provider} is {@link SslProvider#JDK} +- * @param apn Application Protocol Negotiator object +- * @param sessionCacheSize the size of the cache used for storing SSL session objects. +- * {@code 0} to use the default value. +- * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. +- * {@code 0} to use the default value. +- */ +- public OpenSslServerContext( +- File trustCertChainFile, TrustManagerFactory trustManagerFactory, +- File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, +- Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, +- long sessionCacheSize, long sessionTimeout) throws SSLException { +- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER); +- OpenSsl.ensureAvailability(); +- +- checkNotNull(keyCertChainFile, "keyCertChainFile"); +- if (!keyCertChainFile.isFile()) { +- throw new IllegalArgumentException("keyCertChainFile is not a file: " + keyCertChainFile); +- } +- checkNotNull(keyFile, "keyFile"); +- if (!keyFile.isFile()) { +- throw new IllegalArgumentException("keyFile is not a file: " + keyFile); +- } +- if (keyPassword == null) { +- keyPassword = ""; +- } +- +- // Create a new SSL_CTX and configure it. +- boolean success = false; +- try { +- synchronized (OpenSslContext.class) { +- /* Set certificate verification policy. */ +- SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, VERIFY_DEPTH); +- +- /* Load the certificate chain. We must skip the first cert when server mode */ +- if (!SSLContext.setCertificateChainFile(ctx, keyCertChainFile.getPath(), true)) { +- long error = SSL.getLastErrorNumber(); +- if (OpenSsl.isError(error)) { +- String err = SSL.getErrorString(error); +- throw new SSLException( +- "failed to set certificate chain: " + keyCertChainFile + " (" + err + ')'); +- } +- } +- +- /* Load the certificate file and private key. */ +- try { +- if (!SSLContext.setCertificate( +- ctx, keyCertChainFile.getPath(), keyFile.getPath(), keyPassword, SSL.SSL_AIDX_RSA)) { +- long error = SSL.getLastErrorNumber(); +- if (OpenSsl.isError(error)) { +- String err = SSL.getErrorString(error); +- throw new SSLException("failed to set certificate: " + +- keyCertChainFile + " and " + keyFile + " (" + err + ')'); +- } +- } +- } catch (SSLException e) { +- throw e; +- } catch (Exception e) { +- throw new SSLException("failed to set certificate: " + keyCertChainFile + " and " + keyFile, e); +- } +- try { +- if (trustManagerFactory == null) { +- // Mimic the way SSLContext.getInstance(KeyManager[], null, null) works +- trustManagerFactory = TrustManagerFactory.getInstance( +- TrustManagerFactory.getDefaultAlgorithm()); +- } +- if (trustCertChainFile != null) { +- trustManagerFactory = buildTrustManagerFactory(trustCertChainFile, trustManagerFactory); +- } else { +- char[] keyPasswordChars = +- keyPassword == null ? EmptyArrays.EMPTY_CHARS : keyPassword.toCharArray(); +- +- KeyStore ks = buildKeyStore(keyCertChainFile, keyFile, keyPasswordChars); +- trustManagerFactory.init(ks); +- } +- +- final X509TrustManager manager = chooseTrustManager(trustManagerFactory.getTrustManagers()); +- +- // Use this to prevent an error when running on java < 7 +- if (useExtendedTrustManager(manager)) { +- final X509ExtendedTrustManager extendedManager = (X509ExtendedTrustManager) manager; +- SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() { +- @Override +- void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth) +- throws Exception { +- extendedManager.checkClientTrusted(peerCerts, auth, engine); +- } +- }); +- } else { +- SSLContext.setCertVerifyCallback(ctx, new AbstractCertificateVerifier() { +- @Override +- void verify(OpenSslEngine engine, X509Certificate[] peerCerts, String auth) +- throws Exception { +- manager.checkClientTrusted(peerCerts, auth); +- } +- }); +- } +- } catch (Exception e) { +- throw new SSLException("unable to setup trustmanager", e); +- } +- } +- sessionContext = new OpenSslServerSessionContext(ctx); +- success = true; +- } finally { +- if (!success) { +- destroyPools(); +- } +- } +- } +- +- @Override +- public OpenSslServerSessionContext sessionContext() { +- return sessionContext; +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerSessionContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslServerSessionContext.java +deleted file mode 100644 +index 693801f..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerSessionContext.java ++++ /dev/null +@@ -1,79 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import org.apache.tomcat.jni.SSL; +-import org.apache.tomcat.jni.SSLContext; +- +- +-/** +- * {@link OpenSslSessionContext} implementation which offers extra methods which are only useful for the server-side. +- */ +-public final class OpenSslServerSessionContext extends OpenSslSessionContext { +- OpenSslServerSessionContext(long context) { +- super(context); +- } +- +- @Override +- public void setSessionTimeout(int seconds) { +- if (seconds < 0) { +- throw new IllegalArgumentException(); +- } +- SSLContext.setSessionCacheTimeout(context, seconds); +- } +- +- @Override +- public int getSessionTimeout() { +- return (int) SSLContext.getSessionCacheTimeout(context); +- } +- +- @Override +- public void setSessionCacheSize(int size) { +- if (size < 0) { +- throw new IllegalArgumentException(); +- } +- SSLContext.setSessionCacheSize(context, size); +- } +- +- @Override +- public int getSessionCacheSize() { +- return (int) SSLContext.getSessionCacheSize(context); +- } +- +- @Override +- public void setSessionCacheEnabled(boolean enabled) { +- long mode = enabled ? SSL.SSL_SESS_CACHE_SERVER : SSL.SSL_SESS_CACHE_OFF; +- SSLContext.setSessionCacheMode(context, mode); +- } +- +- @Override +- public boolean isSessionCacheEnabled() { +- return SSLContext.getSessionCacheMode(context) == SSL.SSL_SESS_CACHE_SERVER; +- } +- +- /** +- * Set the context within which session be reused (server side only) +- * See +- * man SSL_CTX_set_session_id_context +- * +- * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name +- * of the application and/or the hostname and/or service name +- * @return {@code true} if success, {@code false} otherwise. +- */ +- public boolean setSessionIdContext(byte[] sidCtx) { +- return SSLContext.setSessionIdContext(context, sidCtx); +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java +deleted file mode 100644 +index fd17821..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java ++++ /dev/null +@@ -1,90 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import org.apache.tomcat.jni.SSLContext; +- +-import javax.net.ssl.SSLSession; +-import javax.net.ssl.SSLSessionContext; +-import java.util.Enumeration; +-import java.util.NoSuchElementException; +- +-/** +- * OpenSSL specific {@link SSLSessionContext} implementation. +- */ +-public abstract class OpenSslSessionContext implements SSLSessionContext { +- private static final Enumeration EMPTY = new EmptyEnumeration(); +- +- private final OpenSslSessionStats stats; +- final long context; +- +- OpenSslSessionContext(long context) { +- this.context = context; +- stats = new OpenSslSessionStats(context); +- } +- +- @Override +- public SSLSession getSession(byte[] bytes) { +- if (bytes == null) { +- throw new NullPointerException("bytes"); +- } +- return null; +- } +- +- @Override +- public Enumeration getIds() { +- return EMPTY; +- } +- +- /** +- * Sets the SSL session ticket keys of this context. +- */ +- public void setTicketKeys(byte[] keys) { +- if (keys == null) { +- throw new NullPointerException("keys"); +- } +- SSLContext.setSessionTicketKeys(context, keys); +- } +- +- /** +- * Enable or disable caching of SSL sessions. +- */ +- public abstract void setSessionCacheEnabled(boolean enabled); +- +- /** +- * Return {@code true} if caching of SSL sessions is enabled, {@code false} otherwise. +- */ +- public abstract boolean isSessionCacheEnabled(); +- +- /** +- * Returns the stats of this context. +- */ +- public OpenSslSessionStats stats() { +- return stats; +- } +- +- private static final class EmptyEnumeration implements Enumeration { +- @Override +- public boolean hasMoreElements() { +- return false; +- } +- +- @Override +- public byte[] nextElement() { +- throw new NoSuchElementException(); +- } +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java +deleted file mode 100644 +index 2ec5146..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java ++++ /dev/null +@@ -1,122 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +- +-package io.netty.handler.ssl; +- +-import org.apache.tomcat.jni.SSLContext; +- +-/** +- * Stats exposed by an OpenSSL session context. +- * +- * @see SSL_CTX_sess_number +- */ +-public final class OpenSslSessionStats { +- +- private final long context; +- +- OpenSslSessionStats(long context) { +- this.context = context; +- } +- +- /** +- * Returns the current number of sessions in the internal session cache. +- */ +- public long number() { +- return SSLContext.sessionNumber(context); +- } +- +- /** +- * Returns the number of started SSL/TLS handshakes in client mode. +- */ +- public long connect() { +- return SSLContext.sessionConnect(context); +- } +- +- /** +- * Returns the number of successfully established SSL/TLS sessions in client mode. +- */ +- public long connectGood() { +- return SSLContext.sessionConnectGood(context); +- } +- +- /** +- * Returns the number of start renegotiations in client mode. +- */ +- public long connectRenegotiate() { +- return SSLContext.sessionConnectRenegotiate(context); +- } +- +- /** +- * Returns the number of started SSL/TLS handshakes in server mode. +- */ +- public long accept() { +- return SSLContext.sessionAccept(context); +- } +- +- /** +- * Returns the number of successfully established SSL/TLS sessions in server mode. +- */ +- public long acceptGood() { +- return SSLContext.sessionAcceptGood(context); +- } +- +- /** +- * Returns the number of start renegotiations in server mode. +- */ +- public long acceptRenegotiate() { +- return SSLContext.sessionAcceptRenegotiate(context); +- } +- +- /** +- * Returns the number of successfully reused sessions. In client mode, a session set with {@code SSL_set_session} +- * successfully reused is counted as a hit. In server mode, a session successfully retrieved from internal or +- * external cache is counted as a hit. +- */ +- public long hits() { +- return SSLContext.sessionHits(context); +- } +- +- /** +- * Returns the number of successfully retrieved sessions from the external session cache in server mode. +- */ +- public long cbHits() { +- return SSLContext.sessionCbHits(context); +- } +- +- /** +- * Returns the number of sessions proposed by clients that were not found in the internal session cache +- * in server mode. +- */ +- public long misses() { +- return SSLContext.sessionMisses(context); +- } +- +- /** +- * Returns the number of sessions proposed by clients and either found in the internal or external session cache +- * in server mode, but that were invalid due to timeout. These sessions are not included in the {@link #hits()} +- * count. +- */ +- public long timeouts() { +- return SSLContext.sessionTimeouts(context); +- } +- +- /** +- * Returns the number of sessions that were removed because the maximum session cache size was exceeded. +- */ +- public long cacheFull() { +- return SSLContext.sessionCacheFull(context); +- } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/SslContext.java b/handler/src/main/java/io/netty/handler/ssl/SslContext.java +index 890b362..42abc14 100644 +--- a/handler/src/main/java/io/netty/handler/ssl/SslContext.java ++++ b/handler/src/main/java/io/netty/handler/ssl/SslContext.java +@@ -110,11 +110,7 @@ public abstract class SslContext { + } + + private static SslProvider defaultProvider() { +- if (OpenSsl.isAvailable()) { +- return SslProvider.OPENSSL; +- } else { +- return SslProvider.JDK; +- } ++ return SslProvider.JDK; + } + + /** +@@ -399,10 +395,6 @@ public abstract class SslContext { + return new JdkSslServerContext( + trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, + keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); +- case OPENSSL: +- return new OpenSslServerContext( +- trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, +- keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); + default: + throw new Error(provider.toString()); + } +@@ -729,10 +721,6 @@ public abstract class SslContext { + return new JdkSslClientContext( + trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, + keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); +- case OPENSSL: +- return new OpenSslClientContext( +- trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, +- keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); + } + // Should never happen!! + throw new Error(); +diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +index a3b1716..c492dc4 100644 +--- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java ++++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +@@ -161,6 +161,15 @@ import java.util.regex.Pattern; + */ + public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundHandler { + ++ private static final int MAX_PLAINTEXT_LENGTH = 16 * 1024; // 2^14 ++ private static final int MAX_COMPRESSED_LENGTH = MAX_PLAINTEXT_LENGTH + 1024; ++ private static final int MAX_CIPHERTEXT_LENGTH = MAX_COMPRESSED_LENGTH + 1024; ++ ++ // Header (5) + Data (2^14) + Compression (1024) + Encryption (1024) + MAC (20) + Padding (256) ++ static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 20 + 256; ++ ++ static final int MAX_ENCRYPTION_OVERHEAD_LENGTH = MAX_ENCRYPTED_PACKET_LENGTH - MAX_PLAINTEXT_LENGTH; ++ + private static final InternalLogger logger = + InternalLoggerFactory.getInstance(SslHandler.class); + +@@ -290,7 +299,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH + this.startTls = startTls; + maxPacketBufferSize = engine.getSession().getPacketBufferSize(); + +- boolean opensslEngine = engine instanceof OpenSslEngine; ++ boolean opensslEngine = false; + wantsDirectBuffer = opensslEngine; + wantsLargeOutboundNetworkBuffer = !opensslEngine; + +@@ -883,7 +892,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH + + boolean nonSslRecord = false; + +- while (totalLength < OpenSslEngine.MAX_ENCRYPTED_PACKET_LENGTH) { ++ while (totalLength < MAX_ENCRYPTED_PACKET_LENGTH) { + final int readableBytes = endOffset - offset; + if (readableBytes < 5) { + break; +@@ -904,7 +913,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH + } + + int newTotalLength = totalLength + packetLength; +- if (newTotalLength > OpenSslEngine.MAX_ENCRYPTED_PACKET_LENGTH) { ++ if (newTotalLength > MAX_ENCRYPTED_PACKET_LENGTH) { + // Don't read too much. + break; + } +@@ -1077,47 +1086,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH + private SSLEngineResult unwrap( + SSLEngine engine, ByteBuf in, int readerIndex, int len, ByteBuf out) throws SSLException { + int nioBufferCount = in.nioBufferCount(); +- if (engine instanceof OpenSslEngine && nioBufferCount > 1) { +- /** +- * If {@link OpenSslEngine} is in use, +- * we can use a special {@link OpenSslEngine#unwrap(ByteBuffer[], ByteBuffer[])} method +- * that accepts multiple {@link ByteBuffer}s without additional memory copies. +- */ +- OpenSslEngine opensslEngine = (OpenSslEngine) engine; +- int overflows = 0; +- ByteBuffer[] in0 = in.nioBuffers(readerIndex, len); +- try { +- for (;;) { +- int writerIndex = out.writerIndex(); +- int writableBytes = out.writableBytes(); +- ByteBuffer out0; +- if (out.nioBufferCount() == 1) { +- out0 = out.internalNioBuffer(writerIndex, writableBytes); +- } else { +- out0 = out.nioBuffer(writerIndex, writableBytes); +- } +- singleBuffer[0] = out0; +- SSLEngineResult result = opensslEngine.unwrap(in0, singleBuffer); +- out.writerIndex(out.writerIndex() + result.bytesProduced()); +- switch (result.getStatus()) { +- case BUFFER_OVERFLOW: +- int max = engine.getSession().getApplicationBufferSize(); +- switch (overflows ++) { +- case 0: +- out.ensureWritable(Math.min(max, in.readableBytes())); +- break; +- default: +- out.ensureWritable(max); +- } +- break; +- default: +- return result; +- } +- } +- } finally { +- singleBuffer[0] = null; +- } +- } else { ++ + int overflows = 0; + ByteBuffer in0; + if (nioBufferCount == 1) { +@@ -1154,7 +1123,6 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH + return result; + } + } +- } + } + + /** +@@ -1514,7 +1482,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH + return allocate(ctx, maxPacketBufferSize); + } else { + return allocate(ctx, Math.min( +- pendingBytes + OpenSslEngine.MAX_ENCRYPTION_OVERHEAD_LENGTH, ++ pendingBytes + MAX_ENCRYPTION_OVERHEAD_LENGTH, + maxPacketBufferSize)); + } + } +diff --git a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java +deleted file mode 100644 +index 9482f2b..0000000 +--- a/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java ++++ /dev/null +@@ -1,349 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +-package io.netty.handler.ssl; +- +-import static org.junit.Assert.assertNull; +-import static org.junit.Assert.assertTrue; +-import static org.junit.Assume.assumeNoException; +-import io.netty.bootstrap.Bootstrap; +-import io.netty.bootstrap.ServerBootstrap; +-import io.netty.channel.Channel; +-import io.netty.channel.ChannelFuture; +-import io.netty.channel.ChannelHandlerAdapter; +-import io.netty.channel.ChannelHandlerContext; +-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.JdkApplicationProtocolNegotiator.ProtocolSelector; +-import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory; +-import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +-import io.netty.handler.ssl.util.SelfSignedCertificate; +-import io.netty.util.NetUtil; +- +-import java.net.InetSocketAddress; +-import java.security.cert.CertificateException; +-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 org.junit.Test; +- +-public class JdkSslEngineTest extends SSLEngineTest { +- private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2"; +- private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1"; +- private static final String APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE = "my-protocol-FOO"; +- +- @Test +- public void testNpn() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator apn = new JdkNpnApplicationProtocolNegotiator(true, true, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- mySetup(apn); +- runTest(); +- } catch (RuntimeException 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); +- } +- } +- +- @Test +- public void testNpnNoCompatibleProtocolsNoHandshakeFailure() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false, +- APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); +- mySetup(serverApn, clientApn); +- runTest(null); +- } catch (Exception 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); +- } +- } +- +- @Test +- public void testNpnNoCompatibleProtocolsClientHandshakeFailure() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(true, true, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false, +- APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); +- mySetup(serverApn, clientApn); +- assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); +- assertTrue(clientException instanceof SSLHandshakeException); +- } catch (RuntimeException 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); +- } +- } +- +- @Test +- public void testNpnNoCompatibleProtocolsServerHandshakeFailure() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(true, true, +- APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); +- mySetup(serverApn, clientApn); +- assertTrue(serverLatch.await(2, TimeUnit.SECONDS)); +- assertTrue(serverException instanceof SSLHandshakeException); +- } catch (RuntimeException 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); +- } +- } +- +- @Test +- public void testAlpn() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator apn = new JdkAlpnApplicationProtocolNegotiator(true, true, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- mySetup(apn); +- runTest(); +- } catch (Exception 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); +- } +- } +- +- @Test +- public void testAlpnNoCompatibleProtocolsNoHandshakeFailure() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(false, false, +- APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); +- mySetup(serverApn, clientApn); +- runTest(null); +- } catch (Exception 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); +- } +- } +- +- @Test +- public void testAlpnNoCompatibleProtocolsServerHandshakeFailure() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true, +- APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); +- mySetup(serverApn, clientApn); +- assertTrue(serverLatch.await(2, TimeUnit.SECONDS)); +- assertTrue(serverException instanceof SSLHandshakeException); +- } catch (Exception 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); +- } +- } +- +- @Test +- public void testAlpnCompatibleProtocolsDifferentClientOrder() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- // 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, +- FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL); +- mySetup(serverApn, clientApn); +- assertNull(serverException); +- runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- } catch (Exception 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); +- } +- } +- +- @Test +- public void testAlpnNoCompatibleProtocolsClientHandshakeFailure() throws Exception { +- try { +- // Typical code will not have to check this, but will get a initialization error on class load. +- // 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"); +- } +- JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true, +- PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator( +- new ProtocolSelectorFactory() { +- @Override +- public ProtocolSelector newSelector(SSLEngine engine, Set supportedProtocols) { +- return new ProtocolSelector() { +- @Override +- public void unsupported() { +- } +- +- @Override +- public String select(List protocols) { +- return APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE; +- } +- }; +- } +- }, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY, +- APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); +- mySetup(serverApn, clientApn); +- assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); +- assertTrue(clientException instanceof SSLHandshakeException); +- } catch (Exception 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, +- CertificateException { +- mySetup(apn, apn); +- } +- +- private void mySetup(JdkApplicationProtocolNegotiator serverApn, JdkApplicationProtocolNegotiator 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); +- +- serverConnectedChannel = null; +- sb = new ServerBootstrap(); +- cb = new Bootstrap(); +- +- sb.group(new NioEventLoopGroup(), new NioEventLoopGroup()); +- sb.channel(NioServerSocketChannel.class); +- sb.childHandler(new ChannelInitializer() { +- @Override +- protected void initChannel(Channel ch) throws Exception { +- ChannelPipeline p = ch.pipeline(); +- p.addLast(serverSslCtx.newHandler(ch.alloc())); +- p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch)); +- p.addLast(new ChannelHandlerAdapter() { +- @Override +- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { +- if (cause.getCause() instanceof SSLHandshakeException) { +- serverException = cause.getCause(); +- serverLatch.countDown(); +- } else { +- ctx.fireExceptionCaught(cause); +- } +- } +- }); +- serverConnectedChannel = ch; +- } +- }); +- +- cb.group(new NioEventLoopGroup()); +- cb.channel(NioSocketChannel.class); +- cb.handler(new ChannelInitializer() { +- @Override +- protected void initChannel(Channel ch) throws Exception { +- ChannelPipeline p = ch.pipeline(); +- p.addLast(clientSslCtx.newHandler(ch.alloc())); +- p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch)); +- p.addLast(new ChannelHandlerAdapter() { +- @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(0)).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 runTest() throws Exception { +- runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL); +- } +- +- @Override +- protected SslProvider sslProvider() { +- return SslProvider.JDK; +- } +-} diff --git a/SOURCES/remove-bc-dependency.patch b/SOURCES/remove-bc-dependency.patch new file mode 100644 index 0000000..cf66e1b --- /dev/null +++ b/SOURCES/remove-bc-dependency.patch @@ -0,0 +1,140 @@ +diff --git a/handler/pom.xml b/handler/pom.xml +index 978aa2f..1b8ef3a 100644 +--- a/handler/pom.xml ++++ b/handler/pom.xml +@@ -51,11 +51,6 @@ + true + + +- org.bouncycastle +- bcpkix-jdk15on +- true +- +- + org.eclipse.jetty.npn + npn-api + true +diff --git a/handler/src/main/java/io/netty/handler/ssl/util/BouncyCastleSelfSignedCertGenerator.java b/handler/src/main/java/io/netty/handler/ssl/util/BouncyCastleSelfSignedCertGenerator.java +deleted file mode 100644 +index 88a7c9d..0000000 +--- a/handler/src/main/java/io/netty/handler/ssl/util/BouncyCastleSelfSignedCertGenerator.java ++++ /dev/null +@@ -1,61 +0,0 @@ +-/* +- * Copyright 2014 The Netty Project +- * +- * The Netty Project 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. +- */ +- +-package io.netty.handler.ssl.util; +- +-import org.bouncycastle.asn1.x500.X500Name; +-import org.bouncycastle.cert.X509CertificateHolder; +-import org.bouncycastle.cert.X509v3CertificateBuilder; +-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +-import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +-import org.bouncycastle.jce.provider.BouncyCastleProvider; +-import org.bouncycastle.operator.ContentSigner; +-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +- +-import java.math.BigInteger; +-import java.security.KeyPair; +-import java.security.PrivateKey; +-import java.security.Provider; +-import java.security.SecureRandom; +-import java.security.cert.X509Certificate; +- +-import static io.netty.handler.ssl.util.SelfSignedCertificate.*; +- +-/** +- * Generates a self-signed certificate using Bouncy Castle. +- */ +-final class BouncyCastleSelfSignedCertGenerator { +- +- private static final Provider PROVIDER = new BouncyCastleProvider(); +- +- static String[] generate(String fqdn, KeyPair keypair, SecureRandom random) throws Exception { +- PrivateKey key = keypair.getPrivate(); +- +- // Prepare the information required for generating an X.509 certificate. +- X500Name owner = new X500Name("CN=" + fqdn); +- X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder( +- owner, new BigInteger(64, random), NOT_BEFORE, NOT_AFTER, owner, keypair.getPublic()); +- +- ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(key); +- X509CertificateHolder certHolder = builder.build(signer); +- X509Certificate cert = new JcaX509CertificateConverter().setProvider(PROVIDER).getCertificate(certHolder); +- cert.verify(keypair.getPublic()); +- +- return newSelfSignedCertificate(fqdn, key, cert); +- } +- +- private BouncyCastleSelfSignedCertGenerator() { } +-} +diff --git a/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java b/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java +index 54257a7..074764f 100644 +--- a/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java ++++ b/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java +@@ -48,8 +48,7 @@ import java.util.Date; + * {@link java.io.File#createTempFile(String, String)}, and they are deleted when the JVM exits using + * {@link java.io.File#deleteOnExit()}. + *

+- * At first, this method tries to use OpenJDK's X.509 implementation (the {@code sun.security.x509} package). +- * If it fails, it tries to use Bouncy Castle as a fallback. ++ * This method tries to use OpenJDK's X.509 implementation (the {@code sun.security.x509} package). + *

+ */ + public final class SelfSignedCertificate { +@@ -107,15 +106,9 @@ public final class SelfSignedCertificate { + paths = OpenJdkSelfSignedCertGenerator.generate(fqdn, keypair, random); + } catch (Throwable t) { + logger.debug("Failed to generate a self-signed X.509 certificate using sun.security.x509:", t); +- try { +- // Try Bouncy Castle if the current JVM didn't have sun.security.x509. +- paths = BouncyCastleSelfSignedCertGenerator.generate(fqdn, keypair, random); +- } catch (Throwable t2) { +- logger.debug("Failed to generate a self-signed X.509 certificate using Bouncy Castle:", t2); +- throw new CertificateException( +- "No provider succeeded to generate a self-signed certificate. " + +- "See debug log for the root cause."); +- } ++ throw new CertificateException( ++ "No provider succeeded to generate a self-signed certificate. " + ++ "See debug log for the root cause."); + } + + certificate = new File(paths[0]); +diff --git a/pom.xml b/pom.xml +index b68f446..4a5cbd4 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -677,19 +677,6 @@ + true +
+ +- +- +- org.bouncycastle +- bcpkix-jdk15on +- 1.50 +- compile +- true +- +- + + com.jcraft + jzlib diff --git a/SOURCES/transport-native-epoll-configure-fix.patch b/SOURCES/transport-native-epoll-configure-fix.patch new file mode 100644 index 0000000..08e8489 --- /dev/null +++ b/SOURCES/transport-native-epoll-configure-fix.patch @@ -0,0 +1,14 @@ +diff --git a/netty-netty-4.0.27.Final/transport-native-epoll/pom.xml b/netty-netty-4.0.27.Final/transport-native-epoll/pom.xml +index c9c7b25..b489b3f 100644 +--- a/netty-netty-4.0.27.Final/transport-native-epoll/pom.xml ++++ b/netty-netty-4.0.27.Final/transport-native-epoll/pom.xml +@@ -73,9 +73,6 @@ + . + true + true +- +- ${jni.compiler.args} +- + + + generate diff --git a/SPECS/netty.spec b/SPECS/netty.spec new file mode 100644 index 0000000..7bc8571 --- /dev/null +++ b/SPECS/netty.spec @@ -0,0 +1,303 @@ +%{?scl:%scl_package netty} +%{!?scl:%global pkg_name %{name}} +%{?java_common_find_provides_and_requires} + +# Disable generation of debuginfo package +%global debug_package %{nil} +%global namedreltag .Final +%global namedversion %{version}%{?namedreltag} + +Name: %{?scl_prefix}netty +Version: 4.0.28 +Release: 2.3%{?dist} +Summary: An asynchronous event-driven network application framework and tools for Java +License: ASL 2.0 +URL: https://netty.io/ +Source0: https://github.com/netty/netty/archive/netty-%{namedversion}.tar.gz +Patch0: npn_alpn_ssl_fixes.patch +Patch1: transport-native-epoll-configure-fix.patch +Patch2: netty-old-jzlib.patch +Patch3: remove-bc-dependency.patch + +BuildRequires: %{?scl_prefix}maven-local +BuildRequires: %{?scl_prefix_maven}mvn(ant-contrib:ant-contrib) +BuildRequires: %{?scl_prefix}mvn(com.jcraft:jzlib) +BuildRequires: %{?scl_prefix}mvn(commons-logging:commons-logging) +BuildRequires: %{?scl_prefix}mvn(junit:junit) +BuildRequires: %{?scl_prefix}mvn(log4j:log4j) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.felix:maven-bundle-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-antrun-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-clean-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-dependency-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-deploy-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-jxr-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-release-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.plugins:maven-source-plugin) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.scm:maven-scm-api) +BuildRequires: %{?scl_prefix_maven}mvn(org.apache.maven.scm:maven-scm-provider-gitexe) +BuildRequires: %{?scl_prefix_maven}mvn(org.codehaus.mojo:build-helper-maven-plugin) +BuildRequires: %{?scl_prefix}mvn(org.easymock:easymock:3) +BuildRequires: %{?scl_prefix}mvn(org.fusesource.hawtjni:maven-hawtjni-plugin) +BuildRequires: %{?scl_prefix}mvn(org.javassist:javassist) +BuildRequires: %{?scl_prefix}mvn(org.slf4j:slf4j-api) +BuildRequires: %{?scl_prefix_maven}mvn(org.sonatype.oss:oss-parent:pom:) + +BuildArch: noarch + +%description +Netty is a NIO client server framework which enables quick and easy +development of network applications such as protocol servers and +clients. It greatly simplifies and streamlines network programming +such as TCP and UDP socket server. + +'Quick and easy' doesn't mean that a resulting application will suffer +from a maintainability or a performance issue. Netty has been designed +carefully with the experiences earned from the implementation of a lot +of protocols such as FTP, SMTP, HTTP, and various binary and +text-based legacy protocols. As a result, Netty has succeeded to find +a way to achieve ease of development, performance, stability, and +flexibility without a compromise. + +%package javadoc +Summary: API documentation for %{pkg_name} + +%description javadoc +%{summary}. + +%prep +%{?scl:scl enable %{scl_maven} %{scl} - << "EOF"} +%setup -q -n netty-netty-%{namedversion} + +%patch0 -p1 +%patch1 -p2 +%patch2 -p0 +%patch3 -p1 + +%pom_disable_module "transport-native-epoll" +%pom_remove_dep ":netty-transport-native-epoll" all +# Missing Mavenized rxtx +%pom_disable_module "transport-rxtx" +%pom_remove_dep ":netty-transport-rxtx" all +# Missing com.barchart.udt:barchart-udt-bundle:jar:2.3.0 +%pom_disable_module "transport-udt" +%pom_remove_dep ":netty-transport-udt" all +%pom_remove_dep ":netty-build" all +# Not needed +%pom_xpath_remove "pom:build/pom:extensions" +%pom_disable_module "example" +%pom_remove_dep ":netty-example" all +%pom_disable_module "testsuite" +%pom_disable_module "testsuite-osgi" +%pom_disable_module "tarball" +%pom_disable_module "microbench" +%pom_remove_plugin :maven-checkstyle-plugin +%pom_remove_plugin :animal-sniffer-maven-plugin +%pom_remove_plugin :maven-enforcer-plugin +%pom_remove_plugin :maven-antrun-plugin +%pom_remove_plugin :maven-dependency-plugin +# Optional things we don't ship +%pom_remove_dep ":netty-tcnative" +%pom_remove_dep ":netty-tcnative" handler +%pom_remove_dep "org.eclipse.jetty.npn:npn-api" +%pom_remove_dep "org.eclipse.jetty.npn:npn-api" handler +%pom_remove_dep "org.mortbay.jetty.npn:npn-boot" +%pom_remove_dep "org.mortbay.jetty.npn:npn-boot" handler +%pom_remove_dep "org.eclipse.jetty.alpn:alpn-api" +%pom_remove_dep "org.eclipse.jetty.alpn:alpn-api" handler +%pom_remove_dep "org.mortbay.jetty.alpn:alpn-boot" +%pom_remove_dep "org.mortbay.jetty.alpn:alpn-boot" handler +%pom_remove_dep "com.google.protobuf:protobuf-java" +%pom_remove_dep "com.google.protobuf:protobuf-java" codec +%pom_remove_dep "com.google.protobuf:protobuf-java" all +rm codec/src/main/java/io/netty/handler/codec/protobuf/* +%pom_remove_dep "org.jboss.marshalling:jboss-marshalling" +%pom_remove_dep "org.jboss.marshalling:jboss-marshalling" codec +%pom_remove_dep "org.jboss.marshalling:jboss-marshalling" all +rm codec/src/main/java/io/netty/handler/codec/marshalling/* + +# Remove runtime dep on optional javassist +%pom_xpath_set "pom:dependency[pom:artifactId[text()='javassist']]/pom:scope" "provided" common + +sed -i 's|taskdef|taskdef classpathref="maven.plugin.classpath"|' all/pom.xml + +%pom_xpath_inject "pom:plugins/pom:plugin[pom:artifactId = 'maven-antrun-plugin']" 'ant-contribant-contrib1.0b3' all/pom.xml +%pom_xpath_inject "pom:execution[pom:id = 'build-native-lib']/pom:configuration" 'true' transport-native-epoll/pom.xml + +# Tell xmvn to install attached artifact, which it does not +# do by default. In this case install all attached artifacts with +# the linux classifier. +%mvn_package ":::linux*:" +%{?scl:EOF} + + +%build +%{?scl:scl enable %{scl_maven} %{scl} - << "EOF"} +export CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" +%mvn_build -f +%{?scl:EOF} + + +%install +%{?scl:scl enable %{scl_maven} %{scl} - << "EOF"} +%mvn_install +%{?scl:EOF} + + +%files -f .mfiles +%doc LICENSE.txt NOTICE.txt +%dir %{_javadir}/netty +%dir %{_mavenpomdir}/netty + +%files javadoc -f .mfiles-javadoc +%doc LICENSE.txt NOTICE.txt + +%changelog +* Tue Feb 16 2016 Michal Srb - 4.0.28-2.3 +- Move to rh-java-common SCL + +* Mon Jul 13 2015 Mat Booth - 4.0.28-2.2 +- Fix unowned directories + +* Fri Jul 03 2015 Mat Booth - 4.0.28-2.1 +- Import latest from Fedora + +* Wed Jun 17 2015 Fedora Release Engineering - 4.0.28-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 20 2015 Severin Gehwolf - 4.0.28-1 +- Update to upstream 4.0.28 release. +- Fixes CVE-2015-2156 (HttpOnly cookie bypass). +- Resolves RHBZ#1111502 + +* Wed May 20 2015 Severin Gehwolf - 4.0.27-1 +- Update to upstream 4.0.27 release. + +* Wed Apr 01 2015 Severin Gehwolf - 4.0.19-3 +- Drop mvn(org.easymock:easymockclassextension) BR. + Resolves: RHBZ#1207991 + +* Sun Aug 17 2014 Fedora Release Engineering - 4.0.19-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Mon Jun 9 2014 Mikolaj Izdebski - 4.0.19-1 +- Update to upstream version 4.0.19 +- Convert to arch-specific package + +* Sat Jun 07 2014 Fedora Release Engineering - 4.0.14-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Mar 04 2014 Stanislav Ochotnicky - 4.0.14-4 +- Use Requires: java-headless rebuild (#1067528) + +* Mon Jan 13 2014 Marek Goldmann - 4.0.14-3 +- Enable netty-all.jar artifact + +* Mon Jan 13 2014 Marek Goldmann - 4.0.14-2 +- Bump the release, so Obsoletes work properly + +* Mon Dec 30 2013 Marek Goldmann - 4.0.14-1 +- Upstream release 4.0.14.Final + +* Sat Aug 03 2013 Fedora Release Engineering - 3.6.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Thu May 16 2013 Mikolaj Izdebski - 3.6.6-1 +- Update to upstream version 3.6.6 + +* Wed Apr 10 2013 Mikolaj Izdebski - 3.6.5-1 +- Update to upstream version 3.6.5 + +* Mon Apr 8 2013 Mikolaj Izdebski - 3.6.4-1 +- Update to upstream version 3.6.4 + +* Wed Feb 27 2013 Mikolaj Izdebski - 3.6.3-3 +- Set scope of optional compile dependencies to 'provided' + +* Wed Feb 27 2013 Mikolaj Izdebski - 3.6.3-2 +- Drop dependency on OSGi +- Resolves: rhbz#916139 + +* Mon Feb 25 2013 Mikolaj Izdebski - 3.6.3-1 +- Update to upstream version 3.6.3 + +* Thu Feb 14 2013 Fedora Release Engineering - 3.6.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Feb 06 2013 Java SIG - 3.6.2-2 +- Update for https://fedoraproject.org/wiki/Fedora_19_Maven_Rebuild +- Replace maven BuildRequires with maven-local + +* Wed Jan 16 2013 Mikolaj Izdebski - 3.6.2-1 +- Update to upstream version 3.6.2 + +* Tue Jan 15 2013 Mikolaj Izdebski - 3.6.1-1 +- Update to upstream version 3.6.1 + +* Thu Dec 13 2012 Mikolaj Izdebski - 3.5.11-2 +- Use system jzlib instead of bundled jzlib +- Resolves: rhbz#878391 + +* Mon Dec 3 2012 Mikolaj Izdebski - 3.5.11-1 +- Update to upstream version 3.5.11 + +* Mon Nov 12 2012 Mikolaj Izdebski - 3.5.10-1 +- Update to upstream version 3.5.10 + +* Thu Oct 25 2012 Mikolaj Izdebski - 3.5.9-1 +- Update to upstream version 3.5.9 + +* Fri Oct 5 2012 Mikolaj Izdebski - 3.5.8-1 +- Update to upstream version 3.5.8 + +* Fri Sep 7 2012 Mikolaj Izdebski - 3.5.7-1 +- Update to upstream version 3.5.7 + +* Mon Sep 3 2012 Mikolaj Izdebski - 3.5.6-1 +- Update to upstream version 3.5.6 + +* Thu Aug 23 2012 Mikolaj Izdebski - 3.5.5-1 +- Update to upstream version 3.5.5 + +* Wed Aug 15 2012 Tomas Rohovsky - 3.5.4-1 +- Update to upstream version 3.5.4 + +* Tue Jul 24 2012 Mikolaj Izdebski - 3.5.3-1 +- Update to upstream version 3.5.3 + +* Fri Jul 20 2012 Fedora Release Engineering - 3.5.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jul 16 2012 Mikolaj Izdebski - 3.5.2-2 +- Add additional depmap for org.jboss.netty:netty +- Fixes #840301 + +* Thu Jul 12 2012 Mikolaj Izdebski - 3.5.2-1 +- Update to upstream version 3.5.2 +- Convert patches to POM macros +- Enable jboss-logging + +* Fri May 18 2012 Stanislav Ochotnicky - 3.2.4-4 +- Add enforcer-plugin to BR + +* Wed Apr 18 2012 Stanislav Ochotnicky - 3.2.4-3 +- Remove eclipse plugin from BuildRequires + +* Fri Jan 13 2012 Fedora Release Engineering - 3.2.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Dec 5 2011 Stanislav Ochotnicky - 3.2.4-1 +- Update to latest upstream version + +* Mon Jul 4 2011 Alexander Kurtakov 3.2.3-4 +- Fix FTBFS. +- Adapt to current guidelines. + +* Tue Feb 08 2011 Fedora Release Engineering - 3.2.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 17 2011 Stanislav Ochotnicky - 3.2.3-2 +- Use maven 3 to build +- Drop ant-contrib depmap (no longer needed) + +* Thu Jan 13 2011 Stanislav Ochotnicky - 3.2.3-1 +- Initial version of the package