diff --git a/0001-Remove-optional-dep-Blockhound.patch b/0001-Remove-optional-dep-Blockhound.patch index f98082fc9d657f9436eac463b2359b92095fd482..d870092ee9cb1a965a286a973f6bc70da038434b 100644 --- a/0001-Remove-optional-dep-Blockhound.patch +++ b/0001-Remove-optional-dep-Blockhound.patch @@ -1,19 +1,19 @@ -From fde40bfedf245b8cd6f48d8681a29df1aa5d4036 Mon Sep 17 00:00:00 2001 +From 36ea49fb9506d63fa4198b30b22bc33adc9c74d7 Mon Sep 17 00:00:00 2001 From: Mat Booth Date: Mon, 7 Sep 2020 12:17:31 +0100 -Subject: [PATCH 1/7] Remove optional dep Blockhound +Subject: [PATCH 1/4] Remove optional dep Blockhound --- common/pom.xml | 5 - - .../java/io/netty/util/internal/Hidden.java | 190 ------ + .../java/io/netty/util/internal/Hidden.java | 200 ------ ...ockhound.integration.BlockHoundIntegration | 14 - pom.xml | 8 - - transport-blockhound-tests/pom.xml | 163 ----- - .../NettyBlockHoundIntegrationTest.java | 575 ------------------ + transport-blockhound-tests/pom.xml | 219 ------- + .../NettyBlockHoundIntegrationTest.java | 568 ------------------ .../netty/util/internal/localhost_server.key | 28 - .../netty/util/internal/localhost_server.pem | 17 - .../io/netty/util/internal/mutual_auth_ca.pem | 19 - - 9 files changed, 1019 deletions(-) + 9 files changed, 1078 deletions(-) delete mode 100644 common/src/main/java/io/netty/util/internal/Hidden.java delete mode 100644 common/src/main/resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration delete mode 100644 transport-blockhound-tests/pom.xml @@ -23,7 +23,7 @@ Subject: [PATCH 1/7] Remove optional dep Blockhound delete mode 100644 transport-blockhound-tests/src/test/resources/io/netty/util/internal/mutual_auth_ca.pem diff --git a/common/pom.xml b/common/pom.xml -index d59644adcf..77a3e430da 100644 +index a70b4f3b18..eb83e339af 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -82,11 +82,6 @@ @@ -40,10 +40,10 @@ index d59644adcf..77a3e430da 100644 mockito-core diff --git a/common/src/main/java/io/netty/util/internal/Hidden.java b/common/src/main/java/io/netty/util/internal/Hidden.java deleted file mode 100644 -index cf32e154ff..0000000000 +index e227c90c7e..0000000000 --- a/common/src/main/java/io/netty/util/internal/Hidden.java +++ /dev/null -@@ -1,190 +0,0 @@ +@@ -1,200 +0,0 @@ -/* - * Copyright 2019 The Netty Project - * @@ -142,6 +142,16 @@ index cf32e154ff..0000000000 - ); - - builder.allowBlockingCallsInside( +- "io.netty.buffer.AdaptivePoolingAllocator$1", +- "initialValue" +- ); +- +- builder.allowBlockingCallsInside( +- "io.netty.buffer.AdaptivePoolingAllocator$1", +- "onRemoval" +- ); +- +- builder.allowBlockingCallsInside( - "io.netty.handler.ssl.SslHandler", - "handshake" - ); @@ -256,10 +266,10 @@ index e33bea796c..0000000000 -io.netty.util.internal.Hidden$NettyBlockHoundIntegration \ No newline at end of file diff --git a/pom.xml b/pom.xml -index 0cea28ab0a..bf36e0b533 100644 +index 0626fc25ec..5c5b5f8ef4 100644 --- a/pom.xml +++ b/pom.xml -@@ -779,7 +779,6 @@ +@@ -839,7 +839,6 @@ testsuite-native-image testsuite-native-image-client testsuite-native-image-client-runtime-init @@ -267,7 +277,7 @@ index 0cea28ab0a..bf36e0b533 100644 microbench bom -@@ -1198,13 +1197,6 @@ +@@ -1254,13 +1253,6 @@ ${log4j2.version} test @@ -276,17 +286,17 @@ index 0cea28ab0a..bf36e0b533 100644 - - io.projectreactor.tools - blockhound -- 1.0.6.RELEASE +- 1.0.13.RELEASE - diff --git a/transport-blockhound-tests/pom.xml b/transport-blockhound-tests/pom.xml deleted file mode 100644 -index 4b273251fe..0000000000 +index d63f055214..0000000000 --- a/transport-blockhound-tests/pom.xml +++ /dev/null -@@ -1,163 +0,0 @@ +@@ -1,219 +0,0 @@ - - + + software.amazon.cryptools -- -2.46.1 +2.51.0 diff --git a/0003-Remove-optional-deps-jetty-alpn-and-npn.patch b/0003-Remove-optional-deps-jetty-alpn-and-npn.patch index 8658218f3d6b4b9a59e230c132eafb880eff2802..5b04e7a02fbcc0139d72cb86bad8c2bcb3822518 100644 --- a/0003-Remove-optional-deps-jetty-alpn-and-npn.patch +++ b/0003-Remove-optional-deps-jetty-alpn-and-npn.patch @@ -1,7 +1,7 @@ -From daed233559d36cfb8f5136403eb2224da0d89b82 Mon Sep 17 00:00:00 2001 +From 6be7812aeb2313bbf0fba49f353d9941de26b897 Mon Sep 17 00:00:00 2001 From: Mat Booth Date: Mon, 7 Sep 2020 13:26:20 +0100 -Subject: [PATCH 3/7] Remove optional deps jetty alpn and npn +Subject: [PATCH 3/4] Remove optional deps jetty alpn and npn --- handler/pom.xml | 10 -- @@ -15,7 +15,7 @@ Subject: [PATCH 3/7] Remove optional deps jetty alpn and npn delete mode 100644 handler/src/main/java/io/netty/handler/ssl/JettyNpnSslEngine.java diff --git a/handler/pom.xml b/handler/pom.xml -index 46c20028eb..35bdbf9272 100644 +index 4f1f05513d..2a1556277c 100644 --- a/handler/pom.xml +++ b/handler/pom.xml @@ -86,16 +86,6 @@ @@ -36,18 +36,18 @@ index 46c20028eb..35bdbf9272 100644 org.mockito mockito-core diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java b/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java -index b5715e87ff..df87f0f43a 100644 +index 92b0bc8b56..f0db866388 100644 --- a/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java +++ b/handler/src/main/java/io/netty/handler/ssl/JdkAlpnApplicationProtocolNegotiator.java -@@ -27,7 +27,6 @@ import javax.net.ssl.SSLEngine; +@@ -28,7 +28,6 @@ import javax.net.ssl.SSLEngine; @Deprecated public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator { private static final boolean AVAILABLE = JdkAlpnSslUtils.supportsAlpn() || - JettyAlpnSslEngine.isAvailable() || - BouncyCastle.isAvailable(); + BouncyCastleUtil.isBcTlsAvailable(); private static final SslEngineWrapperFactory ALPN_WRAPPER = AVAILABLE ? new AlpnWrapper() : new FailureWrapper(); -@@ -135,10 +134,6 @@ public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicati +@@ -139,10 +138,6 @@ public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicati if (JdkAlpnSslUtils.supportsAlpn()) { return new JdkAlpnSslEngine(engine, applicationNegotiator, isServer); } @@ -374,10 +374,10 @@ index aad00b5f6d..0000000000 - } -} diff --git a/pom.xml b/pom.xml -index ae68f4ebe8..176b8e9a96 100644 +index 170736db51..9add346f6b 100644 --- a/pom.xml +++ b/pom.xml -@@ -815,20 +815,6 @@ +@@ -875,20 +875,6 @@ true @@ -399,5 +399,5 @@ index ae68f4ebe8..176b8e9a96 100644 com.google.protobuf -- -2.46.1 +2.51.0 diff --git a/0005-Disable-Brotli-and-ZStd-compression.patch b/0004-Disable-Brotli-and-ZStd-compression.patch similarity index 80% rename from 0005-Disable-Brotli-and-ZStd-compression.patch rename to 0004-Disable-Brotli-and-ZStd-compression.patch index fefbec13603ee4f3c9b77c160248fd3c80f9a294..54148d89cb037ef5209e21b3f9dc360ca7bbf956 100644 --- a/0005-Disable-Brotli-and-ZStd-compression.patch +++ b/0004-Disable-Brotli-and-ZStd-compression.patch @@ -1,21 +1,21 @@ -From ce73ba58d8c6c733fdc060d89ac6d229a55fdd28 Mon Sep 17 00:00:00 2001 +From 8445a1513bc95a49a5ab9e89084cd3bf3ca0dd40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fridrich=20=C5=A0trba?= Date: Thu, 30 Mar 2023 13:19:04 +0200 -Subject: [PATCH 4/7] Disable Brotli and ZStd compression +Subject: [PATCH 4/4] Disable Brotli and ZStd compression --- - .../codec/http/HttpContentCompressor.java | 105 +----------------- + .../codec/http/HttpContentCompressor.java | 107 +----------------- .../codec/http/HttpContentDecompressor.java | 22 ---- .../CompressorHttp2ConnectionEncoder.java | 42 +------ .../DelegatingDecompressorFrameListener.java | 20 ---- - .../StandardCompressionOptions.java | 53 +-------- - 5 files changed, 5 insertions(+), 237 deletions(-) + .../StandardCompressionOptions.java | 70 +----------- + 5 files changed, 5 insertions(+), 256 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java -index 0effd37779..51e6c10934 100644 +index 17f55d3ed5..27da52dd9a 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java -@@ -22,9 +22,6 @@ import io.netty.buffer.ByteBuf; +@@ -24,9 +24,6 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.MessageToByteEncoder; @@ -25,7 +25,7 @@ index 0effd37779..51e6c10934 100644 import io.netty.handler.codec.compression.CompressionOptions; import io.netty.handler.codec.compression.DeflateOptions; import io.netty.handler.codec.compression.GzipOptions; -@@ -32,11 +29,6 @@ import io.netty.handler.codec.compression.StandardCompressionOptions; +@@ -34,11 +31,6 @@ import io.netty.handler.codec.compression.StandardCompressionOptions; import io.netty.handler.codec.compression.ZlibCodecFactory; import io.netty.handler.codec.compression.ZlibEncoder; import io.netty.handler.codec.compression.ZlibWrapper; @@ -36,32 +36,20 @@ index 0effd37779..51e6c10934 100644 -import io.netty.handler.codec.compression.SnappyOptions; import io.netty.util.internal.ObjectUtil; - /** -@@ -49,11 +41,8 @@ import io.netty.util.internal.ObjectUtil; + import static io.netty.util.internal.ObjectUtil.checkInRange; +@@ -52,11 +44,8 @@ import static io.netty.util.internal.ObjectUtil.checkInRange; + */ public class HttpContentCompressor extends HttpContentEncoder { - private final boolean supportsCompressionOptions; - private final BrotliOptions brotliOptions; private final GzipOptions gzipOptions; private final DeflateOptions deflateOptions; - private final ZstdOptions zstdOptions; - private final SnappyOptions snappyOptions; - private final int compressionLevel; - private final int windowBits; -@@ -137,11 +126,8 @@ public class HttpContentCompressor extends HttpContentEncoder { - this.windowBits = ObjectUtil.checkInRange(windowBits, 9, 15, "windowBits"); - this.memLevel = ObjectUtil.checkInRange(memLevel, 1, 9, "memLevel"); - this.contentSizeThreshold = ObjectUtil.checkPositiveOrZero(contentSizeThreshold, "contentSizeThreshold"); -- this.brotliOptions = null; - this.gzipOptions = null; - this.deflateOptions = null; -- this.zstdOptions = null; -- this.snappyOptions = null; - this.factories = null; - this.supportsCompressionOptions = false; - } -@@ -170,17 +156,11 @@ public class HttpContentCompressor extends HttpContentEncoder { + private final int contentSizeThreshold; + private ChannelHandlerContext ctx; +@@ -174,11 +163,8 @@ public class HttpContentCompressor extends HttpContentEncoder { */ public HttpContentCompressor(int contentSizeThreshold, CompressionOptions... compressionOptions) { this.contentSizeThreshold = ObjectUtil.checkPositiveOrZero(contentSizeThreshold, "contentSizeThreshold"); @@ -71,33 +59,27 @@ index 0effd37779..51e6c10934 100644 - ZstdOptions zstdOptions = null; - SnappyOptions snappyOptions = null; if (compressionOptions == null || compressionOptions.length == 0) { -- brotliOptions = Brotli.isAvailable() ? StandardCompressionOptions.brotli() : null; - gzipOptions = StandardCompressionOptions.gzip(); - deflateOptions = StandardCompressionOptions.deflate(); -- zstdOptions = Zstd.isAvailable() ? StandardCompressionOptions.zstd() : null; -- snappyOptions = StandardCompressionOptions.snappy(); - } else { - ObjectUtil.deepCheckNotNull("compressionOptions", compressionOptions); - for (CompressionOptions compressionOption : compressionOptions) { -@@ -190,16 +170,10 @@ public class HttpContentCompressor extends HttpContentEncoder { - // This results in the static analysis of native-image identifying the instanceof BrotliOptions check - // and thus BrotliOptions itself as unreachable, enabling native-image to link all classes - // at build time and not complain about the missing Brotli classes. -- if (Brotli.isAvailable() && compressionOption instanceof BrotliOptions) { -- brotliOptions = (BrotliOptions) compressionOption; -- } else if (compressionOption instanceof GzipOptions) { -+ if (compressionOption instanceof GzipOptions) { - gzipOptions = (GzipOptions) compressionOption; - } else if (compressionOption instanceof DeflateOptions) { - deflateOptions = (DeflateOptions) compressionOption; -- } else if (compressionOption instanceof ZstdOptions) { -- zstdOptions = (ZstdOptions) compressionOption; -- } else if (compressionOption instanceof SnappyOptions) { -- snappyOptions = (SnappyOptions) compressionOption; - } else { - throw new IllegalArgumentException("Unsupported " + CompressionOptions.class.getSimpleName() + - ": " + compressionOption); -@@ -209,9 +183,6 @@ public class HttpContentCompressor extends HttpContentEncoder { + compressionOptions = defaultCompressionOptions( + StandardCompressionOptions.gzip(), StandardCompressionOptions.deflate()); +@@ -192,16 +178,10 @@ public class HttpContentCompressor extends HttpContentEncoder { + // This results in the static analysis of native-image identifying the instanceof BrotliOptions check + // and thus BrotliOptions itself as unreachable, enabling native-image to link all classes + // at build time and not complain about the missing Brotli classes. +- if (Brotli.isAvailable() && compressionOption instanceof BrotliOptions) { +- brotliOptions = (BrotliOptions) compressionOption; +- } else if (compressionOption instanceof GzipOptions) { ++ if (compressionOption instanceof GzipOptions) { + gzipOptions = (GzipOptions) compressionOption; + } else if (compressionOption instanceof DeflateOptions) { + deflateOptions = (DeflateOptions) compressionOption; +- } else if (Zstd.isAvailable() && compressionOption instanceof ZstdOptions) { +- zstdOptions = (ZstdOptions) compressionOption; +- } else if (compressionOption instanceof SnappyOptions) { +- snappyOptions = (SnappyOptions) compressionOption; + } else { + throw new IllegalArgumentException("Unsupported " + CompressionOptions.class.getSimpleName() + + ": " + compressionOption); +@@ -210,9 +190,6 @@ public class HttpContentCompressor extends HttpContentEncoder { this.gzipOptions = gzipOptions; this.deflateOptions = deflateOptions; @@ -107,7 +89,7 @@ index 0effd37779..51e6c10934 100644 this.factories = new HashMap(); -@@ -221,15 +192,6 @@ public class HttpContentCompressor extends HttpContentEncoder { +@@ -222,15 +199,6 @@ public class HttpContentCompressor extends HttpContentEncoder { if (this.deflateOptions != null) { this.factories.put("deflate", new DeflateEncoderFactory()); } @@ -120,10 +102,25 @@ index 0effd37779..51e6c10934 100644 - if (this.snappyOptions != null) { - this.factories.put("snappy", new SnappyEncoderFactory()); - } + } - this.compressionLevel = -1; - this.windowBits = -1; -@@ -302,9 +264,6 @@ public class HttpContentCompressor extends HttpContentEncoder { + private static CompressionOptions[] defaultCompressionOptions( +@@ -238,14 +206,6 @@ public class HttpContentCompressor extends HttpContentEncoder { + List options = new ArrayList(5); + options.add(gzipOptions); + options.add(deflateOptions); +- options.add(StandardCompressionOptions.snappy()); +- +- if (Brotli.isAvailable()) { +- options.add(StandardCompressionOptions.brotli()); +- } +- if (Zstd.isAvailable()) { +- options.add(StandardCompressionOptions.zstd()); +- } + return options.toArray(new CompressionOptions[0]); + } + +@@ -289,9 +249,6 @@ public class HttpContentCompressor extends HttpContentEncoder { @SuppressWarnings("FloatingPointEquality") protected String determineEncoding(String acceptEncoding) { float starQ = -1.0f; @@ -133,7 +130,7 @@ index 0effd37779..51e6c10934 100644 float gzipQ = -1.0f; float deflateQ = -1.0f; for (String encoding : acceptEncoding.split(",")) { -@@ -320,41 +279,20 @@ public class HttpContentCompressor extends HttpContentEncoder { +@@ -307,41 +264,20 @@ public class HttpContentCompressor extends HttpContentEncoder { } if (encoding.contains("*")) { starQ = q; @@ -177,7 +174,7 @@ index 0effd37779..51e6c10934 100644 if (gzipQ == -1.0f && this.gzipOptions != null) { return "gzip"; } -@@ -435,41 +373,4 @@ public class HttpContentCompressor extends HttpContentEncoder { +@@ -422,41 +358,4 @@ public class HttpContentCompressor extends HttpContentEncoder { deflateOptions.windowBits(), deflateOptions.memLevel()); } } @@ -220,10 +217,10 @@ index 0effd37779..51e6c10934 100644 - } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java -index 3b1134b038..c2f3150bfd 100644 +index 44e6195332..ea461844af 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java -@@ -15,22 +15,14 @@ +@@ -15,23 +15,15 @@ */ package io.netty.handler.codec.http; @@ -234,6 +231,7 @@ index 3b1134b038..c2f3150bfd 100644 import static io.netty.handler.codec.http.HttpHeaderValues.X_GZIP; -import static io.netty.handler.codec.http.HttpHeaderValues.SNAPPY; -import static io.netty.handler.codec.http.HttpHeaderValues.ZSTD; + import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.codec.compression.Brotli; @@ -246,9 +244,9 @@ index 3b1134b038..c2f3150bfd 100644 /** * Decompresses an {@link HttpMessage} and an {@link HttpContent} compressed in -@@ -72,20 +64,6 @@ public class HttpContentDecompressor extends HttpContentDecoder { +@@ -102,20 +94,6 @@ public class HttpContentDecompressor extends HttpContentDecoder { return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(), - ctx.channel().config(), ZlibCodecFactory.newZlibDecoder(wrapper)); + ctx.channel().config(), ZlibCodecFactory.newZlibDecoder(wrapper, maxAllocation)); } - if (Brotli.isAvailable() && BR.contentEqualsIgnoreCase(contentEncoding)) { - return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(), @@ -372,11 +370,11 @@ index b12213dff6..fdeadaebbe 100644 return null; } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java -index 88245d1116..de44d6013b 100644 +index 73e497ccb8..56a2a93677 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java -@@ -19,24 +19,16 @@ import io.netty.buffer.Unpooled; - import io.netty.channel.ChannelHandlerContext; +@@ -20,24 +20,16 @@ import io.netty.channel.ChannelHandlerContext; + import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.ByteToMessageDecoder; -import io.netty.handler.codec.compression.Brotli; @@ -400,9 +398,9 @@ index 88245d1116..de44d6013b 100644 import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Exception.streamError; import static io.netty.util.internal.ObjectUtil.checkNotNull; -@@ -181,18 +173,6 @@ public class DelegatingDecompressorFrameListener extends Http2FrameListenerDecor +@@ -175,18 +167,6 @@ public class DelegatingDecompressorFrameListener extends Http2FrameListenerDecor return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(), - ctx.channel().config(), ZlibCodecFactory.newZlibDecoder(wrapper)); + ctx.channel().config(), ZlibCodecFactory.newZlibDecoder(wrapper, maxAllocation)); } - if (Brotli.isAvailable() && BR.contentEqualsIgnoreCase(contentEncoding)) { - return new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(), @@ -420,25 +418,27 @@ index 88245d1116..de44d6013b 100644 return null; } diff --git a/codec/src/main/java/io/netty/handler/codec/compression/StandardCompressionOptions.java b/codec/src/main/java/io/netty/handler/codec/compression/StandardCompressionOptions.java -index ac2582418c..698c4b510a 100644 +index 38793a97e6..c1f1c8c17c 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/StandardCompressionOptions.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/StandardCompressionOptions.java -@@ -15,10 +15,8 @@ +@@ -15,11 +15,10 @@ */ package io.netty.handler.codec.compression; -import com.aayushatharva.brotli4j.encoder.Encoder; -- + import io.netty.util.internal.ObjectUtil; + /** - * Standard Compression Options for {@link BrotliOptions}, + * Standard Compression Options for * {@link GzipOptions} and {@link DeflateOptions} */ public final class StandardCompressionOptions { -@@ -28,55 +26,6 @@ public final class StandardCompressionOptions { +@@ -28,73 +27,6 @@ public final class StandardCompressionOptions { + // Prevent outside initialization } - /** +- /** - * Default implementation of {@link BrotliOptions} with {@link Encoder.Parameters#setQuality(int)} set to 4 - * and {@link Encoder.Parameters#setMode(Encoder.Mode)} set to {@link Encoder.Mode#TEXT} - */ @@ -451,12 +451,34 @@ index ac2582418c..698c4b510a 100644 - * - * @param parameters {@link Encoder.Parameters} Instance - * @throws NullPointerException If {@link Encoder.Parameters} is {@code null} +- * @deprecated Use {@link #brotli(int, int, BrotliMode)} - */ +- @Deprecated - public static BrotliOptions brotli(Encoder.Parameters parameters) { - return new BrotliOptions(parameters); - } - - /** +- * Create a new {@link BrotliOptions} +- * +- * @param quality Specifies the compression level. +- * @param window Specifies the size of the sliding window when compressing. +- * @param mode optimizes the compression algorithm based on the type of input data. +- * @throws NullPointerException If {@link BrotliMode} is {@code null} +- */ +- public static BrotliOptions brotli(int quality, int window, BrotliMode mode) { +- ObjectUtil.checkInRange(quality, 0, 11, "quality"); +- ObjectUtil.checkInRange(window, 10, 24, "window"); +- ObjectUtil.checkNotNull(mode, "mode"); +- +- Encoder.Parameters parameters = new Encoder.Parameters() +- .setQuality(quality) +- .setWindow(window) +- .setMode(mode.adapt()); +- return new BrotliOptions(parameters); +- } +- +- /** - * Default implementation of {@link ZstdOptions} with{compressionLevel(int)} set to - * {@link ZstdConstants#DEFAULT_COMPRESSION_LEVEL},{@link ZstdConstants#DEFAULT_BLOCK_SIZE}, - * {@link ZstdConstants#MAX_BLOCK_SIZE} @@ -468,12 +490,9 @@ index ac2582418c..698c4b510a 100644 - /** - * Create a new {@link ZstdOptions} - * -- * @param blockSize -- * is used to calculate the compressionLevel -- * @param maxEncodeSize -- * specifies the size of the largest compressed object -- * @param compressionLevel -- * specifies the level of the compression +- * @param blockSize is used to calculate the compressionLevel +- * @param maxEncodeSize specifies the size of the largest compressed object +- * @param compressionLevel specifies the level of the compression - */ - public static ZstdOptions zstd(int compressionLevel, int blockSize, int maxEncodeSize) { - return new ZstdOptions(compressionLevel, blockSize, maxEncodeSize); @@ -481,16 +500,14 @@ index ac2582418c..698c4b510a 100644 - - /** - * Create a new {@link SnappyOptions} -- * - */ - public static SnappyOptions snappy() { - return new SnappyOptions(); - } - -- /** + /** * Default implementation of {@link GzipOptions} with * {@code compressionLevel()} set to 6, {@code windowBits()} set to 15 and {@code memLevel()} set to 8. - */ -- -2.46.1 +2.51.0 diff --git a/0004-Remove-optional-dep-tcnative.patch b/0004-Remove-optional-dep-tcnative.patch deleted file mode 100644 index eb6642d5f882bf9b526a67cdcf30fd495f386aae..0000000000000000000000000000000000000000 --- a/0004-Remove-optional-dep-tcnative.patch +++ /dev/null @@ -1,10296 +0,0 @@ -From 0d48b0e20264f3391a11c590dc74ac1ee1040156 Mon Sep 17 00:00:00 2001 -From: starlet-dx <15929766099@163.com> -Date: Thu, 14 Nov 2024 14:57:08 +0800 -Subject: [PATCH 1/1] case1 - ---- - handler/pom.xml | 6 - - .../handler/ssl/CipherSuiteConverter.java | 516 --- - .../ssl/DefaultOpenSslKeyMaterial.java | 126 - - .../handler/ssl/ExtendedOpenSslSession.java | 268 -- - .../java/io/netty/handler/ssl/OpenSsl.java | 747 ----- - .../ssl/OpenSslAsyncPrivateKeyMethod.java | 58 - - .../OpenSslCachingKeyMaterialProvider.java | 79 - - .../OpenSslCachingX509KeyManagerFactory.java | 80 - - .../ssl/OpenSslCertificateException.java | 81 - - .../handler/ssl/OpenSslClientContext.java | 212 -- - .../ssl/OpenSslClientSessionCache.java | 188 -- - .../io/netty/handler/ssl/OpenSslContext.java | 64 - - .../handler/ssl/OpenSslContextOption.java | 77 - - .../io/netty/handler/ssl/OpenSslEngine.java | 41 - - .../netty/handler/ssl/OpenSslEngineMap.java | 35 - - .../ssl/OpenSslKeyMaterialManager.java | 138 - - .../ssl/OpenSslKeyMaterialProvider.java | 154 - - .../netty/handler/ssl/OpenSslPrivateKey.java | 191 -- - .../handler/ssl/OpenSslPrivateKeyMethod.java | 62 - - .../handler/ssl/OpenSslServerContext.java | 374 --- - .../ssl/OpenSslServerSessionContext.java | 50 - - .../io/netty/handler/ssl/OpenSslSession.java | 95 - - .../handler/ssl/OpenSslSessionCache.java | 521 ---- - .../handler/ssl/OpenSslSessionContext.java | 229 -- - .../handler/ssl/OpenSslSessionStats.java | 253 -- - .../handler/ssl/OpenSslSessionTicketKey.java | 78 - - .../ssl/OpenSslX509KeyManagerFactory.java | 416 --- - .../ReferenceCountedOpenSslClientContext.java | 324 -- - .../ssl/ReferenceCountedOpenSslContext.java | 1173 ------- - .../ssl/ReferenceCountedOpenSslEngine.java | 2760 ----------------- - .../ReferenceCountedOpenSslServerContext.java | 302 -- - .../java/io/netty/handler/ssl/SslContext.java | 32 +- - .../java/io/netty/handler/ssl/SslHandler.java | 61 +- - .../handler/ssl/SslMasterKeyHandler.java | 3 - - .../io/netty/handler/ssl/SslProvider.java | 23 +- - .../handler/ssl/ocsp/OcspClientHandler.java | 61 - - .../netty/handler/ssl/ocsp/package-info.java | 23 - - 37 files changed, 3 insertions(+), 9898 deletions(-) - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/CipherSuiteConverter.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/DefaultOpenSslKeyMaterial.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSsl.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslAsyncPrivateKeyMethod.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslCachingKeyMaterialProvider.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslCachingX509KeyManagerFactory.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslCertificateException.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslClientSessionCache.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslContextOption.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslEngineMap.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialProvider.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKey.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKeyMethod.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslServerSessionContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslSession.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslSessionCache.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslSessionTicketKey.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/OpenSslX509KeyManagerFactory.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ocsp/OcspClientHandler.java - delete mode 100644 handler/src/main/java/io/netty/handler/ssl/ocsp/package-info.java - -diff --git a/handler/pom.xml b/handler/pom.xml -index 980c79d..08a693c 100644 ---- a/handler/pom.xml -+++ b/handler/pom.xml -@@ -70,12 +70,6 @@ - netty-tcnative-classes - true - -- -- ${project.groupId} -- ${tcnative.artifactId} -- ${tcnative.classifier} -- true -- - - org.bouncycastle - bcpkix-jdk15on -diff --git a/handler/src/main/java/io/netty/handler/ssl/CipherSuiteConverter.java b/handler/src/main/java/io/netty/handler/ssl/CipherSuiteConverter.java -deleted file mode 100644 -index 910b5e3..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/CipherSuiteConverter.java -+++ /dev/null -@@ -1,516 +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: -- * -- * https://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.PlatformDependent; --import io.netty.util.internal.UnstableApi; --import io.netty.util.internal.logging.InternalLogger; --import io.netty.util.internal.logging.InternalLoggerFactory; -- --import java.util.Collections; --import java.util.HashMap; --import java.util.Map; --import java.util.concurrent.ConcurrentMap; --import java.util.regex.Matcher; --import java.util.regex.Pattern; -- --import static java.util.Collections.singletonMap; -- --/** -- * Converts a Java cipher suite string to an OpenSSL cipher suite string and vice versa. -- * -- * @see Wikipedia page about cipher suite -- */ --@UnstableApi --public final class CipherSuiteConverter { -- -- private static final InternalLogger logger = InternalLoggerFactory.getInstance(CipherSuiteConverter.class); -- -- /** -- * A_B_WITH_C_D, where: -- * -- * A - TLS or SSL (protocol) -- * B - handshake algorithm (key exchange and authentication algorithms to be precise) -- * C - bulk cipher -- * D - HMAC algorithm -- * -- * This regular expression assumes that: -- * -- * 1) A is always TLS or SSL, and -- * 2) D is always a single word. -- */ -- private static final Pattern JAVA_CIPHERSUITE_PATTERN = -- Pattern.compile("^(?:TLS|SSL)_((?:(?!_WITH_).)+)_WITH_(.*)_(.*)$"); -- -- /** -- * A-B-C, where: -- * -- * A - handshake algorithm (key exchange and authentication algorithms to be precise) -- * B - bulk cipher -- * C - HMAC algorithm -- * -- * This regular expression assumes that: -- * -- * 1) A has some deterministic pattern as shown below, and -- * 2) C is always a single word -- */ -- private static final Pattern OPENSSL_CIPHERSUITE_PATTERN = -- // Be very careful not to break the indentation while editing. -- Pattern.compile( -- "^(?:(" + // BEGIN handshake algorithm -- "(?:(?:EXP-)?" + -- "(?:" + -- "(?:DHE|EDH|ECDH|ECDHE|SRP|RSA)-(?:DSS|RSA|ECDSA|PSK)|" + -- "(?:ADH|AECDH|KRB5|PSK|SRP)" + -- ')' + -- ")|" + -- "EXP" + -- ")-)?" + // END handshake algorithm -- "(.*)-(.*)$"); -- -- private static final Pattern JAVA_AES_CBC_PATTERN = Pattern.compile("^(AES)_([0-9]+)_CBC$"); -- private static final Pattern JAVA_AES_PATTERN = Pattern.compile("^(AES)_([0-9]+)_(.*)$"); -- private static final Pattern OPENSSL_AES_CBC_PATTERN = Pattern.compile("^(AES)([0-9]+)$"); -- private static final Pattern OPENSSL_AES_PATTERN = Pattern.compile("^(AES)([0-9]+)-(.*)$"); -- -- /** -- * Used to store nullable values in a CHM -- */ -- private static final class CachedValue { -- -- private static final CachedValue NULL = new CachedValue(null); -- -- static CachedValue of(String value) { -- return value != null ? new CachedValue(value) : NULL; -- } -- -- final String value; -- private CachedValue(String value) { -- this.value = value; -- } -- } -- -- /** -- * Java-to-OpenSSL cipher suite conversion map -- * Note that the Java cipher suite has the protocol prefix (TLS_, SSL_) -- */ -- private static final ConcurrentMap j2o = PlatformDependent.newConcurrentHashMap(); -- -- /** -- * OpenSSL-to-Java cipher suite conversion map. -- * Note that one OpenSSL cipher suite can be converted to more than one Java cipher suites because -- * a Java cipher suite has the protocol name prefix (TLS_, SSL_) -- */ -- private static final ConcurrentMap> o2j = PlatformDependent.newConcurrentHashMap(); -- -- private static final Map j2oTls13; -- private static final Map> o2jTls13; -- -- static { -- Map j2oTls13Map = new HashMap(); -- j2oTls13Map.put("TLS_AES_128_GCM_SHA256", "AEAD-AES128-GCM-SHA256"); -- j2oTls13Map.put("TLS_AES_256_GCM_SHA384", "AEAD-AES256-GCM-SHA384"); -- j2oTls13Map.put("TLS_CHACHA20_POLY1305_SHA256", "AEAD-CHACHA20-POLY1305-SHA256"); -- j2oTls13 = Collections.unmodifiableMap(j2oTls13Map); -- -- Map> o2jTls13Map = new HashMap>(); -- o2jTls13Map.put("TLS_AES_128_GCM_SHA256", singletonMap("TLS", "TLS_AES_128_GCM_SHA256")); -- o2jTls13Map.put("TLS_AES_256_GCM_SHA384", singletonMap("TLS", "TLS_AES_256_GCM_SHA384")); -- o2jTls13Map.put("TLS_CHACHA20_POLY1305_SHA256", singletonMap("TLS", "TLS_CHACHA20_POLY1305_SHA256")); -- o2jTls13Map.put("AEAD-AES128-GCM-SHA256", singletonMap("TLS", "TLS_AES_128_GCM_SHA256")); -- o2jTls13Map.put("AEAD-AES256-GCM-SHA384", singletonMap("TLS", "TLS_AES_256_GCM_SHA384")); -- o2jTls13Map.put("AEAD-CHACHA20-POLY1305-SHA256", singletonMap("TLS", "TLS_CHACHA20_POLY1305_SHA256")); -- o2jTls13 = Collections.unmodifiableMap(o2jTls13Map); -- } -- -- /** -- * Clears the cache for testing purpose. -- */ -- static void clearCache() { -- j2o.clear(); -- o2j.clear(); -- } -- -- /** -- * Tests if the specified key-value pair has been cached in Java-to-OpenSSL cache. -- */ -- static boolean isJ2OCached(String key, String value) { -- CachedValue cached = j2o.get(key); -- return cached != null && value.equals(cached.value); -- } -- -- /** -- * Tests if the specified key-value pair has been cached in OpenSSL-to-Java cache. -- */ -- static boolean isO2JCached(String key, String protocol, String value) { -- Map p2j = o2j.get(key); -- if (p2j == null) { -- return false; -- } else { -- return value.equals(p2j.get(protocol)); -- } -- } -- -- /** -- * Converts the specified Java cipher suite to its corresponding OpenSSL cipher suite name. -- * -- * @return {@code null} if the conversion has failed -- */ -- public static String toOpenSsl(String javaCipherSuite, boolean boringSSL) { -- CachedValue converted = j2o.get(javaCipherSuite); -- if (converted != null) { -- return converted.value; -- } -- return cacheFromJava(javaCipherSuite, boringSSL); -- } -- -- private static String cacheFromJava(String javaCipherSuite, boolean boringSSL) { -- String converted = j2oTls13.get(javaCipherSuite); -- if (converted != null) { -- return boringSSL ? converted : javaCipherSuite; -- } -- -- String openSslCipherSuite = toOpenSslUncached(javaCipherSuite, boringSSL); -- -- // Cache the mapping. -- j2o.putIfAbsent(javaCipherSuite, CachedValue.of(openSslCipherSuite)); -- -- if (openSslCipherSuite == null) { -- return null; -- } -- -- // Cache the reverse mapping after stripping the protocol prefix (TLS_ or SSL_) -- final String javaCipherSuiteSuffix = javaCipherSuite.substring(4); -- Map p2j = new HashMap(4); -- p2j.put("", javaCipherSuiteSuffix); -- p2j.put("SSL", "SSL_" + javaCipherSuiteSuffix); -- p2j.put("TLS", "TLS_" + javaCipherSuiteSuffix); -- o2j.put(openSslCipherSuite, p2j); -- -- logger.debug("Cipher suite mapping: {} => {}", javaCipherSuite, openSslCipherSuite); -- -- return openSslCipherSuite; -- } -- -- static String toOpenSslUncached(String javaCipherSuite, boolean boringSSL) { -- String converted = j2oTls13.get(javaCipherSuite); -- if (converted != null) { -- return boringSSL ? converted : javaCipherSuite; -- } -- -- Matcher m = JAVA_CIPHERSUITE_PATTERN.matcher(javaCipherSuite); -- if (!m.matches()) { -- return null; -- } -- -- String handshakeAlgo = toOpenSslHandshakeAlgo(m.group(1)); -- String bulkCipher = toOpenSslBulkCipher(m.group(2)); -- String hmacAlgo = toOpenSslHmacAlgo(m.group(3)); -- if (handshakeAlgo.isEmpty()) { -- return bulkCipher + '-' + hmacAlgo; -- } else if (bulkCipher.contains("CHACHA20")) { -- return handshakeAlgo + '-' + bulkCipher; -- } else { -- return handshakeAlgo + '-' + bulkCipher + '-' + hmacAlgo; -- } -- } -- -- private static String toOpenSslHandshakeAlgo(String handshakeAlgo) { -- final boolean export = handshakeAlgo.endsWith("_EXPORT"); -- if (export) { -- handshakeAlgo = handshakeAlgo.substring(0, handshakeAlgo.length() - 7); -- } -- -- if ("RSA".equals(handshakeAlgo)) { -- handshakeAlgo = ""; -- } else if (handshakeAlgo.endsWith("_anon")) { -- handshakeAlgo = 'A' + handshakeAlgo.substring(0, handshakeAlgo.length() - 5); -- } -- -- if (export) { -- if (handshakeAlgo.isEmpty()) { -- handshakeAlgo = "EXP"; -- } else { -- handshakeAlgo = "EXP-" + handshakeAlgo; -- } -- } -- -- return handshakeAlgo.replace('_', '-'); -- } -- -- private static String toOpenSslBulkCipher(String bulkCipher) { -- if (bulkCipher.startsWith("AES_")) { -- Matcher m = JAVA_AES_CBC_PATTERN.matcher(bulkCipher); -- if (m.matches()) { -- return m.replaceFirst("$1$2"); -- } -- -- m = JAVA_AES_PATTERN.matcher(bulkCipher); -- if (m.matches()) { -- return m.replaceFirst("$1$2-$3"); -- } -- } -- -- if ("3DES_EDE_CBC".equals(bulkCipher)) { -- return "DES-CBC3"; -- } -- -- if ("RC4_128".equals(bulkCipher) || "RC4_40".equals(bulkCipher)) { -- return "RC4"; -- } -- -- if ("DES40_CBC".equals(bulkCipher) || "DES_CBC_40".equals(bulkCipher)) { -- return "DES-CBC"; -- } -- -- if ("RC2_CBC_40".equals(bulkCipher)) { -- return "RC2-CBC"; -- } -- -- return bulkCipher.replace('_', '-'); -- } -- -- private static String toOpenSslHmacAlgo(String hmacAlgo) { -- // Java and OpenSSL use the same algorithm names for: -- // -- // * SHA -- // * SHA256 -- // * MD5 -- // -- return hmacAlgo; -- } -- -- /** -- * Convert from OpenSSL cipher suite name convention to java cipher suite name convention. -- * @param openSslCipherSuite An OpenSSL cipher suite name. -- * @param protocol The cryptographic protocol (i.e. SSL, TLS, ...). -- * @return The translated cipher suite name according to java conventions. This will not be {@code null}. -- */ -- public static String toJava(String openSslCipherSuite, String protocol) { -- Map p2j = o2j.get(openSslCipherSuite); -- if (p2j == null) { -- p2j = cacheFromOpenSsl(openSslCipherSuite); -- // This may happen if this method is queried when OpenSSL doesn't yet have a cipher setup. It will return -- // "(NONE)" in this case. -- if (p2j == null) { -- return null; -- } -- } -- -- String javaCipherSuite = p2j.get(protocol); -- if (javaCipherSuite == null) { -- String cipher = p2j.get(""); -- if (cipher == null) { -- return null; -- } -- javaCipherSuite = protocol + '_' + cipher; -- } -- -- return javaCipherSuite; -- } -- -- private static Map cacheFromOpenSsl(String openSslCipherSuite) { -- Map converted = o2jTls13.get(openSslCipherSuite); -- if (converted != null) { -- return converted; -- } -- -- String javaCipherSuiteSuffix = toJavaUncached0(openSslCipherSuite, false); -- if (javaCipherSuiteSuffix == null) { -- return null; -- } -- -- final String javaCipherSuiteSsl = "SSL_" + javaCipherSuiteSuffix; -- final String javaCipherSuiteTls = "TLS_" + javaCipherSuiteSuffix; -- -- // Cache the mapping. -- final Map p2j = new HashMap(4); -- p2j.put("", javaCipherSuiteSuffix); -- p2j.put("SSL", javaCipherSuiteSsl); -- p2j.put("TLS", javaCipherSuiteTls); -- o2j.putIfAbsent(openSslCipherSuite, p2j); -- -- // Cache the reverse mapping after adding the protocol prefix (TLS_ or SSL_) -- CachedValue cachedValue = CachedValue.of(openSslCipherSuite); -- j2o.putIfAbsent(javaCipherSuiteTls, cachedValue); -- j2o.putIfAbsent(javaCipherSuiteSsl, cachedValue); -- -- logger.debug("Cipher suite mapping: {} => {}", javaCipherSuiteTls, openSslCipherSuite); -- logger.debug("Cipher suite mapping: {} => {}", javaCipherSuiteSsl, openSslCipherSuite); -- -- return p2j; -- } -- -- static String toJavaUncached(String openSslCipherSuite) { -- return toJavaUncached0(openSslCipherSuite, true); -- } -- -- private static String toJavaUncached0(String openSslCipherSuite, boolean checkTls13) { -- if (checkTls13) { -- Map converted = o2jTls13.get(openSslCipherSuite); -- if (converted != null) { -- return converted.get("TLS"); -- } -- } -- -- Matcher m = OPENSSL_CIPHERSUITE_PATTERN.matcher(openSslCipherSuite); -- if (!m.matches()) { -- return null; -- } -- -- String handshakeAlgo = m.group(1); -- final boolean export; -- if (handshakeAlgo == null) { -- handshakeAlgo = ""; -- export = false; -- } else if (handshakeAlgo.startsWith("EXP-")) { -- handshakeAlgo = handshakeAlgo.substring(4); -- export = true; -- } else if ("EXP".equals(handshakeAlgo)) { -- handshakeAlgo = ""; -- export = true; -- } else { -- export = false; -- } -- -- handshakeAlgo = toJavaHandshakeAlgo(handshakeAlgo, export); -- String bulkCipher = toJavaBulkCipher(m.group(2), export); -- String hmacAlgo = toJavaHmacAlgo(m.group(3)); -- -- String javaCipherSuite = handshakeAlgo + "_WITH_" + bulkCipher + '_' + hmacAlgo; -- // For historical reasons the CHACHA20 ciphers do not follow OpenSSL's custom naming convention and omits the -- // HMAC algorithm portion of the name. There is currently no way to derive this information because it is -- // omitted from the OpenSSL cipher name, but they currently all use SHA256 for HMAC [1]. -- // [1] https://www.openssl.org/docs/man1.1.0/apps/ciphers.html -- return bulkCipher.contains("CHACHA20") ? javaCipherSuite + "_SHA256" : javaCipherSuite; -- } -- -- private static String toJavaHandshakeAlgo(String handshakeAlgo, boolean export) { -- if (handshakeAlgo.isEmpty()) { -- handshakeAlgo = "RSA"; -- } else if ("ADH".equals(handshakeAlgo)) { -- handshakeAlgo = "DH_anon"; -- } else if ("AECDH".equals(handshakeAlgo)) { -- handshakeAlgo = "ECDH_anon"; -- } -- -- handshakeAlgo = handshakeAlgo.replace('-', '_'); -- if (export) { -- return handshakeAlgo + "_EXPORT"; -- } else { -- return handshakeAlgo; -- } -- } -- -- private static String toJavaBulkCipher(String bulkCipher, boolean export) { -- if (bulkCipher.startsWith("AES")) { -- Matcher m = OPENSSL_AES_CBC_PATTERN.matcher(bulkCipher); -- if (m.matches()) { -- return m.replaceFirst("$1_$2_CBC"); -- } -- -- m = OPENSSL_AES_PATTERN.matcher(bulkCipher); -- if (m.matches()) { -- return m.replaceFirst("$1_$2_$3"); -- } -- } -- -- if ("DES-CBC3".equals(bulkCipher)) { -- return "3DES_EDE_CBC"; -- } -- -- if ("RC4".equals(bulkCipher)) { -- if (export) { -- return "RC4_40"; -- } else { -- return "RC4_128"; -- } -- } -- -- if ("DES-CBC".equals(bulkCipher)) { -- if (export) { -- return "DES_CBC_40"; -- } else { -- return "DES_CBC"; -- } -- } -- -- if ("RC2-CBC".equals(bulkCipher)) { -- if (export) { -- return "RC2_CBC_40"; -- } else { -- return "RC2_CBC"; -- } -- } -- -- return bulkCipher.replace('-', '_'); -- } -- -- private static String toJavaHmacAlgo(String hmacAlgo) { -- // Java and OpenSSL use the same algorithm names for: -- // -- // * SHA -- // * SHA256 -- // * MD5 -- // -- return hmacAlgo; -- } -- -- /** -- * Convert the given ciphers if needed to OpenSSL format and append them to the correct {@link StringBuilder} -- * depending on if its a TLSv1.3 cipher or not. If this methods returns without throwing an exception its -- * guaranteed that at least one of the {@link StringBuilder}s contain some ciphers that can be used to configure -- * OpenSSL. -- */ -- static void convertToCipherStrings(Iterable cipherSuites, StringBuilder cipherBuilder, -- StringBuilder cipherTLSv13Builder, boolean boringSSL) { -- for (String c: cipherSuites) { -- if (c == null) { -- break; -- } -- -- String converted = toOpenSsl(c, boringSSL); -- if (converted == null) { -- converted = c; -- } -- -- if (!OpenSsl.isCipherSuiteAvailable(converted)) { -- throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')'); -- } -- -- if (SslUtils.isTLSv13Cipher(converted) || SslUtils.isTLSv13Cipher(c)) { -- cipherTLSv13Builder.append(converted); -- cipherTLSv13Builder.append(':'); -- } else { -- cipherBuilder.append(converted); -- cipherBuilder.append(':'); -- } -- } -- -- if (cipherBuilder.length() == 0 && cipherTLSv13Builder.length() == 0) { -- throw new IllegalArgumentException("empty cipher suites"); -- } -- if (cipherBuilder.length() > 0) { -- cipherBuilder.setLength(cipherBuilder.length() - 1); -- } -- if (cipherTLSv13Builder.length() > 0) { -- cipherTLSv13Builder.setLength(cipherTLSv13Builder.length() - 1); -- } -- } -- -- private CipherSuiteConverter() { } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/DefaultOpenSslKeyMaterial.java b/handler/src/main/java/io/netty/handler/ssl/DefaultOpenSslKeyMaterial.java -deleted file mode 100644 -index 6673044..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/DefaultOpenSslKeyMaterial.java -+++ /dev/null -@@ -1,126 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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.internal.tcnative.SSL; --import io.netty.util.AbstractReferenceCounted; --import io.netty.util.IllegalReferenceCountException; --import io.netty.util.ResourceLeakDetector; --import io.netty.util.ResourceLeakDetectorFactory; --import io.netty.util.ResourceLeakTracker; -- --import java.security.cert.X509Certificate; -- --final class DefaultOpenSslKeyMaterial extends AbstractReferenceCounted implements OpenSslKeyMaterial { -- -- private static final ResourceLeakDetector leakDetector = -- ResourceLeakDetectorFactory.instance().newResourceLeakDetector(DefaultOpenSslKeyMaterial.class); -- private final ResourceLeakTracker leak; -- private final X509Certificate[] x509CertificateChain; -- private long chain; -- private long privateKey; -- -- DefaultOpenSslKeyMaterial(long chain, long privateKey, X509Certificate[] x509CertificateChain) { -- this.chain = chain; -- this.privateKey = privateKey; -- this.x509CertificateChain = x509CertificateChain; -- leak = leakDetector.track(this); -- } -- -- @Override -- public X509Certificate[] certificateChain() { -- return x509CertificateChain.clone(); -- } -- -- @Override -- public long certificateChainAddress() { -- if (refCnt() <= 0) { -- throw new IllegalReferenceCountException(); -- } -- return chain; -- } -- -- @Override -- public long privateKeyAddress() { -- if (refCnt() <= 0) { -- throw new IllegalReferenceCountException(); -- } -- return privateKey; -- } -- -- @Override -- protected void deallocate() { -- SSL.freeX509Chain(chain); -- chain = 0; -- SSL.freePrivateKey(privateKey); -- privateKey = 0; -- if (leak != null) { -- boolean closed = leak.close(this); -- assert closed; -- } -- } -- -- @Override -- public DefaultOpenSslKeyMaterial retain() { -- if (leak != null) { -- leak.record(); -- } -- super.retain(); -- return this; -- } -- -- @Override -- public DefaultOpenSslKeyMaterial retain(int increment) { -- if (leak != null) { -- leak.record(); -- } -- super.retain(increment); -- return this; -- } -- -- @Override -- public DefaultOpenSslKeyMaterial touch() { -- if (leak != null) { -- leak.record(); -- } -- super.touch(); -- return this; -- } -- -- @Override -- public DefaultOpenSslKeyMaterial touch(Object hint) { -- if (leak != null) { -- leak.record(hint); -- } -- return this; -- } -- -- @Override -- public boolean release() { -- if (leak != null) { -- leak.record(); -- } -- return super.release(); -- } -- -- @Override -- public boolean release(int decrement) { -- if (leak != null) { -- leak.record(); -- } -- return super.release(decrement); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java b/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java -deleted file mode 100644 -index a016426..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java -+++ /dev/null -@@ -1,268 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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 io.netty.util.internal.SuppressJava6Requirement; -- --import javax.net.ssl.ExtendedSSLSession; --import javax.net.ssl.SSLException; --import javax.net.ssl.SSLPeerUnverifiedException; --import javax.net.ssl.SSLSessionBindingEvent; --import javax.net.ssl.SSLSessionBindingListener; --import javax.security.cert.X509Certificate; --import java.security.Principal; --import java.security.cert.Certificate; --import java.util.Collections; --import java.util.List; --import java.util.Map; -- --/** -- * Delegates all operations to a wrapped {@link OpenSslSession} except the methods defined by {@link ExtendedSSLSession} -- * itself. -- */ --@SuppressJava6Requirement(reason = "Usage guarded by java version check") --abstract class ExtendedOpenSslSession extends ExtendedSSLSession implements OpenSslSession { -- -- // TODO: use OpenSSL API to actually fetch the real data but for now just do what Conscrypt does: -- // https://github.com/google/conscrypt/blob/1.2.0/common/ -- // src/main/java/org/conscrypt/Java7ExtendedSSLSession.java#L32 -- private static final String[] LOCAL_SUPPORTED_SIGNATURE_ALGORITHMS = { -- "SHA512withRSA", "SHA512withECDSA", "SHA384withRSA", "SHA384withECDSA", "SHA256withRSA", -- "SHA256withECDSA", "SHA224withRSA", "SHA224withECDSA", "SHA1withRSA", "SHA1withECDSA", -- "RSASSA-PSS", -- }; -- -- private final OpenSslSession wrapped; -- -- ExtendedOpenSslSession(OpenSslSession wrapped) { -- this.wrapped = wrapped; -- } -- -- // Use rawtypes an unchecked override to be able to also work on java7. -- @Override -- @SuppressWarnings({ "unchecked", "rawtypes" }) -- public abstract List getRequestedServerNames(); -- -- // Do not mark as override so we can compile on java8. -- public List getStatusResponses() { -- // Just return an empty list for now until we support it as otherwise we will fail in java9 -- // because of their sun.security.ssl.X509TrustManagerImpl class. -- return Collections.emptyList(); -- } -- -- @Override -- public void prepareHandshake() { -- wrapped.prepareHandshake(); -- } -- -- @Override -- public Map keyValueStorage() { -- return wrapped.keyValueStorage(); -- } -- -- @Override -- public OpenSslSessionId sessionId() { -- return wrapped.sessionId(); -- } -- -- @Override -- public void setSessionDetails(long creationTime, long lastAccessedTime, OpenSslSessionId id, -- Map keyValueStorage) { -- wrapped.setSessionDetails(creationTime, lastAccessedTime, id, keyValueStorage); -- } -- -- @Override -- public final void setLocalCertificate(Certificate[] localCertificate) { -- wrapped.setLocalCertificate(localCertificate); -- } -- -- @Override -- public String[] getPeerSupportedSignatureAlgorithms() { -- return EmptyArrays.EMPTY_STRINGS; -- } -- -- @Override -- public final void tryExpandApplicationBufferSize(int packetLengthDataOnly) { -- wrapped.tryExpandApplicationBufferSize(packetLengthDataOnly); -- } -- -- @Override -- public final String[] getLocalSupportedSignatureAlgorithms() { -- return LOCAL_SUPPORTED_SIGNATURE_ALGORITHMS.clone(); -- } -- -- @Override -- public final byte[] getId() { -- return wrapped.getId(); -- } -- -- @Override -- public final OpenSslSessionContext getSessionContext() { -- return wrapped.getSessionContext(); -- } -- -- @Override -- public final long getCreationTime() { -- return wrapped.getCreationTime(); -- } -- -- @Override -- public final long getLastAccessedTime() { -- return wrapped.getLastAccessedTime(); -- } -- -- @Override -- public void setLastAccessedTime(long time) { -- wrapped.setLastAccessedTime(time); -- } -- -- @Override -- public final void invalidate() { -- wrapped.invalidate(); -- } -- -- @Override -- public final boolean isValid() { -- return wrapped.isValid(); -- } -- -- @Override -- public final void putValue(String name, Object value) { -- if (value instanceof SSLSessionBindingListener) { -- // Decorate the value if needed so we submit the correct SSLSession instance -- value = new SSLSessionBindingListenerDecorator((SSLSessionBindingListener) value); -- } -- wrapped.putValue(name, value); -- } -- -- @Override -- public final Object getValue(String s) { -- Object value = wrapped.getValue(s); -- if (value instanceof SSLSessionBindingListenerDecorator) { -- // Unwrap as needed so we return the original value -- return ((SSLSessionBindingListenerDecorator) value).delegate; -- } -- return value; -- } -- -- @Override -- public final void removeValue(String s) { -- wrapped.removeValue(s); -- } -- -- @Override -- public final String[] getValueNames() { -- return wrapped.getValueNames(); -- } -- -- @Override -- public final Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { -- return wrapped.getPeerCertificates(); -- } -- -- @Override -- public final Certificate[] getLocalCertificates() { -- return wrapped.getLocalCertificates(); -- } -- -- @Override -- public final X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { -- return wrapped.getPeerCertificateChain(); -- } -- -- @Override -- public final Principal getPeerPrincipal() throws SSLPeerUnverifiedException { -- return wrapped.getPeerPrincipal(); -- } -- -- @Override -- public final Principal getLocalPrincipal() { -- return wrapped.getLocalPrincipal(); -- } -- -- @Override -- public final String getCipherSuite() { -- return wrapped.getCipherSuite(); -- } -- -- @Override -- public String getProtocol() { -- return wrapped.getProtocol(); -- } -- -- @Override -- public final String getPeerHost() { -- return wrapped.getPeerHost(); -- } -- -- @Override -- public final int getPeerPort() { -- return wrapped.getPeerPort(); -- } -- -- @Override -- public final int getPacketBufferSize() { -- return wrapped.getPacketBufferSize(); -- } -- -- @Override -- public final int getApplicationBufferSize() { -- return wrapped.getApplicationBufferSize(); -- } -- -- private final class SSLSessionBindingListenerDecorator implements SSLSessionBindingListener { -- -- final SSLSessionBindingListener delegate; -- -- SSLSessionBindingListenerDecorator(SSLSessionBindingListener delegate) { -- this.delegate = delegate; -- } -- -- @Override -- public void valueBound(SSLSessionBindingEvent event) { -- delegate.valueBound(new SSLSessionBindingEvent(ExtendedOpenSslSession.this, event.getName())); -- } -- -- @Override -- public void valueUnbound(SSLSessionBindingEvent event) { -- delegate.valueUnbound(new SSLSessionBindingEvent(ExtendedOpenSslSession.this, event.getName())); -- } -- } -- -- @Override -- public void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate, -- byte[][] peerCertificateChain, long creationTime, long timeout) throws SSLException { -- wrapped.handshakeFinished(id, cipher, protocol, peerCertificate, peerCertificateChain, creationTime, timeout); -- } -- -- @Override -- public boolean equals(Object o) { -- return wrapped.equals(o); -- } -- -- @Override -- public int hashCode() { -- return wrapped.hashCode(); -- } -- -- @Override -- public String toString() { -- return "ExtendedOpenSslSession{" + -- "wrapped=" + wrapped + -- '}'; -- } --} -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 efd58d2..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java -+++ /dev/null -@@ -1,747 +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: -- * -- * https://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.UnpooledByteBufAllocator; --import io.netty.internal.tcnative.Buffer; --import io.netty.internal.tcnative.Library; --import io.netty.internal.tcnative.SSL; --import io.netty.internal.tcnative.SSLContext; --import io.netty.util.CharsetUtil; --import io.netty.util.ReferenceCountUtil; --import io.netty.util.ReferenceCounted; --import io.netty.util.internal.EmptyArrays; --import io.netty.util.internal.NativeLibraryLoader; --import io.netty.util.internal.PlatformDependent; --import io.netty.util.internal.StringUtil; --import io.netty.util.internal.SystemPropertyUtil; --import io.netty.util.internal.logging.InternalLogger; --import io.netty.util.internal.logging.InternalLoggerFactory; -- --import java.io.ByteArrayInputStream; --import java.security.cert.CertificateException; --import java.security.cert.X509Certificate; --import java.util.ArrayList; --import java.util.Arrays; --import java.util.Collection; --import java.util.Collections; --import java.util.HashSet; --import java.util.LinkedHashSet; --import java.util.List; --import java.util.Set; -- --import static io.netty.handler.ssl.SslUtils.*; -- --/** -- * 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; -- static final List DEFAULT_CIPHERS; -- static final Set AVAILABLE_CIPHER_SUITES; -- private static final Set AVAILABLE_OPENSSL_CIPHER_SUITES; -- private static final Set AVAILABLE_JAVA_CIPHER_SUITES; -- private static final boolean SUPPORTS_KEYMANAGER_FACTORY; -- private static final boolean USE_KEYMANAGER_FACTORY; -- private static final boolean SUPPORTS_OCSP; -- private static final boolean TLSV13_SUPPORTED; -- private static final boolean IS_BORINGSSL; -- private static final Set CLIENT_DEFAULT_PROTOCOLS; -- private static final Set SERVER_DEFAULT_PROTOCOLS; -- static final Set SUPPORTED_PROTOCOLS_SET; -- static final String[] EXTRA_SUPPORTED_TLS_1_3_CIPHERS; -- static final String EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING; -- static final String[] NAMED_GROUPS; -- -- static final boolean JAVAX_CERTIFICATE_CREATION_SUPPORTED; -- -- // Use default that is supported in java 11 and earlier and also in OpenSSL / BoringSSL. -- // See https://github.com/netty/netty-tcnative/issues/567 -- // See https://www.java.com/en/configure_crypto.html for ordering -- private static final String[] DEFAULT_NAMED_GROUPS = { "x25519", "secp256r1", "secp384r1", "secp521r1" }; -- -- static { -- Throwable cause = null; -- -- if (SystemPropertyUtil.getBoolean("io.netty.handler.ssl.noOpenSsl", false)) { -- cause = new UnsupportedOperationException( -- "OpenSSL was explicit disabled with -Dio.netty.handler.ssl.noOpenSsl=true"); -- -- logger.debug( -- "netty-tcnative explicit disabled; " + -- OpenSslEngine.class.getSimpleName() + " will be unavailable.", cause); -- } else { -- // Test if netty-tcnative is in the classpath first. -- try { -- Class.forName("io.netty.internal.tcnative.SSLContext", false, -- PlatformDependent.getClassLoader(OpenSsl.class)); -- } 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 { -- // The JNI library was not already loaded. Load it now. -- loadTcNative(); -- } catch (Throwable t) { -- cause = t; -- logger.debug( -- "Failed to load netty-tcnative; " + -- OpenSslEngine.class.getSimpleName() + " will be unavailable, unless the " + -- "application has already loaded the symbols by some other means. " + -- "See https://netty.io/wiki/forked-tomcat-native.html for more information.", t); -- } -- -- try { -- String engine = SystemPropertyUtil.get("io.netty.handler.ssl.openssl.engine", null); -- if (engine == null) { -- logger.debug("Initialize netty-tcnative using engine: 'default'"); -- } else { -- logger.debug("Initialize netty-tcnative using engine: '{}'", engine); -- } -- initializeTcNative(engine); -- -- // The library was initialized successfully. If loading the library failed above, -- // reset the cause now since it appears that the library was loaded by some other -- // means. -- cause = null; -- } catch (Throwable t) { -- if (cause == null) { -- cause = t; -- } -- logger.debug( -- "Failed to initialize netty-tcnative; " + -- OpenSslEngine.class.getSimpleName() + " will be unavailable. " + -- "See https://netty.io/wiki/forked-tomcat-native.html for more information.", t); -- } -- } -- } -- -- UNAVAILABILITY_CAUSE = cause; -- CLIENT_DEFAULT_PROTOCOLS = defaultProtocols("jdk.tls.client.protocols"); -- SERVER_DEFAULT_PROTOCOLS = defaultProtocols("jdk.tls.server.protocols"); -- -- if (cause == null) { -- logger.debug("netty-tcnative using native library: {}", SSL.versionString()); -- -- final List defaultCiphers = new ArrayList(); -- final Set availableOpenSslCipherSuites = new LinkedHashSet(128); -- boolean supportsKeyManagerFactory = false; -- boolean useKeyManagerFactory = false; -- boolean tlsv13Supported = false; -- String[] namedGroups = DEFAULT_NAMED_GROUPS; -- String[] defaultConvertedNamedGroups = new String[namedGroups.length]; -- for (int i = 0; i < namedGroups.length; i++) { -- defaultConvertedNamedGroups[i] = GroupsConverter.toOpenSsl(namedGroups[i]); -- } -- -- IS_BORINGSSL = "BoringSSL".equals(versionString()); -- if (IS_BORINGSSL) { -- EXTRA_SUPPORTED_TLS_1_3_CIPHERS = new String [] { "TLS_AES_128_GCM_SHA256", -- "TLS_AES_256_GCM_SHA384" , -- "TLS_CHACHA20_POLY1305_SHA256" }; -- -- StringBuilder ciphersBuilder = new StringBuilder(128); -- for (String cipher: EXTRA_SUPPORTED_TLS_1_3_CIPHERS) { -- ciphersBuilder.append(cipher).append(":"); -- } -- ciphersBuilder.setLength(ciphersBuilder.length() - 1); -- EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING = ciphersBuilder.toString(); -- } else { -- EXTRA_SUPPORTED_TLS_1_3_CIPHERS = EmptyArrays.EMPTY_STRINGS; -- EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING = StringUtil.EMPTY_STRING; -- } -- -- try { -- final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER); -- long certBio = 0; -- long keyBio = 0; -- long cert = 0; -- long key = 0; -- try { -- // As we delegate to the KeyManager / TrustManager of the JDK we need to ensure it can actually -- // handle TLSv13 as otherwise we may see runtime exceptions -- if (SslProvider.isTlsv13Supported(SslProvider.JDK)) { -- try { -- StringBuilder tlsv13Ciphers = new StringBuilder(); -- -- for (String cipher : TLSV13_CIPHERS) { -- String converted = CipherSuiteConverter.toOpenSsl(cipher, IS_BORINGSSL); -- if (converted != null) { -- tlsv13Ciphers.append(converted).append(':'); -- } -- } -- if (tlsv13Ciphers.length() == 0) { -- tlsv13Supported = false; -- } else { -- tlsv13Ciphers.setLength(tlsv13Ciphers.length() - 1); -- SSLContext.setCipherSuite(sslCtx, tlsv13Ciphers.toString(), true); -- tlsv13Supported = true; -- } -- -- } catch (Exception ignore) { -- tlsv13Supported = false; -- } -- } -- -- SSLContext.setCipherSuite(sslCtx, "ALL", false); -- -- final long ssl = SSL.newSSL(sslCtx, true); -- try { -- for (String c: SSL.getCiphers(ssl)) { -- // Filter out bad input. -- if (c == null || c.isEmpty() || availableOpenSslCipherSuites.contains(c) || -- // Filter out TLSv1.3 ciphers if not supported. -- !tlsv13Supported && isTLSv13Cipher(c)) { -- continue; -- } -- availableOpenSslCipherSuites.add(c); -- } -- if (IS_BORINGSSL) { -- // Currently BoringSSL does not include these when calling SSL.getCiphers() even when these -- // are supported. -- Collections.addAll(availableOpenSslCipherSuites, EXTRA_SUPPORTED_TLS_1_3_CIPHERS); -- Collections.addAll(availableOpenSslCipherSuites, -- "AEAD-AES128-GCM-SHA256", -- "AEAD-AES256-GCM-SHA384", -- "AEAD-CHACHA20-POLY1305-SHA256"); -- } -- -- PemEncoded privateKey = PemPrivateKey.valueOf(PROBING_KEY.getBytes(CharsetUtil.US_ASCII)); -- try { -- // Let's check if we can set a callback, which may not work if the used OpenSSL version -- // is to old. -- SSLContext.setCertificateCallback(sslCtx, null); -- -- X509Certificate certificate = selfSignedCertificate(); -- certBio = ReferenceCountedOpenSslContext.toBIO(ByteBufAllocator.DEFAULT, certificate); -- cert = SSL.parseX509Chain(certBio); -- -- keyBio = ReferenceCountedOpenSslContext.toBIO( -- UnpooledByteBufAllocator.DEFAULT, privateKey.retain()); -- key = SSL.parsePrivateKey(keyBio, null); -- -- SSL.setKeyMaterial(ssl, cert, key); -- supportsKeyManagerFactory = true; -- try { -- boolean propertySet = SystemPropertyUtil.contains( -- "io.netty.handler.ssl.openssl.useKeyManagerFactory"); -- if (!IS_BORINGSSL) { -- useKeyManagerFactory = SystemPropertyUtil.getBoolean( -- "io.netty.handler.ssl.openssl.useKeyManagerFactory", true); -- -- if (propertySet) { -- logger.info("System property " + -- "'io.netty.handler.ssl.openssl.useKeyManagerFactory'" + -- " is deprecated and so will be ignored in the future"); -- } -- } else { -- useKeyManagerFactory = true; -- if (propertySet) { -- logger.info("System property " + -- "'io.netty.handler.ssl.openssl.useKeyManagerFactory'" + -- " is deprecated and will be ignored when using BoringSSL"); -- } -- } -- } catch (Throwable ignore) { -- logger.debug("Failed to get useKeyManagerFactory system property."); -- } -- } catch (Error ignore) { -- logger.debug("KeyManagerFactory not supported."); -- } finally { -- privateKey.release(); -- } -- } finally { -- SSL.freeSSL(ssl); -- if (certBio != 0) { -- SSL.freeBIO(certBio); -- } -- if (keyBio != 0) { -- SSL.freeBIO(keyBio); -- } -- if (cert != 0) { -- SSL.freeX509Chain(cert); -- } -- if (key != 0) { -- SSL.freePrivateKey(key); -- } -- } -- -- String groups = SystemPropertyUtil.get("jdk.tls.namedGroups", null); -- if (groups != null) { -- String[] nGroups = groups.split(","); -- Set supportedNamedGroups = new LinkedHashSet(nGroups.length); -- Set supportedConvertedNamedGroups = new LinkedHashSet(nGroups.length); -- -- Set unsupportedNamedGroups = new LinkedHashSet(); -- for (String namedGroup : nGroups) { -- String converted = GroupsConverter.toOpenSsl(namedGroup); -- if (SSLContext.setCurvesList(sslCtx, converted)) { -- supportedConvertedNamedGroups.add(converted); -- supportedNamedGroups.add(namedGroup); -- } else { -- unsupportedNamedGroups.add(namedGroup); -- } -- } -- -- if (supportedNamedGroups.isEmpty()) { -- namedGroups = defaultConvertedNamedGroups; -- logger.info("All configured namedGroups are not supported: {}. Use default: {}.", -- Arrays.toString(unsupportedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS)), -- Arrays.toString(DEFAULT_NAMED_GROUPS)); -- } else { -- String[] groupArray = supportedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS); -- if (unsupportedNamedGroups.isEmpty()) { -- logger.info("Using configured namedGroups -D 'jdk.tls.namedGroup': {} ", -- Arrays.toString(groupArray)); -- } else { -- logger.info("Using supported configured namedGroups: {}. Unsupported namedGroups: {}. ", -- Arrays.toString(groupArray), -- Arrays.toString(unsupportedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS))); -- } -- namedGroups = supportedConvertedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS); -- } -- } else { -- namedGroups = defaultConvertedNamedGroups; -- } -- } finally { -- SSLContext.free(sslCtx); -- } -- } catch (Exception e) { -- logger.warn("Failed to get the list of available OpenSSL cipher suites.", e); -- } -- NAMED_GROUPS = namedGroups; -- AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites); -- final Set availableJavaCipherSuites = new LinkedHashSet( -- AVAILABLE_OPENSSL_CIPHER_SUITES.size() * 2); -- for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) { -- // Included converted but also openssl cipher name -- if (!isTLSv13Cipher(cipher)) { -- availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "TLS")); -- availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "SSL")); -- } else { -- // TLSv1.3 ciphers have the correct format. -- availableJavaCipherSuites.add(cipher); -- } -- } -- -- addIfSupported(availableJavaCipherSuites, defaultCiphers, DEFAULT_CIPHER_SUITES); -- addIfSupported(availableJavaCipherSuites, defaultCiphers, TLSV13_CIPHER_SUITES); -- // Also handle the extra supported ciphers as these will contain some more stuff on BoringSSL. -- addIfSupported(availableJavaCipherSuites, defaultCiphers, EXTRA_SUPPORTED_TLS_1_3_CIPHERS); -- -- useFallbackCiphersIfDefaultIsEmpty(defaultCiphers, availableJavaCipherSuites); -- DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers); -- -- AVAILABLE_JAVA_CIPHER_SUITES = Collections.unmodifiableSet(availableJavaCipherSuites); -- -- final Set availableCipherSuites = new LinkedHashSet( -- AVAILABLE_OPENSSL_CIPHER_SUITES.size() + AVAILABLE_JAVA_CIPHER_SUITES.size()); -- availableCipherSuites.addAll(AVAILABLE_OPENSSL_CIPHER_SUITES); -- availableCipherSuites.addAll(AVAILABLE_JAVA_CIPHER_SUITES); -- -- AVAILABLE_CIPHER_SUITES = availableCipherSuites; -- SUPPORTS_KEYMANAGER_FACTORY = supportsKeyManagerFactory; -- USE_KEYMANAGER_FACTORY = useKeyManagerFactory; -- -- Set protocols = new LinkedHashSet(6); -- // Seems like there is no way to explicitly disable SSLv2Hello in openssl so it is always enabled -- protocols.add(SslProtocols.SSL_v2_HELLO); -- if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV2, SSL.SSL_OP_NO_SSLv2)) { -- protocols.add(SslProtocols.SSL_v2); -- } -- if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV3, SSL.SSL_OP_NO_SSLv3)) { -- protocols.add(SslProtocols.SSL_v3); -- } -- if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1, SSL.SSL_OP_NO_TLSv1)) { -- protocols.add(SslProtocols.TLS_v1); -- } -- if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_1, SSL.SSL_OP_NO_TLSv1_1)) { -- protocols.add(SslProtocols.TLS_v1_1); -- } -- if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_2, SSL.SSL_OP_NO_TLSv1_2)) { -- protocols.add(SslProtocols.TLS_v1_2); -- } -- -- // This is only supported by java8u272 and later. -- if (tlsv13Supported && doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_OP_NO_TLSv1_3)) { -- protocols.add(SslProtocols.TLS_v1_3); -- TLSV13_SUPPORTED = true; -- } else { -- TLSV13_SUPPORTED = false; -- } -- -- SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols); -- SUPPORTS_OCSP = doesSupportOcsp(); -- -- if (logger.isDebugEnabled()) { -- logger.debug("Supported protocols (OpenSSL): {} ", SUPPORTED_PROTOCOLS_SET); -- logger.debug("Default cipher suites (OpenSSL): {}", DEFAULT_CIPHERS); -- } -- -- // Check if we can create a javax.security.cert.X509Certificate from our cert. This might fail on -- // JDK17 and above. In this case we will later throw an UnsupportedOperationException if someone -- // tries to access these via SSLSession. See https://github.com/netty/netty/issues/13560. -- boolean javaxCertificateCreationSupported; -- try { -- javax.security.cert.X509Certificate.getInstance(PROBING_CERT.getBytes(CharsetUtil.US_ASCII)); -- javaxCertificateCreationSupported = true; -- } catch (javax.security.cert.CertificateException ex) { -- javaxCertificateCreationSupported = false; -- } -- JAVAX_CERTIFICATE_CREATION_SUPPORTED = javaxCertificateCreationSupported; -- } else { -- DEFAULT_CIPHERS = Collections.emptyList(); -- AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.emptySet(); -- AVAILABLE_JAVA_CIPHER_SUITES = Collections.emptySet(); -- AVAILABLE_CIPHER_SUITES = Collections.emptySet(); -- SUPPORTS_KEYMANAGER_FACTORY = false; -- USE_KEYMANAGER_FACTORY = false; -- SUPPORTED_PROTOCOLS_SET = Collections.emptySet(); -- SUPPORTS_OCSP = false; -- TLSV13_SUPPORTED = false; -- IS_BORINGSSL = false; -- EXTRA_SUPPORTED_TLS_1_3_CIPHERS = EmptyArrays.EMPTY_STRINGS; -- EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING = StringUtil.EMPTY_STRING; -- NAMED_GROUPS = DEFAULT_NAMED_GROUPS; -- JAVAX_CERTIFICATE_CREATION_SUPPORTED = false; -- } -- } -- -- static String checkTls13Ciphers(InternalLogger logger, String ciphers) { -- if (IS_BORINGSSL && !ciphers.isEmpty()) { -- assert EXTRA_SUPPORTED_TLS_1_3_CIPHERS.length > 0; -- Set boringsslTlsv13Ciphers = new HashSet(EXTRA_SUPPORTED_TLS_1_3_CIPHERS.length); -- Collections.addAll(boringsslTlsv13Ciphers, EXTRA_SUPPORTED_TLS_1_3_CIPHERS); -- boolean ciphersNotMatch = false; -- for (String cipher: ciphers.split(":")) { -- if (boringsslTlsv13Ciphers.isEmpty()) { -- ciphersNotMatch = true; -- break; -- } -- if (!boringsslTlsv13Ciphers.remove(cipher) && -- !boringsslTlsv13Ciphers.remove(CipherSuiteConverter.toJava(cipher, "TLS"))) { -- ciphersNotMatch = true; -- break; -- } -- } -- -- // Also check if there are ciphers left. -- ciphersNotMatch |= !boringsslTlsv13Ciphers.isEmpty(); -- -- if (ciphersNotMatch) { -- if (logger.isInfoEnabled()) { -- StringBuilder javaCiphers = new StringBuilder(128); -- for (String cipher : ciphers.split(":")) { -- javaCiphers.append(CipherSuiteConverter.toJava(cipher, "TLS")).append(":"); -- } -- javaCiphers.setLength(javaCiphers.length() - 1); -- logger.info( -- "BoringSSL doesn't allow to enable or disable TLSv1.3 ciphers explicitly." + -- " Provided TLSv1.3 ciphers: '{}', default TLSv1.3 ciphers that will be used: '{}'.", -- javaCiphers, EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING); -- } -- return EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING; -- } -- } -- return ciphers; -- } -- -- static boolean isSessionCacheSupported() { -- return version() >= 0x10100000L; -- } -- -- /** -- * Returns a self-signed {@link X509Certificate} for {@code netty.io}. -- */ -- static X509Certificate selfSignedCertificate() throws CertificateException { -- return (X509Certificate) SslContext.X509_CERT_FACTORY.generateCertificate( -- new ByteArrayInputStream(PROBING_CERT.getBytes(CharsetUtil.US_ASCII)) -- ); -- } -- -- private static boolean doesSupportOcsp() { -- boolean supportsOcsp = false; -- if (version() >= 0x10002000L) { -- long sslCtx = -1; -- try { -- sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_TLSV1_2, SSL.SSL_MODE_SERVER); -- SSLContext.enableOcsp(sslCtx, false); -- supportsOcsp = true; -- } catch (Exception ignore) { -- // ignore -- } finally { -- if (sslCtx != -1) { -- SSLContext.free(sslCtx); -- } -- } -- } -- return supportsOcsp; -- } -- private static boolean doesSupportProtocol(int protocol, int opt) { -- if (opt == 0) { -- // If the opt is 0 the protocol is not supported. This is for example the case with BoringSSL and SSLv2. -- return false; -- } -- long sslCtx = -1; -- try { -- sslCtx = SSLContext.make(protocol, SSL.SSL_MODE_COMBINED); -- return true; -- } catch (Exception ignore) { -- return false; -- } finally { -- if (sslCtx != -1) { -- SSLContext.free(sslCtx); -- } -- } -- } -- -- /** -- * 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. -- * -- * @deprecated use {@link SslProvider#isAlpnSupported(SslProvider)} with {@link SslProvider#OPENSSL}. -- */ -- @Deprecated -- public static boolean isAlpnSupported() { -- return version() >= 0x10002000L; -- } -- -- /** -- * Returns {@code true} if the used version of OpenSSL supports OCSP stapling. -- */ -- public static boolean isOcspSupported() { -- return SUPPORTS_OCSP; -- } -- -- /** -- * Returns the version of the used available OpenSSL library or {@code -1} if {@link #isAvailable()} -- * returns {@code false}. -- */ -- public static int version() { -- return isAvailable() ? SSL.version() : -1; -- } -- -- /** -- * Returns the version string of the used available OpenSSL library or {@code null} if {@link #isAvailable()} -- * returns {@code false}. -- */ -- public static String versionString() { -- return isAvailable() ? SSL.versionString() : 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; -- } -- -- /** -- * @deprecated use {@link #availableOpenSslCipherSuites()} -- */ -- @Deprecated -- public static Set availableCipherSuites() { -- return availableOpenSslCipherSuites(); -- } -- -- /** -- * 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 availableOpenSslCipherSuites() { -- return AVAILABLE_OPENSSL_CIPHER_SUITES; -- } -- -- /** -- * Returns all the available cipher suites (Java-style). -- * Please note that the returned array may include the cipher suites that are insecure or non-functional. -- */ -- public static Set availableJavaCipherSuites() { -- return AVAILABLE_JAVA_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, IS_BORINGSSL); -- if (converted != null) { -- cipherSuite = converted; -- } -- return AVAILABLE_OPENSSL_CIPHER_SUITES.contains(cipherSuite); -- } -- -- /** -- * Returns {@code true} if {@link javax.net.ssl.KeyManagerFactory} is supported when using OpenSSL. -- */ -- public static boolean supportsKeyManagerFactory() { -- return SUPPORTS_KEYMANAGER_FACTORY; -- } -- -- /** -- * Always returns {@code true} if {@link #isAvailable()} returns {@code true}. -- * -- * @deprecated Will be removed because hostname validation is always done by a -- * {@link javax.net.ssl.TrustManager} implementation. -- */ -- @Deprecated -- public static boolean supportsHostnameValidation() { -- return isAvailable(); -- } -- -- static boolean useKeyManagerFactory() { -- return USE_KEYMANAGER_FACTORY; -- } -- -- static long memoryAddress(ByteBuf buf) { -- assert buf.isDirect(); -- return buf.hasMemoryAddress() ? buf.memoryAddress() : -- // Use internalNioBuffer to reduce object creation. -- Buffer.address(buf.internalNioBuffer(0, buf.readableBytes())); -- } -- -- private OpenSsl() { } -- -- private static void loadTcNative() throws Exception { -- String os = PlatformDependent.normalizedOs(); -- String arch = PlatformDependent.normalizedArch(); -- -- Set libNames = new LinkedHashSet(5); -- String staticLibName = "netty_tcnative"; -- -- // First, try loading the platform-specific library. Platform-specific -- // libraries will be available if using a tcnative uber jar. -- if ("linux".equals(os)) { -- Set classifiers = PlatformDependent.normalizedLinuxClassifiers(); -- for (String classifier : classifiers) { -- libNames.add(staticLibName + "_" + os + '_' + arch + "_" + classifier); -- } -- // generic arch-dependent library -- libNames.add(staticLibName + "_" + os + '_' + arch); -- -- // Fedora SSL lib so naming (libssl.so.10 vs libssl.so.1.0.0). -- // note: should already be included from the classifiers but if not, we use this as an -- // additional fallback option here -- libNames.add(staticLibName + "_" + os + '_' + arch + "_fedora"); -- } else { -- libNames.add(staticLibName + "_" + os + '_' + arch); -- } -- libNames.add(staticLibName + "_" + arch); -- libNames.add(staticLibName); -- -- NativeLibraryLoader.loadFirstAvailable(PlatformDependent.getClassLoader(SSLContext.class), -- libNames.toArray(EmptyArrays.EMPTY_STRINGS)); -- } -- -- private static boolean initializeTcNative(String engine) throws Exception { -- return Library.initialize("provided", engine); -- } -- -- static void releaseIfNeeded(ReferenceCounted counted) { -- if (counted.refCnt() > 0) { -- ReferenceCountUtil.safeRelease(counted); -- } -- } -- -- static boolean isTlsv13Supported() { -- return TLSV13_SUPPORTED; -- } -- -- static boolean isOptionSupported(SslContextOption option) { -- if (isAvailable()) { -- if (option == OpenSslContextOption.USE_TASKS) { -- return true; -- } -- // Check for options that are only supported by BoringSSL atm. -- if (isBoringSSL()) { -- return option == OpenSslContextOption.ASYNC_PRIVATE_KEY_METHOD || -- option == OpenSslContextOption.PRIVATE_KEY_METHOD || -- option == OpenSslContextOption.CERTIFICATE_COMPRESSION_ALGORITHMS || -- option == OpenSslContextOption.TLS_FALSE_START || -- option == OpenSslContextOption.MAX_CERTIFICATE_LIST_BYTES; -- } -- } -- return false; -- } -- -- private static Set defaultProtocols(String property) { -- String protocolsString = SystemPropertyUtil.get(property, null); -- Set protocols = new HashSet(); -- if (protocolsString != null) { -- for (String proto : protocolsString.split(",")) { -- String p = proto.trim(); -- protocols.add(p); -- } -- } else { -- protocols.add(SslProtocols.TLS_v1_2); -- protocols.add(SslProtocols.TLS_v1_3); -- } -- return protocols; -- } -- -- static String[] defaultProtocols(boolean isClient) { -- final Collection defaultProtocols = isClient ? CLIENT_DEFAULT_PROTOCOLS : SERVER_DEFAULT_PROTOCOLS; -- assert defaultProtocols != null; -- List protocols = new ArrayList(defaultProtocols.size()); -- for (String proto : defaultProtocols) { -- if (SUPPORTED_PROTOCOLS_SET.contains(proto)) { -- protocols.add(proto); -- } -- } -- return protocols.toArray(EmptyArrays.EMPTY_STRINGS); -- } -- -- static boolean isBoringSSL() { -- return IS_BORINGSSL; -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslAsyncPrivateKeyMethod.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslAsyncPrivateKeyMethod.java -deleted file mode 100644 -index 27edaa6..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslAsyncPrivateKeyMethod.java -+++ /dev/null -@@ -1,58 +0,0 @@ --/* -- * Copyright 2021 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: -- * -- * https://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.internal.tcnative.SSLPrivateKeyMethod; --import io.netty.util.concurrent.Future; -- --import javax.net.ssl.SSLEngine; -- --public interface OpenSslAsyncPrivateKeyMethod { -- int SSL_SIGN_RSA_PKCS1_SHA1 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA1; -- int SSL_SIGN_RSA_PKCS1_SHA256 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA256; -- int SSL_SIGN_RSA_PKCS1_SHA384 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA384; -- int SSL_SIGN_RSA_PKCS1_SHA512 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA512; -- int SSL_SIGN_ECDSA_SHA1 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SHA1; -- int SSL_SIGN_ECDSA_SECP256R1_SHA256 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SECP256R1_SHA256; -- int SSL_SIGN_ECDSA_SECP384R1_SHA384 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SECP384R1_SHA384; -- int SSL_SIGN_ECDSA_SECP521R1_SHA512 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SECP521R1_SHA512; -- int SSL_SIGN_RSA_PSS_RSAE_SHA256 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PSS_RSAE_SHA256; -- int SSL_SIGN_RSA_PSS_RSAE_SHA384 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PSS_RSAE_SHA384; -- int SSL_SIGN_RSA_PSS_RSAE_SHA512 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PSS_RSAE_SHA512; -- int SSL_SIGN_ED25519 = SSLPrivateKeyMethod.SSL_SIGN_ED25519; -- int SSL_SIGN_RSA_PKCS1_MD5_SHA1 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_MD5_SHA1; -- -- /** -- * Signs the input with the given key and notifies the returned {@link Future} with the signed bytes. -- * -- * @param engine the {@link SSLEngine} -- * @param signatureAlgorithm the algorithm to use for signing -- * @param input the digest itself -- * @return the {@link Future} that will be notified with the signed data -- * (must not be {@code null}) when the operation completes. -- */ -- Future sign(SSLEngine engine, int signatureAlgorithm, byte[] input); -- -- /** -- * Decrypts the input with the given key and notifies the returned {@link Future} with the decrypted bytes. -- * -- * @param engine the {@link SSLEngine} -- * @param input the input which should be decrypted -- * @return the {@link Future} that will be notified with the decrypted data -- * (must not be {@code null}) when the operation completes. -- */ -- Future decrypt(SSLEngine engine, byte[] input); --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingKeyMaterialProvider.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingKeyMaterialProvider.java -deleted file mode 100644 -index a55007d..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingKeyMaterialProvider.java -+++ /dev/null -@@ -1,79 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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 javax.net.ssl.X509KeyManager; --import java.util.Iterator; --import java.util.concurrent.ConcurrentHashMap; --import java.util.concurrent.ConcurrentMap; -- --/** -- * {@link OpenSslKeyMaterialProvider} that will cache the {@link OpenSslKeyMaterial} to reduce the overhead -- * of parsing the chain and the key for generation of the material. -- */ --final class OpenSslCachingKeyMaterialProvider extends OpenSslKeyMaterialProvider { -- -- private final int maxCachedEntries; -- private volatile boolean full; -- private final ConcurrentMap cache = new ConcurrentHashMap(); -- -- OpenSslCachingKeyMaterialProvider(X509KeyManager keyManager, String password, int maxCachedEntries) { -- super(keyManager, password); -- this.maxCachedEntries = maxCachedEntries; -- } -- -- @Override -- OpenSslKeyMaterial chooseKeyMaterial(ByteBufAllocator allocator, String alias) throws Exception { -- OpenSslKeyMaterial material = cache.get(alias); -- if (material == null) { -- material = super.chooseKeyMaterial(allocator, alias); -- if (material == null) { -- // No keymaterial should be used. -- return null; -- } -- -- if (full) { -- return material; -- } -- if (cache.size() > maxCachedEntries) { -- full = true; -- // Do not cache... -- return material; -- } -- OpenSslKeyMaterial old = cache.putIfAbsent(alias, material); -- if (old != null) { -- material.release(); -- material = old; -- } -- } -- // We need to call retain() as we want to always have at least a refCnt() of 1 before destroy() was called. -- return material.retain(); -- } -- -- @Override -- void destroy() { -- // Remove and release all entries. -- do { -- Iterator iterator = cache.values().iterator(); -- while (iterator.hasNext()) { -- iterator.next().release(); -- iterator.remove(); -- } -- } while (!cache.isEmpty()); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingX509KeyManagerFactory.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingX509KeyManagerFactory.java -deleted file mode 100644 -index 7f644e2..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingX509KeyManagerFactory.java -+++ /dev/null -@@ -1,80 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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.ObjectUtil; -- --import javax.net.ssl.KeyManager; --import javax.net.ssl.KeyManagerFactory; --import javax.net.ssl.KeyManagerFactorySpi; --import javax.net.ssl.ManagerFactoryParameters; --import javax.net.ssl.X509KeyManager; --import java.security.InvalidAlgorithmParameterException; --import java.security.KeyStore; --import java.security.KeyStoreException; --import java.security.NoSuchAlgorithmException; --import java.security.PrivateKey; --import java.security.UnrecoverableKeyException; --import java.security.cert.X509Certificate; -- --/** -- * Wraps another {@link KeyManagerFactory} and caches its chains / certs for an alias for better performance when using -- * {@link SslProvider#OPENSSL} or {@link SslProvider#OPENSSL_REFCNT}. -- * -- * Because of the caching its important that the wrapped {@link KeyManagerFactory}s {@link X509KeyManager}s always -- * return the same {@link X509Certificate} chain and {@link PrivateKey} for the same alias. -- */ --public final class OpenSslCachingX509KeyManagerFactory extends KeyManagerFactory { -- -- private final int maxCachedEntries; -- -- public OpenSslCachingX509KeyManagerFactory(final KeyManagerFactory factory) { -- this(factory, 1024); -- } -- -- public OpenSslCachingX509KeyManagerFactory(final KeyManagerFactory factory, int maxCachedEntries) { -- super(new KeyManagerFactorySpi() { -- @Override -- protected void engineInit(KeyStore keyStore, char[] chars) -- throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- factory.init(keyStore, chars); -- } -- -- @Override -- protected void engineInit(ManagerFactoryParameters managerFactoryParameters) -- throws InvalidAlgorithmParameterException { -- factory.init(managerFactoryParameters); -- } -- -- @Override -- protected KeyManager[] engineGetKeyManagers() { -- return factory.getKeyManagers(); -- } -- }, factory.getProvider(), factory.getAlgorithm()); -- this.maxCachedEntries = ObjectUtil.checkPositive(maxCachedEntries, "maxCachedEntries"); -- } -- -- OpenSslKeyMaterialProvider newProvider(String password) { -- X509KeyManager keyManager = ReferenceCountedOpenSslContext.chooseX509KeyManager(getKeyManagers()); -- if ("sun.security.ssl.X509KeyManagerImpl".equals(keyManager.getClass().getName())) { -- // Don't do caching if X509KeyManagerImpl is used as the returned aliases are not stable and will change -- // between invocations. -- return new OpenSslKeyMaterialProvider(keyManager, password); -- } -- return new OpenSslCachingKeyMaterialProvider( -- ReferenceCountedOpenSslContext.chooseX509KeyManager(getKeyManagers()), password, maxCachedEntries); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslCertificateException.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslCertificateException.java -deleted file mode 100644 -index 39fddf2..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslCertificateException.java -+++ /dev/null -@@ -1,81 +0,0 @@ --/* -- * Copyright 2016 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: -- * -- * https://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.internal.tcnative.CertificateVerifier; -- --import java.security.cert.CertificateException; -- --/** -- * A special {@link CertificateException} which allows to specify which error code is included in the -- * SSL Record. This only work when {@link SslProvider#OPENSSL} or {@link SslProvider#OPENSSL_REFCNT} is used. -- */ --public final class OpenSslCertificateException extends CertificateException { -- private static final long serialVersionUID = 5542675253797129798L; -- -- private final int errorCode; -- -- /** -- * Construct a new exception with the -- * error code. -- */ -- public OpenSslCertificateException(int errorCode) { -- this((String) null, errorCode); -- } -- -- /** -- * Construct a new exception with the msg and -- * error code . -- */ -- public OpenSslCertificateException(String msg, int errorCode) { -- super(msg); -- this.errorCode = checkErrorCode(errorCode); -- } -- -- /** -- * Construct a new exception with the msg, cause and -- * error code . -- */ -- public OpenSslCertificateException(String message, Throwable cause, int errorCode) { -- super(message, cause); -- this.errorCode = checkErrorCode(errorCode); -- } -- -- /** -- * Construct a new exception with the cause and -- * error code . -- */ -- public OpenSslCertificateException(Throwable cause, int errorCode) { -- this(null, cause, errorCode); -- } -- -- /** -- * Return the error code to use. -- */ -- public int errorCode() { -- return errorCode; -- } -- -- private static int checkErrorCode(int errorCode) { -- // Call OpenSsl.isAvailable() to ensure we try to load the native lib as CertificateVerifier.isValid(...) -- // will depend on it. If loading fails we will just skip the validation. -- if (OpenSsl.isAvailable() && !CertificateVerifier.isValid(errorCode)) { -- throw new IllegalArgumentException("errorCode '" + errorCode + -- "' invalid, see https://www.openssl.org/docs/man1.0.2/apps/verify.html."); -- } -- return errorCode; -- } --} -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 57152de..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java -+++ /dev/null -@@ -1,212 +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: -- * -- * https://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.internal.tcnative.SSL; -- --import java.io.File; --import java.security.KeyStore; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; --import java.util.Map; -- --import javax.net.ssl.KeyManagerFactory; --import javax.net.ssl.SSLException; --import javax.net.ssl.TrustManager; --import javax.net.ssl.TrustManagerFactory; -- --import static io.netty.handler.ssl.ReferenceCountedOpenSslClientContext.newSessionContext; -- --/** -- * A client-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation. -- *

This class will use a finalizer to ensure native resources are automatically cleaned up. To avoid finalizers -- * and manually release the native memory see {@link ReferenceCountedOpenSslClientContext}. -- */ --public final class OpenSslClientContext extends OpenSslContext { -- private final OpenSslSessionContext sessionContext; -- -- /** -- * Creates a new instance. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- 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 -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- 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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- 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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- public OpenSslClientContext(File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException { -- this(certChainFile, trustManagerFactory, 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 -- * @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 use {@link SslContextBuilder} -- */ -- @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); -- } -- -- /** -- * 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 use {@link SslContextBuilder} -- */ -- @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 trustCertCollectionFile an X.509 certificate collection 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 trustCertCollectionFile} -- * @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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- public OpenSslClientContext(File trustCertCollectionFile, TrustManagerFactory trustManagerFactory, -- File keyCertChainFile, File keyFile, String keyPassword, -- KeyManagerFactory keyManagerFactory, Iterable ciphers, -- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, -- long sessionCacheSize, long sessionTimeout) -- throws SSLException { -- this(toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory, -- toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword), -- keyPassword, keyManagerFactory, ciphers, cipherFilter, apn, null, sessionCacheSize, -- sessionTimeout, false, KeyStore.getDefaultType(), null, null); -- } -- -- OpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, -- KeyManagerFactory keyManagerFactory, Iterable ciphers, -- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols, -- long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStore, -- String endpointIdentificationAlgorithm, ResumptionController resumptionController, -- Map.Entry, Object>... options) -- throws SSLException { -- super(ciphers, cipherFilter, apn, SSL.SSL_MODE_CLIENT, keyCertChain, ClientAuth.NONE, protocols, false, -- endpointIdentificationAlgorithm, enableOcsp, resumptionController, options); -- boolean success = false; -- try { -- OpenSslKeyMaterialProvider.validateKeyMaterialSupported(keyCertChain, key, keyPassword); -- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory, -- keyCertChain, key, keyPassword, keyManagerFactory, keyStore, -- sessionCacheSize, sessionTimeout, resumptionController); -- success = true; -- } finally { -- if (!success) { -- release(); -- } -- } -- } -- -- @Override -- public OpenSslSessionContext sessionContext() { -- return sessionContext; -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientSessionCache.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslClientSessionCache.java -deleted file mode 100644 -index 66238c4..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientSessionCache.java -+++ /dev/null -@@ -1,188 +0,0 @@ --/* -- * Copyright 2021 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: -- * -- * https://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.internal.tcnative.SSL; --import io.netty.util.AsciiString; -- --import java.util.ArrayList; --import java.util.HashMap; --import java.util.HashSet; --import java.util.List; --import java.util.Map; --import java.util.Set; -- --/** -- * {@link OpenSslSessionCache} that is used by the client-side. -- */ --final class OpenSslClientSessionCache extends OpenSslSessionCache { -- private final Map> sessions = new HashMap>(); -- -- OpenSslClientSessionCache(OpenSslEngineMap engineMap) { -- super(engineMap); -- } -- -- @Override -- protected boolean sessionCreated(NativeSslSession session) { -- assert Thread.holdsLock(this); -- HostPort hostPort = keyFor(session.getPeerHost(), session.getPeerPort()); -- if (hostPort == null) { -- return false; -- } -- Set sessionsForHost = sessions.get(hostPort); -- if (sessionsForHost == null) { -- // Let's start with something small as usually the server does not provide too many of these per hostPort -- // mapping. -- sessionsForHost = new HashSet(4); -- sessions.put(hostPort, sessionsForHost); -- } -- sessionsForHost.add(session); -- return true; -- } -- -- @Override -- protected void sessionRemoved(NativeSslSession session) { -- assert Thread.holdsLock(this); -- HostPort hostPort = keyFor(session.getPeerHost(), session.getPeerPort()); -- if (hostPort == null) { -- return; -- } -- Set sessionsForHost = sessions.get(hostPort); -- if (sessionsForHost != null) { -- sessionsForHost.remove(session); -- if (sessionsForHost.isEmpty()) { -- sessions.remove(hostPort); -- } -- } -- } -- -- @Override -- boolean setSession(long ssl, OpenSslSession session, String host, int port) { -- HostPort hostPort = keyFor(host, port); -- if (hostPort == null) { -- return false; -- } -- NativeSslSession nativeSslSession = null; -- final boolean reused; -- boolean singleUsed = false; -- synchronized (this) { -- Set sessionsForHost = sessions.get(hostPort); -- if (sessionsForHost == null) { -- return false; -- } -- if (sessionsForHost.isEmpty()) { -- sessions.remove(hostPort); -- // There is no session that we can use. -- return false; -- } -- -- List toBeRemoved = null; -- // Loop through all the sessions that might be usable and check if we can use one of these. -- for (NativeSslSession sslSession : sessionsForHost) { -- if (sslSession.isValid()) { -- nativeSslSession = sslSession; -- break; -- } else { -- if (toBeRemoved == null) { -- toBeRemoved = new ArrayList(2); -- } -- toBeRemoved.add(sslSession); -- } -- } -- -- // Remove everything that is not valid anymore -- if (toBeRemoved != null) { -- for (NativeSslSession sslSession : toBeRemoved) { -- removeSessionWithId(sslSession.sessionId()); -- } -- } -- if (nativeSslSession == null) { -- // Couldn't find a valid session that could be used. -- return false; -- } -- -- // Try to set the session, if true is returned OpenSSL incremented the reference count -- // of the underlying SSL_SESSION*. -- reused = SSL.setSession(ssl, nativeSslSession.session()); -- if (reused) { -- singleUsed = nativeSslSession.shouldBeSingleUse(); -- } -- } -- -- if (reused) { -- if (singleUsed) { -- // Should only be used once -- nativeSslSession.invalidate(); -- session.invalidate(); -- } -- nativeSslSession.setLastAccessedTime(System.currentTimeMillis()); -- session.setSessionDetails(nativeSslSession.getCreationTime(), nativeSslSession.getLastAccessedTime(), -- nativeSslSession.sessionId(), nativeSslSession.keyValueStorage); -- } -- return reused; -- } -- -- private static HostPort keyFor(String host, int port) { -- if (host == null && port < 1) { -- return null; -- } -- return new HostPort(host, port); -- } -- -- @Override -- synchronized void clear() { -- super.clear(); -- sessions.clear(); -- } -- -- /** -- * Host / Port tuple used to find a {@link OpenSslSession} in the cache. -- */ -- private static final class HostPort { -- private final int hash; -- private final String host; -- private final int port; -- -- HostPort(String host, int port) { -- this.host = host; -- this.port = port; -- // Calculate a hashCode that does ignore case. -- this.hash = 31 * AsciiString.hashCode(host) + port; -- } -- -- @Override -- public int hashCode() { -- return hash; -- } -- -- @Override -- public boolean equals(Object obj) { -- if (!(obj instanceof HostPort)) { -- return false; -- } -- HostPort other = (HostPort) obj; -- return port == other.port && host.equalsIgnoreCase(other.host); -- } -- -- @Override -- public String toString() { -- return "HostPort{" + -- "host='" + host + '\'' + -- ", port=" + port + -- '}'; -- } -- } --} -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 62a76fa..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java -+++ /dev/null -@@ -1,64 +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: -- * -- * https://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 java.security.cert.Certificate; --import java.util.Map; -- --import javax.net.ssl.SSLEngine; --import javax.net.ssl.SSLException; -- --/** -- * This class will use a finalizer to ensure native resources are automatically cleaned up. To avoid finalizers -- * and manually release the native memory see {@link ReferenceCountedOpenSslContext}. -- */ --public abstract class OpenSslContext extends ReferenceCountedOpenSslContext { -- OpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apnCfg, -- int mode, Certificate[] keyCertChain, -- ClientAuth clientAuth, String[] protocols, boolean startTls, String endpointIdentificationAlgorithm, -- boolean enableOcsp, ResumptionController resumptionController, -- Map.Entry, Object>... options) -- throws SSLException { -- super(ciphers, cipherFilter, toNegotiator(apnCfg), mode, keyCertChain, -- clientAuth, protocols, startTls, endpointIdentificationAlgorithm, enableOcsp, false, -- resumptionController, options); -- } -- -- OpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, -- int mode, Certificate[] keyCertChain, -- ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp, -- ResumptionController resumptionController, -- Map.Entry, Object>... options) -- throws SSLException { -- super(ciphers, cipherFilter, apn, mode, keyCertChain, -- clientAuth, protocols, startTls, null, enableOcsp, false, resumptionController, options); -- } -- -- @Override -- final SSLEngine newEngine0(ByteBufAllocator alloc, String peerHost, int peerPort, boolean jdkCompatibilityMode) { -- return new OpenSslEngine(this, alloc, peerHost, peerPort, jdkCompatibilityMode, -- endpointIdentificationAlgorithm); -- } -- -- @Override -- @SuppressWarnings("FinalizeDeclaration") -- protected final void finalize() throws Throwable { -- super.finalize(); -- OpenSsl.releaseIfNeeded(this); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslContextOption.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslContextOption.java -deleted file mode 100644 -index 7e538dd..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslContextOption.java -+++ /dev/null -@@ -1,77 +0,0 @@ --/* -- * Copyright 2021 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: -- * -- * https://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; -- --/** -- * {@link SslContextOption}s that are specific to the {@link SslProvider#OPENSSL} / {@link SslProvider#OPENSSL_REFCNT}. -- * -- * @param the type of the value. -- */ --public final class OpenSslContextOption extends SslContextOption { -- -- private OpenSslContextOption(String name) { -- super(name); -- } -- -- /** -- * If enabled heavy-operations may be offloaded from the {@link io.netty.channel.EventLoop} if possible. -- */ -- public static final OpenSslContextOption USE_TASKS = -- new OpenSslContextOption("USE_TASKS"); -- /** -- * If enabled TLS false start will be enabled if supported. -- * When TLS false start is enabled the flow of {@link SslHandshakeCompletionEvent}s may be different compared when, -- * not enabled. -- * -- * This is currently only supported when {@code BoringSSL} and ALPN is used. -- */ -- public static final OpenSslContextOption TLS_FALSE_START = -- new OpenSslContextOption("TLS_FALSE_START"); -- -- /** -- * Set the {@link OpenSslPrivateKeyMethod} to use. This allows to offload private-key operations -- * if needed. -- * -- * This is currently only supported when {@code BoringSSL} is used. -- */ -- public static final OpenSslContextOption PRIVATE_KEY_METHOD = -- new OpenSslContextOption("PRIVATE_KEY_METHOD"); -- -- /** -- * Set the {@link OpenSslAsyncPrivateKeyMethod} to use. This allows to offload private-key operations -- * if needed. -- * -- * This is currently only supported when {@code BoringSSL} is used. -- */ -- public static final OpenSslContextOption ASYNC_PRIVATE_KEY_METHOD = -- new OpenSslContextOption("ASYNC_PRIVATE_KEY_METHOD"); -- -- /** -- * Set the {@link OpenSslCertificateCompressionConfig} to use. This allows for the configuration of certificate -- * compression algorithms which should be used, the priority of those algorithms and the directions in which -- * they should be used. -- * -- * This is currently only supported when {@code BoringSSL} is used. -- */ -- public static final OpenSslContextOption CERTIFICATE_COMPRESSION_ALGORITHMS = -- new OpenSslContextOption("CERTIFICATE_COMPRESSION_ALGORITHMS"); -- -- /** -- * Set the maximum number of bytes that is allowed during the handshake for certificate chain. -- */ -- public static final OpenSslContextOption MAX_CERTIFICATE_LIST_BYTES = -- new OpenSslContextOption("MAX_CERTIFICATE_LIST_BYTES"); --} -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 e43aade..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java -+++ /dev/null -@@ -1,41 +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: -- * -- * https://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 javax.net.ssl.SSLEngine; -- --/** -- * Implements a {@link SSLEngine} using -- * OpenSSL BIO abstractions. -- *

-- * This class will use a finalizer to ensure native resources are automatically cleaned up. To avoid finalizers -- * and manually release the native memory see {@link ReferenceCountedOpenSslEngine}. -- */ --public final class OpenSslEngine extends ReferenceCountedOpenSslEngine { -- OpenSslEngine(OpenSslContext context, ByteBufAllocator alloc, String peerHost, int peerPort, -- boolean jdkCompatibilityMode, String endpointIdentificationAlgorithm) { -- super(context, alloc, peerHost, peerPort, jdkCompatibilityMode, false, endpointIdentificationAlgorithm); -- } -- -- @Override -- @SuppressWarnings("FinalizeDeclaration") -- protected void finalize() throws Throwable { -- super.finalize(); -- OpenSsl.releaseIfNeeded(this); -- } --} -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 68e2df5..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngineMap.java -+++ /dev/null -@@ -1,35 +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: -- * -- * https://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 { -- -- /** -- * Remove the {@link OpenSslEngine} with the given {@code ssl} address and -- * return it. -- */ -- ReferenceCountedOpenSslEngine remove(long ssl); -- -- /** -- * Add a {@link OpenSslEngine} to this {@link OpenSslEngineMap}. -- */ -- void add(ReferenceCountedOpenSslEngine engine); -- -- /** -- * Get the {@link OpenSslEngine} for the given {@code ssl} address. -- */ -- ReferenceCountedOpenSslEngine get(long ssl); --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java -deleted file mode 100644 -index e2e2069..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java -+++ /dev/null -@@ -1,138 +0,0 @@ --/* -- * Copyright 2016 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: -- * -- * https://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.SSLException; --import javax.net.ssl.SSLHandshakeException; --import javax.net.ssl.X509ExtendedKeyManager; --import javax.net.ssl.X509KeyManager; --import javax.security.auth.x500.X500Principal; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; --import java.util.Arrays; --import java.util.HashMap; --import java.util.HashSet; --import java.util.Map; --import java.util.Set; -- -- --/** -- * Manages key material for {@link OpenSslEngine}s and so set the right {@link PrivateKey}s and -- * {@link X509Certificate}s. -- */ --final class OpenSslKeyMaterialManager { -- -- // Code in this class is inspired by code of conscrypts: -- // - https://android.googlesource.com/platform/external/ -- // conscrypt/+/master/src/main/java/org/conscrypt/OpenSSLEngineImpl.java -- // - https://android.googlesource.com/platform/external/ -- // conscrypt/+/master/src/main/java/org/conscrypt/SSLParametersImpl.java -- // -- static final String KEY_TYPE_RSA = "RSA"; -- static final String KEY_TYPE_DH_RSA = "DH_RSA"; -- static final String KEY_TYPE_EC = "EC"; -- static final String KEY_TYPE_EC_EC = "EC_EC"; -- static final String KEY_TYPE_EC_RSA = "EC_RSA"; -- -- // key type mappings for types. -- private static final Map KEY_TYPES = new HashMap(); -- static { -- KEY_TYPES.put("RSA", KEY_TYPE_RSA); -- KEY_TYPES.put("DHE_RSA", KEY_TYPE_RSA); -- KEY_TYPES.put("ECDHE_RSA", KEY_TYPE_RSA); -- KEY_TYPES.put("ECDHE_ECDSA", KEY_TYPE_EC); -- KEY_TYPES.put("ECDH_RSA", KEY_TYPE_EC_RSA); -- KEY_TYPES.put("ECDH_ECDSA", KEY_TYPE_EC_EC); -- KEY_TYPES.put("DH_RSA", KEY_TYPE_DH_RSA); -- } -- -- private final OpenSslKeyMaterialProvider provider; -- -- OpenSslKeyMaterialManager(OpenSslKeyMaterialProvider provider) { -- this.provider = provider; -- } -- -- void setKeyMaterialServerSide(ReferenceCountedOpenSslEngine engine) throws SSLException { -- String[] authMethods = engine.authMethods(); -- if (authMethods.length == 0) { -- throw new SSLHandshakeException("Unable to find key material"); -- } -- -- // authMethods may contain duplicates or may result in the same type -- // but call chooseServerAlias(...) may be expensive. So let's ensure -- // we filter out duplicates. -- Set typeSet = new HashSet(KEY_TYPES.size()); -- for (String authMethod : authMethods) { -- String type = KEY_TYPES.get(authMethod); -- if (type != null && typeSet.add(type)) { -- String alias = chooseServerAlias(engine, type); -- if (alias != null) { -- // We found a match... let's set the key material and return. -- setKeyMaterial(engine, alias); -- return; -- } -- } -- } -- throw new SSLHandshakeException("Unable to find key material for auth method(s): " -- + Arrays.toString(authMethods)); -- } -- -- void setKeyMaterialClientSide(ReferenceCountedOpenSslEngine engine, String[] keyTypes, -- X500Principal[] issuer) throws SSLException { -- String alias = chooseClientAlias(engine, keyTypes, issuer); -- // Only try to set the keymaterial if we have a match. This is also consistent with what OpenJDK does: -- // https://hg.openjdk.java.net/jdk/jdk11/file/76072a077ee1/ -- // src/java.base/share/classes/sun/security/ssl/CertificateRequest.java#l362 -- if (alias != null) { -- setKeyMaterial(engine, alias); -- } -- } -- -- private void setKeyMaterial(ReferenceCountedOpenSslEngine engine, String alias) throws SSLException { -- OpenSslKeyMaterial keyMaterial = null; -- try { -- keyMaterial = provider.chooseKeyMaterial(engine.alloc, alias); -- if (keyMaterial == null) { -- return; -- } -- engine.setKeyMaterial(keyMaterial); -- } catch (SSLException e) { -- throw e; -- } catch (Exception e) { -- throw new SSLException(e); -- } finally { -- if (keyMaterial != null) { -- keyMaterial.release(); -- } -- } -- } -- private String chooseClientAlias(ReferenceCountedOpenSslEngine engine, -- String[] keyTypes, X500Principal[] issuer) { -- X509KeyManager manager = provider.keyManager(); -- if (manager instanceof X509ExtendedKeyManager) { -- return ((X509ExtendedKeyManager) manager).chooseEngineClientAlias(keyTypes, issuer, engine); -- } -- return manager.chooseClientAlias(keyTypes, issuer, null); -- } -- -- private String chooseServerAlias(ReferenceCountedOpenSslEngine engine, String type) { -- X509KeyManager manager = provider.keyManager(); -- if (manager instanceof X509ExtendedKeyManager) { -- return ((X509ExtendedKeyManager) manager).chooseEngineServerAlias(type, null, engine); -- } -- return manager.chooseServerAlias(type, null, null); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialProvider.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialProvider.java -deleted file mode 100644 -index adf545f..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialProvider.java -+++ /dev/null -@@ -1,154 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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.buffer.UnpooledByteBufAllocator; --import io.netty.internal.tcnative.SSL; -- --import javax.net.ssl.SSLException; --import javax.net.ssl.X509KeyManager; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; -- --import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.toBIO; -- --/** -- * Provides {@link OpenSslKeyMaterial} for a given alias. -- */ --class OpenSslKeyMaterialProvider { -- -- private final X509KeyManager keyManager; -- private final String password; -- -- OpenSslKeyMaterialProvider(X509KeyManager keyManager, String password) { -- this.keyManager = keyManager; -- this.password = password; -- } -- -- static void validateKeyMaterialSupported(X509Certificate[] keyCertChain, PrivateKey key, String keyPassword) -- throws SSLException { -- validateSupported(keyCertChain); -- validateSupported(key, keyPassword); -- } -- -- private static void validateSupported(PrivateKey key, String password) throws SSLException { -- if (key == null) { -- return; -- } -- -- long pkeyBio = 0; -- long pkey = 0; -- -- try { -- pkeyBio = toBIO(UnpooledByteBufAllocator.DEFAULT, key); -- pkey = SSL.parsePrivateKey(pkeyBio, password); -- } catch (Exception e) { -- throw new SSLException("PrivateKey type not supported " + key.getFormat(), e); -- } finally { -- SSL.freeBIO(pkeyBio); -- if (pkey != 0) { -- SSL.freePrivateKey(pkey); -- } -- } -- } -- -- private static void validateSupported(X509Certificate[] certificates) throws SSLException { -- if (certificates == null || certificates.length == 0) { -- return; -- } -- -- long chainBio = 0; -- long chain = 0; -- PemEncoded encoded = null; -- try { -- encoded = PemX509Certificate.toPEM(UnpooledByteBufAllocator.DEFAULT, true, certificates); -- chainBio = toBIO(UnpooledByteBufAllocator.DEFAULT, encoded.retain()); -- chain = SSL.parseX509Chain(chainBio); -- } catch (Exception e) { -- throw new SSLException("Certificate type not supported", e); -- } finally { -- SSL.freeBIO(chainBio); -- if (chain != 0) { -- SSL.freeX509Chain(chain); -- } -- if (encoded != null) { -- encoded.release(); -- } -- } -- } -- -- /** -- * Returns the underlying {@link X509KeyManager} that is used. -- */ -- X509KeyManager keyManager() { -- return keyManager; -- } -- -- /** -- * Returns the {@link OpenSslKeyMaterial} or {@code null} (if none) that should be used during the handshake by -- * OpenSSL. -- */ -- OpenSslKeyMaterial chooseKeyMaterial(ByteBufAllocator allocator, String alias) throws Exception { -- X509Certificate[] certificates = keyManager.getCertificateChain(alias); -- if (certificates == null || certificates.length == 0) { -- return null; -- } -- -- PrivateKey key = keyManager.getPrivateKey(alias); -- PemEncoded encoded = PemX509Certificate.toPEM(allocator, true, certificates); -- long chainBio = 0; -- long pkeyBio = 0; -- long chain = 0; -- long pkey = 0; -- try { -- chainBio = toBIO(allocator, encoded.retain()); -- chain = SSL.parseX509Chain(chainBio); -- -- OpenSslKeyMaterial keyMaterial; -- if (key instanceof OpenSslPrivateKey) { -- keyMaterial = ((OpenSslPrivateKey) key).newKeyMaterial(chain, certificates); -- } else { -- pkeyBio = toBIO(allocator, key); -- pkey = key == null ? 0 : SSL.parsePrivateKey(pkeyBio, password); -- keyMaterial = new DefaultOpenSslKeyMaterial(chain, pkey, certificates); -- } -- -- // See the chain and pkey to 0 so we will not release it as the ownership was -- // transferred to OpenSslKeyMaterial. -- chain = 0; -- pkey = 0; -- return keyMaterial; -- } finally { -- SSL.freeBIO(chainBio); -- SSL.freeBIO(pkeyBio); -- if (chain != 0) { -- SSL.freeX509Chain(chain); -- } -- if (pkey != 0) { -- SSL.freePrivateKey(pkey); -- } -- encoded.release(); -- } -- } -- -- /** -- * Will be invoked once the provider should be destroyed. -- */ -- void destroy() { -- // NOOP. -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKey.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKey.java -deleted file mode 100644 -index fb6caed..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKey.java -+++ /dev/null -@@ -1,191 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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.internal.tcnative.SSL; --import io.netty.util.AbstractReferenceCounted; --import io.netty.util.IllegalReferenceCountException; --import io.netty.util.internal.EmptyArrays; -- --import javax.security.auth.Destroyable; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; -- --final class OpenSslPrivateKey extends AbstractReferenceCounted implements PrivateKey { -- -- private long privateKeyAddress; -- -- OpenSslPrivateKey(long privateKeyAddress) { -- this.privateKeyAddress = privateKeyAddress; -- } -- -- @Override -- public String getAlgorithm() { -- return "unknown"; -- } -- -- @Override -- public String getFormat() { -- // As we do not support encoding we should return null as stated in the javadocs of PrivateKey. -- return null; -- } -- -- @Override -- public byte[] getEncoded() { -- return null; -- } -- -- private long privateKeyAddress() { -- if (refCnt() <= 0) { -- throw new IllegalReferenceCountException(); -- } -- return privateKeyAddress; -- } -- -- @Override -- protected void deallocate() { -- SSL.freePrivateKey(privateKeyAddress); -- privateKeyAddress = 0; -- } -- -- @Override -- public OpenSslPrivateKey retain() { -- super.retain(); -- return this; -- } -- -- @Override -- public OpenSslPrivateKey retain(int increment) { -- super.retain(increment); -- return this; -- } -- -- @Override -- public OpenSslPrivateKey touch() { -- super.touch(); -- return this; -- } -- -- @Override -- public OpenSslPrivateKey touch(Object hint) { -- return this; -- } -- -- /** -- * NOTE: This is a JDK8 interface/method. Due to backwards compatibility -- * reasons it's not possible to slap the {@code @Override} annotation onto -- * this method. -- * -- * @see Destroyable#destroy() -- */ -- @Override -- public void destroy() { -- release(refCnt()); -- } -- -- /** -- * NOTE: This is a JDK8 interface/method. Due to backwards compatibility -- * reasons it's not possible to slap the {@code @Override} annotation onto -- * this method. -- * -- * @see Destroyable#isDestroyed() -- */ -- @Override -- public boolean isDestroyed() { -- return refCnt() == 0; -- } -- -- /** -- * Create a new {@link OpenSslKeyMaterial} which uses the private key that is held by {@link OpenSslPrivateKey}. -- * -- * When the material is created we increment the reference count of the enclosing {@link OpenSslPrivateKey} and -- * decrement it again when the reference count of the {@link OpenSslKeyMaterial} reaches {@code 0}. -- */ -- OpenSslKeyMaterial newKeyMaterial(long certificateChain, X509Certificate[] chain) { -- return new OpenSslPrivateKeyMaterial(certificateChain, chain); -- } -- -- // Package-private for unit-test only -- final class OpenSslPrivateKeyMaterial extends AbstractReferenceCounted implements OpenSslKeyMaterial { -- -- // Package-private for unit-test only -- long certificateChain; -- private final X509Certificate[] x509CertificateChain; -- -- OpenSslPrivateKeyMaterial(long certificateChain, X509Certificate[] x509CertificateChain) { -- this.certificateChain = certificateChain; -- this.x509CertificateChain = x509CertificateChain == null ? -- EmptyArrays.EMPTY_X509_CERTIFICATES : x509CertificateChain; -- OpenSslPrivateKey.this.retain(); -- } -- -- @Override -- public X509Certificate[] certificateChain() { -- return x509CertificateChain.clone(); -- } -- -- @Override -- public long certificateChainAddress() { -- if (refCnt() <= 0) { -- throw new IllegalReferenceCountException(); -- } -- return certificateChain; -- } -- -- @Override -- public long privateKeyAddress() { -- if (refCnt() <= 0) { -- throw new IllegalReferenceCountException(); -- } -- return OpenSslPrivateKey.this.privateKeyAddress(); -- } -- -- @Override -- public OpenSslKeyMaterial touch(Object hint) { -- OpenSslPrivateKey.this.touch(hint); -- return this; -- } -- -- @Override -- public OpenSslKeyMaterial retain() { -- super.retain(); -- return this; -- } -- -- @Override -- public OpenSslKeyMaterial retain(int increment) { -- super.retain(increment); -- return this; -- } -- -- @Override -- public OpenSslKeyMaterial touch() { -- OpenSslPrivateKey.this.touch(); -- return this; -- } -- -- @Override -- protected void deallocate() { -- releaseChain(); -- OpenSslPrivateKey.this.release(); -- } -- -- private void releaseChain() { -- SSL.freeX509Chain(certificateChain); -- certificateChain = 0; -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKeyMethod.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKeyMethod.java -deleted file mode 100644 -index 84c8229..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslPrivateKeyMethod.java -+++ /dev/null -@@ -1,62 +0,0 @@ --/* -- * Copyright 2019 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: -- * -- * https://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.internal.tcnative.SSLPrivateKeyMethod; --import io.netty.util.internal.UnstableApi; -- --import javax.net.ssl.SSLEngine; -- --/** -- * Allow to customize private key signing / decrypting (when using RSA). Only supported when using BoringSSL atm. -- */ --@UnstableApi --public interface OpenSslPrivateKeyMethod { -- int SSL_SIGN_RSA_PKCS1_SHA1 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA1; -- int SSL_SIGN_RSA_PKCS1_SHA256 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA256; -- int SSL_SIGN_RSA_PKCS1_SHA384 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA384; -- int SSL_SIGN_RSA_PKCS1_SHA512 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_SHA512; -- int SSL_SIGN_ECDSA_SHA1 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SHA1; -- int SSL_SIGN_ECDSA_SECP256R1_SHA256 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SECP256R1_SHA256; -- int SSL_SIGN_ECDSA_SECP384R1_SHA384 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SECP384R1_SHA384; -- int SSL_SIGN_ECDSA_SECP521R1_SHA512 = SSLPrivateKeyMethod.SSL_SIGN_ECDSA_SECP521R1_SHA512; -- int SSL_SIGN_RSA_PSS_RSAE_SHA256 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PSS_RSAE_SHA256; -- int SSL_SIGN_RSA_PSS_RSAE_SHA384 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PSS_RSAE_SHA384; -- int SSL_SIGN_RSA_PSS_RSAE_SHA512 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PSS_RSAE_SHA512; -- int SSL_SIGN_ED25519 = SSLPrivateKeyMethod.SSL_SIGN_ED25519; -- int SSL_SIGN_RSA_PKCS1_MD5_SHA1 = SSLPrivateKeyMethod.SSL_SIGN_RSA_PKCS1_MD5_SHA1; -- -- /** -- * Signs the input with the given key and returns the signed bytes. -- * -- * @param engine the {@link SSLEngine} -- * @param signatureAlgorithm the algorithm to use for signing -- * @param input the digest itself -- * @return the signed data (must not be {@code null}) -- * @throws Exception thrown if an error is encountered during the signing -- */ -- byte[] sign(SSLEngine engine, int signatureAlgorithm, byte[] input) throws Exception; -- -- /** -- * Decrypts the input with the given key and returns the decrypted bytes. -- * -- * @param engine the {@link SSLEngine} -- * @param input the input which should be decrypted -- * @return the decrypted data (must not be {@code null}) -- * @throws Exception thrown if an error is encountered during the decrypting -- */ -- byte[] decrypt(SSLEngine engine, byte[] input) throws Exception; --} -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 feca8d1..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java -+++ /dev/null -@@ -1,374 +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: -- * -- * https://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.internal.tcnative.SSL; -- --import java.io.File; --import java.security.KeyStore; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; --import java.util.Map; -- --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 static io.netty.handler.ssl.ReferenceCountedOpenSslServerContext.newSessionContext; -- --/** -- * A server-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation. -- *

This class will use a finalizer to ensure native resources are automatically cleaned up. To avoid finalizers -- * and manually release the native memory see {@link ReferenceCountedOpenSslServerContext}. -- */ --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 -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- 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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- public OpenSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException { -- this(certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE, -- ApplicationProtocolConfig.DISABLED, 0, 0); -- } -- -- /** -- * 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 use {@link SslContextBuilder} -- */ -- @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); -- } -- -- /** -- * 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 use {@link SslContextBuilder} -- */ -- @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 SslContextBuilder} -- */ -- @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 SslContextBuilder} -- */ -- @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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- 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 trustCertCollectionFile an X.509 certificate collection file in PEM format. -- * This provides the certificate collection 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 trustCertCollectionFile}. -- * @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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- public OpenSslServerContext( -- File trustCertCollectionFile, TrustManagerFactory trustManagerFactory, -- File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, -- Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig config, -- long sessionCacheSize, long sessionTimeout) throws SSLException { -- this(trustCertCollectionFile, 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 use {@link SslContextBuilder} -- */ -- @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 SslContextBuilder}} -- */ -- @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 trustCertCollectionFile an X.509 certificate collection file in PEM format. -- * This provides the certificate collection 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 trustCertCollectionFile}. -- * @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. -- * @deprecated use {@link SslContextBuilder} -- */ -- @Deprecated -- public OpenSslServerContext( -- File trustCertCollectionFile, TrustManagerFactory trustManagerFactory, -- File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, -- Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, -- long sessionCacheSize, long sessionTimeout) throws SSLException { -- this(toX509CertificatesInternal(trustCertCollectionFile), trustManagerFactory, -- toX509CertificatesInternal(keyCertChainFile), toPrivateKeyInternal(keyFile, keyPassword), -- keyPassword, keyManagerFactory, ciphers, cipherFilter, -- apn, sessionCacheSize, sessionTimeout, ClientAuth.NONE, null, false, false, KeyStore.getDefaultType(), -- null); -- } -- -- OpenSslServerContext( -- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, -- Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, -- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, -- boolean enableOcsp, String keyStore, ResumptionController resumptionController, -- Map.Entry, Object>... options) -- throws SSLException { -- this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers, -- cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls, -- enableOcsp, keyStore, resumptionController, options); -- } -- -- @SuppressWarnings("deprecation") -- private OpenSslServerContext( -- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, -- Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, -- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, -- boolean enableOcsp, String keyStore, ResumptionController resumptionController, -- Map.Entry, Object>... options) -- throws SSLException { -- super(ciphers, cipherFilter, apn, SSL.SSL_MODE_SERVER, keyCertChain, -- clientAuth, protocols, startTls, enableOcsp, resumptionController, options); -- -- // Create a new SSL_CTX and configure it. -- boolean success = false; -- try { -- OpenSslKeyMaterialProvider.validateKeyMaterialSupported(keyCertChain, key, keyPassword); -- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory, -- keyCertChain, key, keyPassword, keyManagerFactory, keyStore, -- sessionCacheSize, sessionTimeout, resumptionController); -- success = true; -- } finally { -- if (!success) { -- release(); -- } -- } -- } -- -- @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 eba161f..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerSessionContext.java -+++ /dev/null -@@ -1,50 +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: -- * -- * https://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.internal.tcnative.SSL; --import io.netty.internal.tcnative.SSLContext; -- --import java.util.concurrent.locks.Lock; -- -- --/** -- * {@link OpenSslSessionContext} implementation which offers extra methods which are only useful for the server-side. -- */ --public final class OpenSslServerSessionContext extends OpenSslSessionContext { -- OpenSslServerSessionContext(ReferenceCountedOpenSslContext context, OpenSslKeyMaterialProvider provider) { -- super(context, provider, SSL.SSL_SESS_CACHE_SERVER, new OpenSslSessionCache(context.engineMap)); -- } -- -- /** -- * 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) { -- Lock writerLock = context.ctxLock.writeLock(); -- writerLock.lock(); -- try { -- return SSLContext.setSessionIdContext(context.ctx, sidCtx); -- } finally { -- writerLock.unlock(); -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslSession.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSession.java -deleted file mode 100644 -index d7ed0fa..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSession.java -+++ /dev/null -@@ -1,95 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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.SSLException; --import javax.net.ssl.SSLSession; --import java.security.cert.Certificate; --import java.util.Map; -- --/** -- * {@link SSLSession} that is specific to our native implementation. -- */ --interface OpenSslSession extends SSLSession { -- -- /** -- * Called on a handshake session before being exposed to a {@link javax.net.ssl.TrustManager}. -- * Session data must be cleared by this call. -- */ -- void prepareHandshake(); -- -- /** -- * Return the {@link OpenSslSessionId} that can be used to identify this session. -- */ -- OpenSslSessionId sessionId(); -- -- /** -- * Set the local certificate chain that is used. It is not expected that this array will be changed at all -- * and so its ok to not copy the array. -- */ -- void setLocalCertificate(Certificate[] localCertificate); -- -- /** -- * Set the details for the session which might come from a cache. -- * -- * @param creationTime the time at which the session was created. -- * @param lastAccessedTime the time at which the session was last accessed via the session infrastructure (cache). -- * @param id the {@link OpenSslSessionId} -- * @param keyValueStorage the key value store. See {@link #keyValueStorage()}. -- */ -- void setSessionDetails(long creationTime, long lastAccessedTime, OpenSslSessionId id, -- Map keyValueStorage); -- -- /** -- * Return the underlying {@link Map} that is used by the following methods: -- * -- *

    -- *
  • {@link #putValue(String, Object)}
  • -- *
  • {@link #removeValue(String)}
  • -- *
  • {@link #getValue(String)}
  • -- *
  • {@link #getValueNames()}
  • -- *
-- * -- * The {@link Map} must be thread-safe! -- * -- * @return storage -- */ -- Map keyValueStorage(); -- -- /** -- * Set the last access time which will be returned by {@link #getLastAccessedTime()}. -- * -- * @param time the time -- */ -- void setLastAccessedTime(long time); -- -- @Override -- OpenSslSessionContext getSessionContext(); -- -- /** -- * Expand (or increase) the value returned by {@link #getApplicationBufferSize()} if necessary. -- *

-- * This is only called in a synchronized block, so no need to use atomic operations. -- * @param packetLengthDataOnly The packet size which exceeds the current {@link #getApplicationBufferSize()}. -- */ -- void tryExpandApplicationBufferSize(int packetLengthDataOnly); -- -- /** -- * Called once the handshake has completed. -- */ -- void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate, -- byte[][] peerCertificateChain, long creationTime, long timeout) throws SSLException; --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionCache.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionCache.java -deleted file mode 100644 -index 7a04419..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionCache.java -+++ /dev/null -@@ -1,521 +0,0 @@ --/* -- * Copyright 2021 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: -- * -- * https://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.internal.tcnative.SSLSession; --import io.netty.internal.tcnative.SSLSessionCache; --import io.netty.util.ResourceLeakDetector; --import io.netty.util.ResourceLeakDetectorFactory; --import io.netty.util.ResourceLeakTracker; --import io.netty.util.internal.EmptyArrays; --import io.netty.util.internal.SystemPropertyUtil; -- --import javax.security.cert.X509Certificate; --import java.security.Principal; --import java.security.cert.Certificate; --import java.util.ArrayList; --import java.util.Iterator; --import java.util.LinkedHashMap; --import java.util.List; --import java.util.Map; --import java.util.concurrent.atomic.AtomicInteger; -- --/** -- * {@link SSLSessionCache} implementation for our native SSL implementation. -- */ --class OpenSslSessionCache implements SSLSessionCache { -- private static final OpenSslSession[] EMPTY_SESSIONS = new OpenSslSession[0]; -- -- private static final int DEFAULT_CACHE_SIZE; -- static { -- // Respect the same system property as the JDK implementation to make it easy to switch between implementations. -- int cacheSize = SystemPropertyUtil.getInt("javax.net.ssl.sessionCacheSize", 20480); -- if (cacheSize >= 0) { -- DEFAULT_CACHE_SIZE = cacheSize; -- } else { -- DEFAULT_CACHE_SIZE = 20480; -- } -- } -- private final OpenSslEngineMap engineMap; -- -- private final Map sessions = -- new LinkedHashMap() { -- -- private static final long serialVersionUID = -7773696788135734448L; -- -- @Override -- protected boolean removeEldestEntry(Map.Entry eldest) { -- int maxSize = maximumCacheSize.get(); -- if (maxSize >= 0 && size() > maxSize) { -- removeSessionWithId(eldest.getKey()); -- } -- // We always need to return false as we modify the map directly. -- return false; -- } -- }; -- -- private final AtomicInteger maximumCacheSize = new AtomicInteger(DEFAULT_CACHE_SIZE); -- -- // Let's use the same default value as OpenSSL does. -- // See https://www.openssl.org/docs/man1.1.1/man3/SSL_get_default_timeout.html -- private final AtomicInteger sessionTimeout = new AtomicInteger(300); -- private int sessionCounter; -- -- OpenSslSessionCache(OpenSslEngineMap engineMap) { -- this.engineMap = engineMap; -- } -- -- final void setSessionTimeout(int seconds) { -- int oldTimeout = sessionTimeout.getAndSet(seconds); -- if (oldTimeout > seconds) { -- // Drain the whole cache as this way we can use the ordering of the LinkedHashMap to detect early -- // if there are any other sessions left that are invalid. -- clear(); -- } -- } -- -- final int getSessionTimeout() { -- return sessionTimeout.get(); -- } -- -- /** -- * Called once a new {@link OpenSslSession} was created. -- * -- * @param session the new session. -- * @return {@code true} if the session should be cached, {@code false} otherwise. -- */ -- protected boolean sessionCreated(NativeSslSession session) { -- return true; -- } -- -- /** -- * Called once an {@link OpenSslSession} was removed from the cache. -- * -- * @param session the session to remove. -- */ -- protected void sessionRemoved(NativeSslSession session) { } -- -- final void setSessionCacheSize(int size) { -- long oldSize = maximumCacheSize.getAndSet(size); -- if (oldSize > size || size == 0) { -- // Just keep it simple for now and drain the whole cache. -- clear(); -- } -- } -- -- final int getSessionCacheSize() { -- return maximumCacheSize.get(); -- } -- -- private void expungeInvalidSessions() { -- if (sessions.isEmpty()) { -- return; -- } -- long now = System.currentTimeMillis(); -- Iterator> iterator = sessions.entrySet().iterator(); -- while (iterator.hasNext()) { -- NativeSslSession session = iterator.next().getValue(); -- // As we use a LinkedHashMap we can break the while loop as soon as we find a valid session. -- // This is true as we always drain the cache as soon as we change the timeout to a smaller value as -- // it was set before. This way its true that the insertion order matches the timeout order. -- if (session.isValid(now)) { -- break; -- } -- iterator.remove(); -- -- notifyRemovalAndFree(session); -- } -- } -- -- @Override -- public boolean sessionCreated(long ssl, long sslSession) { -- ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- if (engine == null) { -- // We couldn't find the engine itself. -- return false; -- } -- OpenSslSession openSslSession = (OpenSslSession) engine.getSession(); -- // Create the native session that we will put into our cache. We will share the key-value storage -- // with the already existing session instance. -- NativeSslSession session = new NativeSslSession(sslSession, engine.getPeerHost(), engine.getPeerPort(), -- getSessionTimeout() * 1000L, openSslSession.keyValueStorage()); -- -- openSslSession.setSessionDetails( -- session.creationTime, session.lastAccessedTime, session.sessionId(), session.keyValueStorage); -- synchronized (this) { -- // Mimic what OpenSSL is doing and expunge every 255 new sessions -- // See https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_flush_sessions.html -- if (++sessionCounter == 255) { -- sessionCounter = 0; -- expungeInvalidSessions(); -- } -- -- if (!sessionCreated(session)) { -- // Should not be cached, return false. In this case we also need to call close() to ensure we -- // close the ResourceLeakTracker. -- session.close(); -- return false; -- } -- final NativeSslSession old = sessions.put(session.sessionId(), session); -- if (old != null) { -- notifyRemovalAndFree(old); -- } -- } -- return true; -- } -- -- @Override -- public final long getSession(long ssl, byte[] sessionId) { -- OpenSslSessionId id = new OpenSslSessionId(sessionId); -- final NativeSslSession session; -- synchronized (this) { -- session = sessions.get(id); -- if (session == null) { -- return -1; -- } -- -- // If the session is not valid anymore we should remove it from the cache and just signal back -- // that we couldn't find a session that is re-usable. -- if (!session.isValid() || -- // This needs to happen in the synchronized block so we ensure we never destroy it before we -- // incremented the reference count. If we cant increment the reference count there is something -- // wrong. In this case just remove the session from the cache and signal back that we couldn't -- // find a session for re-use. -- !session.upRef()) { -- // Remove the session from the cache. This will also take care of calling SSL_SESSION_free(...) -- removeSessionWithId(session.sessionId()); -- return -1; -- } -- -- // At this point we already incremented the reference count via SSL_SESSION_up_ref(...). -- if (session.shouldBeSingleUse()) { -- // Should only be used once. In this case invalidate the session which will also ensure we remove it -- // from the cache and call SSL_SESSION_free(...). -- removeSessionWithId(session.sessionId()); -- } -- } -- session.setLastAccessedTime(System.currentTimeMillis()); -- ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- if (engine != null) { -- OpenSslSession sslSession = (OpenSslSession) engine.getSession(); -- sslSession.setSessionDetails(session.getCreationTime(), -- session.getLastAccessedTime(), session.sessionId(), session.keyValueStorage); -- } -- -- return session.session(); -- } -- -- boolean setSession(long ssl, OpenSslSession session, String host, int port) { -- // Do nothing by default as this needs special handling for the client side. -- return false; -- } -- -- /** -- * Remove the session with the given id from the cache -- */ -- final synchronized void removeSessionWithId(OpenSslSessionId id) { -- NativeSslSession sslSession = sessions.remove(id); -- if (sslSession != null) { -- notifyRemovalAndFree(sslSession); -- } -- } -- -- /** -- * Returns {@code true} if there is a session for the given id in the cache. -- */ -- final synchronized boolean containsSessionWithId(OpenSslSessionId id) { -- return sessions.containsKey(id); -- } -- -- private void notifyRemovalAndFree(NativeSslSession session) { -- sessionRemoved(session); -- session.free(); -- } -- -- /** -- * Return the {@link OpenSslSession} which is cached for the given id. -- */ -- final synchronized OpenSslSession getSession(OpenSslSessionId id) { -- NativeSslSession session = sessions.get(id); -- if (session != null && !session.isValid()) { -- // The session is not valid anymore, let's remove it and just signal back that there is no session -- // with the given ID in the cache anymore. This also takes care of calling SSL_SESSION_free(...) -- removeSessionWithId(session.sessionId()); -- return null; -- } -- return session; -- } -- -- /** -- * Returns a snapshot of the session ids of the current valid sessions. -- */ -- final List getIds() { -- final OpenSslSession[] sessionsArray; -- synchronized (this) { -- sessionsArray = sessions.values().toArray(EMPTY_SESSIONS); -- } -- List ids = new ArrayList(sessionsArray.length); -- for (OpenSslSession session: sessionsArray) { -- if (session.isValid()) { -- ids.add(session.sessionId()); -- } -- } -- return ids; -- } -- -- /** -- * Clear the cache and free all cached SSL_SESSION*. -- */ -- synchronized void clear() { -- Iterator> iterator = sessions.entrySet().iterator(); -- while (iterator.hasNext()) { -- NativeSslSession session = iterator.next().getValue(); -- iterator.remove(); -- -- // Notify about removal. This also takes care of calling SSL_SESSION_free(...). -- notifyRemovalAndFree(session); -- } -- } -- -- /** -- * {@link OpenSslSession} implementation which wraps the native SSL_SESSION* while in cache. -- */ -- static final class NativeSslSession implements OpenSslSession { -- static final ResourceLeakDetector LEAK_DETECTOR = ResourceLeakDetectorFactory.instance() -- .newResourceLeakDetector(NativeSslSession.class); -- private final ResourceLeakTracker leakTracker; -- -- final Map keyValueStorage; -- -- private final long session; -- private final String peerHost; -- private final int peerPort; -- private final OpenSslSessionId id; -- private final long timeout; -- private final long creationTime = System.currentTimeMillis(); -- private volatile long lastAccessedTime = creationTime; -- private volatile boolean valid = true; -- private boolean freed; -- -- NativeSslSession(long session, String peerHost, int peerPort, long timeout, -- Map keyValueStorage) { -- this.session = session; -- this.peerHost = peerHost; -- this.peerPort = peerPort; -- this.timeout = timeout; -- this.id = new OpenSslSessionId(io.netty.internal.tcnative.SSLSession.getSessionId(session)); -- this.keyValueStorage = keyValueStorage; -- leakTracker = LEAK_DETECTOR.track(this); -- } -- -- @Override -- public Map keyValueStorage() { -- return keyValueStorage; -- } -- -- @Override -- public void prepareHandshake() { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public void setSessionDetails(long creationTime, long lastAccessedTime, -- OpenSslSessionId id, Map keyValueStorage) { -- throw new UnsupportedOperationException(); -- } -- -- boolean shouldBeSingleUse() { -- assert !freed; -- return SSLSession.shouldBeSingleUse(session); -- } -- -- long session() { -- assert !freed; -- return session; -- } -- -- boolean upRef() { -- assert !freed; -- return SSLSession.upRef(session); -- } -- -- synchronized void free() { -- close(); -- SSLSession.free(session); -- } -- -- void close() { -- assert !freed; -- freed = true; -- invalidate(); -- if (leakTracker != null) { -- leakTracker.close(this); -- } -- } -- -- @Override -- public OpenSslSessionId sessionId() { -- return id; -- } -- -- boolean isValid(long now) { -- return creationTime + timeout >= now && valid; -- } -- -- @Override -- public void setLocalCertificate(Certificate[] localCertificate) { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public OpenSslSessionContext getSessionContext() { -- return null; -- } -- -- @Override -- public void tryExpandApplicationBufferSize(int packetLengthDataOnly) { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate, -- byte[][] peerCertificateChain, long creationTime, long timeout) { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public byte[] getId() { -- return id.cloneBytes(); -- } -- -- @Override -- public long getCreationTime() { -- return creationTime; -- } -- -- @Override -- public void setLastAccessedTime(long time) { -- lastAccessedTime = time; -- } -- -- @Override -- public long getLastAccessedTime() { -- return lastAccessedTime; -- } -- -- @Override -- public void invalidate() { -- valid = false; -- } -- -- @Override -- public boolean isValid() { -- return isValid(System.currentTimeMillis()); -- } -- -- @Override -- public void putValue(String name, Object value) { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public Object getValue(String name) { -- return null; -- } -- -- @Override -- public void removeValue(String name) { -- // NOOP -- } -- -- @Override -- public String[] getValueNames() { -- return EmptyArrays.EMPTY_STRINGS; -- } -- -- @Override -- public Certificate[] getPeerCertificates() { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public Certificate[] getLocalCertificates() { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public X509Certificate[] getPeerCertificateChain() { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public Principal getPeerPrincipal() { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public Principal getLocalPrincipal() { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public String getCipherSuite() { -- return null; -- } -- -- @Override -- public String getProtocol() { -- return null; -- } -- -- @Override -- public String getPeerHost() { -- return peerHost; -- } -- -- @Override -- public int getPeerPort() { -- return peerPort; -- } -- -- @Override -- public int getPacketBufferSize() { -- return ReferenceCountedOpenSslEngine.MAX_RECORD_SIZE; -- } -- -- @Override -- public int getApplicationBufferSize() { -- return ReferenceCountedOpenSslEngine.MAX_PLAINTEXT_LENGTH; -- } -- -- @Override -- public int hashCode() { -- return id.hashCode(); -- } -- -- @Override -- public boolean equals(Object o) { -- if (this == o) { -- return true; -- } -- if (!(o instanceof OpenSslSession)) { -- return false; -- } -- OpenSslSession session1 = (OpenSslSession) o; -- return id.equals(session1.sessionId()); -- } -- } --} -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 baa83d3..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java -+++ /dev/null -@@ -1,229 +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: -- * -- * https://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.internal.tcnative.SSL; --import io.netty.internal.tcnative.SSLContext; --import io.netty.internal.tcnative.SessionTicketKey; --import io.netty.util.internal.ObjectUtil; -- --import javax.net.ssl.SSLSession; --import javax.net.ssl.SSLSessionContext; --import java.util.Arrays; --import java.util.Enumeration; --import java.util.Iterator; --import java.util.concurrent.locks.Lock; -- --/** -- * OpenSSL specific {@link SSLSessionContext} implementation. -- */ --public abstract class OpenSslSessionContext implements SSLSessionContext { -- -- private final OpenSslSessionStats stats; -- -- // The OpenSslKeyMaterialProvider is not really used by the OpenSslSessionContext but only be stored here -- // to make it easier to destroy it later because the ReferenceCountedOpenSslContext will hold a reference -- // to OpenSslSessionContext. -- private final OpenSslKeyMaterialProvider provider; -- -- final ReferenceCountedOpenSslContext context; -- -- private final OpenSslSessionCache sessionCache; -- private final long mask; -- -- // IMPORTANT: We take the OpenSslContext and not just the long (which points the native instance) to prevent -- // the GC to collect OpenSslContext as this would also free the pointer and so could result in a -- // segfault when the user calls any of the methods here that try to pass the pointer down to the native -- // level. -- OpenSslSessionContext(ReferenceCountedOpenSslContext context, OpenSslKeyMaterialProvider provider, long mask, -- OpenSslSessionCache cache) { -- this.context = context; -- this.provider = provider; -- this.mask = mask; -- stats = new OpenSslSessionStats(context); -- sessionCache = cache; -- SSLContext.setSSLSessionCache(context.ctx, cache); -- } -- -- final boolean useKeyManager() { -- return provider != null; -- } -- -- @Override -- public void setSessionCacheSize(int size) { -- ObjectUtil.checkPositiveOrZero(size, "size"); -- sessionCache.setSessionCacheSize(size); -- } -- -- @Override -- public int getSessionCacheSize() { -- return sessionCache.getSessionCacheSize(); -- } -- -- @Override -- public void setSessionTimeout(int seconds) { -- ObjectUtil.checkPositiveOrZero(seconds, "seconds"); -- -- Lock writerLock = context.ctxLock.writeLock(); -- writerLock.lock(); -- try { -- SSLContext.setSessionCacheTimeout(context.ctx, seconds); -- sessionCache.setSessionTimeout(seconds); -- } finally { -- writerLock.unlock(); -- } -- } -- -- @Override -- public int getSessionTimeout() { -- return sessionCache.getSessionTimeout(); -- } -- -- @Override -- public SSLSession getSession(byte[] bytes) { -- return sessionCache.getSession(new OpenSslSessionId(bytes)); -- } -- -- @Override -- public Enumeration getIds() { -- return new Enumeration() { -- private final Iterator ids = sessionCache.getIds().iterator(); -- @Override -- public boolean hasMoreElements() { -- return ids.hasNext(); -- } -- -- @Override -- public byte[] nextElement() { -- return ids.next().cloneBytes(); -- } -- }; -- } -- -- /** -- * Sets the SSL session ticket keys of this context. -- * @deprecated use {@link #setTicketKeys(OpenSslSessionTicketKey...)}. -- */ -- @Deprecated -- public void setTicketKeys(byte[] keys) { -- if (keys.length % SessionTicketKey.TICKET_KEY_SIZE != 0) { -- throw new IllegalArgumentException("keys.length % " + SessionTicketKey.TICKET_KEY_SIZE + " != 0"); -- } -- SessionTicketKey[] tickets = new SessionTicketKey[keys.length / SessionTicketKey.TICKET_KEY_SIZE]; -- for (int i = 0, a = 0; i < tickets.length; i++) { -- byte[] name = Arrays.copyOfRange(keys, a, SessionTicketKey.NAME_SIZE); -- a += SessionTicketKey.NAME_SIZE; -- byte[] hmacKey = Arrays.copyOfRange(keys, a, SessionTicketKey.HMAC_KEY_SIZE); -- i += SessionTicketKey.HMAC_KEY_SIZE; -- byte[] aesKey = Arrays.copyOfRange(keys, a, SessionTicketKey.AES_KEY_SIZE); -- a += SessionTicketKey.AES_KEY_SIZE; -- tickets[i] = new SessionTicketKey(name, hmacKey, aesKey); -- } -- Lock writerLock = context.ctxLock.writeLock(); -- writerLock.lock(); -- try { -- SSLContext.clearOptions(context.ctx, SSL.SSL_OP_NO_TICKET); -- SSLContext.setSessionTicketKeys(context.ctx, tickets); -- } finally { -- writerLock.unlock(); -- } -- } -- -- /** -- * Sets the SSL session ticket keys of this context. Depending on the underlying native library you may omit the -- * argument or pass an empty array and so let the native library handle the key generation and rotating for you. -- * If this is supported by the underlying native library should be checked in this case. For example -- * -- * BoringSSL is known to support this. -- */ -- public void setTicketKeys(OpenSslSessionTicketKey... keys) { -- ObjectUtil.checkNotNull(keys, "keys"); -- SessionTicketKey[] ticketKeys = new SessionTicketKey[keys.length]; -- for (int i = 0; i < ticketKeys.length; i++) { -- ticketKeys[i] = keys[i].key; -- } -- Lock writerLock = context.ctxLock.writeLock(); -- writerLock.lock(); -- try { -- SSLContext.clearOptions(context.ctx, SSL.SSL_OP_NO_TICKET); -- if (ticketKeys.length > 0) { -- SSLContext.setSessionTicketKeys(context.ctx, ticketKeys); -- } -- } finally { -- writerLock.unlock(); -- } -- } -- -- /** -- * Enable or disable caching of SSL sessions. -- */ -- public void setSessionCacheEnabled(boolean enabled) { -- long mode = enabled ? mask | SSL.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | -- SSL.SSL_SESS_CACHE_NO_INTERNAL_STORE : SSL.SSL_SESS_CACHE_OFF; -- Lock writerLock = context.ctxLock.writeLock(); -- writerLock.lock(); -- try { -- SSLContext.setSessionCacheMode(context.ctx, mode); -- if (!enabled) { -- sessionCache.clear(); -- } -- } finally { -- writerLock.unlock(); -- } -- } -- -- /** -- * Return {@code true} if caching of SSL sessions is enabled, {@code false} otherwise. -- */ -- public boolean isSessionCacheEnabled() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return (SSLContext.getSessionCacheMode(context.ctx) & mask) != 0; -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the stats of this context. -- */ -- public OpenSslSessionStats stats() { -- return stats; -- } -- -- /** -- * Remove the given {@link OpenSslSession} from the cache, and so not re-use it for new connections. -- */ -- final void removeFromCache(OpenSslSessionId id) { -- sessionCache.removeSessionWithId(id); -- } -- -- final boolean isInCache(OpenSslSessionId id) { -- return sessionCache.containsSessionWithId(id); -- } -- -- boolean setSessionFromCache(long ssl, OpenSslSession session, String host, int port) { -- return sessionCache.setSession(ssl, session, host, port); -- } -- -- final void destroy() { -- if (provider != null) { -- provider.destroy(); -- } -- sessionCache.clear(); -- } --} -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 85a0ee8..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java -+++ /dev/null -@@ -1,253 +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: -- * -- * https://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.internal.tcnative.SSLContext; -- --import java.util.concurrent.locks.Lock; -- --/** -- * Stats exposed by an OpenSSL session context. -- * -- * @see SSL_CTX_sess_number -- */ --public final class OpenSslSessionStats { -- -- private final ReferenceCountedOpenSslContext context; -- -- // IMPORTANT: We take the OpenSslContext and not just the long (which points the native instance) to prevent -- // the GC to collect OpenSslContext as this would also free the pointer and so could result in a -- // segfault when the user calls any of the methods here that try to pass the pointer down to the native -- // level. -- OpenSslSessionStats(ReferenceCountedOpenSslContext context) { -- this.context = context; -- } -- -- /** -- * Returns the current number of sessions in the internal session cache. -- */ -- public long number() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionNumber(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of started SSL/TLS handshakes in client mode. -- */ -- public long connect() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionConnect(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of successfully established SSL/TLS sessions in client mode. -- */ -- public long connectGood() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionConnectGood(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of start renegotiations in client mode. -- */ -- public long connectRenegotiate() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionConnectRenegotiate(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of started SSL/TLS handshakes in server mode. -- */ -- public long accept() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionAccept(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of successfully established SSL/TLS sessions in server mode. -- */ -- public long acceptGood() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionAcceptGood(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of start renegotiations in server mode. -- */ -- public long acceptRenegotiate() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionAcceptRenegotiate(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * 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() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionHits(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of successfully retrieved sessions from the external session cache in server mode. -- */ -- public long cbHits() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionCbHits(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of sessions proposed by clients that were not found in the internal session cache -- * in server mode. -- */ -- public long misses() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionMisses(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * 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() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionTimeouts(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of sessions that were removed because the maximum session cache size was exceeded. -- */ -- public long cacheFull() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionCacheFull(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of times a client presented a ticket that did not match any key in the list. -- */ -- public long ticketKeyFail() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionTicketKeyFail(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of times a client did not present a ticket and we issued a new one -- */ -- public long ticketKeyNew() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionTicketKeyNew(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of times a client presented a ticket derived from an older key, -- * and we upgraded to the primary key. -- */ -- public long ticketKeyRenew() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionTicketKeyRenew(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Returns the number of times a client presented a ticket derived from the primary key. -- */ -- public long ticketKeyResume() { -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.sessionTicketKeyResume(context.ctx); -- } finally { -- readerLock.unlock(); -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionTicketKey.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionTicketKey.java -deleted file mode 100644 -index 175a37e..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionTicketKey.java -+++ /dev/null -@@ -1,78 +0,0 @@ --/* -- * Copyright 2015 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: -- * -- * https://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.internal.tcnative.SessionTicketKey; -- --/** -- * Session Ticket Key -- */ --public final class OpenSslSessionTicketKey { -- -- /** -- * Size of session ticket key name -- */ -- public static final int NAME_SIZE = SessionTicketKey.NAME_SIZE; -- /** -- * Size of session ticket key HMAC key -- */ -- public static final int HMAC_KEY_SIZE = SessionTicketKey.HMAC_KEY_SIZE; -- /** -- * Size of session ticket key AES key -- */ -- public static final int AES_KEY_SIZE = SessionTicketKey.AES_KEY_SIZE; -- /** -- * Size of session ticker key -- */ -- public static final int TICKET_KEY_SIZE = SessionTicketKey.TICKET_KEY_SIZE; -- -- final SessionTicketKey key; -- -- /** -- * Construct a OpenSslSessionTicketKey. -- * -- * @param name the name of the session ticket key -- * @param hmacKey the HMAC key of the session ticket key -- * @param aesKey the AES key of the session ticket key -- */ -- public OpenSslSessionTicketKey(byte[] name, byte[] hmacKey, byte[] aesKey) { -- key = new SessionTicketKey(name.clone(), hmacKey.clone(), aesKey.clone()); -- } -- -- /** -- * Get name. -- * @return the name of the session ticket key -- */ -- public byte[] name() { -- return key.getName().clone(); -- } -- -- /** -- * Get HMAC key. -- * @return the HMAC key of the session ticket key -- */ -- public byte[] hmacKey() { -- return key.getHmacKey().clone(); -- } -- -- /** -- * Get AES Key. -- * @return the AES key of the session ticket key -- */ -- public byte[] aesKey() { -- return key.getAesKey().clone(); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslX509KeyManagerFactory.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslX509KeyManagerFactory.java -deleted file mode 100644 -index df711a0..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/OpenSslX509KeyManagerFactory.java -+++ /dev/null -@@ -1,416 +0,0 @@ --/* -- * Copyright 2018 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: -- * -- * https://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.checkNonEmpty; --import static io.netty.util.internal.ObjectUtil.checkNotNull; -- --import io.netty.buffer.ByteBufAllocator; --import io.netty.buffer.UnpooledByteBufAllocator; --import io.netty.internal.tcnative.SSL; --import io.netty.util.ReferenceCountUtil; --import io.netty.util.internal.ObjectUtil; -- --import javax.net.ssl.KeyManager; --import javax.net.ssl.KeyManagerFactory; --import javax.net.ssl.KeyManagerFactorySpi; --import javax.net.ssl.ManagerFactoryParameters; --import javax.net.ssl.X509KeyManager; --import java.io.File; --import java.io.IOException; --import java.io.InputStream; --import java.io.OutputStream; --import java.security.InvalidAlgorithmParameterException; --import java.security.Key; --import java.security.KeyStore; --import java.security.KeyStoreException; --import java.security.KeyStoreSpi; --import java.security.NoSuchAlgorithmException; --import java.security.PrivateKey; --import java.security.Provider; --import java.security.UnrecoverableKeyException; --import java.security.cert.Certificate; --import java.security.cert.CertificateException; --import java.security.cert.X509Certificate; --import java.util.Collections; --import java.util.Date; --import java.util.Enumeration; --import java.util.HashMap; --import java.util.Map; -- --/** -- * Special {@link KeyManagerFactory} that pre-compute the keymaterial used when {@link SslProvider#OPENSSL} or -- * {@link SslProvider#OPENSSL_REFCNT} is used and so will improve handshake times and its performance. -- * -- * -- * -- * Because the keymaterial is pre-computed any modification to the {@link KeyStore} is ignored after -- * {@link #init(KeyStore, char[])} is called. -- * -- * {@link #init(ManagerFactoryParameters)} is not supported by this implementation and so a call to it will always -- * result in an {@link InvalidAlgorithmParameterException}. -- */ --public final class OpenSslX509KeyManagerFactory extends KeyManagerFactory { -- -- private final OpenSslKeyManagerFactorySpi spi; -- -- public OpenSslX509KeyManagerFactory() { -- this(newOpenSslKeyManagerFactorySpi(null)); -- } -- -- public OpenSslX509KeyManagerFactory(Provider provider) { -- this(newOpenSslKeyManagerFactorySpi(provider)); -- } -- -- public OpenSslX509KeyManagerFactory(String algorithm, Provider provider) throws NoSuchAlgorithmException { -- this(newOpenSslKeyManagerFactorySpi(algorithm, provider)); -- } -- -- private OpenSslX509KeyManagerFactory(OpenSslKeyManagerFactorySpi spi) { -- super(spi, spi.kmf.getProvider(), spi.kmf.getAlgorithm()); -- this.spi = spi; -- } -- -- private static OpenSslKeyManagerFactorySpi newOpenSslKeyManagerFactorySpi(Provider provider) { -- try { -- return newOpenSslKeyManagerFactorySpi(null, provider); -- } catch (NoSuchAlgorithmException e) { -- // This should never happen as we use the default algorithm. -- throw new IllegalStateException(e); -- } -- } -- -- private static OpenSslKeyManagerFactorySpi newOpenSslKeyManagerFactorySpi(String algorithm, Provider provider) -- throws NoSuchAlgorithmException { -- if (algorithm == null) { -- algorithm = KeyManagerFactory.getDefaultAlgorithm(); -- } -- return new OpenSslKeyManagerFactorySpi( -- provider == null ? KeyManagerFactory.getInstance(algorithm) : -- KeyManagerFactory.getInstance(algorithm, provider)); -- } -- -- OpenSslKeyMaterialProvider newProvider() { -- return spi.newProvider(); -- } -- -- private static final class OpenSslKeyManagerFactorySpi extends KeyManagerFactorySpi { -- final KeyManagerFactory kmf; -- private volatile ProviderFactory providerFactory; -- -- OpenSslKeyManagerFactorySpi(KeyManagerFactory kmf) { -- this.kmf = ObjectUtil.checkNotNull(kmf, "kmf"); -- } -- -- @Override -- protected synchronized void engineInit(KeyStore keyStore, char[] chars) -- throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- if (providerFactory != null) { -- throw new KeyStoreException("Already initialized"); -- } -- if (!keyStore.aliases().hasMoreElements()) { -- throw new KeyStoreException("No aliases found"); -- } -- -- kmf.init(keyStore, chars); -- providerFactory = new ProviderFactory(ReferenceCountedOpenSslContext.chooseX509KeyManager( -- kmf.getKeyManagers()), password(chars), Collections.list(keyStore.aliases())); -- } -- -- private static String password(char[] password) { -- if (password == null || password.length == 0) { -- return null; -- } -- return new String(password); -- } -- -- @Override -- protected void engineInit(ManagerFactoryParameters managerFactoryParameters) -- throws InvalidAlgorithmParameterException { -- throw new InvalidAlgorithmParameterException("Not supported"); -- } -- -- @Override -- protected KeyManager[] engineGetKeyManagers() { -- ProviderFactory providerFactory = this.providerFactory; -- if (providerFactory == null) { -- throw new IllegalStateException("engineInit(...) not called yet"); -- } -- return new KeyManager[] { providerFactory.keyManager }; -- } -- -- OpenSslKeyMaterialProvider newProvider() { -- ProviderFactory providerFactory = this.providerFactory; -- if (providerFactory == null) { -- throw new IllegalStateException("engineInit(...) not called yet"); -- } -- return providerFactory.newProvider(); -- } -- -- private static final class ProviderFactory { -- private final X509KeyManager keyManager; -- private final String password; -- private final Iterable aliases; -- -- ProviderFactory(X509KeyManager keyManager, String password, Iterable aliases) { -- this.keyManager = keyManager; -- this.password = password; -- this.aliases = aliases; -- } -- -- OpenSslKeyMaterialProvider newProvider() { -- return new OpenSslPopulatedKeyMaterialProvider(keyManager, -- password, aliases); -- } -- -- /** -- * {@link OpenSslKeyMaterialProvider} implementation that pre-compute the {@link OpenSslKeyMaterial} for -- * all aliases. -- */ -- private static final class OpenSslPopulatedKeyMaterialProvider extends OpenSslKeyMaterialProvider { -- private final Map materialMap; -- -- OpenSslPopulatedKeyMaterialProvider( -- X509KeyManager keyManager, String password, Iterable aliases) { -- super(keyManager, password); -- materialMap = new HashMap(); -- boolean initComplete = false; -- try { -- for (String alias: aliases) { -- if (alias != null && !materialMap.containsKey(alias)) { -- try { -- materialMap.put(alias, super.chooseKeyMaterial( -- UnpooledByteBufAllocator.DEFAULT, alias)); -- } catch (Exception e) { -- // Just store the exception and rethrow it when we try to choose the keymaterial -- // for this alias later on. -- materialMap.put(alias, e); -- } -- } -- } -- initComplete = true; -- } finally { -- if (!initComplete) { -- destroy(); -- } -- } -- checkNonEmpty(materialMap, "materialMap"); -- } -- -- @Override -- OpenSslKeyMaterial chooseKeyMaterial(ByteBufAllocator allocator, String alias) throws Exception { -- Object value = materialMap.get(alias); -- if (value == null) { -- // There is no keymaterial for the requested alias, return null -- return null; -- } -- if (value instanceof OpenSslKeyMaterial) { -- return ((OpenSslKeyMaterial) value).retain(); -- } -- throw (Exception) value; -- } -- -- @Override -- void destroy() { -- for (Object material: materialMap.values()) { -- ReferenceCountUtil.release(material); -- } -- materialMap.clear(); -- } -- } -- } -- } -- -- /** -- * Create a new initialized {@link OpenSslX509KeyManagerFactory} which loads its {@link PrivateKey} directly from -- * an {@code OpenSSL engine} via the -- * ENGINE_load_private_key -- * function. -- */ -- public static OpenSslX509KeyManagerFactory newEngineBased(File certificateChain, String password) -- throws CertificateException, IOException, -- KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- return newEngineBased(SslContext.toX509Certificates(certificateChain), password); -- } -- -- /** -- * Create a new initialized {@link OpenSslX509KeyManagerFactory} which loads its {@link PrivateKey} directly from -- * an {@code OpenSSL engine} via the -- * ENGINE_load_private_key -- * function. -- */ -- public static OpenSslX509KeyManagerFactory newEngineBased(X509Certificate[] certificateChain, String password) -- throws CertificateException, IOException, -- KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- checkNotNull(certificateChain, "certificateChain"); -- KeyStore store = new OpenSslKeyStore(certificateChain.clone(), false); -- store.load(null, null); -- OpenSslX509KeyManagerFactory factory = new OpenSslX509KeyManagerFactory(); -- factory.init(store, password == null ? null : password.toCharArray()); -- return factory; -- } -- -- /** -- * See {@link OpenSslX509KeyManagerFactory#newEngineBased(X509Certificate[], String)}. -- */ -- public static OpenSslX509KeyManagerFactory newKeyless(File chain) -- throws CertificateException, IOException, -- KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- return newKeyless(SslContext.toX509Certificates(chain)); -- } -- -- /** -- * See {@link OpenSslX509KeyManagerFactory#newEngineBased(X509Certificate[], String)}. -- */ -- public static OpenSslX509KeyManagerFactory newKeyless(InputStream chain) -- throws CertificateException, IOException, -- KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- return newKeyless(SslContext.toX509Certificates(chain)); -- } -- -- /** -- * Returns a new initialized {@link OpenSslX509KeyManagerFactory} which will provide its private key by using the -- * {@link OpenSslPrivateKeyMethod}. -- */ -- public static OpenSslX509KeyManagerFactory newKeyless(X509Certificate... certificateChain) -- throws CertificateException, IOException, -- KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { -- checkNotNull(certificateChain, "certificateChain"); -- KeyStore store = new OpenSslKeyStore(certificateChain.clone(), true); -- store.load(null, null); -- OpenSslX509KeyManagerFactory factory = new OpenSslX509KeyManagerFactory(); -- factory.init(store, null); -- return factory; -- } -- -- private static final class OpenSslKeyStore extends KeyStore { -- private OpenSslKeyStore(final X509Certificate[] certificateChain, final boolean keyless) { -- super(new KeyStoreSpi() { -- -- private final Date creationDate = new Date(); -- -- @Override -- public Key engineGetKey(String alias, char[] password) throws UnrecoverableKeyException { -- if (engineContainsAlias(alias)) { -- final long privateKeyAddress; -- if (keyless) { -- privateKeyAddress = 0; -- } else { -- try { -- privateKeyAddress = SSL.loadPrivateKeyFromEngine( -- alias, password == null ? null : new String(password)); -- } catch (Exception e) { -- UnrecoverableKeyException keyException = -- new UnrecoverableKeyException("Unable to load key from engine"); -- keyException.initCause(e); -- throw keyException; -- } -- } -- return new OpenSslPrivateKey(privateKeyAddress); -- } -- return null; -- } -- -- @Override -- public Certificate[] engineGetCertificateChain(String alias) { -- return engineContainsAlias(alias)? certificateChain.clone() : null; -- } -- -- @Override -- public Certificate engineGetCertificate(String alias) { -- return engineContainsAlias(alias)? certificateChain[0] : null; -- } -- -- @Override -- public Date engineGetCreationDate(String alias) { -- return engineContainsAlias(alias)? creationDate : null; -- } -- -- @Override -- public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) -- throws KeyStoreException { -- throw new KeyStoreException("Not supported"); -- } -- -- @Override -- public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { -- throw new KeyStoreException("Not supported"); -- } -- -- @Override -- public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException { -- throw new KeyStoreException("Not supported"); -- } -- -- @Override -- public void engineDeleteEntry(String alias) throws KeyStoreException { -- throw new KeyStoreException("Not supported"); -- } -- -- @Override -- public Enumeration engineAliases() { -- return Collections.enumeration(Collections.singleton(SslContext.ALIAS)); -- } -- -- @Override -- public boolean engineContainsAlias(String alias) { -- return SslContext.ALIAS.equals(alias); -- } -- -- @Override -- public int engineSize() { -- return 1; -- } -- -- @Override -- public boolean engineIsKeyEntry(String alias) { -- return engineContainsAlias(alias); -- } -- -- @Override -- public boolean engineIsCertificateEntry(String alias) { -- return engineContainsAlias(alias); -- } -- -- @Override -- public String engineGetCertificateAlias(Certificate cert) { -- if (cert instanceof X509Certificate) { -- for (X509Certificate x509Certificate : certificateChain) { -- if (x509Certificate.equals(cert)) { -- return SslContext.ALIAS; -- } -- } -- } -- return null; -- } -- -- @Override -- public void engineStore(OutputStream stream, char[] password) { -- throw new UnsupportedOperationException(); -- } -- -- @Override -- public void engineLoad(InputStream stream, char[] password) { -- if (stream != null && password != null) { -- throw new UnsupportedOperationException(); -- } -- } -- }, null, "native"); -- -- OpenSsl.ensureAvailability(); -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java -deleted file mode 100644 -index 3eb233d..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java -+++ /dev/null -@@ -1,324 +0,0 @@ --/* -- * Copyright 2016 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: -- * -- * https://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.internal.tcnative.CertificateCallback; --import io.netty.util.internal.EmptyArrays; --import io.netty.util.internal.SuppressJava6Requirement; --import io.netty.internal.tcnative.SSL; --import io.netty.internal.tcnative.SSLContext; -- --import java.security.KeyStore; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; -- --import java.util.Arrays; --import java.util.Collections; --import java.util.HashSet; --import java.util.LinkedHashSet; --import java.util.Map; --import java.util.Set; -- --import javax.net.ssl.KeyManagerFactory; --import javax.net.ssl.SSLException; --import javax.net.ssl.TrustManagerFactory; --import javax.net.ssl.X509ExtendedTrustManager; --import javax.net.ssl.X509TrustManager; --import javax.security.auth.x500.X500Principal; -- --/** -- * A client-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation. -- *

Instances of this class must be {@link #release() released} or else native memory will leak! -- * -- *

Instances of this class must not be released before any {@link ReferenceCountedOpenSslEngine} -- * which depends upon the instance of this class is released. Otherwise if any method of -- * {@link ReferenceCountedOpenSslEngine} is called which uses this class's JNI resources the JVM may crash. -- */ --public final class ReferenceCountedOpenSslClientContext extends ReferenceCountedOpenSslContext { -- -- private static final Set SUPPORTED_KEY_TYPES = Collections.unmodifiableSet(new LinkedHashSet( -- Arrays.asList(OpenSslKeyMaterialManager.KEY_TYPE_RSA, -- OpenSslKeyMaterialManager.KEY_TYPE_DH_RSA, -- OpenSslKeyMaterialManager.KEY_TYPE_EC, -- OpenSslKeyMaterialManager.KEY_TYPE_EC_RSA, -- OpenSslKeyMaterialManager.KEY_TYPE_EC_EC))); -- -- private final OpenSslSessionContext sessionContext; -- -- ReferenceCountedOpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, -- KeyManagerFactory keyManagerFactory, Iterable ciphers, -- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, -- String[] protocols, long sessionCacheSize, long sessionTimeout, -- boolean enableOcsp, String keyStore, String endpointIdentificationAlgorithm, -- ResumptionController resumptionController, -- Map.Entry, Object>... options) throws SSLException { -- super(ciphers, cipherFilter, toNegotiator(apn), SSL.SSL_MODE_CLIENT, keyCertChain, -- ClientAuth.NONE, protocols, false, endpointIdentificationAlgorithm, enableOcsp, true, -- resumptionController, options); -- boolean success = false; -- try { -- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory, -- keyCertChain, key, keyPassword, keyManagerFactory, keyStore, -- sessionCacheSize, sessionTimeout, resumptionController); -- success = true; -- } finally { -- if (!success) { -- release(); -- } -- } -- } -- -- @Override -- public OpenSslSessionContext sessionContext() { -- return sessionContext; -- } -- -- static OpenSslSessionContext newSessionContext(ReferenceCountedOpenSslContext thiz, long ctx, -- OpenSslEngineMap engineMap, -- X509Certificate[] trustCertCollection, -- TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, -- String keyPassword, KeyManagerFactory keyManagerFactory, -- String keyStore, long sessionCacheSize, long sessionTimeout, -- ResumptionController resumptionController) -- throws SSLException { -- if (key == null && keyCertChain != null || key != null && keyCertChain == null) { -- throw new IllegalArgumentException( -- "Either both keyCertChain and key needs to be null or none of them"); -- } -- OpenSslKeyMaterialProvider keyMaterialProvider = null; -- try { -- try { -- if (!OpenSsl.useKeyManagerFactory()) { -- if (keyManagerFactory != null) { -- throw new IllegalArgumentException( -- "KeyManagerFactory not supported"); -- } -- if (keyCertChain != null/* && key != null*/) { -- setKeyMaterial(ctx, keyCertChain, key, keyPassword); -- } -- } else { -- // javadocs state that keyManagerFactory has precedent over keyCertChain -- if (keyManagerFactory == null && keyCertChain != null) { -- char[] keyPasswordChars = keyStorePassword(keyPassword); -- KeyStore ks = buildKeyStore(keyCertChain, key, keyPasswordChars, keyStore); -- if (ks.aliases().hasMoreElements()) { -- keyManagerFactory = new OpenSslX509KeyManagerFactory(); -- } else { -- keyManagerFactory = new OpenSslCachingX509KeyManagerFactory( -- KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())); -- } -- keyManagerFactory.init(ks, keyPasswordChars); -- keyMaterialProvider = providerFor(keyManagerFactory, keyPassword); -- } else if (keyManagerFactory != null) { -- keyMaterialProvider = providerFor(keyManagerFactory, keyPassword); -- } -- -- if (keyMaterialProvider != null) { -- OpenSslKeyMaterialManager materialManager = new OpenSslKeyMaterialManager(keyMaterialProvider); -- SSLContext.setCertificateCallback(ctx, new OpenSslClientCertificateCallback( -- engineMap, materialManager)); -- } -- } -- } catch (Exception e) { -- throw new SSLException("failed to set certificate and key", e); -- } -- -- // On the client side we always need to use SSL_CVERIFY_OPTIONAL (which will translate to SSL_VERIFY_PEER) -- // to ensure that when the TrustManager throws we will produce the correct alert back to the server. -- // -- // See: -- // - https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html -- // - https://github.com/netty/netty/issues/8942 -- SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_OPTIONAL, VERIFY_DEPTH); -- -- try { -- if (trustCertCollection != null) { -- trustManagerFactory = buildTrustManagerFactory(trustCertCollection, trustManagerFactory, keyStore); -- } else if (trustManagerFactory == null) { -- trustManagerFactory = TrustManagerFactory.getInstance( -- TrustManagerFactory.getDefaultAlgorithm()); -- trustManagerFactory.init((KeyStore) null); -- } -- final X509TrustManager manager = chooseTrustManager( -- trustManagerFactory.getTrustManagers(), resumptionController); -- -- // IMPORTANT: The callbacks set for verification must be static to prevent memory leak as -- // otherwise the context can never be collected. This is because the JNI code holds -- // a global reference to the callbacks. -- // -- // See https://github.com/netty/netty/issues/5372 -- -- setVerifyCallback(ctx, engineMap, manager); -- } catch (Exception e) { -- if (keyMaterialProvider != null) { -- keyMaterialProvider.destroy(); -- } -- throw new SSLException("unable to setup trustmanager", e); -- } -- OpenSslClientSessionContext context = new OpenSslClientSessionContext(thiz, keyMaterialProvider); -- context.setSessionCacheEnabled(CLIENT_ENABLE_SESSION_CACHE); -- if (sessionCacheSize > 0) { -- context.setSessionCacheSize((int) Math.min(sessionCacheSize, Integer.MAX_VALUE)); -- } -- if (sessionTimeout > 0) { -- context.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE)); -- } -- -- if (CLIENT_ENABLE_SESSION_TICKET) { -- context.setTicketKeys(); -- } -- -- keyMaterialProvider = null; -- return context; -- } finally { -- if (keyMaterialProvider != null) { -- keyMaterialProvider.destroy(); -- } -- } -- } -- -- @SuppressJava6Requirement(reason = "Guarded by java version check") -- private static void setVerifyCallback(long ctx, OpenSslEngineMap engineMap, X509TrustManager manager) { -- // Use this to prevent an error when running on java < 7 -- if (useExtendedTrustManager(manager)) { -- SSLContext.setCertVerifyCallback(ctx, -- new ExtendedTrustManagerVerifyCallback(engineMap, (X509ExtendedTrustManager) manager)); -- } else { -- SSLContext.setCertVerifyCallback(ctx, new TrustManagerVerifyCallback(engineMap, manager)); -- } -- } -- -- static final class OpenSslClientSessionContext extends OpenSslSessionContext { -- OpenSslClientSessionContext(ReferenceCountedOpenSslContext context, OpenSslKeyMaterialProvider provider) { -- super(context, provider, SSL.SSL_SESS_CACHE_CLIENT, new OpenSslClientSessionCache(context.engineMap)); -- } -- } -- -- private static final class TrustManagerVerifyCallback extends AbstractCertificateVerifier { -- private final X509TrustManager manager; -- -- TrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509TrustManager manager) { -- super(engineMap); -- this.manager = manager; -- } -- -- @Override -- void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth) -- throws Exception { -- manager.checkServerTrusted(peerCerts, auth); -- } -- } -- -- @SuppressJava6Requirement(reason = "Usage guarded by java version check") -- private static final class ExtendedTrustManagerVerifyCallback extends AbstractCertificateVerifier { -- private final X509ExtendedTrustManager manager; -- -- ExtendedTrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509ExtendedTrustManager manager) { -- super(engineMap); -- this.manager = manager; -- } -- -- @Override -- void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth) -- throws Exception { -- manager.checkServerTrusted(peerCerts, auth, engine); -- } -- } -- -- private static final class OpenSslClientCertificateCallback implements CertificateCallback { -- private final OpenSslEngineMap engineMap; -- private final OpenSslKeyMaterialManager keyManagerHolder; -- -- OpenSslClientCertificateCallback(OpenSslEngineMap engineMap, OpenSslKeyMaterialManager keyManagerHolder) { -- this.engineMap = engineMap; -- this.keyManagerHolder = keyManagerHolder; -- } -- -- @Override -- public void handle(long ssl, byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) throws Exception { -- final ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- // May be null if it was destroyed in the meantime. -- if (engine == null) { -- return; -- } -- try { -- final Set keyTypesSet = supportedClientKeyTypes(keyTypeBytes); -- final String[] keyTypes = keyTypesSet.toArray(EmptyArrays.EMPTY_STRINGS); -- final X500Principal[] issuers; -- if (asn1DerEncodedPrincipals == null) { -- issuers = null; -- } else { -- issuers = new X500Principal[asn1DerEncodedPrincipals.length]; -- for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { -- issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); -- } -- } -- keyManagerHolder.setKeyMaterialClientSide(engine, keyTypes, issuers); -- } catch (Throwable cause) { -- engine.initHandshakeException(cause); -- if (cause instanceof Exception) { -- throw (Exception) cause; -- } -- throw new SSLException(cause); -- } -- } -- -- /** -- * Gets the supported key types for client certificates. -- * -- * @param clientCertificateTypes {@code ClientCertificateType} values provided by the server. -- * See https://www.ietf.org/assignments/tls-parameters/tls-parameters.xml. -- * @return supported key types that can be used in {@code X509KeyManager.chooseClientAlias} and -- * {@code X509ExtendedKeyManager.chooseEngineClientAlias}. -- */ -- private static Set supportedClientKeyTypes(byte[] clientCertificateTypes) { -- if (clientCertificateTypes == null) { -- // Try all of the supported key types. -- return SUPPORTED_KEY_TYPES; -- } -- Set result = new HashSet(clientCertificateTypes.length); -- for (byte keyTypeCode : clientCertificateTypes) { -- String keyType = clientKeyType(keyTypeCode); -- if (keyType == null) { -- // Unsupported client key type -- ignore -- continue; -- } -- result.add(keyType); -- } -- return result; -- } -- -- private static String clientKeyType(byte clientCertificateType) { -- // See also https://www.ietf.org/assignments/tls-parameters/tls-parameters.xml -- switch (clientCertificateType) { -- case CertificateCallback.TLS_CT_RSA_SIGN: -- return OpenSslKeyMaterialManager.KEY_TYPE_RSA; // RFC rsa_sign -- case CertificateCallback.TLS_CT_RSA_FIXED_DH: -- return OpenSslKeyMaterialManager.KEY_TYPE_DH_RSA; // RFC rsa_fixed_dh -- case CertificateCallback.TLS_CT_ECDSA_SIGN: -- return OpenSslKeyMaterialManager.KEY_TYPE_EC; // RFC ecdsa_sign -- case CertificateCallback.TLS_CT_RSA_FIXED_ECDH: -- return OpenSslKeyMaterialManager.KEY_TYPE_EC_RSA; // RFC rsa_fixed_ecdh -- case CertificateCallback.TLS_CT_ECDSA_FIXED_ECDH: -- return OpenSslKeyMaterialManager.KEY_TYPE_EC_EC; // RFC ecdsa_fixed_ecdh -- default: -- return null; -- } -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java -deleted file mode 100644 -index 59c5cb0..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java -+++ /dev/null -@@ -1,1173 +0,0 @@ --/* -- * Copyright 2016 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: -- * -- * https://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.handler.ssl.util.LazyX509Certificate; --import io.netty.internal.tcnative.AsyncSSLPrivateKeyMethod; --import io.netty.internal.tcnative.CertificateCompressionAlgo; --import io.netty.internal.tcnative.CertificateVerifier; --import io.netty.internal.tcnative.ResultCallback; --import io.netty.internal.tcnative.SSL; --import io.netty.internal.tcnative.SSLContext; --import io.netty.internal.tcnative.SSLPrivateKeyMethod; --import io.netty.util.AbstractReferenceCounted; --import io.netty.util.ReferenceCounted; --import io.netty.util.ResourceLeakDetector; --import io.netty.util.ResourceLeakDetectorFactory; --import io.netty.util.ResourceLeakTracker; --import io.netty.util.concurrent.Future; --import io.netty.util.concurrent.FutureListener; --import io.netty.util.concurrent.ImmediateExecutor; --import io.netty.util.internal.EmptyArrays; --import io.netty.util.internal.PlatformDependent; --import io.netty.util.internal.StringUtil; --import io.netty.util.internal.SuppressJava6Requirement; --import io.netty.util.internal.SystemPropertyUtil; --import io.netty.util.internal.UnstableApi; --import io.netty.util.internal.logging.InternalLogger; --import io.netty.util.internal.logging.InternalLoggerFactory; -- --import java.security.PrivateKey; --import java.security.SignatureException; --import java.security.cert.CertPathValidatorException; --import java.security.cert.Certificate; --import java.security.cert.CertificateExpiredException; --import java.security.cert.CertificateNotYetValidException; --import java.security.cert.CertificateRevokedException; --import java.security.cert.X509Certificate; --import java.util.ArrayList; --import java.util.Collections; --import java.util.LinkedHashSet; --import java.util.List; --import java.util.Map; --import java.util.concurrent.Executor; --import java.util.concurrent.locks.Lock; --import java.util.concurrent.locks.ReadWriteLock; --import java.util.concurrent.locks.ReentrantReadWriteLock; -- --import javax.net.ssl.KeyManager; --import javax.net.ssl.KeyManagerFactory; --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.X509KeyManager; --import javax.net.ssl.X509TrustManager; -- --import static io.netty.handler.ssl.OpenSsl.DEFAULT_CIPHERS; --import static io.netty.handler.ssl.OpenSsl.availableJavaCipherSuites; --import static io.netty.util.internal.ObjectUtil.checkNotNull; --import static io.netty.util.internal.ObjectUtil.checkNonEmpty; --import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; -- --/** -- * An implementation of {@link SslContext} which works with libraries that support the -- * OpenSsl C library API. -- *

Instances of this class must be {@link #release() released} or else native memory will leak! -- * -- *

Instances of this class must not be released before any {@link ReferenceCountedOpenSslEngine} -- * which depends upon the instance of this class is released. Otherwise if any method of -- * {@link ReferenceCountedOpenSslEngine} is called which uses this class's JNI resources the JVM may crash. -- */ --public abstract class ReferenceCountedOpenSslContext extends SslContext implements ReferenceCounted { -- private static final InternalLogger logger = -- InternalLoggerFactory.getInstance(ReferenceCountedOpenSslContext.class); -- -- private static final int DEFAULT_BIO_NON_APPLICATION_BUFFER_SIZE = Math.max(1, -- SystemPropertyUtil.getInt("io.netty.handler.ssl.openssl.bioNonApplicationBufferSize", -- 2048)); -- // Let's use tasks by default but still allow the user to disable it via system property just in case. -- static final boolean USE_TASKS = -- SystemPropertyUtil.getBoolean("io.netty.handler.ssl.openssl.useTasks", true); -- private static final Integer DH_KEY_LENGTH; -- private static final ResourceLeakDetector leakDetector = -- ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslContext.class); -- -- // TODO: Maybe make configurable ? -- protected static final int VERIFY_DEPTH = 10; -- -- static final boolean CLIENT_ENABLE_SESSION_TICKET = -- SystemPropertyUtil.getBoolean("jdk.tls.client.enableSessionTicketExtension", false); -- -- static final boolean CLIENT_ENABLE_SESSION_TICKET_TLSV13 = -- SystemPropertyUtil.getBoolean("jdk.tls.client.enableSessionTicketExtension", true); -- -- static final boolean SERVER_ENABLE_SESSION_TICKET = -- SystemPropertyUtil.getBoolean("jdk.tls.server.enableSessionTicketExtension", false); -- -- static final boolean SERVER_ENABLE_SESSION_TICKET_TLSV13 = -- SystemPropertyUtil.getBoolean("jdk.tls.server.enableSessionTicketExtension", true); -- -- static final boolean SERVER_ENABLE_SESSION_CACHE = -- SystemPropertyUtil.getBoolean("io.netty.handler.ssl.openssl.sessionCacheServer", true); -- static final boolean CLIENT_ENABLE_SESSION_CACHE = -- SystemPropertyUtil.getBoolean("io.netty.handler.ssl.openssl.sessionCacheClient", true); -- -- /** -- * The OpenSSL SSL_CTX object. -- * -- * {@link #ctxLock} must be hold while using ctx! -- */ -- protected long ctx; -- private final List unmodifiableCiphers; -- private final OpenSslApplicationProtocolNegotiator apn; -- private final int mode; -- -- // Reference Counting -- private final ResourceLeakTracker leak; -- private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() { -- @Override -- public ReferenceCounted touch(Object hint) { -- if (leak != null) { -- leak.record(hint); -- } -- -- return ReferenceCountedOpenSslContext.this; -- } -- -- @Override -- protected void deallocate() { -- destroy(); -- if (leak != null) { -- boolean closed = leak.close(ReferenceCountedOpenSslContext.this); -- assert closed; -- } -- } -- }; -- -- final Certificate[] keyCertChain; -- final ClientAuth clientAuth; -- final String[] protocols; -- final String endpointIdentificationAlgorithm; -- final boolean hasTLSv13Cipher; -- -- final boolean enableOcsp; -- final OpenSslEngineMap engineMap = new DefaultOpenSslEngineMap(); -- final ReadWriteLock ctxLock = new ReentrantReadWriteLock(); -- -- private volatile int bioNonApplicationBufferSize = DEFAULT_BIO_NON_APPLICATION_BUFFER_SIZE; -- -- @SuppressWarnings("deprecation") -- 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 ApplicationProtocolConfig.SelectorFailureBehavior selectorFailureBehavior() { -- return ApplicationProtocolConfig.SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL; -- } -- -- @Override -- public ApplicationProtocolConfig.SelectedListenerFailureBehavior selectedListenerFailureBehavior() { -- return ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT; -- } -- }; -- -- static { -- Integer dhLen = null; -- -- try { -- String dhKeySize = SystemPropertyUtil.get("jdk.tls.ephemeralDHKeySize"); -- if (dhKeySize != null) { -- try { -- dhLen = Integer.valueOf(dhKeySize); -- } catch (NumberFormatException e) { -- logger.debug("ReferenceCountedOpenSslContext supports -Djdk.tls.ephemeralDHKeySize={int}, but got: " -- + dhKeySize); -- } -- } -- } catch (Throwable ignore) { -- // ignore -- } -- DH_KEY_LENGTH = dhLen; -- } -- -- final boolean tlsFalseStart; -- -- ReferenceCountedOpenSslContext(Iterable ciphers, CipherSuiteFilter cipherFilter, -- OpenSslApplicationProtocolNegotiator apn, int mode, Certificate[] keyCertChain, -- ClientAuth clientAuth, String[] protocols, boolean startTls, -- String endpointIdentificationAlgorithm, boolean enableOcsp, -- boolean leakDetection, ResumptionController resumptionController, -- Map.Entry, Object>... ctxOptions) -- throws SSLException { -- super(startTls, resumptionController); -- -- OpenSsl.ensureAvailability(); -- -- if (enableOcsp && !OpenSsl.isOcspSupported()) { -- throw new IllegalStateException("OCSP is not supported."); -- } -- -- 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"); -- } -- -- boolean tlsFalseStart = false; -- boolean useTasks = USE_TASKS; -- OpenSslPrivateKeyMethod privateKeyMethod = null; -- OpenSslAsyncPrivateKeyMethod asyncPrivateKeyMethod = null; -- OpenSslCertificateCompressionConfig certCompressionConfig = null; -- Integer maxCertificateList = null; -- -- if (ctxOptions != null) { -- for (Map.Entry, Object> ctxOpt : ctxOptions) { -- SslContextOption option = ctxOpt.getKey(); -- -- if (option == OpenSslContextOption.TLS_FALSE_START) { -- tlsFalseStart = (Boolean) ctxOpt.getValue(); -- } else if (option == OpenSslContextOption.USE_TASKS) { -- useTasks = (Boolean) ctxOpt.getValue(); -- } else if (option == OpenSslContextOption.PRIVATE_KEY_METHOD) { -- privateKeyMethod = (OpenSslPrivateKeyMethod) ctxOpt.getValue(); -- } else if (option == OpenSslContextOption.ASYNC_PRIVATE_KEY_METHOD) { -- asyncPrivateKeyMethod = (OpenSslAsyncPrivateKeyMethod) ctxOpt.getValue(); -- } else if (option == OpenSslContextOption.CERTIFICATE_COMPRESSION_ALGORITHMS) { -- certCompressionConfig = (OpenSslCertificateCompressionConfig) ctxOpt.getValue(); -- } else if (option == OpenSslContextOption.MAX_CERTIFICATE_LIST_BYTES) { -- maxCertificateList = (Integer) ctxOpt.getValue(); -- } else { -- logger.debug("Skipping unsupported " + SslContextOption.class.getSimpleName() -- + ": " + ctxOpt.getKey()); -- } -- } -- } -- if (privateKeyMethod != null && asyncPrivateKeyMethod != null) { -- throw new IllegalArgumentException("You can either only use " -- + OpenSslAsyncPrivateKeyMethod.class.getSimpleName() + " or " -- + OpenSslPrivateKeyMethod.class.getSimpleName()); -- } -- -- this.tlsFalseStart = tlsFalseStart; -- -- leak = leakDetection ? leakDetector.track(this) : null; -- this.mode = mode; -- this.clientAuth = isServer() ? checkNotNull(clientAuth, "clientAuth") : ClientAuth.NONE; -- this.protocols = protocols == null ? OpenSsl.defaultProtocols(mode == SSL.SSL_MODE_CLIENT) : protocols; -- this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; -- this.enableOcsp = enableOcsp; -- -- this.keyCertChain = keyCertChain == null ? null : keyCertChain.clone(); -- -- String[] suites = checkNotNull(cipherFilter, "cipherFilter").filterCipherSuites( -- ciphers, DEFAULT_CIPHERS, availableJavaCipherSuites()); -- // Filter out duplicates. -- LinkedHashSet suitesSet = new LinkedHashSet(suites.length); -- Collections.addAll(suitesSet, suites); -- unmodifiableCiphers = new ArrayList(suitesSet); -- -- this.apn = checkNotNull(apn, "apn"); -- -- // Create a new SSL_CTX and configure it. -- boolean success = false; -- try { -- boolean tlsv13Supported = OpenSsl.isTlsv13Supported(); -- boolean anyTlsv13Ciphers = false; -- try { -- int protocolOpts = SSL.SSL_PROTOCOL_SSLV3 | SSL.SSL_PROTOCOL_TLSV1 | -- SSL.SSL_PROTOCOL_TLSV1_1 | SSL.SSL_PROTOCOL_TLSV1_2; -- if (tlsv13Supported) { -- protocolOpts |= SSL.SSL_PROTOCOL_TLSV1_3; -- } -- ctx = SSLContext.make(protocolOpts, mode); -- } catch (Exception e) { -- throw new SSLException("failed to create an SSL_CTX", e); -- } -- -- StringBuilder cipherBuilder = new StringBuilder(); -- StringBuilder cipherTLSv13Builder = new StringBuilder(); -- -- /* List the ciphers that are permitted to negotiate. */ -- try { -- if (unmodifiableCiphers.isEmpty()) { -- // Set non TLSv1.3 ciphers. -- SSLContext.setCipherSuite(ctx, StringUtil.EMPTY_STRING, false); -- if (tlsv13Supported) { -- // Set TLSv1.3 ciphers. -- SSLContext.setCipherSuite(ctx, StringUtil.EMPTY_STRING, true); -- } -- } else { -- CipherSuiteConverter.convertToCipherStrings( -- unmodifiableCiphers, cipherBuilder, cipherTLSv13Builder, OpenSsl.isBoringSSL()); -- -- // Set non TLSv1.3 ciphers. -- SSLContext.setCipherSuite(ctx, cipherBuilder.toString(), false); -- if (tlsv13Supported) { -- // Set TLSv1.3 ciphers. -- String tlsv13Ciphers = OpenSsl.checkTls13Ciphers(logger, cipherTLSv13Builder.toString()); -- SSLContext.setCipherSuite(ctx, tlsv13Ciphers, true); -- if (!tlsv13Ciphers.isEmpty()) { -- anyTlsv13Ciphers = true; -- } -- } -- } -- } catch (SSLException e) { -- throw e; -- } catch (Exception e) { -- throw new SSLException("failed to set cipher suite: " + unmodifiableCiphers, e); -- } -- -- int options = SSLContext.getOptions(ctx) | -- SSL.SSL_OP_NO_SSLv2 | -- SSL.SSL_OP_NO_SSLv3 | -- // Disable TLSv1 and TLSv1.1 by default as these are not considered secure anymore -- // and the JDK is doing the same: -- // https://www.oracle.com/java/technologies/javase/8u291-relnotes.html -- SSL.SSL_OP_NO_TLSv1 | -- SSL.SSL_OP_NO_TLSv1_1 | -- -- SSL.SSL_OP_CIPHER_SERVER_PREFERENCE | -- -- // We do not support compression at the moment so we should explicitly disable it. -- SSL.SSL_OP_NO_COMPRESSION | -- -- // Disable ticket support by default to be more inline with SSLEngineImpl of the JDK. -- // This also let SSLSession.getId() work the same way for the JDK implementation and the -- // OpenSSLEngine. If tickets are supported SSLSession.getId() will only return an ID on the -- // server-side if it could make use of tickets. -- SSL.SSL_OP_NO_TICKET; -- -- if (cipherBuilder.length() == 0) { -- // No ciphers that are compatible with SSLv2 / SSLv3 / TLSv1 / TLSv1.1 / TLSv1.2 -- options |= SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 -- | SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2; -- } -- -- if (!tlsv13Supported) { -- // Explicit disable TLSv1.3 -- // See: -- // - https://github.com/netty/netty/issues/12968 -- options |= SSL.SSL_OP_NO_TLSv1_3; -- } -- -- hasTLSv13Cipher = anyTlsv13Ciphers; -- SSLContext.setOptions(ctx, options); -- -- // We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change between -- // calling OpenSSLEngine.wrap(...). -- // See https://github.com/netty/netty-tcnative/issues/100 -- SSLContext.setMode(ctx, SSLContext.getMode(ctx) | SSL.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); -- -- if (DH_KEY_LENGTH != null) { -- SSLContext.setTmpDHLength(ctx, DH_KEY_LENGTH); -- } -- -- List nextProtoList = apn.protocols(); -- /* Set next protocols for next protocol negotiation extension, if specified */ -- if (!nextProtoList.isEmpty()) { -- String[] appProtocols = nextProtoList.toArray(EmptyArrays.EMPTY_STRINGS); -- int selectorBehavior = opensslSelectorFailureBehavior(apn.selectorFailureBehavior()); -- -- switch (apn.protocol()) { -- case NPN: -- SSLContext.setNpnProtos(ctx, appProtocols, selectorBehavior); -- break; -- case ALPN: -- SSLContext.setAlpnProtos(ctx, appProtocols, selectorBehavior); -- break; -- case NPN_AND_ALPN: -- SSLContext.setNpnProtos(ctx, appProtocols, selectorBehavior); -- SSLContext.setAlpnProtos(ctx, appProtocols, selectorBehavior); -- break; -- default: -- throw new Error(); -- } -- } -- -- if (enableOcsp) { -- SSLContext.enableOcsp(ctx, isClient()); -- } -- -- SSLContext.setUseTasks(ctx, useTasks); -- if (privateKeyMethod != null) { -- SSLContext.setPrivateKeyMethod(ctx, new PrivateKeyMethod(engineMap, privateKeyMethod)); -- } -- if (asyncPrivateKeyMethod != null) { -- SSLContext.setPrivateKeyMethod(ctx, new AsyncPrivateKeyMethod(engineMap, asyncPrivateKeyMethod)); -- } -- if (certCompressionConfig != null) { -- for (OpenSslCertificateCompressionConfig.AlgorithmConfig configPair : certCompressionConfig) { -- final CertificateCompressionAlgo algo = new CompressionAlgorithm(engineMap, configPair.algorithm()); -- switch (configPair.mode()) { -- case Decompress: -- SSLContext.addCertificateCompressionAlgorithm( -- ctx, SSL.SSL_CERT_COMPRESSION_DIRECTION_DECOMPRESS, algo); -- break; -- case Compress: -- SSLContext.addCertificateCompressionAlgorithm( -- ctx, SSL.SSL_CERT_COMPRESSION_DIRECTION_COMPRESS, algo); -- break; -- case Both: -- SSLContext.addCertificateCompressionAlgorithm( -- ctx, SSL.SSL_CERT_COMPRESSION_DIRECTION_BOTH, algo); -- break; -- default: -- throw new IllegalStateException(); -- } -- } -- } -- if (maxCertificateList != null) { -- SSLContext.setMaxCertList(ctx, maxCertificateList); -- } -- // Set the curves. -- SSLContext.setCurvesList(ctx, OpenSsl.NAMED_GROUPS); -- success = true; -- } finally { -- if (!success) { -- release(); -- } -- } -- } -- -- private static int opensslSelectorFailureBehavior(ApplicationProtocolConfig.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 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) { -- return newEngine0(alloc, peerHost, peerPort, true); -- } -- -- @Override -- protected final SslHandler newHandler(ByteBufAllocator alloc, boolean startTls) { -- return new SslHandler(newEngine0(alloc, null, -1, false), startTls, ImmediateExecutor.INSTANCE, -- resumptionController); -- } -- -- @Override -- protected final SslHandler newHandler(ByteBufAllocator alloc, String peerHost, int peerPort, boolean startTls) { -- return new SslHandler(newEngine0(alloc, peerHost, peerPort, false), startTls, ImmediateExecutor.INSTANCE, -- resumptionController); -- } -- -- @Override -- protected SslHandler newHandler(ByteBufAllocator alloc, boolean startTls, Executor executor) { -- return new SslHandler(newEngine0(alloc, null, -1, false), startTls, executor, resumptionController); -- } -- -- @Override -- protected SslHandler newHandler(ByteBufAllocator alloc, String peerHost, int peerPort, -- boolean startTls, Executor executor) { -- return new SslHandler(newEngine0(alloc, peerHost, peerPort, false), false, executor, resumptionController); -- } -- -- SSLEngine newEngine0(ByteBufAllocator alloc, String peerHost, int peerPort, boolean jdkCompatibilityMode) { -- return new ReferenceCountedOpenSslEngine(this, alloc, peerHost, peerPort, jdkCompatibilityMode, true, -- endpointIdentificationAlgorithm); -- } -- -- /** -- * Returns a new server-side {@link SSLEngine} with the current configuration. -- */ -- @Override -- public final SSLEngine newEngine(ByteBufAllocator alloc) { -- return newEngine(alloc, null, -1); -- } -- -- /** -- * Returns the pointer to the {@code SSL_CTX} object for this {@link ReferenceCountedOpenSslContext}. -- * Be aware that it is freed as soon as the {@link #finalize()} method is called. -- * At this point {@code 0} will be returned. -- * -- * @deprecated this method is considered unsafe as the returned pointer may be released later. Dont use it! -- */ -- @Deprecated -- public final long context() { -- return sslCtxPointer(); -- } -- -- /** -- * Returns the stats of this context. -- * -- * @deprecated use {@link #sessionContext#stats()} -- */ -- @Deprecated -- public final OpenSslSessionStats stats() { -- return sessionContext().stats(); -- } -- -- /** -- * {@deprecated Renegotiation is not supported} -- * 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. -- */ -- @Deprecated -- public void setRejectRemoteInitiatedRenegotiation(boolean rejectRemoteInitiatedRenegotiation) { -- if (!rejectRemoteInitiatedRenegotiation) { -- throw new UnsupportedOperationException("Renegotiation is not supported"); -- } -- } -- -- /** -- * {@deprecated Renegotiation is not supported} -- * @return {@code true} because renegotiation is not supported. -- */ -- @Deprecated -- public boolean getRejectRemoteInitiatedRenegotiation() { -- return true; -- } -- -- /** -- * Set the size of the buffer used by the BIO for non-application based writes -- * (e.g. handshake, renegotiation, etc...). -- */ -- public void setBioNonApplicationBufferSize(int bioNonApplicationBufferSize) { -- this.bioNonApplicationBufferSize = -- checkPositiveOrZero(bioNonApplicationBufferSize, "bioNonApplicationBufferSize"); -- } -- -- /** -- * Returns the size of the buffer used by the BIO for non-application based writes -- */ -- public int getBioNonApplicationBufferSize() { -- return bioNonApplicationBufferSize; -- } -- -- /** -- * 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(); -- -- /** -- * Returns the pointer to the {@code SSL_CTX} object for this {@link ReferenceCountedOpenSslContext}. -- * Be aware that it is freed as soon as the {@link #release()} method is called. -- * At this point {@code 0} will be returned. -- * -- * @deprecated this method is considered unsafe as the returned pointer may be released later. Dont use it! -- */ -- @Deprecated -- public final long sslCtxPointer() { -- Lock readerLock = ctxLock.readLock(); -- readerLock.lock(); -- try { -- return SSLContext.getSslCtx(ctx); -- } finally { -- readerLock.unlock(); -- } -- } -- -- /** -- * Set the {@link OpenSslPrivateKeyMethod} to use. This allows to offload private-key operations -- * if needed. -- * -- * This method is currently only supported when {@code BoringSSL} is used. -- * -- * @param method method to use. -- * @deprecated use {@link SslContextBuilder#option(SslContextOption, Object)} with -- * {@link OpenSslContextOption#PRIVATE_KEY_METHOD}. -- */ -- @Deprecated -- @UnstableApi -- public final void setPrivateKeyMethod(OpenSslPrivateKeyMethod method) { -- checkNotNull(method, "method"); -- Lock writerLock = ctxLock.writeLock(); -- writerLock.lock(); -- try { -- SSLContext.setPrivateKeyMethod(ctx, new PrivateKeyMethod(engineMap, method)); -- } finally { -- writerLock.unlock(); -- } -- } -- -- /** -- * @deprecated use {@link SslContextBuilder#option(SslContextOption, Object)} with -- * {@link OpenSslContextOption#USE_TASKS}. -- */ -- @Deprecated -- public final void setUseTasks(boolean useTasks) { -- Lock writerLock = ctxLock.writeLock(); -- writerLock.lock(); -- try { -- SSLContext.setUseTasks(ctx, useTasks); -- } finally { -- writerLock.unlock(); -- } -- } -- -- // IMPORTANT: This method must only be called from either the constructor or the finalizer as a user MUST never -- // get access to an OpenSslSessionContext after this method was called to prevent the user from -- // producing a segfault. -- private void destroy() { -- Lock writerLock = ctxLock.writeLock(); -- writerLock.lock(); -- try { -- if (ctx != 0) { -- if (enableOcsp) { -- SSLContext.disableOcsp(ctx); -- } -- -- SSLContext.free(ctx); -- ctx = 0; -- -- OpenSslSessionContext context = sessionContext(); -- if (context != null) { -- context.destroy(); -- } -- } -- } finally { -- writerLock.unlock(); -- } -- } -- -- protected static X509Certificate[] certificates(byte[][] chain) { -- X509Certificate[] peerCerts = new X509Certificate[chain.length]; -- for (int i = 0; i < peerCerts.length; i++) { -- peerCerts[i] = new LazyX509Certificate(chain[i]); -- } -- return peerCerts; -- } -- -- /** -- * @deprecated This method is kept for API backwards compatibility. -- */ -- @Deprecated -- protected static X509TrustManager chooseTrustManager(TrustManager[] managers) { -- return chooseTrustManager(managers, null); -- } -- -- static X509TrustManager chooseTrustManager(TrustManager[] managers, -- ResumptionController resumptionController) { -- for (TrustManager m : managers) { -- if (m instanceof X509TrustManager) { -- X509TrustManager tm = (X509TrustManager) m; -- if (PlatformDependent.javaVersion() >= 7) { -- if (resumptionController != null) { -- tm = (X509TrustManager) resumptionController.wrapIfNeeded(tm); -- } -- tm = OpenSslX509TrustManagerWrapper.wrapIfNeeded(tm); -- if (useExtendedTrustManager(tm)) { -- // Wrap the TrustManager to provide a better exception message for users to debug hostname -- // validation failures. -- tm = new EnhancingX509ExtendedTrustManager(tm); -- } -- } -- return tm; -- } -- } -- throw new IllegalStateException("no X509TrustManager found"); -- } -- -- protected static X509KeyManager chooseX509KeyManager(KeyManager[] kms) { -- for (KeyManager km : kms) { -- if (km instanceof X509KeyManager) { -- return (X509KeyManager) km; -- } -- } -- throw new IllegalStateException("no X509KeyManager 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 -- */ -- @SuppressWarnings("deprecation") -- 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(); -- } -- } -- -- @SuppressJava6Requirement(reason = "Guarded by java version check") -- static boolean useExtendedTrustManager(X509TrustManager trustManager) { -- return PlatformDependent.javaVersion() >= 7 && trustManager instanceof X509ExtendedTrustManager; -- } -- -- @Override -- public final int refCnt() { -- return refCnt.refCnt(); -- } -- -- @Override -- public final ReferenceCounted retain() { -- refCnt.retain(); -- return this; -- } -- -- @Override -- public final ReferenceCounted retain(int increment) { -- refCnt.retain(increment); -- return this; -- } -- -- @Override -- public final ReferenceCounted touch() { -- refCnt.touch(); -- return this; -- } -- -- @Override -- public final ReferenceCounted touch(Object hint) { -- refCnt.touch(hint); -- return this; -- } -- -- @Override -- public final boolean release() { -- return refCnt.release(); -- } -- -- @Override -- public final boolean release(int decrement) { -- return refCnt.release(decrement); -- } -- -- abstract static class AbstractCertificateVerifier extends CertificateVerifier { -- private final OpenSslEngineMap engineMap; -- -- AbstractCertificateVerifier(OpenSslEngineMap engineMap) { -- this.engineMap = engineMap; -- } -- -- @Override -- public final int verify(long ssl, byte[][] chain, String auth) { -- final ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- if (engine == null) { -- // May be null if it was destroyed in the meantime. -- return CertificateVerifier.X509_V_ERR_UNSPECIFIED; -- } -- X509Certificate[] peerCerts = certificates(chain); -- try { -- verify(engine, peerCerts, auth); -- return CertificateVerifier.X509_V_OK; -- } catch (Throwable cause) { -- logger.debug("verification of certificate failed", cause); -- engine.initHandshakeException(cause); -- -- // Try to extract the correct error code that should be used. -- if (cause instanceof OpenSslCertificateException) { -- // This will never return a negative error code as its validated when constructing the -- // OpenSslCertificateException. -- return ((OpenSslCertificateException) cause).errorCode(); -- } -- if (cause instanceof CertificateExpiredException) { -- return CertificateVerifier.X509_V_ERR_CERT_HAS_EXPIRED; -- } -- if (cause instanceof CertificateNotYetValidException) { -- return CertificateVerifier.X509_V_ERR_CERT_NOT_YET_VALID; -- } -- if (PlatformDependent.javaVersion() >= 7) { -- return translateToError(cause); -- } -- -- // Could not detect a specific error code to use, so fallback to a default code. -- return CertificateVerifier.X509_V_ERR_UNSPECIFIED; -- } -- } -- -- @SuppressJava6Requirement(reason = "Usage guarded by java version check") -- private static int translateToError(Throwable cause) { -- if (cause instanceof CertificateRevokedException) { -- return CertificateVerifier.X509_V_ERR_CERT_REVOKED; -- } -- -- // The X509TrustManagerImpl uses a Validator which wraps a CertPathValidatorException into -- // an CertificateException. So we need to handle the wrapped CertPathValidatorException to be -- // able to send the correct alert. -- Throwable wrapped = cause.getCause(); -- while (wrapped != null) { -- if (wrapped instanceof CertPathValidatorException) { -- CertPathValidatorException ex = (CertPathValidatorException) wrapped; -- CertPathValidatorException.Reason reason = ex.getReason(); -- if (reason == CertPathValidatorException.BasicReason.EXPIRED) { -- return CertificateVerifier.X509_V_ERR_CERT_HAS_EXPIRED; -- } -- if (reason == CertPathValidatorException.BasicReason.NOT_YET_VALID) { -- return CertificateVerifier.X509_V_ERR_CERT_NOT_YET_VALID; -- } -- if (reason == CertPathValidatorException.BasicReason.REVOKED) { -- return CertificateVerifier.X509_V_ERR_CERT_REVOKED; -- } -- } -- wrapped = wrapped.getCause(); -- } -- return CertificateVerifier.X509_V_ERR_UNSPECIFIED; -- } -- -- abstract void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, -- String auth) throws Exception; -- } -- -- private static final class DefaultOpenSslEngineMap implements OpenSslEngineMap { -- private final Map engines = PlatformDependent.newConcurrentHashMap(); -- -- @Override -- public ReferenceCountedOpenSslEngine remove(long ssl) { -- return engines.remove(ssl); -- } -- -- @Override -- public void add(ReferenceCountedOpenSslEngine engine) { -- engines.put(engine.sslPointer(), engine); -- } -- -- @Override -- public ReferenceCountedOpenSslEngine get(long ssl) { -- return engines.get(ssl); -- } -- } -- -- static void setKeyMaterial(long ctx, X509Certificate[] keyCertChain, PrivateKey key, String keyPassword) -- throws SSLException { -- /* Load the certificate file and private key. */ -- long keyBio = 0; -- long keyCertChainBio = 0; -- long keyCertChainBio2 = 0; -- PemEncoded encoded = null; -- try { -- // Only encode one time -- encoded = PemX509Certificate.toPEM(ByteBufAllocator.DEFAULT, true, keyCertChain); -- keyCertChainBio = toBIO(ByteBufAllocator.DEFAULT, encoded.retain()); -- keyCertChainBio2 = toBIO(ByteBufAllocator.DEFAULT, encoded.retain()); -- -- if (key != null) { -- keyBio = toBIO(ByteBufAllocator.DEFAULT, key); -- } -- -- SSLContext.setCertificateBio( -- ctx, keyCertChainBio, keyBio, -- keyPassword == null ? StringUtil.EMPTY_STRING : keyPassword); -- // We may have more then one cert in the chain so add all of them now. -- SSLContext.setCertificateChainBio(ctx, keyCertChainBio2, true); -- } catch (SSLException e) { -- throw e; -- } catch (Exception e) { -- throw new SSLException("failed to set certificate and key", e); -- } finally { -- freeBio(keyBio); -- freeBio(keyCertChainBio); -- freeBio(keyCertChainBio2); -- if (encoded != null) { -- encoded.release(); -- } -- } -- } -- -- static void freeBio(long bio) { -- if (bio != 0) { -- SSL.freeBIO(bio); -- } -- } -- -- /** -- * Return the pointer to a in-memory BIO -- * or {@code 0} if the {@code key} is {@code null}. The BIO contains the content of the {@code key}. -- */ -- static long toBIO(ByteBufAllocator allocator, PrivateKey key) throws Exception { -- if (key == null) { -- return 0; -- } -- -- PemEncoded pem = PemPrivateKey.toPEM(allocator, true, key); -- try { -- return toBIO(allocator, pem.retain()); -- } finally { -- pem.release(); -- } -- } -- -- /** -- * Return the pointer to a in-memory BIO -- * or {@code 0} if the {@code certChain} is {@code null}. The BIO contains the content of the {@code certChain}. -- */ -- static long toBIO(ByteBufAllocator allocator, X509Certificate... certChain) throws Exception { -- if (certChain == null) { -- return 0; -- } -- -- checkNonEmpty(certChain, "certChain"); -- -- PemEncoded pem = PemX509Certificate.toPEM(allocator, true, certChain); -- try { -- return toBIO(allocator, pem.retain()); -- } finally { -- pem.release(); -- } -- } -- -- static long toBIO(ByteBufAllocator allocator, PemEncoded pem) throws Exception { -- try { -- // We can turn direct buffers straight into BIOs. No need to -- // make a yet another copy. -- ByteBuf content = pem.content(); -- -- if (content.isDirect()) { -- return newBIO(content.retainedSlice()); -- } -- -- ByteBuf buffer = allocator.directBuffer(content.readableBytes()); -- try { -- buffer.writeBytes(content, content.readerIndex(), content.readableBytes()); -- return newBIO(buffer.retainedSlice()); -- } finally { -- try { -- // If the contents of the ByteBuf is sensitive (e.g. a PrivateKey) we -- // need to zero out the bytes of the copy before we're releasing it. -- if (pem.isSensitive()) { -- SslUtils.zeroout(buffer); -- } -- } finally { -- buffer.release(); -- } -- } -- } finally { -- pem.release(); -- } -- } -- -- private static long newBIO(ByteBuf buffer) throws Exception { -- try { -- long bio = SSL.newMemBIO(); -- int readable = buffer.readableBytes(); -- if (SSL.bioWrite(bio, OpenSsl.memoryAddress(buffer) + buffer.readerIndex(), readable) != readable) { -- SSL.freeBIO(bio); -- throw new IllegalStateException("Could not write data to memory BIO"); -- } -- return bio; -- } finally { -- buffer.release(); -- } -- } -- -- /** -- * Returns the {@link OpenSslKeyMaterialProvider} that should be used for OpenSSL. Depending on the given -- * {@link KeyManagerFactory} this may cache the {@link OpenSslKeyMaterial} for better performance if it can -- * ensure that the same material is always returned for the same alias. -- */ -- static OpenSslKeyMaterialProvider providerFor(KeyManagerFactory factory, String password) { -- if (factory instanceof OpenSslX509KeyManagerFactory) { -- return ((OpenSslX509KeyManagerFactory) factory).newProvider(); -- } -- -- if (factory instanceof OpenSslCachingX509KeyManagerFactory) { -- // The user explicit used OpenSslCachingX509KeyManagerFactory which signals us that its fine to cache. -- return ((OpenSslCachingX509KeyManagerFactory) factory).newProvider(password); -- } -- // We can not be sure if the material may change at runtime so we will not cache it. -- return new OpenSslKeyMaterialProvider(chooseX509KeyManager(factory.getKeyManagers()), password); -- } -- -- private static ReferenceCountedOpenSslEngine retrieveEngine(OpenSslEngineMap engineMap, long ssl) -- throws SSLException { -- ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- if (engine == null) { -- throw new SSLException("Could not find a " + -- StringUtil.simpleClassName(ReferenceCountedOpenSslEngine.class) + " for sslPointer " + ssl); -- } -- return engine; -- } -- -- private static final class PrivateKeyMethod implements SSLPrivateKeyMethod { -- -- private final OpenSslEngineMap engineMap; -- private final OpenSslPrivateKeyMethod keyMethod; -- PrivateKeyMethod(OpenSslEngineMap engineMap, OpenSslPrivateKeyMethod keyMethod) { -- this.engineMap = engineMap; -- this.keyMethod = keyMethod; -- } -- -- @Override -- public byte[] sign(long ssl, int signatureAlgorithm, byte[] digest) throws Exception { -- ReferenceCountedOpenSslEngine engine = retrieveEngine(engineMap, ssl); -- try { -- return verifyResult(keyMethod.sign(engine, signatureAlgorithm, digest)); -- } catch (Exception e) { -- engine.initHandshakeException(e); -- throw e; -- } -- } -- -- @Override -- public byte[] decrypt(long ssl, byte[] input) throws Exception { -- ReferenceCountedOpenSslEngine engine = retrieveEngine(engineMap, ssl); -- try { -- return verifyResult(keyMethod.decrypt(engine, input)); -- } catch (Exception e) { -- engine.initHandshakeException(e); -- throw e; -- } -- } -- } -- -- private static final class AsyncPrivateKeyMethod implements AsyncSSLPrivateKeyMethod { -- -- private final OpenSslEngineMap engineMap; -- private final OpenSslAsyncPrivateKeyMethod keyMethod; -- -- AsyncPrivateKeyMethod(OpenSslEngineMap engineMap, OpenSslAsyncPrivateKeyMethod keyMethod) { -- this.engineMap = engineMap; -- this.keyMethod = keyMethod; -- } -- -- @Override -- public void sign(long ssl, int signatureAlgorithm, byte[] bytes, ResultCallback resultCallback) { -- try { -- ReferenceCountedOpenSslEngine engine = retrieveEngine(engineMap, ssl); -- keyMethod.sign(engine, signatureAlgorithm, bytes) -- .addListener(new ResultCallbackListener(engine, ssl, resultCallback)); -- } catch (SSLException e) { -- resultCallback.onError(ssl, e); -- } -- } -- -- @Override -- public void decrypt(long ssl, byte[] bytes, ResultCallback resultCallback) { -- try { -- ReferenceCountedOpenSslEngine engine = retrieveEngine(engineMap, ssl); -- keyMethod.decrypt(engine, bytes) -- .addListener(new ResultCallbackListener(engine, ssl, resultCallback)); -- } catch (SSLException e) { -- resultCallback.onError(ssl, e); -- } -- } -- -- private static final class ResultCallbackListener implements FutureListener { -- private final ReferenceCountedOpenSslEngine engine; -- private final long ssl; -- private final ResultCallback resultCallback; -- -- ResultCallbackListener(ReferenceCountedOpenSslEngine engine, long ssl, -- ResultCallback resultCallback) { -- this.engine = engine; -- this.ssl = ssl; -- this.resultCallback = resultCallback; -- } -- -- @Override -- public void operationComplete(Future future) { -- Throwable cause = future.cause(); -- if (cause == null) { -- try { -- byte[] result = verifyResult(future.getNow()); -- resultCallback.onSuccess(ssl, result); -- return; -- } catch (SignatureException e) { -- cause = e; -- engine.initHandshakeException(e); -- } -- } -- resultCallback.onError(ssl, cause); -- } -- } -- } -- -- private static byte[] verifyResult(byte[] result) throws SignatureException { -- if (result == null) { -- throw new SignatureException(); -- } -- return result; -- } -- -- private static final class CompressionAlgorithm implements CertificateCompressionAlgo { -- private final OpenSslEngineMap engineMap; -- private final OpenSslCertificateCompressionAlgorithm compressionAlgorithm; -- -- CompressionAlgorithm(OpenSslEngineMap engineMap, OpenSslCertificateCompressionAlgorithm compressionAlgorithm) { -- this.engineMap = engineMap; -- this.compressionAlgorithm = compressionAlgorithm; -- } -- -- @Override -- public byte[] compress(long ssl, byte[] bytes) throws Exception { -- ReferenceCountedOpenSslEngine engine = retrieveEngine(engineMap, ssl); -- return compressionAlgorithm.compress(engine, bytes); -- } -- -- @Override -- public byte[] decompress(long ssl, int len, byte[] bytes) throws Exception { -- ReferenceCountedOpenSslEngine engine = retrieveEngine(engineMap, ssl); -- return compressionAlgorithm.decompress(engine, len, bytes); -- } -- -- @Override -- public int algorithmId() { -- return compressionAlgorithm.algorithmId(); -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java -deleted file mode 100644 -index 937b469..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java -+++ /dev/null -@@ -1,2760 +0,0 @@ --/* -- * Copyright 2016 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: -- * -- * https://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.handler.ssl.util.LazyJavaxX509Certificate; --import io.netty.handler.ssl.util.LazyX509Certificate; --import io.netty.internal.tcnative.AsyncTask; --import io.netty.internal.tcnative.Buffer; --import io.netty.internal.tcnative.SSL; --import io.netty.util.AbstractReferenceCounted; --import io.netty.util.CharsetUtil; --import io.netty.util.ReferenceCounted; --import io.netty.util.ResourceLeakDetector; --import io.netty.util.ResourceLeakDetectorFactory; --import io.netty.util.ResourceLeakTracker; --import io.netty.util.internal.EmptyArrays; --import io.netty.util.internal.PlatformDependent; --import io.netty.util.internal.StringUtil; --import io.netty.util.internal.SuppressJava6Requirement; --import io.netty.util.internal.ThrowableUtil; --import io.netty.util.internal.UnstableApi; --import io.netty.util.internal.logging.InternalLogger; --import io.netty.util.internal.logging.InternalLoggerFactory; -- --import java.nio.ByteBuffer; --import java.nio.ReadOnlyBufferException; --import java.security.Principal; --import java.security.cert.Certificate; --import java.util.Arrays; --import java.util.Collection; --import java.util.Collections; --import java.util.HashSet; --import java.util.LinkedHashSet; --import java.util.List; --import java.util.Map; --import java.util.Set; --import java.util.concurrent.ConcurrentHashMap; --import java.util.concurrent.locks.Lock; -- --import javax.crypto.spec.SecretKeySpec; --import javax.net.ssl.SSLEngine; --import javax.net.ssl.SSLEngineResult; --import javax.net.ssl.SSLException; --import javax.net.ssl.SSLHandshakeException; --import javax.net.ssl.SSLParameters; --import javax.net.ssl.SSLPeerUnverifiedException; --import javax.net.ssl.SSLSession; --import javax.net.ssl.SSLSessionBindingEvent; --import javax.net.ssl.SSLSessionBindingListener; --import javax.security.cert.X509Certificate; -- --import static io.netty.handler.ssl.OpenSsl.memoryAddress; --import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH; --import static io.netty.util.internal.EmptyArrays.EMPTY_STRINGS; --import static io.netty.util.internal.ObjectUtil.checkNotNull; --import static io.netty.util.internal.ObjectUtil.checkNotNullArrayParam; --import static io.netty.util.internal.ObjectUtil.checkNotNullWithIAE; --import static java.lang.Integer.MAX_VALUE; --import static java.lang.Math.min; --import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED; --import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_TASK; --import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP; --import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP; --import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; --import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW; --import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW; --import static javax.net.ssl.SSLEngineResult.Status.CLOSED; --import static javax.net.ssl.SSLEngineResult.Status.OK; -- --/** -- * Implements a {@link SSLEngine} using -- * OpenSSL BIO abstractions. -- *

Instances of this class must be {@link #release() released} or else native memory will leak! -- * -- *

Instances of this class must be released before the {@link ReferenceCountedOpenSslContext} -- * the instance depends upon are released. Otherwise if any method of this class is called which uses the -- * the {@link ReferenceCountedOpenSslContext} JNI resources the JVM may crash. -- */ --public class ReferenceCountedOpenSslEngine extends SSLEngine implements ReferenceCounted, ApplicationProtocolAccessor { -- -- private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslEngine.class); -- -- private static final ResourceLeakDetector leakDetector = -- ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class); -- private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2 = 0; -- private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3 = 1; -- private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2; -- private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3; -- private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4; -- private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3 = 5; -- private static final int[] OPENSSL_OP_NO_PROTOCOLS = { -- SSL.SSL_OP_NO_SSLv2, -- SSL.SSL_OP_NO_SSLv3, -- SSL.SSL_OP_NO_TLSv1, -- SSL.SSL_OP_NO_TLSv1_1, -- SSL.SSL_OP_NO_TLSv1_2, -- SSL.SSL_OP_NO_TLSv1_3 -- }; -- -- /** -- * Depends upon tcnative ... only use if tcnative is available! -- */ -- static final int MAX_PLAINTEXT_LENGTH = SSL.SSL_MAX_PLAINTEXT_LENGTH; -- /** -- * Depends upon tcnative ... only use if tcnative is available! -- */ -- static final int MAX_RECORD_SIZE = SSL.SSL_MAX_RECORD_LENGTH; -- -- 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; -- -- private enum HandshakeState { -- /** -- * Not started yet. -- */ -- NOT_STARTED, -- /** -- * Started via unwrap/wrap. -- */ -- STARTED_IMPLICITLY, -- /** -- * Started via {@link #beginHandshake()}. -- */ -- STARTED_EXPLICITLY, -- /** -- * Handshake is finished. -- */ -- FINISHED -- } -- -- private HandshakeState handshakeState = HandshakeState.NOT_STARTED; -- private boolean receivedShutdown; -- private volatile boolean destroyed; -- private volatile String applicationProtocol; -- private volatile boolean needTask; -- private boolean hasTLSv13Cipher; -- private boolean sessionSet; -- -- // Reference Counting -- private final ResourceLeakTracker leak; -- private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() { -- @Override -- public ReferenceCounted touch(Object hint) { -- if (leak != null) { -- leak.record(hint); -- } -- -- return ReferenceCountedOpenSslEngine.this; -- } -- -- @Override -- protected void deallocate() { -- shutdown(); -- if (leak != null) { -- boolean closed = leak.close(ReferenceCountedOpenSslEngine.this); -- assert closed; -- } -- parentContext.release(); -- } -- }; -- -- private final Set enabledProtocols = new LinkedHashSet(); -- -- private volatile ClientAuth clientAuth = ClientAuth.NONE; -- -- private String endpointIdentificationAlgorithm; -- // Store as object as AlgorithmConstraints only exists since java 7. -- private Object algorithmConstraints; -- private List sniHostNames; -- -- // Mark as volatile as accessed by checkSniHostnameMatch(...) and also not specify the SNIMatcher type to allow us -- // using it with java7. -- private volatile Collection matchers; -- -- // SSL Engine status variables -- private boolean isInboundDone; -- private boolean outboundClosed; -- -- final boolean jdkCompatibilityMode; -- private final boolean clientMode; -- final ByteBufAllocator alloc; -- private final OpenSslEngineMap engineMap; -- private final OpenSslApplicationProtocolNegotiator apn; -- private final ReferenceCountedOpenSslContext parentContext; -- private final OpenSslSession session; -- private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1]; -- private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1]; -- private final boolean enableOcsp; -- private int maxWrapOverhead; -- private int maxWrapBufferSize; -- private Throwable pendingException; -- -- /** -- * Create a new instance. -- * @param context Reference count release responsibility is not transferred! The callee still owns this object. -- * @param alloc The allocator to use. -- * @param peerHost The peer host name. -- * @param peerPort The peer port. -- * @param jdkCompatibilityMode {@code true} to behave like described in -- * https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html. -- * {@code false} allows for partial and/or multiple packets to be process in a single -- * wrap or unwrap call. -- * @param leakDetection {@code true} to enable leak detection of this object. -- */ -- ReferenceCountedOpenSslEngine(ReferenceCountedOpenSslContext context, final ByteBufAllocator alloc, String peerHost, -- int peerPort, boolean jdkCompatibilityMode, boolean leakDetection, -- String endpointIdentificationAlgorithm) { -- super(peerHost, peerPort); -- OpenSsl.ensureAvailability(); -- engineMap = context.engineMap; -- enableOcsp = context.enableOcsp; -- this.jdkCompatibilityMode = jdkCompatibilityMode; -- this.alloc = checkNotNull(alloc, "alloc"); -- apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator(); -- clientMode = context.isClient(); -- this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; -- -- if (PlatformDependent.javaVersion() >= 7) { -- session = new ExtendedOpenSslSession(new DefaultOpenSslSession(context.sessionContext())) { -- private String[] peerSupportedSignatureAlgorithms; -- private List requestedServerNames; -- -- @Override -- public List getRequestedServerNames() { -- if (clientMode) { -- return Java8SslUtils.getSniHostNames(sniHostNames); -- } else { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (requestedServerNames == null) { -- if (isDestroyed()) { -- requestedServerNames = Collections.emptyList(); -- } else { -- String name = SSL.getSniHostname(ssl); -- if (name == null) { -- requestedServerNames = Collections.emptyList(); -- } else { -- // Convert to bytes as we do not want to do any strict validation of the -- // SNIHostName while creating it. -- requestedServerNames = -- Java8SslUtils.getSniHostName( -- SSL.getSniHostname(ssl).getBytes(CharsetUtil.UTF_8)); -- } -- } -- } -- return requestedServerNames; -- } -- } -- } -- -- @Override -- public String[] getPeerSupportedSignatureAlgorithms() { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (peerSupportedSignatureAlgorithms == null) { -- if (isDestroyed()) { -- peerSupportedSignatureAlgorithms = EMPTY_STRINGS; -- } else { -- String[] algs = SSL.getSigAlgs(ssl); -- if (algs == null) { -- peerSupportedSignatureAlgorithms = EMPTY_STRINGS; -- } else { -- Set algorithmList = new LinkedHashSet(algs.length); -- for (String alg: algs) { -- String converted = SignatureAlgorithmConverter.toJavaName(alg); -- -- if (converted != null) { -- algorithmList.add(converted); -- } -- } -- peerSupportedSignatureAlgorithms = algorithmList.toArray(EMPTY_STRINGS); -- } -- } -- } -- return peerSupportedSignatureAlgorithms.clone(); -- } -- } -- -- @Override -- public List getStatusResponses() { -- byte[] ocspResponse = null; -- if (enableOcsp && clientMode) { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (!isDestroyed()) { -- ocspResponse = SSL.getOcspResponse(ssl); -- } -- } -- } -- return ocspResponse == null ? -- Collections.emptyList() : Collections.singletonList(ocspResponse); -- } -- }; -- } else { -- session = new DefaultOpenSslSession(context.sessionContext()); -- } -- -- if (!context.sessionContext().useKeyManager()) { -- session.setLocalCertificate(context.keyCertChain); -- } -- -- Lock readerLock = context.ctxLock.readLock(); -- readerLock.lock(); -- final long finalSsl; -- try { -- finalSsl = SSL.newSSL(context.ctx, !context.isClient()); -- } finally { -- readerLock.unlock(); -- } -- synchronized (this) { -- ssl = finalSsl; -- try { -- networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize()); -- -- // Set the client auth mode, this needs to be done via setClientAuth(...) method so we actually call the -- // needed JNI methods. -- setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth); -- -- assert context.protocols != null; -- this.hasTLSv13Cipher = context.hasTLSv13Cipher; -- -- setEnabledProtocols(context.protocols); -- -- // Use SNI if peerHost was specified and a valid hostname -- // See https://github.com/netty/netty/issues/4746 -- if (clientMode && SslUtils.isValidHostNameForSNI(peerHost)) { -- // If on java8 and later we should do some extra validation to ensure we can construct the -- // SNIHostName later again. -- if (PlatformDependent.javaVersion() >= 8) { -- if (Java8SslUtils.isValidHostNameForSNI(peerHost)) { -- SSL.setTlsExtHostName(ssl, peerHost); -- sniHostNames = Collections.singletonList(peerHost); -- } -- } else { -- SSL.setTlsExtHostName(ssl, peerHost); -- sniHostNames = Collections.singletonList(peerHost); -- } -- } -- -- if (enableOcsp) { -- SSL.enableOcsp(ssl); -- } -- -- if (!jdkCompatibilityMode) { -- SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE); -- } -- -- if (isProtocolEnabled(SSL.getOptions(ssl), SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) { -- final boolean enableTickets = clientMode ? -- ReferenceCountedOpenSslContext.CLIENT_ENABLE_SESSION_TICKET_TLSV13 : -- ReferenceCountedOpenSslContext.SERVER_ENABLE_SESSION_TICKET_TLSV13; -- if (enableTickets) { -- // We should enable session tickets for stateless resumption when TLSv1.3 is enabled. This -- // is also done by OpenJDK and without this session resumption does not work at all with -- // BoringSSL when TLSv1.3 is used as BoringSSL only supports stateless resumption with TLSv1.3: -- // -- // See: -- // - https://bugs.openjdk.java.net/browse/JDK-8223922 -- // - https://boringssl.googlesource.com/boringssl/+/refs/heads/master/ssl/tls13_server.cc#104 -- SSL.clearOptions(ssl, SSL.SSL_OP_NO_TICKET); -- } -- } -- -- if (OpenSsl.isBoringSSL() && clientMode) { -- // If in client-mode and BoringSSL let's allow to renegotiate once as the server may use this -- // for client auth. -- // -- // See https://github.com/netty/netty/issues/11529 -- SSL.setRenegotiateMode(ssl, SSL.SSL_RENEGOTIATE_ONCE); -- } -- // setMode may impact the overhead. -- calculateMaxWrapOverhead(); -- -- // Configure any endpoint verification specified by the SslContext. -- configureEndpointVerification(endpointIdentificationAlgorithm); -- } catch (Throwable cause) { -- // Call shutdown so we are sure we correctly release all native memory and also guard against the -- // case when shutdown() will be called by the finalizer again. -- shutdown(); -- -- PlatformDependent.throwException(cause); -- } -- } -- -- // Now that everything looks good and we're going to successfully return the -- // object so we need to retain a reference to the parent context. -- parentContext = context; -- parentContext.retain(); -- -- // Only create the leak after everything else was executed and so ensure we don't produce a false-positive for -- // the ResourceLeakDetector. -- leak = leakDetection ? leakDetector.track(this) : null; -- } -- -- final synchronized String[] authMethods() { -- if (isDestroyed()) { -- return EMPTY_STRINGS; -- } -- return SSL.authenticationMethods(ssl); -- } -- -- final boolean setKeyMaterial(OpenSslKeyMaterial keyMaterial) throws Exception { -- synchronized (this) { -- if (isDestroyed()) { -- return false; -- } -- SSL.setKeyMaterial(ssl, keyMaterial.certificateChainAddress(), keyMaterial.privateKeyAddress()); -- } -- session.setLocalCertificate(keyMaterial.certificateChain()); -- return true; -- } -- -- final synchronized SecretKeySpec masterKey() { -- if (isDestroyed()) { -- return null; -- } -- return new SecretKeySpec(SSL.getMasterKey(ssl), "AES"); -- } -- -- synchronized boolean isSessionReused() { -- if (isDestroyed()) { -- return false; -- } -- return SSL.isSessionReused(ssl); -- } -- -- /** -- * Sets the OCSP response. -- */ -- @UnstableApi -- public void setOcspResponse(byte[] response) { -- if (!enableOcsp) { -- throw new IllegalStateException("OCSP stapling is not enabled"); -- } -- -- if (clientMode) { -- throw new IllegalStateException("Not a server SSLEngine"); -- } -- -- synchronized (this) { -- if (!isDestroyed()) { -- SSL.setOcspResponse(ssl, response); -- } -- } -- } -- -- /** -- * Returns the OCSP response or {@code null} if the server didn't provide a stapled OCSP response. -- */ -- @UnstableApi -- public byte[] getOcspResponse() { -- if (!enableOcsp) { -- throw new IllegalStateException("OCSP stapling is not enabled"); -- } -- -- if (!clientMode) { -- throw new IllegalStateException("Not a client SSLEngine"); -- } -- -- synchronized (this) { -- if (isDestroyed()) { -- return EmptyArrays.EMPTY_BYTES; -- } -- return SSL.getOcspResponse(ssl); -- } -- } -- -- @Override -- public final int refCnt() { -- return refCnt.refCnt(); -- } -- -- @Override -- public final ReferenceCounted retain() { -- refCnt.retain(); -- return this; -- } -- -- @Override -- public final ReferenceCounted retain(int increment) { -- refCnt.retain(increment); -- return this; -- } -- -- @Override -- public final ReferenceCounted touch() { -- refCnt.touch(); -- return this; -- } -- -- @Override -- public final ReferenceCounted touch(Object hint) { -- refCnt.touch(hint); -- return this; -- } -- -- @Override -- public final boolean release() { -- return refCnt.release(); -- } -- -- @Override -- public final boolean release(int decrement) { -- return refCnt.release(decrement); -- } -- -- // These method will override the method defined by Java 8u251 and later. As we may compile with an earlier -- // java8 version we don't use @Override annotations here. -- public String getApplicationProtocol() { -- return applicationProtocol; -- } -- -- // These method will override the method defined by Java 8u251 and later. As we may compile with an earlier -- // java8 version we don't use @Override annotations here. -- public String getHandshakeApplicationProtocol() { -- return applicationProtocol; -- } -- -- @Override -- public final synchronized SSLSession getHandshakeSession() { -- // Javadocs state return value should be: -- // null if this instance is not currently handshaking, or if the current handshake has not -- // progressed far enough to create a basic SSLSession. Otherwise, this method returns the -- // SSLSession currently being negotiated. -- switch(handshakeState) { -- case NOT_STARTED: -- case FINISHED: -- return null; -- default: -- return session; -- } -- } -- -- /** -- * Returns the pointer to the {@code SSL} object for this {@link ReferenceCountedOpenSslEngine}. -- * Be aware that it is freed as soon as the {@link #release()} or {@link #shutdown()} methods are called. -- * At this point {@code 0} will be returned. -- */ -- public final synchronized long sslPointer() { -- return ssl; -- } -- -- /** -- * Destroys this engine. -- */ -- public final synchronized void shutdown() { -- if (!destroyed) { -- destroyed = true; -- // Let's check if engineMap is null as it could be in theory if we throw an OOME during the construction of -- // ReferenceCountedOpenSslEngine (before we assign the field). This is needed as shutdown() is called from -- // the finalizer as well. -- if (engineMap != null) { -- engineMap.remove(ssl); -- } -- SSL.freeSSL(ssl); -- ssl = networkBIO = 0; -- -- isInboundDone = outboundClosed = true; -- } -- -- // On shutdown clear all errors -- SSL.clearError(); -- } -- -- /** -- * Write plaintext data to the OpenSSL internal BIO -- * -- * Calling this function with src.remaining == 0 is undefined. -- */ -- private int writePlaintextData(final ByteBuffer src, int len) { -- final int pos = src.position(); -- final int limit = src.limit(); -- final int sslWrote; -- -- if (src.isDirect()) { -- sslWrote = SSL.writeToSSL(ssl, bufferAddress(src) + pos, len); -- if (sslWrote > 0) { -- src.position(pos + sslWrote); -- } -- } else { -- ByteBuf buf = alloc.directBuffer(len); -- try { -- src.limit(pos + len); -- -- buf.setBytes(0, src); -- src.limit(limit); -- -- sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len); -- if (sslWrote > 0) { -- src.position(pos + sslWrote); -- } else { -- src.position(pos); -- } -- } finally { -- buf.release(); -- } -- } -- return sslWrote; -- } -- -- synchronized void bioSetFd(int fd) { -- if (!isDestroyed()) { -- SSL.bioSetFd(this.ssl, fd); -- } -- } -- -- /** -- * Write encrypted data to the OpenSSL network BIO. -- */ -- private ByteBuf writeEncryptedData(final ByteBuffer src, int len) throws SSLException { -- final int pos = src.position(); -- if (src.isDirect()) { -- SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false); -- } else { -- final ByteBuf buf = alloc.directBuffer(len); -- try { -- final int limit = src.limit(); -- src.limit(pos + len); -- buf.writeBytes(src); -- // Restore the original position and limit because we don't want to consume from `src`. -- src.position(pos); -- src.limit(limit); -- -- SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false); -- return buf; -- } catch (Throwable cause) { -- buf.release(); -- PlatformDependent.throwException(cause); -- } -- } -- return null; -- } -- -- /** -- * Read plaintext data from the OpenSSL internal BIO -- */ -- private int readPlaintextData(final ByteBuffer dst) throws SSLException { -- final int sslRead; -- final int pos = dst.position(); -- if (dst.isDirect()) { -- sslRead = SSL.readFromSSL(ssl, bufferAddress(dst) + pos, dst.limit() - pos); -- if (sslRead > 0) { -- dst.position(pos + sslRead); -- } -- } else { -- final int limit = dst.limit(); -- final int len = min(maxEncryptedPacketLength0(), limit - pos); -- final ByteBuf buf = alloc.directBuffer(len); -- try { -- sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len); -- if (sslRead > 0) { -- dst.limit(pos + sslRead); -- buf.getBytes(buf.readerIndex(), dst); -- dst.limit(limit); -- } -- } finally { -- buf.release(); -- } -- } -- -- return sslRead; -- } -- -- /** -- * Visible only for testing! -- */ -- final synchronized int maxWrapOverhead() { -- return maxWrapOverhead; -- } -- -- /** -- * Visible only for testing! -- */ -- final synchronized int maxEncryptedPacketLength() { -- return maxEncryptedPacketLength0(); -- } -- -- /** -- * This method is intentionally not synchronized, only use if you know you are in the EventLoop -- * thread and visibility on {@link #maxWrapOverhead} is achieved via other synchronized blocks. -- */ -- final int maxEncryptedPacketLength0() { -- return maxWrapOverhead + MAX_PLAINTEXT_LENGTH; -- } -- -- /** -- * This method is intentionally not synchronized, only use if you know you are in the EventLoop -- * thread and visibility on {@link #maxWrapBufferSize} and {@link #maxWrapOverhead} is achieved -- * via other synchronized blocks. -- *
-- * Calculates the max size of a single wrap operation for the given plaintextLength and -- * numComponents. -- */ -- final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) { -- return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents); -- } -- -- /** -- * This method is intentionally not synchronized, only use if you know you are in the EventLoop -- * thread and visibility on {@link #maxWrapOverhead} is achieved via other synchronized blocks. -- *
-- * Calculates the size of the out net buf to create for the given plaintextLength and numComponents. -- * This is not related to the max size per wrap, as we can wrap chunks at a time into one out net buf. -- */ -- final int calculateOutNetBufSize(int plaintextLength, int numComponents) { -- return (int) min(MAX_VALUE, plaintextLength + (long) maxWrapOverhead * numComponents); -- } -- -- final synchronized int sslPending() { -- return sslPending0(); -- } -- -- /** -- * It is assumed this method is called in a synchronized block (or the constructor)! -- */ -- private void calculateMaxWrapOverhead() { -- maxWrapOverhead = SSL.getMaxWrapOverhead(ssl); -- -- // maxWrapBufferSize must be set after maxWrapOverhead because there is a dependency on this value. -- // If jdkCompatibility mode is off we allow enough space to encrypt 16 buffers at a time. This could be -- // configurable in the future if necessary. -- maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4; -- } -- -- private int sslPending0() { -- // OpenSSL has a limitation where if you call SSL_pending before the handshake is complete OpenSSL will throw a -- // "called a function you should not call" error. Using the TLS_method instead of SSLv23_method may solve this -- // issue but this API is only available in 1.1.0+ [1]. -- // [1] https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_new.html -- return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl); -- } -- -- private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) { -- return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength; -- } -- -- @Override -- public final SSLEngineResult wrap( -- final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException { -- // Throw required runtime exceptions -- checkNotNullWithIAE(srcs, "srcs"); -- checkNotNullWithIAE(dst, "dst"); -- -- 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(); -- } -- -- synchronized (this) { -- if (isOutboundDone()) { -- // All drained in the outbound buffer -- return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED; -- } -- -- int bytesProduced = 0; -- ByteBuf bioReadCopyBuf = null; -- try { -- // Setup the BIO buffer so that we directly write the encryption results into dst. -- if (dst.isDirect()) { -- SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(), -- true); -- } else { -- bioReadCopyBuf = alloc.directBuffer(dst.remaining()); -- SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(), -- true); -- } -- -- int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO); -- -- // Explicitly use outboundClosed as we want to drain any bytes that are still present. -- if (outboundClosed) { -- // If the outbound was closed we want to ensure we can produce the alert to the destination buffer. -- // This is true even if we not using jdkCompatibilityMode. -- // -- // We use a plaintextLength of 2 as we at least want to have an alert fit into it. -- // https://tools.ietf.org/html/rfc5246#section-7.2 -- if (!isBytesAvailableEnoughForWrap(dst.remaining(), 2, 1)) { -- return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0); -- } -- -- // There is something left to drain. -- // See https://github.com/netty/netty/issues/6260 -- bytesProduced = SSL.bioFlushByteBuffer(networkBIO); -- if (bytesProduced <= 0) { -- return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0); -- } -- // It is possible when the outbound was closed there was not enough room in the non-application -- // buffers to hold the close_notify. We should keep trying to close until we consume all the data -- // OpenSSL can give us. -- if (!doSSLShutdown()) { -- return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced); -- } -- bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO); -- return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced); -- } -- -- // Flush any data that may be implicitly generated by OpenSSL (handshake, close, etc..). -- SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING; -- HandshakeState oldHandshakeState = handshakeState; -- -- // Prepare OpenSSL to work in server mode and receive handshake -- if (handshakeState != HandshakeState.FINISHED) { -- if (handshakeState != HandshakeState.STARTED_EXPLICITLY) { -- // Update accepted so we know we triggered the handshake via wrap -- handshakeState = HandshakeState.STARTED_IMPLICITLY; -- } -- -- // Flush any data that may have been written implicitly during the handshake by OpenSSL. -- bytesProduced = SSL.bioFlushByteBuffer(networkBIO); -- -- if (pendingException != null) { -- // TODO(scott): It is possible that when the handshake failed there was not enough room in the -- // non-application buffers to hold the alert. We should get all the data before progressing on. -- // However I'm not aware of a way to do this with the OpenSSL APIs. -- // See https://github.com/netty/netty/issues/6385. -- -- // We produced / consumed some data during the handshake, signal back to the caller. -- // If there is a handshake exception and we have produced data, we should send the data before -- // we allow handshake() to throw the handshake exception. -- // -- // When the user calls wrap() again we will propagate the handshake error back to the user as -- // soon as there is no more data to was produced (as part of an alert etc). -- if (bytesProduced > 0) { -- return newResult(NEED_WRAP, 0, bytesProduced); -- } -- // Nothing was produced see if there is a handshakeException that needs to be propagated -- // to the caller by calling handshakeException() which will return the right HandshakeStatus -- // if it can "recover" from the exception for now. -- return newResult(handshakeException(), 0, 0); -- } -- -- status = handshake(); -- -- // Handshake may have generated more data, for example if the internal SSL buffer is small -- // we may have freed up space by flushing above. -- bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO); -- -- if (status == NEED_TASK) { -- return newResult(status, 0, bytesProduced); -- } -- -- if (bytesProduced > 0) { -- // If we have filled up the dst buffer and we have not finished the handshake we should try to -- // wrap again. Otherwise we should only try to wrap again if there is still data pending in -- // SSL buffers. -- return newResult(mayFinishHandshake(status != FINISHED ? -- bytesProduced == bioLengthBefore ? NEED_WRAP : -- getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED), -- 0, bytesProduced); -- } -- -- if (status == NEED_UNWRAP) { -- // Signal if the outbound is done or not. -- return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK; -- } -- -- // Explicit use outboundClosed and not outboundClosed() as we want to drain any bytes that are -- // still present. -- if (outboundClosed) { -- bytesProduced = SSL.bioFlushByteBuffer(networkBIO); -- return newResultMayFinishHandshake(status, 0, bytesProduced); -- } -- } -- -- final int endOffset = offset + length; -- if (jdkCompatibilityMode || -- // If the handshake was not finished before we entered the method, we also ensure we only -- // wrap one record. We do this to ensure we not produce any extra data before the caller -- // of the method is able to observe handshake completion and react on it. -- oldHandshakeState != HandshakeState.FINISHED) { -- int srcsLen = 0; -- for (int i = offset; i < endOffset; ++i) { -- final ByteBuffer src = srcs[i]; -- if (src == null) { -- throw new IllegalArgumentException("srcs[" + i + "] is null"); -- } -- if (srcsLen == MAX_PLAINTEXT_LENGTH) { -- continue; -- } -- -- srcsLen += src.remaining(); -- if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) { -- // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to MAX_PLAINTEXT_LENGTH. -- // This also help us to guard against overflow. -- // We not break out here as we still need to check for null entries in srcs[]. -- srcsLen = MAX_PLAINTEXT_LENGTH; -- } -- } -- -- // jdkCompatibilityMode will only produce a single TLS packet, and we don't aggregate src buffers, -- // so we always fix the number of buffers to 1 when checking if the dst buffer is large enough. -- if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) { -- return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0); -- } -- } -- -- // There was no pending data in the network BIO -- encrypt any application data -- int bytesConsumed = 0; -- assert bytesProduced == 0; -- -- // Flush any data that may have been written implicitly by OpenSSL in case a shutdown/alert occurs. -- bytesProduced = SSL.bioFlushByteBuffer(networkBIO); -- -- if (bytesProduced > 0) { -- return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced); -- } -- // There was a pending exception that we just delayed because there was something to produce left. -- // Throw it now and shutdown the engine. -- if (pendingException != null) { -- Throwable error = pendingException; -- pendingException = null; -- shutdown(); -- // Throw a new exception wrapping the pending exception, so the stacktrace is meaningful and -- // contains all the details. -- throw new SSLException(error); -- } -- -- for (; offset < endOffset; ++offset) { -- final ByteBuffer src = srcs[offset]; -- final int remaining = src.remaining(); -- if (remaining == 0) { -- continue; -- } -- -- final int bytesWritten; -- if (jdkCompatibilityMode) { -- // Write plaintext application data to the SSL engine. We don't have to worry about checking -- // if there is enough space if jdkCompatibilityMode because we only wrap at most -- // MAX_PLAINTEXT_LENGTH and we loop over the input before hand and check if there is space. -- bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed)); -- } else { -- // OpenSSL's SSL_write keeps state between calls. We should make sure the amount we attempt to -- // write is guaranteed to succeed so we don't have to worry about keeping state consistent -- // between calls. -- final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead; -- if (availableCapacityForWrap <= 0) { -- return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed, -- bytesProduced); -- } -- bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap)); -- } -- -- // Determine how much encrypted data was generated. -- // -- // Even if SSL_write doesn't consume any application data it is possible that OpenSSL will -- // produce non-application data into the BIO. For example session tickets.... -- // See https://github.com/netty/netty/issues/10041 -- final int pendingNow = SSL.bioLengthByteBuffer(networkBIO); -- bytesProduced += bioLengthBefore - pendingNow; -- bioLengthBefore = pendingNow; -- -- if (bytesWritten > 0) { -- bytesConsumed += bytesWritten; -- -- if (jdkCompatibilityMode || bytesProduced == dst.remaining()) { -- return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced); -- } -- } else { -- int sslError = SSL.getError(ssl, bytesWritten); -- if (sslError == SSL.SSL_ERROR_ZERO_RETURN) { -- // This means the connection was shutdown correctly, close inbound and outbound -- if (!receivedShutdown) { -- closeAll(); -- -- bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO); -- -- // If we have filled up the dst buffer and we have not finished the handshake we should -- // try to wrap again. Otherwise we should only try to wrap again if there is still data -- // pending in SSL buffers. -- SSLEngineResult.HandshakeStatus hs = mayFinishHandshake( -- status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP -- : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) -- : FINISHED); -- return newResult(hs, bytesConsumed, bytesProduced); -- } -- -- return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced); -- } else if (sslError == SSL.SSL_ERROR_WANT_READ) { -- // If there is no pending data to read from BIO we should go back to event loop and try -- // to read more data [1]. It is also possible that event loop will detect the socket has -- // been closed. [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html -- return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced); -- } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) { -- // SSL_ERROR_WANT_WRITE typically means that the underlying transport is not writable -- // and we should set the "want write" flag on the selector and try again when the -- // underlying transport is writable [1]. However we are not directly writing to the -- // underlying transport and instead writing to a BIO buffer. The OpenSsl documentation -- // says we should do the following [1]: -- // -- // "When using a buffering BIO, like a BIO pair, data must be written into or retrieved -- // out of the BIO before being able to continue." -- // -- // In practice this means the destination buffer doesn't have enough space for OpenSSL -- // to write encrypted data to. This is an OVERFLOW condition. -- // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html -- if (bytesProduced > 0) { -- // If we produced something we should report this back and let the user call -- // wrap again. -- return newResult(NEED_WRAP, bytesConsumed, bytesProduced); -- } -- return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced); -- } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP || -- sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY || -- sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) { -- -- return newResult(NEED_TASK, bytesConsumed, bytesProduced); -- } else { -- // Everything else is considered as error -- throw shutdownWithError("SSL_write", sslError); -- } -- } -- } -- return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced); -- } finally { -- SSL.bioClearByteBuffer(networkBIO); -- if (bioReadCopyBuf == null) { -- dst.position(dst.position() + bytesProduced); -- } else { -- assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst + -- " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf; -- dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced)); -- bioReadCopyBuf.release(); -- } -- } -- } -- } -- -- private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) { -- return newResult(OK, hs, bytesConsumed, bytesProduced); -- } -- -- private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs, -- int bytesConsumed, int bytesProduced) { -- // If isOutboundDone, then the data from the network BIO -- // was the close_notify message and all was consumed we are not required to wait -- // for the receipt the peer's close_notify message -- shutdown. -- if (isOutboundDone()) { -- if (isInboundDone()) { -- // If the inbound was done as well, we need to ensure we return NOT_HANDSHAKING to signal we are done. -- hs = NOT_HANDSHAKING; -- -- // As the inbound and the outbound is done we can shutdown the engine now. -- shutdown(); -- } -- return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced); -- } -- if (hs == NEED_TASK) { -- // Set needTask to true so getHandshakeStatus() will return the correct value. -- needTask = true; -- } -- return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced); -- } -- -- private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs, -- int bytesConsumed, int bytesProduced) throws SSLException { -- return newResult(mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced); -- } -- -- private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status, -- SSLEngineResult.HandshakeStatus hs, -- int bytesConsumed, int bytesProduced) throws SSLException { -- return newResult(status, mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced); -- } -- -- /** -- * Log the error, shutdown the engine and throw an exception. -- */ -- private SSLException shutdownWithError(String operations, int sslError) { -- return shutdownWithError(operations, sslError, SSL.getLastErrorNumber()); -- } -- -- private SSLException shutdownWithError(String operation, int sslError, int error) { -- if (logger.isDebugEnabled()) { -- String errorString = SSL.getErrorString(error); -- logger.debug("{} failed with {}: OpenSSL error: {} {}", -- operation, sslError, error, errorString); -- } -- -- // There was an internal error -- shutdown -- shutdown(); -- -- SSLException exception = newSSLExceptionForError(error); -- // If we have a pendingException stored already we should include it as well to help the user debug things. -- if (pendingException != null) { -- exception.initCause(pendingException); -- pendingException = null; -- } -- return exception; -- } -- -- private SSLEngineResult handleUnwrapException(int bytesConsumed, int bytesProduced, SSLException e) -- throws SSLException { -- int lastError = SSL.getLastErrorNumber(); -- if (lastError != 0) { -- return sslReadErrorResult(SSL.SSL_ERROR_SSL, lastError, bytesConsumed, -- bytesProduced); -- } -- throw e; -- } -- -- public final SSLEngineResult unwrap( -- final ByteBuffer[] srcs, int srcsOffset, final int srcsLength, -- final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException { -- -- // Throw required runtime exceptions -- checkNotNullWithIAE(srcs, "srcs"); -- if (srcsOffset >= srcs.length -- || srcsOffset + srcsLength > srcs.length) { -- throw new IndexOutOfBoundsException( -- "offset: " + srcsOffset + ", length: " + srcsLength + -- " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))"); -- } -- checkNotNullWithIAE(dsts, "dsts"); -- if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) { -- throw new IndexOutOfBoundsException( -- "offset: " + dstsOffset + ", length: " + dstsLength + -- " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))"); -- } -- long capacity = 0; -- final int dstsEndOffset = dstsOffset + dstsLength; -- for (int i = dstsOffset; i < dstsEndOffset; i ++) { -- ByteBuffer dst = checkNotNullArrayParam(dsts[i], i, "dsts"); -- if (dst.isReadOnly()) { -- throw new ReadOnlyBufferException(); -- } -- capacity += dst.remaining(); -- } -- -- final int srcsEndOffset = srcsOffset + srcsLength; -- long len = 0; -- for (int i = srcsOffset; i < srcsEndOffset; i++) { -- ByteBuffer src = checkNotNullArrayParam(srcs[i], i, "srcs"); -- len += src.remaining(); -- } -- -- synchronized (this) { -- if (isInboundDone()) { -- return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED; -- } -- -- SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING; -- HandshakeState oldHandshakeState = handshakeState; -- // Prepare OpenSSL to work in server mode and receive handshake -- if (handshakeState != HandshakeState.FINISHED) { -- if (handshakeState != HandshakeState.STARTED_EXPLICITLY) { -- // Update accepted so we know we triggered the handshake via wrap -- handshakeState = HandshakeState.STARTED_IMPLICITLY; -- } -- -- status = handshake(); -- -- if (status == NEED_TASK) { -- return newResult(status, 0, 0); -- } -- -- if (status == NEED_WRAP) { -- return NEED_WRAP_OK; -- } -- // Check if the inbound is considered to be closed if so let us try to wrap again. -- if (isInboundDone) { -- return NEED_WRAP_CLOSED; -- } -- } -- -- int sslPending = sslPending0(); -- int packetLength; -- // The JDK implies that only a single SSL packet should be processed per unwrap call [1]. If we are in -- // JDK compatibility mode then we should honor this, but if not we just wrap as much as possible. If there -- // are multiple records or partial records this may reduce thrashing events through the pipeline. -- // [1] https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html -- if (jdkCompatibilityMode || -- // If the handshake was not finished before we entered the method, we also ensure we only -- // unwrap one record. We do this to ensure we not produce any extra data before the caller -- // of the method is able to observe handshake completion and react on it. -- oldHandshakeState != HandshakeState.FINISHED) { -- if (len < SSL_RECORD_HEADER_LENGTH) { -- return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0); -- } -- -- packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset); -- if (packetLength == SslUtils.NOT_ENCRYPTED) { -- throw new NotSslRecordException("not an SSL/TLS record"); -- } -- -- final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH; -- if (packetLengthDataOnly > capacity) { -- // Not enough space in the destination buffer so signal the caller that the buffer needs to be -- // increased. -- if (packetLengthDataOnly > MAX_RECORD_SIZE) { -- // The packet length MUST NOT exceed 2^14 [1]. However we do accommodate more data to support -- // legacy use cases which may violate this condition (e.g. OpenJDK's SslEngineImpl). If the max -- // length is exceeded we fail fast here to avoid an infinite loop due to the fact that we -- // won't allocate a buffer large enough. -- // [1] https://tools.ietf.org/html/rfc5246#section-6.2.1 -- throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " + -- session.getApplicationBufferSize()); -- } else { -- session.tryExpandApplicationBufferSize(packetLengthDataOnly); -- } -- return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0); -- } -- -- if (len < packetLength) { -- // We either don't have enough data to read the packet length or not enough for reading the whole -- // packet. -- return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0); -- } -- } else if (len == 0 && sslPending <= 0) { -- return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0); -- } else if (capacity == 0) { -- return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0); -- } else { -- packetLength = (int) min(MAX_VALUE, len); -- } -- -- // This must always be the case when we reached here as if not we returned BUFFER_UNDERFLOW. -- assert srcsOffset < srcsEndOffset; -- -- // This must always be the case if we reached here. -- assert capacity > 0; -- -- // Number of produced bytes -- int bytesProduced = 0; -- int bytesConsumed = 0; -- try { -- srcLoop: -- for (;;) { -- ByteBuffer src = srcs[srcsOffset]; -- int remaining = src.remaining(); -- final ByteBuf bioWriteCopyBuf; -- int pendingEncryptedBytes; -- if (remaining == 0) { -- if (sslPending <= 0) { -- // We must skip empty buffers as BIO_write will return 0 if asked to write something -- // with length 0. -- if (++srcsOffset >= srcsEndOffset) { -- break; -- } -- continue; -- } else { -- bioWriteCopyBuf = null; -- pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO); -- } -- } else { -- // Write more encrypted data into the BIO. Ensure we only read one packet at a time as -- // stated in the SSLEngine javadocs. -- pendingEncryptedBytes = min(packetLength, remaining); -- try { -- bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes); -- } catch (SSLException e) { -- // Ensure we correctly handle the error stack. -- return handleUnwrapException(bytesConsumed, bytesProduced, e); -- } -- } -- try { -- for (;;) { -- ByteBuffer dst = dsts[dstsOffset]; -- if (!dst.hasRemaining()) { -- // No space left in the destination buffer, skip it. -- if (++dstsOffset >= dstsEndOffset) { -- break srcLoop; -- } -- continue; -- } -- -- int bytesRead; -- try { -- bytesRead = readPlaintextData(dst); -- } catch (SSLException e) { -- // Ensure we correctly handle the error stack. -- return handleUnwrapException(bytesConsumed, bytesProduced, e); -- } -- // We are directly using the ByteBuffer memory for the write, and so we only know what has -- // been consumed after we let SSL decrypt the data. At this point we should update the -- // number of bytes consumed, update the ByteBuffer position, and release temp ByteBuf. -- int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO); -- bytesConsumed += localBytesConsumed; -- packetLength -= localBytesConsumed; -- pendingEncryptedBytes -= localBytesConsumed; -- src.position(src.position() + localBytesConsumed); -- -- if (bytesRead > 0) { -- bytesProduced += bytesRead; -- -- if (!dst.hasRemaining()) { -- sslPending = sslPending0(); -- // Move to the next dst buffer as this one is full. -- if (++dstsOffset >= dstsEndOffset) { -- return sslPending > 0 ? -- newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) : -- newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, -- bytesConsumed, bytesProduced); -- } -- } else if (packetLength == 0 || jdkCompatibilityMode) { -- // We either consumed all data or we are in jdkCompatibilityMode and have consumed -- // a single TLS packet and should stop consuming until this method is called again. -- break srcLoop; -- } -- } else { -- int sslError = SSL.getError(ssl, bytesRead); -- if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) { -- // break to the outer loop as we want to read more data which means we need to -- // write more to the BIO. -- break; -- } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) { -- // This means the connection was shutdown correctly, close inbound and outbound -- if (!receivedShutdown) { -- closeAll(); -- } -- return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, -- bytesConsumed, bytesProduced); -- } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP || -- sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY || -- sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) { -- return newResult(isInboundDone() ? CLOSED : OK, -- NEED_TASK, bytesConsumed, bytesProduced); -- } else { -- return sslReadErrorResult(sslError, SSL.getLastErrorNumber(), bytesConsumed, -- bytesProduced); -- } -- } -- } -- -- if (++srcsOffset >= srcsEndOffset) { -- break; -- } -- } finally { -- if (bioWriteCopyBuf != null) { -- bioWriteCopyBuf.release(); -- } -- } -- } -- } finally { -- SSL.bioClearByteBuffer(networkBIO); -- rejectRemoteInitiatedRenegotiation(); -- } -- -- // 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) { -- closeAll(); -- } -- -- return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced); -- } -- } -- -- private boolean needWrapAgain(int stackError) { -- // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the -- // BIO first or can just shutdown and throw it now. -- // This is needed so we ensure close_notify etc is correctly send to the remote peer. -- // See https://github.com/netty/netty/issues/3900 -- if (SSL.bioLengthNonApplication(networkBIO) > 0) { -- // we seem to have data left that needs to be transferred and so the user needs -- // call wrap(...). Store the error so we can pick it up later. -- if (pendingException == null) { -- pendingException = newSSLExceptionForError(stackError); -- } else if (shouldAddSuppressed(pendingException, stackError)) { -- ThrowableUtil.addSuppressed(pendingException, newSSLExceptionForError(stackError)); -- } -- // We need to clear all errors so we not pick up anything that was left on the stack on the next -- // operation. Note that shutdownWithError(...) will cleanup the stack as well so its only needed here. -- SSL.clearError(); -- return true; -- } -- return false; -- } -- -- private SSLException newSSLExceptionForError(int stackError) { -- String message = SSL.getErrorString(stackError); -- return handshakeState == HandshakeState.FINISHED ? -- new OpenSslException(message, stackError) : new OpenSslHandshakeException(message, stackError); -- } -- -- private static boolean shouldAddSuppressed(Throwable target, int errorCode) { -- for (Throwable suppressed: ThrowableUtil.getSuppressed(target)) { -- if (suppressed instanceof NativeSslException && -- ((NativeSslException) suppressed).errorCode() == errorCode) { -- /// An exception with this errorCode was already added before. -- return false; -- } -- } -- return true; -- } -- -- private SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced) -- throws SSLException { -- if (needWrapAgain(stackError)) { -- // There is something that needs to be send to the remote peer before we can teardown. -- // This is most likely some alert. -- return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced); -- } -- throw shutdownWithError("SSL_read", error, stackError); -- } -- -- private void closeAll() throws SSLException { -- receivedShutdown = true; -- closeOutbound(); -- closeInbound(); -- } -- -- private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException { -- // As rejectRemoteInitiatedRenegotiation() is called in a finally block we also need to check if we shutdown -- // the engine before as otherwise SSL.getHandshakeCount(ssl) will throw an NPE if the passed in ssl is 0. -- // See https://github.com/netty/netty/issues/7353 -- if (!isDestroyed() && (!clientMode && SSL.getHandshakeCount(ssl) > 1 || -- // Let's allow to renegotiate once for client auth. -- clientMode && SSL.getHandshakeCount(ssl) > 2) && -- // As we may count multiple handshakes when TLSv1.3 is used we should just ignore this here as -- // renegotiation is not supported in TLSv1.3 as per spec. -- !SslProtocols.TLS_v1_3.equals(session.getProtocol()) && handshakeState == HandshakeState.FINISHED) { -- // 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 renegotiation not allowed"); -- } -- } -- -- public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException { -- return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length); -- } -- -- private ByteBuffer[] singleSrcBuffer(ByteBuffer src) { -- singleSrcBuffer[0] = src; -- return singleSrcBuffer; -- } -- -- private void resetSingleSrcBuffer() { -- singleSrcBuffer[0] = null; -- } -- -- private ByteBuffer[] singleDstBuffer(ByteBuffer src) { -- singleDstBuffer[0] = src; -- return singleDstBuffer; -- } -- -- private void resetSingleDstBuffer() { -- singleDstBuffer[0] = null; -- } -- -- @Override -- public final synchronized SSLEngineResult unwrap( -- final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException { -- try { -- return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length); -- } finally { -- resetSingleSrcBuffer(); -- } -- } -- -- @Override -- public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException { -- try { -- return wrap(singleSrcBuffer(src), dst); -- } finally { -- resetSingleSrcBuffer(); -- } -- } -- -- @Override -- public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException { -- try { -- return unwrap(singleSrcBuffer(src), singleDstBuffer(dst)); -- } finally { -- resetSingleSrcBuffer(); -- resetSingleDstBuffer(); -- } -- } -- -- @Override -- public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException { -- try { -- return unwrap(singleSrcBuffer(src), dsts); -- } finally { -- resetSingleSrcBuffer(); -- } -- } -- -- private class TaskDecorator implements Runnable { -- protected final R task; -- TaskDecorator(R task) { -- this.task = task; -- } -- -- @Override -- public void run() { -- runAndResetNeedTask(task); -- } -- } -- -- private final class AsyncTaskDecorator extends TaskDecorator implements AsyncRunnable { -- AsyncTaskDecorator(AsyncTask task) { -- super(task); -- } -- -- @Override -- public void run(final Runnable runnable) { -- if (isDestroyed()) { -- // The engine was destroyed in the meantime, just return. -- return; -- } -- task.runAsync(new TaskDecorator(runnable)); -- } -- } -- -- private void runAndResetNeedTask(Runnable task) { -- // We need to synchronize on the ReferenceCountedOpenSslEngine, we are sure the SSL object -- // will not be freed by the user calling for example shutdown() concurrently. -- synchronized (ReferenceCountedOpenSslEngine.this) { -- try { -- if (isDestroyed()) { -- // The engine was destroyed in the meantime, just return. -- return; -- } -- task.run(); -- if (handshakeState != HandshakeState.FINISHED && !isDestroyed()) { -- // Call SSL.doHandshake(...) If the handshake was not finished yet. This might be needed -- // to fill the application buffer and so have getHandshakeStatus() return the right value -- // in this case. -- if (SSL.doHandshake(ssl) <= 0) { -- SSL.clearError(); -- } -- } -- } finally { -- // The task was run, reset needTask to false so getHandshakeStatus() returns the correct value. -- needTask = false; -- } -- } -- } -- -- @Override -- public final synchronized Runnable getDelegatedTask() { -- if (isDestroyed()) { -- return null; -- } -- final Runnable task = SSL.getTask(ssl); -- if (task == null) { -- return null; -- } -- if (task instanceof AsyncTask) { -- return new AsyncTaskDecorator((AsyncTask) task); -- } -- return new TaskDecorator(task); -- } -- -- @Override -- public final synchronized void closeInbound() throws SSLException { -- if (isInboundDone) { -- return; -- } -- -- isInboundDone = true; -- -- if (isOutboundDone()) { -- // Only call shutdown if there is no outbound data pending. -- // See https://github.com/netty/netty/issues/6167 -- shutdown(); -- } -- -- if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) { -- throw new SSLException( -- "Inbound closed before receiving peer's close_notify: possible truncation attack?"); -- } -- } -- -- @Override -- public final synchronized boolean isInboundDone() { -- return isInboundDone; -- } -- -- @Override -- public final synchronized void closeOutbound() { -- if (outboundClosed) { -- return; -- } -- -- outboundClosed = true; -- -- if (handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()) { -- int mode = SSL.getShutdown(ssl); -- if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) { -- doSSLShutdown(); -- } -- } else { -- // engine closing before initial handshake -- shutdown(); -- } -- } -- -- /** -- * Attempt to call {@link SSL#shutdownSSL(long)}. -- * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error. -- */ -- private boolean doSSLShutdown() { -- if (SSL.isInInit(ssl) != 0) { -- // Only try to call SSL_shutdown if we are not in the init state anymore. -- // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs. -- // -- // See also https://hg.nginx.org/nginx/rev/062c189fee20 -- return false; -- } -- int err = SSL.shutdownSSL(ssl); -- if (err < 0) { -- int sslErr = SSL.getError(ssl, err); -- if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) { -- if (logger.isDebugEnabled()) { -- int error = SSL.getLastErrorNumber(); -- logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error)); -- } -- // There was an internal error -- shutdown -- shutdown(); -- return false; -- } -- SSL.clearError(); -- } -- return true; -- } -- -- @Override -- public final synchronized boolean isOutboundDone() { -- // Check if there is anything left in the outbound buffer. -- // We need to ensure we only call SSL.pendingWrittenBytesInBIO(...) if the engine was not destroyed yet. -- return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0); -- } -- -- @Override -- public final String[] getSupportedCipherSuites() { -- return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(EMPTY_STRINGS); -- } -- -- @Override -- public final String[] getEnabledCipherSuites() { -- final String[] extraCiphers; -- final String[] enabled; -- final boolean tls13Enabled; -- synchronized (this) { -- if (!isDestroyed()) { -- enabled = SSL.getCiphers(ssl); -- int opts = SSL.getOptions(ssl); -- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) { -- extraCiphers = OpenSsl.EXTRA_SUPPORTED_TLS_1_3_CIPHERS; -- tls13Enabled = true; -- } else { -- extraCiphers = EMPTY_STRINGS; -- tls13Enabled = false; -- } -- } else { -- return EMPTY_STRINGS; -- } -- } -- if (enabled == null) { -- return EMPTY_STRINGS; -- } else { -- Set enabledSet = new LinkedHashSet(enabled.length + extraCiphers.length); -- synchronized (this) { -- for (int i = 0; i < enabled.length; i++) { -- String mapped = toJavaCipherSuite(enabled[i]); -- final String cipher = mapped == null ? enabled[i] : mapped; -- if ((!tls13Enabled || !OpenSsl.isTlsv13Supported()) && SslUtils.isTLSv13Cipher(cipher)) { -- continue; -- } -- enabledSet.add(cipher); -- } -- Collections.addAll(enabledSet, extraCiphers); -- } -- return enabledSet.toArray(EMPTY_STRINGS); -- } -- } -- -- @Override -- public final void setEnabledCipherSuites(String[] cipherSuites) { -- checkNotNull(cipherSuites, "cipherSuites"); -- -- final StringBuilder buf = new StringBuilder(); -- final StringBuilder bufTLSv13 = new StringBuilder(); -- -- CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13, OpenSsl.isBoringSSL()); -- final String cipherSuiteSpec = buf.toString(); -- final String cipherSuiteSpecTLSv13 = bufTLSv13.toString(); -- -- if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) { -- throw new IllegalArgumentException("TLSv1.3 is not supported by this java version."); -- } -- synchronized (this) { -- hasTLSv13Cipher = !cipherSuiteSpecTLSv13.isEmpty(); -- if (!isDestroyed()) { -- try { -- // Set non TLSv1.3 ciphers. -- SSL.setCipherSuites(ssl, cipherSuiteSpec, false); -- if (OpenSsl.isTlsv13Supported()) { -- // Set TLSv1.3 ciphers. -- SSL.setCipherSuites(ssl, OpenSsl.checkTls13Ciphers(logger, cipherSuiteSpecTLSv13), true); -- } -- -- // We also need to update the enabled protocols to ensure we disable the protocol if there are -- // no compatible ciphers left. -- Set protocols = new HashSet(enabledProtocols); -- -- // We have no ciphers that are compatible with none-TLSv1.3, let us explicit disable all other -- // protocols. -- if (cipherSuiteSpec.isEmpty()) { -- protocols.remove(SslProtocols.TLS_v1); -- protocols.remove(SslProtocols.TLS_v1_1); -- protocols.remove(SslProtocols.TLS_v1_2); -- protocols.remove(SslProtocols.SSL_v3); -- protocols.remove(SslProtocols.SSL_v2); -- protocols.remove(SslProtocols.SSL_v2_HELLO); -- } -- // We have no ciphers that are compatible with TLSv1.3, let us explicit disable it. -- if (cipherSuiteSpecTLSv13.isEmpty()) { -- protocols.remove(SslProtocols.TLS_v1_3); -- } -- // Update the protocols but not cache the value. We only cache when we call it from the user -- // code or when we construct the engine. -- setEnabledProtocols0(protocols.toArray(EMPTY_STRINGS), !hasTLSv13Cipher); -- } 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 final String[] getSupportedProtocols() { -- return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(EMPTY_STRINGS); -- } -- -- @Override -- public final String[] getEnabledProtocols() { -- return enabledProtocols.toArray(EMPTY_STRINGS); -- } -- -- private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) { -- // We also need to check if the actual protocolString is supported as depending on the openssl API -- // implementations it may use a disableMask of 0 (BoringSSL is doing this for example). -- return (opts & disableMask) == 0 && OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(protocolString); -- } -- -- /** -- * {@inheritDoc} -- * TLS doesn't support a way to advertise non-contiguous versions from the client's perspective, and the client -- * just advertises the max supported version. The TLS protocol also doesn't support all different combinations of -- * discrete protocols, and instead assumes contiguous ranges. OpenSSL has some unexpected behavior -- * (e.g. handshake failures) if non-contiguous protocols are used even where there is a compatible set of protocols -- * and ciphers. For these reasons this method will determine the minimum protocol and the maximum protocol and -- * enabled a contiguous range from [min protocol, max protocol] in OpenSSL. -- */ -- @Override -- public final void setEnabledProtocols(String[] protocols) { -- checkNotNullWithIAE(protocols, "protocols"); -- synchronized (this) { -- enabledProtocols.clear(); -- // Seems like there is no way to explicit disable SSLv2Hello in openssl, so it is always enabled -- enabledProtocols.add(SslProtocols.SSL_v2_HELLO); -- -- Collections.addAll(enabledProtocols, protocols); -- -- setEnabledProtocols0(protocols, !hasTLSv13Cipher); -- } -- } -- -- private void setEnabledProtocols0(String[] protocols, boolean explicitDisableTLSv13) { -- assert Thread.holdsLock(this); -- // This is correct from the API docs -- int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length; -- int maxProtocolIndex = 0; -- for (String p: protocols) { -- if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) { -- throw new IllegalArgumentException("Protocol " + p + " is not supported."); -- } -- if (p.equals(SslProtocols.SSL_v2)) { -- if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) { -- minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2; -- } -- if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) { -- maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2; -- } -- } else if (p.equals(SslProtocols.SSL_v3)) { -- if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) { -- minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3; -- } -- if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) { -- maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3; -- } -- } else if (p.equals(SslProtocols.TLS_v1)) { -- if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) { -- minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1; -- } -- if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) { -- maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1; -- } -- } else if (p.equals(SslProtocols.TLS_v1_1)) { -- if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) { -- minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1; -- } -- if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) { -- maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1; -- } -- } else if (p.equals(SslProtocols.TLS_v1_2)) { -- if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) { -- minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2; -- } -- if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) { -- maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2; -- } -- } else if (!explicitDisableTLSv13 && p.equals(SslProtocols.TLS_v1_3)) { -- if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) { -- minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3; -- } -- if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) { -- maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3; -- } -- } -- } -- if (!isDestroyed()) { -- // Clear out options which disable protocols -- SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 | -- SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2 | SSL.SSL_OP_NO_TLSv1_3); -- -- int opts = 0; -- for (int i = 0; i < minProtocolIndex; ++i) { -- opts |= OPENSSL_OP_NO_PROTOCOLS[i]; -- } -- assert maxProtocolIndex != MAX_VALUE; -- for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) { -- opts |= OPENSSL_OP_NO_PROTOCOLS[i]; -- } -- -- // Disable protocols we do not want -- SSL.setOptions(ssl, opts); -- } else { -- throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols)); -- } -- } -- -- @Override -- public final SSLSession getSession() { -- return session; -- } -- -- @Override -- public final synchronized void beginHandshake() throws SSLException { -- switch (handshakeState) { -- case STARTED_IMPLICITLY: -- checkEngineClosed(); -- -- // 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. -- -- handshakeState = HandshakeState.STARTED_EXPLICITLY; // Next time this method is invoked by the user, -- calculateMaxWrapOverhead(); -- // we should raise an exception. -- break; -- case STARTED_EXPLICITLY: -- // Nothing to do as the handshake is not done yet. -- break; -- case FINISHED: -- throw new SSLException("renegotiation unsupported"); -- case NOT_STARTED: -- handshakeState = HandshakeState.STARTED_EXPLICITLY; -- if (handshake() == NEED_TASK) { -- // Set needTask to true so getHandshakeStatus() will return the correct value. -- needTask = true; -- } -- calculateMaxWrapOverhead(); -- break; -- default: -- throw new Error(); -- } -- } -- -- private void checkEngineClosed() throws SSLException { -- if (isDestroyed()) { -- throw new SSLException("engine closed"); -- } -- } -- -- private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) { -- // Depending on if there is something left in the BIO we need to WRAP or UNWRAP -- return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP; -- } -- -- private static boolean isEmpty(Object[] arr) { -- return arr == null || arr.length == 0; -- } -- -- private static boolean isEmpty(byte[] cert) { -- return cert == null || cert.length == 0; -- } -- -- private SSLEngineResult.HandshakeStatus handshakeException() throws SSLException { -- if (SSL.bioLengthNonApplication(networkBIO) > 0) { -- // There is something pending, we need to consume it first via a WRAP so we don't loose anything. -- return NEED_WRAP; -- } -- -- Throwable exception = pendingException; -- assert exception != null; -- pendingException = null; -- shutdown(); -- if (exception instanceof SSLHandshakeException) { -- throw (SSLHandshakeException) exception; -- } -- SSLHandshakeException e = new SSLHandshakeException("General OpenSslEngine problem"); -- e.initCause(exception); -- throw e; -- } -- -- /** -- * Should be called if the handshake will be failed due a callback that throws an exception. -- * This cause will then be used to give more details as part of the {@link SSLHandshakeException}. -- */ -- final void initHandshakeException(Throwable cause) { -- if (pendingException == null) { -- pendingException = cause; -- } else { -- ThrowableUtil.addSuppressed(pendingException, cause); -- } -- } -- -- private SSLEngineResult.HandshakeStatus handshake() throws SSLException { -- if (needTask) { -- return NEED_TASK; -- } -- if (handshakeState == HandshakeState.FINISHED) { -- return FINISHED; -- } -- -- checkEngineClosed(); -- -- if (pendingException != null) { -- // Let's call SSL.doHandshake(...) again in case there is some async operation pending that would fill the -- // outbound buffer. -- if (SSL.doHandshake(ssl) <= 0) { -- // Clear any error that was put on the stack by the handshake -- SSL.clearError(); -- } -- return handshakeException(); -- } -- -- // Adding the OpenSslEngine to the OpenSslEngineMap so it can be used in the AbstractCertificateVerifier. -- engineMap.add(this); -- -- if (!sessionSet) { -- if (!parentContext.sessionContext().setSessionFromCache(ssl, session, getPeerHost(), getPeerPort())) { -- // The session was not reused via the cache. Call prepareHandshake() to ensure we remove all previous -- // stored key-value pairs. -- session.prepareHandshake(); -- } -- sessionSet = true; -- } -- -- int code = SSL.doHandshake(ssl); -- if (code <= 0) { -- int sslError = SSL.getError(ssl, code); -- if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) { -- return pendingStatus(SSL.bioLengthNonApplication(networkBIO)); -- } -- -- if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP || -- sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY || -- sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) { -- return NEED_TASK; -- } -- -- if (needWrapAgain(SSL.getLastErrorNumber())) { -- // There is something that needs to be send to the remote peer before we can teardown. -- // This is most likely some alert. -- return NEED_WRAP; -- } -- // Check if we have a pending exception that was created during the handshake and if so throw it after -- // shutdown the connection. -- if (pendingException != null) { -- return handshakeException(); -- } -- -- // Everything else is considered as error -- throw shutdownWithError("SSL_do_handshake", sslError); -- } -- // We have produced more data as part of the handshake if this is the case the user should call wrap(...) -- if (SSL.bioLengthNonApplication(networkBIO) > 0) { -- return NEED_WRAP; -- } -- // if SSL_do_handshake returns > 0 or sslError == SSL.SSL_ERROR_NAME it means the handshake was finished. -- session.handshakeFinished(SSL.getSessionId(ssl), SSL.getCipherForSSL(ssl), SSL.getVersion(ssl), -- SSL.getPeerCertificate(ssl), SSL.getPeerCertChain(ssl), -- SSL.getTime(ssl) * 1000L, parentContext.sessionTimeout() * 1000L); -- selectApplicationProtocol(); -- return FINISHED; -- } -- -- private SSLEngineResult.HandshakeStatus mayFinishHandshake( -- SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) throws SSLException { -- return hs == NEED_UNWRAP && bytesProduced > 0 || hs == NEED_WRAP && bytesConsumed > 0 ? -- handshake() : mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED); -- } -- -- private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status) -- throws SSLException { -- if (status == NOT_HANDSHAKING) { -- if (handshakeState != HandshakeState.FINISHED) { -- // If the status was NOT_HANDSHAKING and we not finished the handshake we need to call -- // SSL_do_handshake() again -- return handshake(); -- } -- if (!isDestroyed() && SSL.bioLengthNonApplication(networkBIO) > 0) { -- // We have something left that needs to be wrapped. -- return NEED_WRAP; -- } -- } -- return status; -- } -- -- @Override -- public final synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() { -- // Check if we are in the initial handshake phase or shutdown phase -- if (needPendingStatus()) { -- if (needTask) { -- // There is a task outstanding -- return NEED_TASK; -- } -- return pendingStatus(SSL.bioLengthNonApplication(networkBIO)); -- } -- return NOT_HANDSHAKING; -- } -- -- private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) { -- // Check if we are in the initial handshake phase or shutdown phase -- if (needPendingStatus()) { -- if (needTask) { -- // There is a task outstanding -- return NEED_TASK; -- } -- return pendingStatus(pending); -- } -- return NOT_HANDSHAKING; -- } -- -- private boolean needPendingStatus() { -- return handshakeState != HandshakeState.NOT_STARTED && !isDestroyed() -- && (handshakeState != HandshakeState.FINISHED || isInboundDone() || isOutboundDone()); -- } -- -- /** -- * Converts the specified OpenSSL cipher suite to the Java cipher suite. -- */ -- private String toJavaCipherSuite(String openSslCipherSuite) { -- if (openSslCipherSuite == null) { -- return null; -- } -- -- String version = SSL.getVersion(ssl); -- String prefix = toJavaCipherSuitePrefix(version); -- 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.isEmpty()) { -- c = 0; -- } else { -- c = protocolVersion.charAt(0); -- } -- -- switch (c) { -- case 'T': -- return "TLS"; -- case 'S': -- return "SSL"; -- default: -- return "UNKNOWN"; -- } -- } -- -- @Override -- public final void setUseClientMode(boolean clientMode) { -- if (clientMode != this.clientMode) { -- throw new UnsupportedOperationException(); -- } -- } -- -- @Override -- public final boolean getUseClientMode() { -- return clientMode; -- } -- -- @Override -- public final void setNeedClientAuth(boolean b) { -- setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE); -- } -- -- @Override -- public final boolean getNeedClientAuth() { -- return clientAuth == ClientAuth.REQUIRE; -- } -- -- @Override -- public final void setWantClientAuth(boolean b) { -- setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE); -- } -- -- @Override -- public final boolean getWantClientAuth() { -- return clientAuth == ClientAuth.OPTIONAL; -- } -- -- /** -- * See SSL_set_verify and -- * {@link SSL#setVerify(long, int, int)}. -- */ -- @UnstableApi -- public final synchronized void setVerify(int verifyMode, int depth) { -- if (!isDestroyed()) { -- SSL.setVerify(ssl, verifyMode, depth); -- } -- } -- -- private void setClientAuth(ClientAuth mode) { -- if (clientMode) { -- return; -- } -- synchronized (this) { -- if (clientAuth == mode) { -- // No need to issue any JNI calls if the mode is the same -- return; -- } -- if (!isDestroyed()) { -- switch (mode) { -- case NONE: -- SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH); -- break; -- case REQUIRE: -- SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH); -- break; -- case OPTIONAL: -- SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH); -- break; -- default: -- throw new Error(mode.toString()); -- } -- } -- clientAuth = mode; -- } -- } -- -- @Override -- public final void setEnableSessionCreation(boolean b) { -- if (b) { -- throw new UnsupportedOperationException(); -- } -- } -- -- @Override -- public final boolean getEnableSessionCreation() { -- return false; -- } -- -- @SuppressJava6Requirement(reason = "Usage guarded by java version check") -- @Override -- public final synchronized SSLParameters getSSLParameters() { -- SSLParameters sslParameters = super.getSSLParameters(); -- -- int version = PlatformDependent.javaVersion(); -- if (version >= 7) { -- Java7SslParametersUtils.setEndpointIdentificationAlgorithm(sslParameters, endpointIdentificationAlgorithm); -- Java7SslParametersUtils.setAlgorithmConstraints(sslParameters, algorithmConstraints); -- if (version >= 8) { -- if (sniHostNames != null) { -- Java8SslUtils.setSniHostNames(sslParameters, sniHostNames); -- } -- if (!isDestroyed()) { -- Java8SslUtils.setUseCipherSuitesOrder( -- sslParameters, (SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0); -- } -- -- Java8SslUtils.setSNIMatchers(sslParameters, matchers); -- } -- } -- return sslParameters; -- } -- -- @SuppressJava6Requirement(reason = "Usage guarded by java version check") -- @Override -- public final synchronized void setSSLParameters(SSLParameters sslParameters) { -- int version = PlatformDependent.javaVersion(); -- if (version >= 7) { -- if (sslParameters.getAlgorithmConstraints() != null) { -- throw new IllegalArgumentException("AlgorithmConstraints are not supported."); -- } -- -- boolean isDestroyed = isDestroyed(); -- if (version >= 8) { -- if (!isDestroyed) { -- if (clientMode) { -- final List sniHostNames = Java8SslUtils.getSniHostNames(sslParameters); -- for (String name: sniHostNames) { -- SSL.setTlsExtHostName(ssl, name); -- } -- this.sniHostNames = sniHostNames; -- } -- if (Java8SslUtils.getUseCipherSuitesOrder(sslParameters)) { -- SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); -- } else { -- SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); -- } -- } -- matchers = sslParameters.getSNIMatchers(); -- } -- -- final String endpointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm(); -- if (!isDestroyed) { -- configureEndpointVerification(endpointIdentificationAlgorithm); -- } -- this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; -- algorithmConstraints = sslParameters.getAlgorithmConstraints(); -- } -- super.setSSLParameters(sslParameters); -- } -- -- private void configureEndpointVerification(String endpointIdentificationAlgorithm) { -- // If the user asks for hostname verification we must ensure we verify the peer. -- // If the user disables hostname verification we leave it up to the user to change the mode manually. -- if (clientMode && isEndPointVerificationEnabled(endpointIdentificationAlgorithm)) { -- SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1); -- } -- } -- -- private static boolean isEndPointVerificationEnabled(String endPointIdentificationAlgorithm) { -- return endPointIdentificationAlgorithm != null && !endPointIdentificationAlgorithm.isEmpty(); -- } -- -- private boolean isDestroyed() { -- return destroyed; -- } -- -- final boolean checkSniHostnameMatch(byte[] hostname) { -- return Java8SslUtils.checkSniHostnameMatch(matchers, hostname); -- } -- -- @Override -- public String getNegotiatedApplicationProtocol() { -- return applicationProtocol; -- } -- -- private static long bufferAddress(ByteBuffer b) { -- assert b.isDirect(); -- if (PlatformDependent.hasUnsafe()) { -- return PlatformDependent.directBufferAddress(b); -- } -- return Buffer.address(b); -- } -- -- /** -- * Select the application protocol used. -- */ -- private void selectApplicationProtocol() throws SSLException { -- ApplicationProtocolConfig.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) { -- ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol( -- protocols, behavior, applicationProtocol); -- } -- break; -- case NPN: -- applicationProtocol = SSL.getNextProtoNegotiated(ssl); -- if (applicationProtocol != null) { -- ReferenceCountedOpenSslEngine.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) { -- ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol( -- protocols, behavior, applicationProtocol); -- } -- break; -- default: -- throw new Error(); -- } -- } -- -- private String selectApplicationProtocol(List protocols, -- ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior, -- String applicationProtocol) throws SSLException { -- if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) { -- return applicationProtocol; -- } else { -- int size = protocols.size(); -- assert size > 0; -- if (protocols.contains(applicationProtocol)) { -- return applicationProtocol; -- } else { -- if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) { -- return protocols.get(size - 1); -- } else { -- throw new SSLException("unknown protocol " + applicationProtocol); -- } -- } -- } -- } -- -- private static final X509Certificate[] JAVAX_CERTS_NOT_SUPPORTED = new X509Certificate[0]; -- -- private final class DefaultOpenSslSession implements OpenSslSession { -- private final OpenSslSessionContext sessionContext; -- -- // These are guarded by synchronized(OpenSslEngine.this) as handshakeFinished() may be triggered by any -- // thread. -- private X509Certificate[] x509PeerCerts; -- private Certificate[] peerCerts; -- -- private boolean valid = true; -- private String protocol; -- private String cipher; -- private OpenSslSessionId id = OpenSslSessionId.NULL_ID; -- private long creationTime; -- -- // Updated once a new handshake is started and so the SSLSession reused. -- private long lastAccessed = -1; -- -- private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH; -- private volatile Certificate[] localCertificateChain; -- private volatile Map keyValueStorage = new ConcurrentHashMap(); -- -- DefaultOpenSslSession(OpenSslSessionContext sessionContext) { -- this.sessionContext = sessionContext; -- } -- -- private SSLSessionBindingEvent newSSLSessionBindingEvent(String name) { -- return new SSLSessionBindingEvent(session, name); -- } -- -- @Override -- public void prepareHandshake() { -- keyValueStorage.clear(); -- } -- -- @Override -- public void setSessionDetails( -- long creationTime, long lastAccessedTime, OpenSslSessionId sessionId, -- Map keyValueStorage) { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (this.id == OpenSslSessionId.NULL_ID) { -- this.id = sessionId; -- this.creationTime = creationTime; -- this.lastAccessed = lastAccessedTime; -- -- // Update the key value storage. It's fine to just drop the previous stored values on the floor -- // as the JDK does the same in the sense that it will use a new SSLSessionImpl instance once the -- // handshake was done -- this.keyValueStorage = keyValueStorage; -- } -- } -- } -- -- @Override -- public Map keyValueStorage() { -- return keyValueStorage; -- } -- -- @Override -- public OpenSslSessionId sessionId() { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (this.id == OpenSslSessionId.NULL_ID && !isDestroyed()) { -- byte[] sessionId = SSL.getSessionId(ssl); -- if (sessionId != null) { -- id = new OpenSslSessionId(sessionId); -- } -- } -- -- return id; -- } -- } -- -- @Override -- public void setLocalCertificate(Certificate[] localCertificate) { -- this.localCertificateChain = localCertificate; -- } -- -- @Override -- public byte[] getId() { -- return sessionId().cloneBytes(); -- } -- -- @Override -- public OpenSslSessionContext getSessionContext() { -- return sessionContext; -- } -- -- @Override -- public long getCreationTime() { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- return creationTime; -- } -- } -- -- @Override -- public void setLastAccessedTime(long time) { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- this.lastAccessed = time; -- } -- } -- -- @Override -- public long getLastAccessedTime() { -- // if lastAccessed is -1 we will just return the creation time as the handshake was not started yet. -- synchronized (ReferenceCountedOpenSslEngine.this) { -- return lastAccessed == -1 ? creationTime : lastAccessed; -- } -- } -- -- @Override -- public void invalidate() { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- valid = false; -- sessionContext.removeFromCache(id); -- } -- } -- -- @Override -- public boolean isValid() { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- return valid || sessionContext.isInCache(id); -- } -- } -- -- @Override -- public void putValue(String name, Object value) { -- checkNotNull(name, "name"); -- checkNotNull(value, "value"); -- -- final Object old = keyValueStorage.put(name, value); -- if (value instanceof SSLSessionBindingListener) { -- // Use newSSLSessionBindingEvent so we always use the wrapper if needed. -- ((SSLSessionBindingListener) value).valueBound(newSSLSessionBindingEvent(name)); -- } -- notifyUnbound(old, name); -- } -- -- @Override -- public Object getValue(String name) { -- checkNotNull(name, "name"); -- return keyValueStorage.get(name); -- } -- -- @Override -- public void removeValue(String name) { -- checkNotNull(name, "name"); -- final Object old = keyValueStorage.remove(name); -- notifyUnbound(old, name); -- } -- -- @Override -- public String[] getValueNames() { -- return keyValueStorage.keySet().toArray(EMPTY_STRINGS); -- } -- -- private void notifyUnbound(Object value, String name) { -- if (value instanceof SSLSessionBindingListener) { -- // Use newSSLSessionBindingEvent so we always use the wrapper if needed. -- ((SSLSessionBindingListener) value).valueUnbound(newSSLSessionBindingEvent(name)); -- } -- } -- -- /** -- * Finish the handshake and so init everything in the {@link OpenSslSession} that should be accessible by -- * the user. -- */ -- @Override -- public void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate, -- byte[][] peerCertificateChain, long creationTime, long timeout) -- throws SSLException { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (!isDestroyed()) { -- if (this.id == OpenSslSessionId.NULL_ID) { -- // if the handshake finished and it was not a resumption let ensure we try to set the id -- -- this.id = id == null ? OpenSslSessionId.NULL_ID : new OpenSslSessionId(id); -- // Once the handshake was done the lastAccessed and creationTime should be the same if we -- // did not set it earlier via setSessionDetails(...) -- this.creationTime = lastAccessed = creationTime; -- } -- this.cipher = toJavaCipherSuite(cipher); -- this.protocol = protocol; -- -- if (clientMode) { -- if (isEmpty(peerCertificateChain)) { -- peerCerts = EmptyArrays.EMPTY_CERTIFICATES; -- if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) { -- x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES; -- } else { -- x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED; -- } -- } else { -- peerCerts = new Certificate[peerCertificateChain.length]; -- if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) { -- x509PeerCerts = new X509Certificate[peerCertificateChain.length]; -- } else { -- x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED; -- } -- initCerts(peerCertificateChain, 0); -- } -- } else { -- // 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 -- if (isEmpty(peerCertificate)) { -- peerCerts = EmptyArrays.EMPTY_CERTIFICATES; -- x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES; -- } else { -- if (isEmpty(peerCertificateChain)) { -- peerCerts = new Certificate[] {new LazyX509Certificate(peerCertificate)}; -- if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) { -- x509PeerCerts = new X509Certificate[] { -- new LazyJavaxX509Certificate(peerCertificate) -- }; -- } else { -- x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED; -- } -- } else { -- peerCerts = new Certificate[peerCertificateChain.length + 1]; -- peerCerts[0] = new LazyX509Certificate(peerCertificate); -- -- if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) { -- x509PeerCerts = new X509Certificate[peerCertificateChain.length + 1]; -- x509PeerCerts[0] = new LazyJavaxX509Certificate(peerCertificate); -- } else { -- x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED; -- } -- -- initCerts(peerCertificateChain, 1); -- } -- } -- } -- -- calculateMaxWrapOverhead(); -- -- handshakeState = HandshakeState.FINISHED; -- } else { -- throw new SSLException("Already closed"); -- } -- } -- } -- -- private void initCerts(byte[][] chain, int startPos) { -- for (int i = 0; i < chain.length; i++) { -- int certPos = startPos + i; -- peerCerts[certPos] = new LazyX509Certificate(chain[i]); -- if (x509PeerCerts != JAVAX_CERTS_NOT_SUPPORTED) { -- x509PeerCerts[certPos] = new LazyJavaxX509Certificate(chain[i]); -- } -- } -- } -- -- @Override -- public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (isEmpty(peerCerts)) { -- throw new SSLPeerUnverifiedException("peer not verified"); -- } -- return peerCerts.clone(); -- } -- } -- -- @Override -- public Certificate[] getLocalCertificates() { -- Certificate[] localCerts = this.localCertificateChain; -- if (localCerts == null) { -- return null; -- } -- return localCerts.clone(); -- } -- -- @Override -- public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (x509PeerCerts == JAVAX_CERTS_NOT_SUPPORTED) { -- // Not supported by the underlying JDK, so just throw. This is fine in terms of the API -- // contract. See SSLSession.html#getPeerCertificateChain(). -- throw new UnsupportedOperationException(); -- } -- if (isEmpty(x509PeerCerts)) { -- throw new SSLPeerUnverifiedException("peer not verified"); -- } -- return x509PeerCerts.clone(); -- } -- } -- -- @Override -- public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { -- Certificate[] peer = getPeerCertificates(); -- // No need for null or length > 0 is needed as this is done in getPeerCertificates() -- // already. -- return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal(); -- } -- -- @Override -- public Principal getLocalPrincipal() { -- Certificate[] local = this.localCertificateChain; -- if (local == null || local.length == 0) { -- return null; -- } -- return ((java.security.cert.X509Certificate) local[0]).getSubjectX500Principal(); -- } -- -- @Override -- public String getCipherSuite() { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (cipher == null) { -- return SslUtils.INVALID_CIPHER; -- } -- return cipher; -- } -- } -- -- @Override -- public String getProtocol() { -- String protocol = this.protocol; -- if (protocol == null) { -- synchronized (ReferenceCountedOpenSslEngine.this) { -- if (!isDestroyed()) { -- protocol = SSL.getVersion(ssl); -- } else { -- protocol = StringUtil.EMPTY_STRING; -- } -- } -- } -- return protocol; -- } -- -- @Override -- public String getPeerHost() { -- return ReferenceCountedOpenSslEngine.this.getPeerHost(); -- } -- -- @Override -- public int getPeerPort() { -- return ReferenceCountedOpenSslEngine.this.getPeerPort(); -- } -- -- @Override -- public int getPacketBufferSize() { -- return SSL.SSL_MAX_ENCRYPTED_LENGTH; -- } -- -- @Override -- public int getApplicationBufferSize() { -- return applicationBufferSize; -- } -- -- @Override -- public void tryExpandApplicationBufferSize(int packetLengthDataOnly) { -- if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) { -- applicationBufferSize = MAX_RECORD_SIZE; -- } -- } -- -- @Override -- public String toString() { -- return "DefaultOpenSslSession{" + -- "sessionContext=" + sessionContext + -- ", id=" + id + -- '}'; -- } -- -- @Override -- public int hashCode() { -- return sessionId().hashCode(); -- } -- -- @Override -- public boolean equals(Object o) { -- if (o == this) { -- return true; -- } -- // We trust all sub-types as we use different types but the interface is package-private -- if (!(o instanceof OpenSslSession)) { -- return false; -- } -- return sessionId().equals(((OpenSslSession) o).sessionId()); -- } -- } -- -- private interface NativeSslException { -- int errorCode(); -- } -- -- private static final class OpenSslException extends SSLException implements NativeSslException { -- private final int errorCode; -- -- OpenSslException(String reason, int errorCode) { -- super(reason); -- this.errorCode = errorCode; -- } -- -- @Override -- public int errorCode() { -- return errorCode; -- } -- } -- -- private static final class OpenSslHandshakeException extends SSLHandshakeException implements NativeSslException { -- private final int errorCode; -- -- OpenSslHandshakeException(String reason, int errorCode) { -- super(reason); -- this.errorCode = errorCode; -- } -- -- @Override -- public int errorCode() { -- return errorCode; -- } -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java -deleted file mode 100644 -index 862ab72..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java -+++ /dev/null -@@ -1,302 +0,0 @@ --/* -- * Copyright 2016 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: -- * -- * https://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.internal.tcnative.CertificateCallback; --import io.netty.internal.tcnative.SSL; --import io.netty.internal.tcnative.SSLContext; --import io.netty.internal.tcnative.SniHostNameMatcher; --import io.netty.util.CharsetUtil; --import io.netty.util.internal.PlatformDependent; --import io.netty.util.internal.SuppressJava6Requirement; --import io.netty.util.internal.logging.InternalLogger; --import io.netty.util.internal.logging.InternalLoggerFactory; -- --import java.security.KeyStore; --import java.security.PrivateKey; --import java.security.cert.X509Certificate; --import java.util.Map; --import javax.net.ssl.KeyManagerFactory; --import javax.net.ssl.SSLException; --import javax.net.ssl.TrustManagerFactory; --import javax.net.ssl.X509ExtendedTrustManager; --import javax.net.ssl.X509TrustManager; -- --import static io.netty.util.internal.ObjectUtil.checkNotNull; -- --/** -- * A server-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation. -- *

Instances of this class must be {@link #release() released} or else native memory will leak! -- * -- *

Instances of this class must not be released before any {@link ReferenceCountedOpenSslEngine} -- * which depends upon the instance of this class is released. Otherwise if any method of -- * {@link ReferenceCountedOpenSslEngine} is called which uses this class's JNI resources the JVM may crash. -- */ --public final class ReferenceCountedOpenSslServerContext extends ReferenceCountedOpenSslContext { -- private static final InternalLogger logger = -- InternalLoggerFactory.getInstance(ReferenceCountedOpenSslServerContext.class); -- private static final byte[] ID = {'n', 'e', 't', 't', 'y'}; -- private final OpenSslServerSessionContext sessionContext; -- -- ReferenceCountedOpenSslServerContext( -- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, -- Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, -- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, -- boolean enableOcsp, String keyStore, ResumptionController resumptionController, -- Map.Entry, Object>... options) throws SSLException { -- this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers, -- cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls, -- enableOcsp, keyStore, resumptionController, options); -- } -- -- ReferenceCountedOpenSslServerContext( -- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, -- Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, -- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, -- boolean enableOcsp, String keyStore, ResumptionController resumptionController, -- Map.Entry, Object>... options) throws SSLException { -- super(ciphers, cipherFilter, apn, SSL.SSL_MODE_SERVER, keyCertChain, -- clientAuth, protocols, startTls, -- null, // No endpoint validation for servers. -- enableOcsp, true, resumptionController, options); -- // Create a new SSL_CTX and configure it. -- boolean success = false; -- try { -- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory, -- keyCertChain, key, keyPassword, keyManagerFactory, keyStore, -- sessionCacheSize, sessionTimeout, resumptionController); -- if (SERVER_ENABLE_SESSION_TICKET) { -- sessionContext.setTicketKeys(); -- } -- success = true; -- } finally { -- if (!success) { -- release(); -- } -- } -- } -- -- @Override -- public OpenSslServerSessionContext sessionContext() { -- return sessionContext; -- } -- -- static OpenSslServerSessionContext newSessionContext(ReferenceCountedOpenSslContext thiz, long ctx, -- OpenSslEngineMap engineMap, -- X509Certificate[] trustCertCollection, -- TrustManagerFactory trustManagerFactory, -- X509Certificate[] keyCertChain, PrivateKey key, -- String keyPassword, KeyManagerFactory keyManagerFactory, -- String keyStore, long sessionCacheSize, long sessionTimeout, -- ResumptionController resumptionController) -- throws SSLException { -- OpenSslKeyMaterialProvider keyMaterialProvider = null; -- try { -- try { -- SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, VERIFY_DEPTH); -- if (!OpenSsl.useKeyManagerFactory()) { -- if (keyManagerFactory != null) { -- throw new IllegalArgumentException( -- "KeyManagerFactory not supported"); -- } -- checkNotNull(keyCertChain, "keyCertChain"); -- -- setKeyMaterial(ctx, keyCertChain, key, keyPassword); -- } else { -- // javadocs state that keyManagerFactory has precedent over keyCertChain, and we must have a -- // keyManagerFactory for the server so build one if it is not specified. -- if (keyManagerFactory == null) { -- char[] keyPasswordChars = keyStorePassword(keyPassword); -- KeyStore ks = buildKeyStore(keyCertChain, key, keyPasswordChars, keyStore); -- if (ks.aliases().hasMoreElements()) { -- keyManagerFactory = new OpenSslX509KeyManagerFactory(); -- } else { -- keyManagerFactory = new OpenSslCachingX509KeyManagerFactory( -- KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())); -- } -- keyManagerFactory.init(ks, keyPasswordChars); -- } -- keyMaterialProvider = providerFor(keyManagerFactory, keyPassword); -- -- SSLContext.setCertificateCallback(ctx, new OpenSslServerCertificateCallback( -- engineMap, new OpenSslKeyMaterialManager(keyMaterialProvider))); -- } -- } catch (Exception e) { -- throw new SSLException("failed to set certificate and key", e); -- } -- try { -- if (trustCertCollection != null) { -- trustManagerFactory = buildTrustManagerFactory(trustCertCollection, trustManagerFactory, keyStore); -- } else if (trustManagerFactory == null) { -- // Mimic the way SSLContext.getInstance(KeyManager[], null, null) works -- trustManagerFactory = TrustManagerFactory.getInstance( -- TrustManagerFactory.getDefaultAlgorithm()); -- trustManagerFactory.init((KeyStore) null); -- } -- -- final X509TrustManager manager = chooseTrustManager( -- trustManagerFactory.getTrustManagers(), resumptionController); -- -- // IMPORTANT: The callbacks set for verification must be static to prevent memory leak as -- // otherwise the context can never be collected. This is because the JNI code holds -- // a global reference to the callbacks. -- // -- // See https://github.com/netty/netty/issues/5372 -- -- setVerifyCallback(ctx, engineMap, manager); -- -- X509Certificate[] issuers = manager.getAcceptedIssuers(); -- if (issuers != null && issuers.length > 0) { -- long bio = 0; -- try { -- bio = toBIO(ByteBufAllocator.DEFAULT, issuers); -- if (!SSLContext.setCACertificateBio(ctx, bio)) { -- throw new SSLException("unable to setup accepted issuers for trustmanager " + manager); -- } -- } finally { -- freeBio(bio); -- } -- } -- -- if (PlatformDependent.javaVersion() >= 8) { -- // Only do on Java8+ as SNIMatcher is not supported in earlier releases. -- // IMPORTANT: The callbacks set for hostname matching must be static to prevent memory leak as -- // otherwise the context can never be collected. This is because the JNI code holds -- // a global reference to the matcher. -- SSLContext.setSniHostnameMatcher(ctx, new OpenSslSniHostnameMatcher(engineMap)); -- } -- } catch (SSLException e) { -- throw e; -- } catch (Exception e) { -- throw new SSLException("unable to setup trustmanager", e); -- } -- -- OpenSslServerSessionContext sessionContext = new OpenSslServerSessionContext(thiz, keyMaterialProvider); -- sessionContext.setSessionIdContext(ID); -- // Enable session caching by default -- sessionContext.setSessionCacheEnabled(SERVER_ENABLE_SESSION_CACHE); -- if (sessionCacheSize > 0) { -- sessionContext.setSessionCacheSize((int) Math.min(sessionCacheSize, Integer.MAX_VALUE)); -- } -- if (sessionTimeout > 0) { -- sessionContext.setSessionTimeout((int) Math.min(sessionTimeout, Integer.MAX_VALUE)); -- } -- -- keyMaterialProvider = null; -- -- return sessionContext; -- } finally { -- if (keyMaterialProvider != null) { -- keyMaterialProvider.destroy(); -- } -- } -- } -- -- @SuppressJava6Requirement(reason = "Guarded by java version check") -- private static void setVerifyCallback(long ctx, OpenSslEngineMap engineMap, X509TrustManager manager) { -- // Use this to prevent an error when running on java < 7 -- if (useExtendedTrustManager(manager)) { -- SSLContext.setCertVerifyCallback(ctx, new ExtendedTrustManagerVerifyCallback( -- engineMap, (X509ExtendedTrustManager) manager)); -- } else { -- SSLContext.setCertVerifyCallback(ctx, new TrustManagerVerifyCallback(engineMap, manager)); -- } -- } -- -- private static final class OpenSslServerCertificateCallback implements CertificateCallback { -- private final OpenSslEngineMap engineMap; -- private final OpenSslKeyMaterialManager keyManagerHolder; -- -- OpenSslServerCertificateCallback(OpenSslEngineMap engineMap, OpenSslKeyMaterialManager keyManagerHolder) { -- this.engineMap = engineMap; -- this.keyManagerHolder = keyManagerHolder; -- } -- -- @Override -- public void handle(long ssl, byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) throws Exception { -- final ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- if (engine == null) { -- // Maybe null if destroyed in the meantime. -- return; -- } -- try { -- // For now we just ignore the asn1DerEncodedPrincipals as this is kind of inline with what the -- // OpenJDK SSLEngineImpl does. -- keyManagerHolder.setKeyMaterialServerSide(engine); -- } catch (Throwable cause) { -- engine.initHandshakeException(cause); -- -- if (cause instanceof Exception) { -- throw (Exception) cause; -- } -- throw new SSLException(cause); -- } -- } -- } -- -- private static final class TrustManagerVerifyCallback extends AbstractCertificateVerifier { -- private final X509TrustManager manager; -- -- TrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509TrustManager manager) { -- super(engineMap); -- this.manager = manager; -- } -- -- @Override -- void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth) -- throws Exception { -- manager.checkClientTrusted(peerCerts, auth); -- } -- } -- -- @SuppressJava6Requirement(reason = "Usage guarded by java version check") -- private static final class ExtendedTrustManagerVerifyCallback extends AbstractCertificateVerifier { -- private final X509ExtendedTrustManager manager; -- -- ExtendedTrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509ExtendedTrustManager manager) { -- super(engineMap); -- this.manager = manager; -- } -- -- @Override -- void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth) -- throws Exception { -- manager.checkClientTrusted(peerCerts, auth, engine); -- } -- } -- -- private static final class OpenSslSniHostnameMatcher implements SniHostNameMatcher { -- private final OpenSslEngineMap engineMap; -- -- OpenSslSniHostnameMatcher(OpenSslEngineMap engineMap) { -- this.engineMap = engineMap; -- } -- -- @Override -- public boolean match(long ssl, String hostname) { -- ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); -- if (engine != null) { -- // TODO: In the next release of tcnative we should pass the byte[] directly in and not use a String. -- return engine.checkSniHostnameMatch(hostname.getBytes(CharsetUtil.UTF_8)); -- } -- logger.warn("No ReferenceCountedOpenSslEngine found for SSL pointer: {}", ssl); -- return false; -- } -- } --} -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 137cbf3..7b649d9 100644 ---- a/handler/src/main/java/io/netty/handler/ssl/SslContext.java -+++ b/handler/src/main/java/io/netty/handler/ssl/SslContext.java -@@ -129,11 +129,7 @@ public abstract class SslContext { - } - - private static SslProvider defaultProvider() { -- if (OpenSsl.isAvailable()) { -- return SslProvider.OPENSSL; -- } else { -- return SslProvider.JDK; -- } -+ return SslProvider.JDK; - } - - /** -@@ -479,18 +475,6 @@ public abstract class SslContext { - trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, - keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, - clientAuth, protocols, startTls, secureRandom, keyStoreType, resumptionController); -- case OPENSSL: -- verifyNullSslContextProvider(provider, sslContextProvider); -- return new OpenSslServerContext( -- trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, -- keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, -- clientAuth, protocols, startTls, enableOcsp, keyStoreType, resumptionController, ctxOptions); -- case OPENSSL_REFCNT: -- verifyNullSslContextProvider(provider, sslContextProvider); -- return new ReferenceCountedOpenSslServerContext( -- trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, -- keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, -- clientAuth, protocols, startTls, enableOcsp, keyStoreType, resumptionController, ctxOptions); - default: - throw new Error(provider.toString()); - } -@@ -841,20 +825,6 @@ public abstract class SslContext { - keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, - sessionTimeout, secureRandom, keyStoreType, endpointIdentificationAlgorithm, - resumptionController); -- case OPENSSL: -- verifyNullSslContextProvider(provider, sslContextProvider); -- OpenSsl.ensureAvailability(); -- return new OpenSslClientContext( -- trustCert, trustManagerFactory, keyCertChain, key, keyPassword, -- keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout, -- enableOcsp, keyStoreType, endpointIdentificationAlgorithm, resumptionController, options); -- case OPENSSL_REFCNT: -- verifyNullSslContextProvider(provider, sslContextProvider); -- OpenSsl.ensureAvailability(); -- return new ReferenceCountedOpenSslClientContext( -- trustCert, trustManagerFactory, keyCertChain, key, keyPassword, -- keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout, -- enableOcsp, keyStoreType, endpointIdentificationAlgorithm, resumptionController, options); - default: - throw new Error(provider.toString()); - } -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 40a46d2..53afec2 100644 ---- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java -+++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java -@@ -200,57 +200,6 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH - private static final int MAX_PLAINTEXT_LENGTH = 16 * 1024; - - private enum SslEngineType { -- TCNATIVE(true, COMPOSITE_CUMULATOR) { -- @Override -- SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int len, ByteBuf out) throws SSLException { -- int nioBufferCount = in.nioBufferCount(); -- int writerIndex = out.writerIndex(); -- final SSLEngineResult result; -- if (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. -- */ -- ReferenceCountedOpenSslEngine opensslEngine = (ReferenceCountedOpenSslEngine) handler.engine; -- try { -- handler.singleBuffer[0] = toByteBuffer(out, writerIndex, out.writableBytes()); -- result = opensslEngine.unwrap(in.nioBuffers(in.readerIndex(), len), handler.singleBuffer); -- } finally { -- handler.singleBuffer[0] = null; -- } -- } else { -- result = handler.engine.unwrap(toByteBuffer(in, in.readerIndex(), len), -- toByteBuffer(out, writerIndex, out.writableBytes())); -- } -- out.writerIndex(writerIndex + result.bytesProduced()); -- return result; -- } -- -- @Override -- ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator, -- int pendingBytes, int numComponents) { -- return allocator.directBuffer(((ReferenceCountedOpenSslEngine) handler.engine) -- .calculateOutNetBufSize(pendingBytes, numComponents)); -- } -- -- @Override -- int calculateRequiredOutBufSpace(SslHandler handler, int pendingBytes, int numComponents) { -- return ((ReferenceCountedOpenSslEngine) handler.engine) -- .calculateMaxLengthForWrap(pendingBytes, numComponents); -- } -- -- @Override -- int calculatePendingData(SslHandler handler, int guess) { -- int sslPending = ((ReferenceCountedOpenSslEngine) handler.engine).sslPending(); -- return sslPending > 0 ? sslPending : guess; -- } -- -- @Override -- boolean jdkCompatibilityMode(SSLEngine engine) { -- return ((ReferenceCountedOpenSslEngine) engine).jdkCompatibilityMode; -- } -- }, - JDK(false, MERGE_CUMULATOR) { - @Override - SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int len, ByteBuf out) throws SSLException { -@@ -309,7 +258,7 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH - }; - - static SslEngineType forEngine(SSLEngine engine) { -- return engine instanceof ReferenceCountedOpenSslEngine ? TCNATIVE : JDK; -+ return JDK; - } - - SslEngineType(boolean wantsDirectBuffer, Cumulator cumulator) { -@@ -2078,7 +2027,6 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH - } - }; - -- setOpensslEngineSocketFd(channel); - boolean fastOpen = Boolean.TRUE.equals(channel.config().getOption(ChannelOption.TCP_FASTOPEN_CONNECT)); - boolean active = channel.isActive(); - if (active || fastOpen) { -@@ -2238,18 +2186,11 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH - ctx.flush(); - } - -- private void setOpensslEngineSocketFd(Channel c) { -- if (c instanceof UnixChannel && engine instanceof ReferenceCountedOpenSslEngine) { -- ((ReferenceCountedOpenSslEngine) engine).bioSetFd(((UnixChannel) c).fd().intValue()); -- } -- } -- - /** - * Issues an initial TLS handshake once connected when used in client-mode - */ - @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { -- setOpensslEngineSocketFd(ctx.channel()); - if (!startTls) { - startHandshakeProcessing(true); - } -diff --git a/handler/src/main/java/io/netty/handler/ssl/SslMasterKeyHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslMasterKeyHandler.java -index 3d8628e..c477dda 100644 ---- a/handler/src/main/java/io/netty/handler/ssl/SslMasterKeyHandler.java -+++ b/handler/src/main/java/io/netty/handler/ssl/SslMasterKeyHandler.java -@@ -139,9 +139,6 @@ public abstract class SslMasterKeyHandler extends ChannelInboundHandlerAdapter { - "via reflection.", e); - } - accept(secretKey, sslSession); -- } else if (OpenSsl.isAvailable() && engine instanceof ReferenceCountedOpenSslEngine) { -- SecretKeySpec secretKey = ((ReferenceCountedOpenSslEngine) engine).masterKey(); -- accept(secretKey, sslSession); - } - } - -diff --git a/handler/src/main/java/io/netty/handler/ssl/SslProvider.java b/handler/src/main/java/io/netty/handler/ssl/SslProvider.java -index 952b9e8..44dc842 100644 ---- a/handler/src/main/java/io/netty/handler/ssl/SslProvider.java -+++ b/handler/src/main/java/io/netty/handler/ssl/SslProvider.java -@@ -28,16 +28,7 @@ public enum SslProvider { - /** - * JDK's default implementation. - */ -- JDK, -- /** -- * OpenSSL-based implementation. -- */ -- OPENSSL, -- /** -- * OpenSSL-based implementation which does not have finalizers and instead implements {@link ReferenceCounted}. -- */ -- @UnstableApi -- OPENSSL_REFCNT; -+ JDK; - - /** - * Returns {@code true} if the specified {@link SslProvider} supports -@@ -48,9 +39,6 @@ public enum SslProvider { - switch (provider) { - case JDK: - return JdkAlpnApplicationProtocolNegotiator.isAlpnSupported(); -- case OPENSSL: -- case OPENSSL_REFCNT: -- return OpenSsl.isAlpnSupported(); - default: - throw new Error("Unknown SslProvider: " + provider); - } -@@ -72,9 +60,6 @@ public enum SslProvider { - switch (sslProvider) { - case JDK: - return SslUtils.isTLSv13SupportedByJDK(provider); -- case OPENSSL: -- case OPENSSL_REFCNT: -- return OpenSsl.isTlsv13Supported(); - default: - throw new Error("Unknown SslProvider: " + sslProvider); - } -@@ -89,9 +74,6 @@ public enum SslProvider { - case JDK: - // We currently don't support any SslContextOptions when using the JDK implementation - return false; -- case OPENSSL: -- case OPENSSL_REFCNT: -- return OpenSsl.isOptionSupported(option); - default: - throw new Error("Unknown SslProvider: " + sslProvider); - } -@@ -105,9 +87,6 @@ public enum SslProvider { - switch (sslProvider) { - case JDK: - return SslUtils.isTLSv13EnabledByJDK(provider); -- case OPENSSL: -- case OPENSSL_REFCNT: -- return OpenSsl.isTlsv13Supported(); - default: - throw new Error("Unknown SslProvider: " + sslProvider); - } -diff --git a/handler/src/main/java/io/netty/handler/ssl/ocsp/OcspClientHandler.java b/handler/src/main/java/io/netty/handler/ssl/ocsp/OcspClientHandler.java -deleted file mode 100644 -index 7f9cdf6..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ocsp/OcspClientHandler.java -+++ /dev/null -@@ -1,61 +0,0 @@ --/* -- * Copyright 2017 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: -- * -- * https://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.ocsp; -- --import io.netty.channel.ChannelHandlerContext; --import io.netty.channel.ChannelInboundHandlerAdapter; --import io.netty.handler.ssl.ReferenceCountedOpenSslContext; --import io.netty.handler.ssl.ReferenceCountedOpenSslEngine; --import io.netty.handler.ssl.SslHandshakeCompletionEvent; --import io.netty.util.internal.ObjectUtil; --import io.netty.util.internal.UnstableApi; -- --import javax.net.ssl.SSLHandshakeException; -- --/** -- * A handler for SSL clients to handle and act upon stapled OCSP responses. -- * -- * @see ReferenceCountedOpenSslContext#enableOcsp() -- * @see ReferenceCountedOpenSslEngine#getOcspResponse() -- */ --@UnstableApi --public abstract class OcspClientHandler extends ChannelInboundHandlerAdapter { -- -- private final ReferenceCountedOpenSslEngine engine; -- -- protected OcspClientHandler(ReferenceCountedOpenSslEngine engine) { -- this.engine = ObjectUtil.checkNotNull(engine, "engine"); -- } -- -- /** -- * @see ReferenceCountedOpenSslEngine#getOcspResponse() -- */ -- protected abstract boolean verify(ChannelHandlerContext ctx, ReferenceCountedOpenSslEngine engine) throws Exception; -- -- @Override -- public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { -- if (evt instanceof SslHandshakeCompletionEvent) { -- ctx.pipeline().remove(this); -- -- SslHandshakeCompletionEvent event = (SslHandshakeCompletionEvent) evt; -- if (event.isSuccess() && !verify(ctx, engine)) { -- throw new SSLHandshakeException("Bad OCSP response"); -- } -- } -- -- ctx.fireUserEventTriggered(evt); -- } --} -diff --git a/handler/src/main/java/io/netty/handler/ssl/ocsp/package-info.java b/handler/src/main/java/io/netty/handler/ssl/ocsp/package-info.java -deleted file mode 100644 -index 7e81ae6..0000000 ---- a/handler/src/main/java/io/netty/handler/ssl/ocsp/package-info.java -+++ /dev/null -@@ -1,23 +0,0 @@ --/* -- * Copyright 2017 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: -- * -- * https://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. -- */ -- --/** -- * OCSP stapling, -- * formally known as the TLS Certificate Status Request extension, is an -- * alternative approach to the Online Certificate Status Protocol (OCSP) -- * for checking the revocation status of X.509 digital certificates. -- */ --package io.netty.handler.ssl.ocsp; --- -2.47.0 - diff --git a/0006-Do-not-use-the-Graal-annotations.patch b/0006-Do-not-use-the-Graal-annotations.patch deleted file mode 100644 index afc2220c0d7d273b7376dfb66356528f93bd2aae..0000000000000000000000000000000000000000 --- a/0006-Do-not-use-the-Graal-annotations.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 6cc11ea389160c067b103bd4d0c356bb13442c77 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fridrich=20=C5=A0trba?= -Date: Thu, 30 Mar 2023 13:19:45 +0200 -Subject: [PATCH 5/7] Do not use the Graal annotations - ---- - .../java/io/netty/util/NetUtilSubstitutions.java | 13 ------------- - .../util/internal/svm/CleanerJava6Substitution.java | 10 ---------- - .../svm/PlatformDependent0Substitution.java | 10 ---------- - .../internal/svm/PlatformDependentSubstitution.java | 9 --------- - .../svm/UnsafeRefArrayAccessSubstitution.java | 9 --------- - 5 files changed, 51 deletions(-) - -diff --git a/common/src/main/java/io/netty/util/NetUtilSubstitutions.java b/common/src/main/java/io/netty/util/NetUtilSubstitutions.java -index 65c7bb94a5..18bfc1664f 100644 ---- a/common/src/main/java/io/netty/util/NetUtilSubstitutions.java -+++ b/common/src/main/java/io/netty/util/NetUtilSubstitutions.java -@@ -15,35 +15,22 @@ - */ - package io.netty.util; - --import com.oracle.svm.core.annotate.Alias; --import com.oracle.svm.core.annotate.InjectAccessors; --import com.oracle.svm.core.annotate.TargetClass; -- - import java.net.Inet4Address; - import java.net.Inet6Address; - import java.net.InetAddress; - import java.net.NetworkInterface; - import java.util.Collection; - --@TargetClass(NetUtil.class) - final class NetUtilSubstitutions { - private NetUtilSubstitutions() { - } - -- @Alias -- @InjectAccessors(NetUtilLocalhost4Accessor.class) - public static Inet4Address LOCALHOST4; - -- @Alias -- @InjectAccessors(NetUtilLocalhost6Accessor.class) - public static Inet6Address LOCALHOST6; - -- @Alias -- @InjectAccessors(NetUtilLocalhostAccessor.class) - public static InetAddress LOCALHOST; - -- @Alias -- @InjectAccessors(NetUtilNetworkInterfacesAccessor.class) - public static Collection NETWORK_INTERFACES; - - private static final class NetUtilLocalhost4Accessor { -diff --git a/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java b/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java -index aed4777a0d..0fa5a858ab 100644 ---- a/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java -+++ b/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java -@@ -15,19 +15,9 @@ - */ - package io.netty.util.internal.svm; - --import com.oracle.svm.core.annotate.Alias; --import com.oracle.svm.core.annotate.RecomputeFieldValue; --import com.oracle.svm.core.annotate.TargetClass; -- --@TargetClass(className = "io.netty.util.internal.CleanerJava6") - final class CleanerJava6Substitution { - private CleanerJava6Substitution() { - } - -- @Alias -- @RecomputeFieldValue( -- kind = RecomputeFieldValue.Kind.FieldOffset, -- declClassName = "java.nio.DirectByteBuffer", -- name = "cleaner") - private static long CLEANER_FIELD_OFFSET; - } -diff --git a/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java b/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java -index 1a06a5518d..3bd61f467a 100644 ---- a/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java -+++ b/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java -@@ -15,19 +15,9 @@ - */ - package io.netty.util.internal.svm; - --import com.oracle.svm.core.annotate.Alias; --import com.oracle.svm.core.annotate.RecomputeFieldValue; --import com.oracle.svm.core.annotate.TargetClass; -- --@TargetClass(className = "io.netty.util.internal.PlatformDependent0") - final class PlatformDependent0Substitution { - private PlatformDependent0Substitution() { - } - -- @Alias -- @RecomputeFieldValue( -- kind = RecomputeFieldValue.Kind.FieldOffset, -- declClassName = "java.nio.Buffer", -- name = "address") - private static long ADDRESS_FIELD_OFFSET; - } -diff --git a/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java b/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java -index 08932da772..8df7f18218 100644 ---- a/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java -+++ b/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java -@@ -15,11 +15,6 @@ - */ - package io.netty.util.internal.svm; - --import com.oracle.svm.core.annotate.Alias; --import com.oracle.svm.core.annotate.RecomputeFieldValue; --import com.oracle.svm.core.annotate.TargetClass; -- --@TargetClass(className = "io.netty.util.internal.PlatformDependent") - final class PlatformDependentSubstitution { - private PlatformDependentSubstitution() { - } -@@ -31,9 +26,5 @@ final class PlatformDependentSubstitution { - * in PlatformDependent happens during image building, the non-recomputed value - * is cached. - */ -- @Alias -- @RecomputeFieldValue( -- kind = RecomputeFieldValue.Kind.ArrayBaseOffset, -- declClass = byte[].class) - private static long BYTE_ARRAY_BASE_OFFSET; - } -diff --git a/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java b/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java -index 08f492f132..f0b10d7cde 100644 ---- a/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java -+++ b/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java -@@ -15,18 +15,9 @@ - */ - package io.netty.util.internal.svm; - --import com.oracle.svm.core.annotate.Alias; --import com.oracle.svm.core.annotate.RecomputeFieldValue; --import com.oracle.svm.core.annotate.TargetClass; -- --@TargetClass(className = "io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess") - final class UnsafeRefArrayAccessSubstitution { - private UnsafeRefArrayAccessSubstitution() { - } - -- @Alias -- @RecomputeFieldValue( -- kind = RecomputeFieldValue.Kind.ArrayIndexShift, -- declClass = Object[].class) - public static int REF_ELEMENT_SHIFT; - } --- -2.46.1 - diff --git a/0007-Do-not-use-the-Jetbrains-annotations.patch b/0007-Do-not-use-the-Jetbrains-annotations.patch deleted file mode 100644 index 82fb0887b0631e1278b31f1a0587fd1db464b2b9..0000000000000000000000000000000000000000 --- a/0007-Do-not-use-the-Jetbrains-annotations.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 3d2d165de5adfaf0ab6cf79d48bc27d0546238bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fridrich=20=C5=A0trba?= -Date: Thu, 30 Mar 2023 13:20:35 +0200 -Subject: [PATCH 6/7] Do not use the Jetbrains annotations - ---- - common/src/main/java/io/netty/util/Recycler.java | 2 -- - .../java/io/netty/util/concurrent/AbstractEventExecutor.java | 4 +--- - .../java/io/netty/util/concurrent/GlobalEventExecutor.java | 4 +--- - .../io/netty/util/concurrent/SingleThreadEventExecutor.java | 5 ++--- - .../test/java/io/netty/util/RecyclerFastThreadLocalTest.java | 2 -- - common/src/test/java/io/netty/util/RecyclerTest.java | 4 +--- - 6 files changed, 5 insertions(+), 16 deletions(-) - -diff --git a/common/src/main/java/io/netty/util/Recycler.java b/common/src/main/java/io/netty/util/Recycler.java -index c434874bff..3df4f1d772 100644 ---- a/common/src/main/java/io/netty/util/Recycler.java -+++ b/common/src/main/java/io/netty/util/Recycler.java -@@ -24,7 +24,6 @@ import io.netty.util.internal.UnstableApi; - import io.netty.util.internal.logging.InternalLogger; - import io.netty.util.internal.logging.InternalLoggerFactory; - import org.jctools.queues.MessagePassingQueue; --import org.jetbrains.annotations.VisibleForTesting; - - import java.util.ArrayDeque; - import java.util.Queue; -@@ -208,7 +207,6 @@ public abstract class Recycler { - return true; - } - -- @VisibleForTesting - final int threadLocalSize() { - LocalPool localPool = threadLocal.getIfExists(); - return localPool == null ? 0 : localPool.pooledHandles.size() + localPool.batch.size(); -diff --git a/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java -index 6409578637..e9463935ba 100644 ---- a/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java -+++ b/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java -@@ -19,8 +19,6 @@ import io.netty.util.internal.UnstableApi; - import io.netty.util.internal.logging.InternalLogger; - import io.netty.util.internal.logging.InternalLoggerFactory; - --import org.jetbrains.annotations.Async.Execute; -- - import java.util.Collection; - import java.util.Collections; - import java.util.Iterator; -@@ -169,7 +167,7 @@ public abstract class AbstractEventExecutor extends AbstractExecutorService impl - } - } - -- protected static void runTask(@Execute Runnable task) { -+ protected static void runTask(Runnable task) { - task.run(); - } - -diff --git a/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java -index 4514c023a3..542eecee3f 100644 ---- a/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java -+++ b/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java -@@ -21,8 +21,6 @@ import io.netty.util.internal.ThreadExecutorMap; - import io.netty.util.internal.logging.InternalLogger; - import io.netty.util.internal.logging.InternalLoggerFactory; - --import org.jetbrains.annotations.Async.Schedule; -- - import java.security.AccessController; - import java.security.PrivilegedAction; - import java.util.Queue; -@@ -221,7 +219,7 @@ public final class GlobalEventExecutor extends AbstractScheduledEventExecutor im - execute0(task); - } - -- private void execute0(@Schedule Runnable task) { -+ private void execute0(Runnable task) { - addTask(ObjectUtil.checkNotNull(task, "task")); - if (!inEventLoop()) { - startThread(); -diff --git a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java -index b93b7cd377..7838cb7787 100644 ---- a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java -+++ b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java -@@ -21,7 +21,6 @@ import io.netty.util.internal.SystemPropertyUtil; - import io.netty.util.internal.ThreadExecutorMap; - import io.netty.util.internal.logging.InternalLogger; - import io.netty.util.internal.logging.InternalLoggerFactory; --import org.jetbrains.annotations.Async.Schedule; - - import java.lang.Thread.State; - import java.util.ArrayList; -@@ -822,12 +821,12 @@ public abstract class SingleThreadEventExecutor extends AbstractScheduledEventEx - lazyExecute0(task); - } - -- private void execute0(@Schedule Runnable task) { -+ private void execute0(Runnable task) { - ObjectUtil.checkNotNull(task, "task"); - execute(task, wakesUpForTask(task)); - } - -- private void lazyExecute0(@Schedule Runnable task) { -+ private void lazyExecute0(Runnable task) { - execute(ObjectUtil.checkNotNull(task, "task"), false); - } - -diff --git a/common/src/test/java/io/netty/util/RecyclerFastThreadLocalTest.java b/common/src/test/java/io/netty/util/RecyclerFastThreadLocalTest.java -index 7c8d4da113..1dfaffc7da 100644 ---- a/common/src/test/java/io/netty/util/RecyclerFastThreadLocalTest.java -+++ b/common/src/test/java/io/netty/util/RecyclerFastThreadLocalTest.java -@@ -16,7 +16,6 @@ - package io.netty.util; - - import io.netty.util.concurrent.FastThreadLocalThread; --import org.jetbrains.annotations.NotNull; - import org.junit.jupiter.api.Test; - import org.junit.jupiter.api.Timeout; - import org.junit.jupiter.api.extension.ExtendWith; -@@ -29,7 +28,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; - - @ExtendWith(RunInFastThreadLocalThreadExtension.class) - public class RecyclerFastThreadLocalTest extends RecyclerTest { -- @NotNull - @Override - protected Thread newThread(Runnable runnable) { - return new FastThreadLocalThread(runnable); -diff --git a/common/src/test/java/io/netty/util/RecyclerTest.java b/common/src/test/java/io/netty/util/RecyclerTest.java -index 49359ff962..1ee4c6bd5c 100644 ---- a/common/src/test/java/io/netty/util/RecyclerTest.java -+++ b/common/src/test/java/io/netty/util/RecyclerTest.java -@@ -15,7 +15,6 @@ - */ - package io.netty.util; - --import org.jetbrains.annotations.NotNull; - import org.junit.jupiter.api.Test; - import org.junit.jupiter.api.Timeout; - import org.junit.jupiter.api.function.Executable; -@@ -55,7 +54,6 @@ public class RecyclerTest { - }; - } - -- @NotNull - protected Thread newThread(Runnable runnable) { - return new Thread(runnable); - } -@@ -341,7 +339,7 @@ public class RecyclerTest { - - ExecutorService single = Executors.newSingleThreadExecutor(new ThreadFactory() { - @Override -- public Thread newThread(@NotNull Runnable r) { -+ public Thread newThread(Runnable r) { - return RecyclerTest.this.newThread(r); - } - }); --- -2.46.1 - diff --git a/CVE-2025-24970.patch b/CVE-2025-24970.patch deleted file mode 100644 index 47ab2bb0131bee2b82a114643f7cd0226f1091a8..0000000000000000000000000000000000000000 --- a/CVE-2025-24970.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 87f40725155b2f89adfde68c7732f97c153676c4 Mon Sep 17 00:00:00 2001 -From: Norman Maurer -Date: Mon, 10 Feb 2025 16:17:04 +0100 -Subject: [PATCH] Merge commit from fork - -Motivation: - -We need to handle the situation correctly in all cases when there is not enough data yet to unwrap the packet. Not doing so might cause undefined behaviour - -Modifications: - -- Correctly check for SslUtils.NOT_ENOUGH_DATA -- Add assert - -Result: - -Correctly handle incomplete packets while unwrap ---- - .../ssl/ReferenceCountedOpenSslEngine.java | 2 ++ - .../java/io/netty/handler/ssl/SslUtils.java | 23 ++++++++++++++----- - 2 files changed, 19 insertions(+), 6 deletions(-) - -diff --git a/handler/src/main/java/io/netty/handler/ssl/SslUtils.java b/handler/src/main/java/io/netty/handler/ssl/SslUtils.java -index 271da51b83f7..4761a02fb4dd 100644 ---- a/handler/src/main/java/io/netty/handler/ssl/SslUtils.java -+++ b/handler/src/main/java/io/netty/handler/ssl/SslUtils.java -@@ -314,8 +314,12 @@ static SSLHandshakeException toSSLHandshakeException(Throwable e) { - * the given {@link ByteBuf} is not encrypted at all. - */ - static int getEncryptedPacketLength(ByteBuf buffer, int offset, boolean probeSSLv2) { -+ assert offset >= buffer.readerIndex(); -+ int remaining = buffer.writerIndex() - offset; -+ if (remaining < SSL_RECORD_HEADER_LENGTH) { -+ return NOT_ENOUGH_DATA; -+ } - int packetLength = 0; -- - // SSLv3 or TLS - Check ContentType - boolean tls; - switch (buffer.getUnsignedByte(offset)) { -@@ -346,7 +350,7 @@ static int getEncryptedPacketLength(ByteBuf buffer, int offset, boolean probeSSL - tls = false; - } - } else if (version == DTLS_1_0 || version == DTLS_1_2 || version == DTLS_1_3) { -- if (buffer.readableBytes() < offset + DTLS_RECORD_HEADER_LENGTH) { -+ if (remaining < DTLS_RECORD_HEADER_LENGTH) { - return NOT_ENOUGH_DATA; - } - // length is the last 2 bytes in the 13 byte header. -@@ -367,7 +371,8 @@ static int getEncryptedPacketLength(ByteBuf buffer, int offset, boolean probeSSL - packetLength = headerLength == 2 ? - (shortBE(buffer, offset) & 0x7FFF) + 2 : (shortBE(buffer, offset) & 0x3FFF) + 3; - if (packetLength <= headerLength) { -- return NOT_ENOUGH_DATA; -+ // If there's no data then consider this package as not encrypted. -+ return NOT_ENCRYPTED; - } - } else { - return NOT_ENCRYPTED; -@@ -420,7 +425,7 @@ static int getEncryptedPacketLength(ByteBuffer[] buffers, int offset) { - } - - // We need to copy 5 bytes into a temporary buffer so we can parse out the packet length easily. -- ByteBuffer tmp = ByteBuffer.allocate(5); -+ ByteBuffer tmp = ByteBuffer.allocate(SSL_RECORD_HEADER_LENGTH); - - do { - buffer = buffers[offset++].duplicate(); -@@ -428,7 +433,7 @@ static int getEncryptedPacketLength(ByteBuffer[] buffers, int offset) { - buffer.limit(buffer.position() + tmp.remaining()); - } - tmp.put(buffer); -- } while (tmp.hasRemaining()); -+ } while (tmp.hasRemaining() && offset < buffers.length); - - // Done, flip the buffer so we can read from it. - tmp.flip(); -@@ -436,8 +441,13 @@ static int getEncryptedPacketLength(ByteBuffer[] buffers, int offset) { - } - - private static int getEncryptedPacketLength(ByteBuffer buffer) { -+ int remaining = buffer.remaining(); -+ if (remaining < SSL_RECORD_HEADER_LENGTH) { -+ return NOT_ENOUGH_DATA; -+ } - int packetLength = 0; - int pos = buffer.position(); -+ - // SSLv3 or TLS - Check ContentType - boolean tls; - switch (unsignedByte(buffer.get(pos))) { -@@ -478,7 +488,8 @@ private static int getEncryptedPacketLength(ByteBuffer buffer) { - packetLength = headerLength == 2 ? - (shortBE(buffer, pos) & 0x7FFF) + 2 : (shortBE(buffer, pos) & 0x3FFF) + 3; - if (packetLength <= headerLength) { -- return NOT_ENOUGH_DATA; -+ // If there's no data then consider this package as not encrypted. -+ return NOT_ENCRYPTED; - } - } else { - return NOT_ENCRYPTED; diff --git a/CVE-2025-55163.patch b/CVE-2025-55163.patch deleted file mode 100644 index 82d454e4ae91be42376260763b51c53e93a0b16b..0000000000000000000000000000000000000000 --- a/CVE-2025-55163.patch +++ /dev/null @@ -1,138 +0,0 @@ -commit be53dc3c9acd9af2e20d0c3c07cd77115a594cf1 -Author: Norman Maurer -Date: Mon Jul 28 08:25:35 2025 -1000 - - HTTP2: Http2ConnectionHandler should always use Http2ConnectionEncode… (#15518) - - …r (#15516) - - Motivation: - - We sometimes directly used the Http2FrameWriter which is not correct as - someone might have supplied a custom Http2ConnectionEncoder - - Modifications: - - Use Http2ConnectionEncoder when writing RST frames - - Result: - - Don't by-pass Http2ConnectionEncoder - -diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java -index 4e661e865d..61e9cd1213 100644 ---- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java -+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java -@@ -717,7 +717,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http - try { - stream = encoder.connection().remote().createStream(streamId, true); - } catch (Http2Exception e) { -- resetUnknownStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise()); -+ encoder().writeRstStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise()); - return; - } - } -@@ -734,10 +734,10 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http - - if (stream == null) { - if (!outbound || connection().local().mayHaveCreatedStream(streamId)) { -- resetUnknownStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise()); -+ encoder().writeRstStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise()); - } - } else { -- resetStream(ctx, stream, http2Ex.error().code(), ctx.newPromise()); -+ encoder().writeRstStream(ctx, streamId, http2Ex.error().code(), ctx.newPromise()); - } - } - -diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java -index 9d5a1c463c..4c48e2780d 100644 ---- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java -+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java -@@ -421,7 +421,7 @@ public class Http2ConnectionHandlerTest { - when(connection.isServer()).thenReturn(true); - when(stream.isHeadersSent()).thenReturn(false); - when(remote.lastStreamCreated()).thenReturn(STREAM_ID); -- when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), -+ when(encoder.writeRstStream(eq(ctx), eq(STREAM_ID), - eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future); - - handler.exceptionCaught(ctx, e); -@@ -431,7 +431,7 @@ public class Http2ConnectionHandlerTest { - captor.capture(), eq(padding), eq(true), eq(promise)); - Http2Headers headers = captor.getValue(); - assertEquals(HttpResponseStatus.REQUEST_HEADER_FIELDS_TOO_LARGE.codeAsText(), headers.status()); -- verify(frameWriter).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); -+ verify(encoder).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); - } - - @Test -@@ -445,14 +445,14 @@ public class Http2ConnectionHandlerTest { - when(connection.isServer()).thenReturn(true); - when(stream.isHeadersSent()).thenReturn(false); - when(remote.lastStreamCreated()).thenReturn(STREAM_ID); -- when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), -+ when(encoder.writeRstStream(eq(ctx), eq(STREAM_ID), - eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future); - - handler.exceptionCaught(ctx, e); - - verify(encoder, never()).writeHeaders(eq(ctx), eq(STREAM_ID), - any(Http2Headers.class), eq(padding), eq(true), eq(promise)); -- verify(frameWriter).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); -+ verify(encoder).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); - } - - @Test -@@ -466,14 +466,14 @@ public class Http2ConnectionHandlerTest { - when(connection.isServer()).thenReturn(false); - when(stream.isHeadersSent()).thenReturn(false); - when(remote.lastStreamCreated()).thenReturn(STREAM_ID); -- when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), -+ when(encoder.writeRstStream(eq(ctx), eq(STREAM_ID), - eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future); - - handler.exceptionCaught(ctx, e); - - verify(encoder, never()).writeHeaders(eq(ctx), eq(STREAM_ID), - any(Http2Headers.class), eq(padding), eq(true), eq(promise)); -- verify(frameWriter).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); -+ verify(encoder).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); - } - - @Test -@@ -502,14 +502,14 @@ public class Http2ConnectionHandlerTest { - when(connection.isServer()).thenReturn(true); - when(stream.isHeadersSent()).thenReturn(true); - when(remote.lastStreamCreated()).thenReturn(STREAM_ID); -- when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), -+ when(encoder.writeRstStream(eq(ctx), eq(STREAM_ID), - eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future); - handler.exceptionCaught(ctx, e); - - verify(encoder, never()).writeHeaders(eq(ctx), eq(STREAM_ID), - any(Http2Headers.class), eq(padding), eq(true), eq(promise)); - -- verify(frameWriter).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); -+ verify(encoder).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); - } - - @Test -@@ -526,7 +526,7 @@ public class Http2ConnectionHandlerTest { - when(connection.isServer()).thenReturn(true); - when(stream.isHeadersSent()).thenReturn(false); - when(remote.lastStreamCreated()).thenReturn(STREAM_ID); -- when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), -+ when(encoder.writeRstStream(eq(ctx), eq(STREAM_ID), - eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future); - handler.exceptionCaught(ctx, e); - -@@ -534,7 +534,7 @@ public class Http2ConnectionHandlerTest { - verify(encoder).writeHeaders(eq(ctx), eq(STREAM_ID), - any(Http2Headers.class), eq(padding), eq(true), eq(promise)); - -- verify(frameWriter).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); -+ verify(encoder).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise); - } - - @Test diff --git a/fix-strip.patch b/fix-strip.patch index ea696cb95d50c2a7d289738b2685099e2658bfed..94236076eaf72235031575a38d2812fb8842adb6 100644 --- a/fix-strip.patch +++ b/fix-strip.patch @@ -1,7 +1,7 @@ diff -Nur a/transport-native-epoll/pom.xml b/transport-native-epoll/pom.xml ---- a/transport-native-epoll/pom.xml 2024-11-18 14:43:59.659694000 +0800 -+++ b/transport-native-epoll/pom.xml 2024-11-18 14:43:44.271694000 +0800 -@@ -37,8 +37,8 @@ +--- a/transport-native-epoll/pom.xml 2025-09-08 15:37:39.281041787 +0800 ++++ b/transport-native-epoll/pom.xml 2025-09-08 15:39:41.699041787 +0800 +@@ -36,8 +36,8 @@ ${project.build.directory}/unix-common-lib ${unix.common.lib.dir}/META-INF/native/lib ${unix.common.lib.dir}/META-INF/native/include @@ -9,6 +9,6 @@ diff -Nur a/transport-native-epoll/pom.xml b/transport-native-epoll/pom.xml - LDFLAGS=-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections -L${unix.common.lib.unpacked.dir} + CFLAGS=-O2 -pipe -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -D_FORTIFY_SOURCE=2 -ffunction-sections -fdata-sections -Wl,-s -I${unix.common.include.unpacked.dir} + LDFLAGS=-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--gc-sections -Wl,-s -L${unix.common.lib.unpacked.dir} - LIBS=-Wl,--whole-archive -l${unix.common.lib.name} -Wl,--no-whole-archive -ldl + LIBS=-Wl,--whole-archive -l${unix.common.lib.name} -Wl,--no-whole-archive -ldl -lrt ${project.basedir}/src/main/c true diff --git a/netty-4.1.114.Final.tar.gz b/netty-4.1.126.Final.tar.gz similarity index 31% rename from netty-4.1.114.Final.tar.gz rename to netty-4.1.126.Final.tar.gz index da24fb41af930d460345a8e6eeb93b4c875fcdee..f7bf231954d22d97c81164b2ceff5f117c28cce2 100644 Binary files a/netty-4.1.114.Final.tar.gz and b/netty-4.1.126.Final.tar.gz differ diff --git a/netty.spec b/netty.spec index ebd9721d08a787eb898f7c4a93978bd055f89488..7b318c76cf2c17fc6255c8735aa771ac621cf17b 100644 --- a/netty.spec +++ b/netty.spec @@ -1,8 +1,8 @@ %global debug_package %{nil} Name: netty -Version: 4.1.114 -Release: 3 +Version: 4.1.126 +Release: 1 Summary: An asynchronous event-driven network application framework and tools for Java License: Apache-2.0 URL: https://netty.io/ @@ -12,21 +12,17 @@ Source2: https://repo1.maven.org/maven2/io/netty/netty-jni-util/0.0.9.F Patch0000: 0001-Remove-optional-dep-Blockhound.patch Patch0001: 0002-Remove-optional-dep-conscrypt.patch Patch0002: 0003-Remove-optional-deps-jetty-alpn-and-npn.patch -Patch0003: 0004-Remove-optional-dep-tcnative.patch -Patch0004: 0005-Disable-Brotli-and-ZStd-compression.patch -Patch0005: 0006-Do-not-use-the-Graal-annotations.patch -Patch0006: 0007-Do-not-use-the-Jetbrains-annotations.patch -Patch0007: no-werror.patch -Patch0008: reproducible.patch -Patch0009: fix-strip.patch -Patch0010: CVE-2025-24970.patch -Patch0011: CVE-2025-55163.patch +Patch0003: 0004-Disable-Brotli-and-ZStd-compression.patch +Patch0004: no-werror.patch +Patch0005: reproducible.patch +Patch0006: fix-strip.patch BuildRequires: autoconf automake libtool gcc BuildRequires: maven-local BuildRequires: mvn(com.fasterxml:aalto-xml) BuildRequires: mvn(com.jcraft:jzlib) BuildRequires: mvn(commons-logging:commons-logging) +BuildRequires: mvn(io.netty:netty-tcnative) >= 2.0.60 BuildRequires: mvn(io.netty:netty-tcnative-classes) >= 2.0.60 BuildRequires: mvn(kr.motd.maven:os-maven-plugin) BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) @@ -42,10 +38,28 @@ BuildRequires: mvn(org.codehaus.mojo:exec-maven-plugin) BuildRequires: mvn(org.fusesource.hawtjni:hawtjni-maven-plugin) BuildRequires: mvn(org.jctools:jctools-core) BuildRequires: mvn(org.slf4j:slf4j-api) +BuildRequires: jurand fdupes %description Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. + +%package bom +Summary: POM-only artifacts for %{name} +Obsoletes: %{name}-poms +BuildArch: noarch + +%description bom +%{summary}. + +%package parent +Summary: POM-only artifacts for %{name} +Obsoletes: %{name}-poms +BuildArch: noarch + +%description parent +%{summary}. + %package help Summary: Documents for %{name} Buildarch: noarch @@ -58,29 +72,21 @@ Man pages and other related documents for %{name}. %prep %autosetup -p1 -n netty-netty-%{version}.Final -%pom_disable_module transport-rxtx -%pom_remove_dep -r :netty-transport-rxtx -%pom_disable_module transport-udt -%pom_remove_dep -r :netty-transport-udt -%pom_remove_dep -r :netty-tcnative-classes +# remove annotations for which we have no dependencies +# Graal annotations +%{java_remove_annotations} common -p "com.oracle.svm.core.annotate" +# Jetbrains annotation +%{java_remove_annotations} common -p "org.jetbrains.annotations" -%pom_remove_parent . bom dev-tools +%pom_remove_parent . bom %pom_disable_module "example" %pom_disable_module "microbench" -%pom_xpath_inject 'pom:plugin[pom:artifactId="maven-remote-resources-plugin"]' ' - - -io.netty -netty-dev-tools -${project.version} - -' - %pom_remove_plugin :maven-antrun-plugin %pom_remove_plugin :maven-dependency-plugin %pom_remove_plugin :xml-maven-plugin +%pom_remove_plugin :japicmp-maven-plugin %pom_remove_plugin -r :maven-checkstyle-plugin %pom_remove_plugin -r :animal-sniffer-maven-plugin %pom_remove_plugin -r :maven-enforcer-plugin @@ -94,12 +100,13 @@ Man pages and other related documents for %{name}. %pom_remove_plugin -r :forbiddenapis %pom_remove_plugin -r :revapi-maven-plugin %pom_remove_plugin -r :bom-helper-maven-plugin -%pom_remove_plugin :japicmp-maven-plugin +%pom_remove_plugin -r :central-publishing-maven-plugin +%pom_remove_plugin -r :nexus-staging-maven-plugin +%pom_remove_plugin -r :flatten-maven-plugin %pom_remove_plugin :duplicate-finder-maven-plugin all -%pom_remove_plugin :flatten-maven-plugin all cp %{SOURCE1} common/codegen.bash -chmod a+x common/codegen.bash +chmod +x common/codegen.bash %pom_add_plugin org.codehaus.mojo:exec-maven-plugin common ' @@ -131,13 +138,21 @@ rm codec/src/main/java/io/netty/handler/codec/marshalling/* rm codec/src/*/java/io/netty/handler/codec/compression/Lzma*.java %pom_remove_dep -r com.ning:compress-lzf rm codec/src/*/java/io/netty/handler/codec/compression/Lzf*.java -%pom_remove_dep -r net.jpountz.lz4:lz4 +%pom_remove_dep -r org.lz4:lz4-java rm codec/src/*/java/io/netty/handler/codec/compression/Lz4*.java %pom_remove_dep -r com.aayushatharva.brotli4j: rm codec/src/*/java/io/netty/handler/codec/compression/Brotli*.java %pom_remove_dep -r com.github.luben:zstd-jni rm codec/src/*/java/io/netty/handler/codec/compression/Zstd*.java +%pom_disable_module transport-rxtx +%pom_remove_dep -r :netty-transport-rxtx +%pom_disable_module transport-udt +%pom_remove_dep -r :netty-transport-udt + +%pom_remove_dep -r :netty-build-common +%pom_remove_dep :netty-dev-tools + %pom_disable_module resolver-dns-native-macos %pom_remove_dep -r :netty-resolver-dns-native-macos @@ -159,10 +174,22 @@ unzip %{SOURCE2} -d transport-native-unix-common/target/netty-jni-util %pom_xpath_remove "pom:build/pom:plugins/pom:plugin[pom:artifactId = 'maven-bundle-plugin']/pom:executions/pom:execution[pom:id = 'generate-manifest']/pom:configuration/pom:instructions/pom:Import-Package" common/pom.xml +%pom_xpath_inject "pom:project" ' +io.netty.dev.tools +' dev-tools + %pom_remove_dep -r :annotations-java5 +%pom_xpath_remove "pom:profiles/pom:profile[pom:id = 'staging']" all + +# 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*:" +%mvn_package ":netty-parent" parent +%mvn_package ":netty-bom" bom + %mvn_package ':*-tests' __noinstall %build @@ -171,13 +198,22 @@ export CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" %install %mvn_install +%fdupes -s %{buildroot}%{_javadocdir} %files -f .mfiles %doc LICENSE.txt NOTICE.txt +%files parent -f .mfiles-parent +%license LICENSE.txt NOTICE.txt + +%files bom -f .mfiles-bom + %files help -f .mfiles-javadoc %changelog +* Thu Sep 18 2025 yaoxin <1024769339@qq.com> - 4.1.126-1 +- Update to 4.1.126 for fix CVE-2025-58056 and CVE-2025-58057 + * Thu Aug 14 2025 Yu Peng - 4.1.114-3 - Fix CVE-2025-55163