netty/0004-Remove-optional-dep-tc...

8568 lines
364 KiB
Diff

From c60f3b8d7ca0575bba15682a329dced786f898da Mon Sep 17 00:00:00 2001
From: Mat Booth <mat.booth@redhat.com>
Date: Mon, 7 Sep 2020 13:41:44 +0100
Subject: [PATCH 4/5] Remove optional dep tcnative
---
handler/pom.xml | 6 -
.../handler/ssl/CipherSuiteConverter.java | 494 ----
.../ssl/DefaultOpenSslKeyMaterial.java | 126 -
.../java/io/netty/handler/ssl/OpenSsl.java | 610 ----
.../OpenSslCachingKeyMaterialProvider.java | 79 -
.../OpenSslCachingX509KeyManagerFactory.java | 81 -
.../ssl/OpenSslCertificateException.java | 81 -
.../handler/ssl/OpenSslClientContext.java | 208 --
.../io/netty/handler/ssl/OpenSslContext.java | 58 -
.../io/netty/handler/ssl/OpenSslEngine.java | 41 -
.../netty/handler/ssl/OpenSslEngineMap.java | 35 -
.../ssl/OpenSslKeyMaterialManager.java | 127 -
.../ssl/OpenSslKeyMaterialProvider.java | 154 -
.../netty/handler/ssl/OpenSslPrivateKey.java | 191 --
.../handler/ssl/OpenSslPrivateKeyMethod.java | 62 -
.../handler/ssl/OpenSslServerContext.java | 367 ---
.../ssl/OpenSslServerSessionContext.java | 124 -
.../handler/ssl/OpenSslSessionContext.java | 158 --
.../handler/ssl/OpenSslSessionStats.java | 253 --
.../handler/ssl/OpenSslSessionTicketKey.java | 78 -
...OpenSslTlsv13X509ExtendedTrustManager.java | 240 --
.../ssl/OpenSslX509KeyManagerFactory.java | 413 ---
.../ReferenceCountedOpenSslClientContext.java | 343 ---
.../ssl/ReferenceCountedOpenSslContext.java | 968 -------
.../ssl/ReferenceCountedOpenSslEngine.java | 2467 -----------------
.../ReferenceCountedOpenSslServerContext.java | 286 --
.../java/io/netty/handler/ssl/SslContext.java | 30 +-
.../java/io/netty/handler/ssl/SslHandler.java | 49 +-
.../handler/ssl/SslMasterKeyHandler.java | 3 -
.../io/netty/handler/ssl/SslProvider.java | 14 +-
.../handler/ssl/ocsp/OcspClientHandler.java | 61 -
.../netty/handler/ssl/ocsp/package-info.java | 23 -
pom.xml | 10 -
33 files changed, 3 insertions(+), 8237 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/OpenSsl.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/OpenSslContext.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/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/OpenSslTlsv13X509ExtendedTrustManager.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 be8206dc89..e28cc6f7af 100644
--- a/handler/pom.xml
+++ b/handler/pom.xml
@@ -60,12 +60,6 @@
<artifactId>netty-codec</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>${tcnative.artifactId}</artifactId>
- <classifier>${tcnative.classifier}</classifier>
- <optional>true</optional>
- </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
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 94e951f7f5..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/CipherSuiteConverter.java
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package io.netty.handler.ssl;
-
-import io.netty.util.internal.PlatformDependent;
-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 <a href="http://en.wikipedia.org/wiki/Cipher_suite">Wikipedia page about cipher suite</a>
- */
-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]+)-(.*)$");
-
- /**
- * Java-to-OpenSSL cipher suite conversion map
- * Note that the Java cipher suite has the protocol prefix (TLS_, SSL_)
- */
- private static final ConcurrentMap<String, String> 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<String, Map<String, String>> o2j = PlatformDependent.newConcurrentHashMap();
-
- private static final Map<String, String> j2oTls13;
- private static final Map<String, Map<String, String>> o2jTls13;
-
- static {
- Map<String, String> j2oTls13Map = new HashMap<String, String>();
- 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<String, Map<String, String>> o2jTls13Map = new HashMap<String, Map<String, String>>();
- 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) {
- return value.equals(j2o.get(key));
- }
-
- /**
- * 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<String, String> 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
- */
- static String toOpenSsl(String javaCipherSuite, boolean boringSSL) {
- String converted = j2o.get(javaCipherSuite);
- if (converted != null) {
- return converted;
- }
- 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);
- if (openSslCipherSuite == null) {
- return null;
- }
-
- // Cache the mapping.
- j2o.putIfAbsent(javaCipherSuite, openSslCipherSuite);
-
- // Cache the reverse mapping after stripping the protocol prefix (TLS_ or SSL_)
- final String javaCipherSuiteSuffix = javaCipherSuite.substring(4);
- Map<String, String> p2j = new HashMap<String, String>(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}.
- */
- static String toJava(String openSslCipherSuite, String protocol) {
- Map<String, String> 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<String, String> cacheFromOpenSsl(String openSslCipherSuite) {
- Map<String, String> 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<String, String> p2j = new HashMap<String, String>(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_)
- j2o.putIfAbsent(javaCipherSuiteTls, openSslCipherSuite);
- j2o.putIfAbsent(javaCipherSuiteSsl, openSslCipherSuite);
-
- 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<String, String> 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<String> 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 fcea5266f2..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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<DefaultOpenSslKeyMaterial> leakDetector =
- ResourceLeakDetectorFactory.instance().newResourceLeakDetector(DefaultOpenSslKeyMaterial.class);
- private final ResourceLeakTracker<DefaultOpenSslKeyMaterial> 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/OpenSsl.java b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
deleted file mode 100644
index d7d44cf3e7..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.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.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.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import static io.netty.handler.ssl.SslUtils.*;
-
-/**
- * Tells if <a href="https://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> 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<String> DEFAULT_CIPHERS;
- static final Set<String> AVAILABLE_CIPHER_SUITES;
- private static final Set<String> AVAILABLE_OPENSSL_CIPHER_SUITES;
- private static final Set<String> 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;
- static final Set<String> SUPPORTED_PROTOCOLS_SET;
- static final String[] EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
-
- // self-signed certificate for netty.io and the matching private-key
- private static final String CERT = "-----BEGIN CERTIFICATE-----\n" +
- "MIICrjCCAZagAwIBAgIIdSvQPv1QAZQwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBs\n" +
- "ZS5jb20wIBcNMTgwNDA2MjIwNjU5WhgPOTk5OTEyMzEyMzU5NTlaMBYxFDASBgNVBAMTC2V4YW1w\n" +
- "bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAggbWsmDQ6zNzRZ5AW8E3eoGl\n" +
- "qWvOBDb5Fs1oBRrVQHuYmVAoaqwDzXYJ0LOwa293AgWEQ1jpcbZ2hpoYQzqEZBTLnFhMrhRFlH6K\n" +
- "bJND8Y33kZ/iSVBBDuGbdSbJShlM+4WwQ9IAso4MZ4vW3S1iv5fGGpLgbtXRmBf/RU8omN0Gijlv\n" +
- "WlLWHWijLN8xQtySFuBQ7ssW8RcKAary3pUm6UUQB+Co6lnfti0Tzag8PgjhAJq2Z3wbsGRnP2YS\n" +
- "vYoaK6qzmHXRYlp/PxrjBAZAmkLJs4YTm/XFF+fkeYx4i9zqHbyone5yerRibsHaXZWLnUL+rFoe\n" +
- "MdKvr0VS3sGmhQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQADQi441pKmXf9FvUV5EHU4v8nJT9Iq\n" +
- "yqwsKwXnr7AsUlDGHBD7jGrjAXnG5rGxuNKBQ35wRxJATKrUtyaquFUL6H8O6aGQehiFTk6zmPbe\n" +
- "12Gu44vqqTgIUxnv3JQJiox8S2hMxsSddpeCmSdvmalvD6WG4NthH6B9ZaBEiep1+0s0RUaBYn73\n" +
- "I7CCUaAtbjfR6pcJjrFk5ei7uwdQZFSJtkP2z8r7zfeANJddAKFlkaMWn7u+OIVuB4XPooWicObk\n" +
- "NAHFtP65bocUYnDpTVdiyvn8DdqyZ/EO8n1bBKBzuSLplk2msW4pdgaFgY7Vw/0wzcFXfUXmL1uy\n" +
- "G8sQD/wx\n" +
- "-----END CERTIFICATE-----";
-
- private static final String KEY = "-----BEGIN PRIVATE KEY-----\n" +
- "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCCBtayYNDrM3NFnkBbwTd6gaWp\n" +
- "a84ENvkWzWgFGtVAe5iZUChqrAPNdgnQs7Brb3cCBYRDWOlxtnaGmhhDOoRkFMucWEyuFEWUfops\n" +
- "k0PxjfeRn+JJUEEO4Zt1JslKGUz7hbBD0gCyjgxni9bdLWK/l8YakuBu1dGYF/9FTyiY3QaKOW9a\n" +
- "UtYdaKMs3zFC3JIW4FDuyxbxFwoBqvLelSbpRRAH4KjqWd+2LRPNqDw+COEAmrZnfBuwZGc/ZhK9\n" +
- "ihorqrOYddFiWn8/GuMEBkCaQsmzhhOb9cUX5+R5jHiL3OodvKid7nJ6tGJuwdpdlYudQv6sWh4x\n" +
- "0q+vRVLewaaFAgMBAAECggEAP8tPJvFtTxhNJAkCloHz0D0vpDHqQBMgntlkgayqmBqLwhyb18pR\n" +
- "i0qwgh7HHc7wWqOOQuSqlEnrWRrdcI6TSe8R/sErzfTQNoznKWIPYcI/hskk4sdnQ//Yn9/Jvnsv\n" +
- "U/BBjOTJxtD+sQbhAl80JcA3R+5sArURQkfzzHOL/YMqzAsn5hTzp7HZCxUqBk3KaHRxV7NefeOE\n" +
- "xlZuWSmxYWfbFIs4kx19/1t7h8CHQWezw+G60G2VBtSBBxDnhBWvqG6R/wpzJ3nEhPLLY9T+XIHe\n" +
- "ipzdMOOOUZorfIg7M+pyYPji+ZIZxIpY5OjrOzXHciAjRtr5Y7l99K1CG1LguQKBgQDrQfIMxxtZ\n" +
- "vxU/1cRmUV9l7pt5bjV5R6byXq178LxPKVYNjdZ840Q0/OpZEVqaT1xKVi35ohP1QfNjxPLlHD+K\n" +
- "iDAR9z6zkwjIrbwPCnb5kuXy4lpwPcmmmkva25fI7qlpHtbcuQdoBdCfr/KkKaUCMPyY89LCXgEw\n" +
- "5KTDj64UywKBgQCNfbO+eZLGzhiHhtNJurresCsIGWlInv322gL8CSfBMYl6eNfUTZvUDdFhPISL\n" +
- "UljKWzXDrjw0ujFSPR0XhUGtiq89H+HUTuPPYv25gVXO+HTgBFZEPl4PpA+BUsSVZy0NddneyqLk\n" +
- "42Wey9omY9Q8WsdNQS5cbUvy0uG6WFoX7wKBgQDZ1jpW8pa0x2bZsQsm4vo+3G5CRnZlUp+XlWt2\n" +
- "dDcp5dC0xD1zbs1dc0NcLeGDOTDv9FSl7hok42iHXXq8AygjEm/QcuwwQ1nC2HxmQP5holAiUs4D\n" +
- "WHM8PWs3wFYPzE459EBoKTxeaeP/uWAn+he8q7d5uWvSZlEcANs/6e77eQKBgD21Ar0hfFfj7mK8\n" +
- "9E0FeRZBsqK3omkfnhcYgZC11Xa2SgT1yvs2Va2n0RcdM5kncr3eBZav2GYOhhAdwyBM55XuE/sO\n" +
- "eokDVutNeuZ6d5fqV96TRaRBpvgfTvvRwxZ9hvKF4Vz+9wfn/JvCwANaKmegF6ejs7pvmF3whq2k\n" +
- "drZVAoGAX5YxQ5XMTD0QbMAl7/6qp6S58xNoVdfCkmkj1ZLKaHKIjS/benkKGlySVQVPexPfnkZx\n" +
- "p/Vv9yyphBoudiTBS9Uog66ueLYZqpgxlM/6OhYg86Gm3U2ycvMxYjBM1NFiyze21AqAhI+HX+Ot\n" +
- "mraV2/guSgDgZAhukRZzeQ2RucI=\n" +
- "-----END PRIVATE KEY-----";
-
- 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, OpenSsl.class.getClassLoader());
- } catch (ClassNotFoundException t) {
- cause = t;
- logger.debug(
- "netty-tcnative not in the classpath; " +
- OpenSslEngine.class.getSimpleName() + " will be unavailable.");
- }
-
- // If in the classpath, try to load the native library and initialize netty-tcnative.
- if (cause == null) {
- try {
- // 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;
-
- if (cause == null) {
- logger.debug("netty-tcnative using native library: {}", SSL.versionString());
-
- final List<String> defaultCiphers = new ArrayList<String>();
- final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128);
- boolean supportsKeyManagerFactory = false;
- boolean useKeyManagerFactory = false;
- boolean tlsv13Supported = false;
-
- 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" };
- } else {
- EXTRA_SUPPORTED_TLS_1_3_CIPHERS = EmptyArrays.EMPTY_STRINGS;
- }
-
- 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 {
- 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(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);
- }
- }
- } finally {
- SSLContext.free(sslCtx);
- }
- } catch (Exception e) {
- logger.warn("Failed to get the list of available OpenSSL cipher suites.", e);
- }
- AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites);
- final Set<String> availableJavaCipherSuites = new LinkedHashSet<String>(
- 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);
-
- useFallbackCiphersIfDefaultIsEmpty(defaultCiphers, availableJavaCipherSuites);
- DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers);
-
- AVAILABLE_JAVA_CIPHER_SUITES = Collections.unmodifiableSet(availableJavaCipherSuites);
-
- final Set<String> availableCipherSuites = new LinkedHashSet<String>(
- 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<String> protocols = new LinkedHashSet<String>(6);
- // Seems like there is no way to explicitly disable SSLv2Hello in openssl so it is always enabled
- protocols.add(PROTOCOL_SSL_V2_HELLO);
- if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV2, SSL.SSL_OP_NO_SSLv2)) {
- protocols.add(PROTOCOL_SSL_V2);
- }
- if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV3, SSL.SSL_OP_NO_SSLv3)) {
- protocols.add(PROTOCOL_SSL_V3);
- }
- if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1, SSL.SSL_OP_NO_TLSv1)) {
- protocols.add(PROTOCOL_TLS_V1);
- }
- if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_1, SSL.SSL_OP_NO_TLSv1_1)) {
- protocols.add(PROTOCOL_TLS_V1_1);
- }
- if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_2, SSL.SSL_OP_NO_TLSv1_2)) {
- protocols.add(PROTOCOL_TLS_V1_2);
- }
-
- // This is only supported by java11 and later.
- if (tlsv13Supported && doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_OP_NO_TLSv1_3)) {
- protocols.add(PROTOCOL_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);
- }
- } 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;
- }
- }
-
- /**
- * Returns a self-signed {@link X509Certificate} for {@code netty.io}.
- */
- static X509Certificate selfSignedCertificate() throws CertificateException {
- return (X509Certificate) SslContext.X509_CERT_FACTORY.generateCertificate(
- new ByteArrayInputStream(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
- * <a href="https://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support
- * are available.
- */
- public static boolean isAvailable() {
- return UNAVAILABILITY_CAUSE == null;
- }
-
- /**
- * Returns {@code true} if the used version of openssl supports
- * <a href="https://tools.ietf.org/html/rfc7301">ALPN</a>.
- *
- * @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 <a href="https://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> 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
- * <a href="https://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> 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<String> 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<String> 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<String> 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() : Buffer.address(buf.nioBuffer());
- }
-
- private OpenSsl() { }
-
- private static void loadTcNative() throws Exception {
- String os = PlatformDependent.normalizedOs();
- String arch = PlatformDependent.normalizedArch();
-
- Set<String> libNames = new LinkedHashSet<String>(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".equalsIgnoreCase(os)) {
- Set<String> 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(SSLContext.class.getClassLoader(),
- libNames.toArray(new String[0]));
- }
-
- 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 isBoringSSL() {
- return IS_BORINGSSL;
- }
-}
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 07b67d9fa7..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBufAllocator;
-
-import 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<String, OpenSslKeyMaterial> cache = new ConcurrentHashMap<String, OpenSslKeyMaterial>();
-
- 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<OpenSslKeyMaterial> 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 7f67bc8198..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslCachingX509KeyManagerFactory.java
+++ /dev/null
@@ -1,81 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.util.internal.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.X509ExtendedKeyManager;
-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 f20b2d3ba0..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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
- * <a href="https://www.openssl.org/docs/manmaster/apps/verify.html">error code</a>.
- */
- public OpenSslCertificateException(int errorCode) {
- this((String) null, errorCode);
- }
-
- /**
- * Construct a new exception with the msg and
- * <a href="https://www.openssl.org/docs/manmaster/apps/verify.html">error code</a> .
- */
- public OpenSslCertificateException(String msg, int errorCode) {
- super(msg);
- this.errorCode = checkErrorCode(errorCode);
- }
-
- /**
- * Construct a new exception with the msg, cause and
- * <a href="https://www.openssl.org/docs/manmaster/apps/verify.html">error code</a> .
- */
- public OpenSslCertificateException(String message, Throwable cause, int errorCode) {
- super(message, cause);
- this.errorCode = checkErrorCode(errorCode);
- }
-
- /**
- * Construct a new exception with the cause and
- * <a href="https://www.openssl.org/docs/manmaster/apps/verify.html">error code</a> .
- */
- public OpenSslCertificateException(Throwable cause, int errorCode) {
- this(null, cause, errorCode);
- }
-
- /**
- * Return the <a href="https://www.openssl.org/docs/man1.0.2/apps/verify.html">error code</a> 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 7f9b39a8dd..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.internal.tcnative.SSL;
-
-import java.io.File;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-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.
- * <p>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<String> 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<String> 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<String> 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());
- }
-
- OpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
- KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
- long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStore)
- throws SSLException {
- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain,
- ClientAuth.NONE, protocols, false, enableOcsp);
- boolean success = false;
- try {
- OpenSslKeyMaterialProvider.validateKeyMaterialSupported(keyCertChain, key, keyPassword);
- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
- keyCertChain, key, keyPassword, keyManagerFactory, keyStore);
- success = true;
- } finally {
- if (!success) {
- release();
- }
- }
- }
-
- @Override
- public OpenSslSessionContext sessionContext() {
- return sessionContext;
- }
-}
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 f18c0643fc..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBufAllocator;
-
-import java.security.cert.Certificate;
-
-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<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apnCfg,
- long sessionCacheSize, long sessionTimeout, int mode, Certificate[] keyCertChain,
- ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp)
- throws SSLException {
- super(ciphers, cipherFilter, apnCfg, sessionCacheSize, sessionTimeout, mode, keyCertChain,
- clientAuth, protocols, startTls, enableOcsp, false);
- }
-
- OpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
- OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize,
- long sessionTimeout, int mode, Certificate[] keyCertChain,
- ClientAuth clientAuth, String[] protocols, boolean startTls,
- boolean enableOcsp) throws SSLException {
- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, mode, keyCertChain, clientAuth, protocols,
- startTls, enableOcsp, false);
- }
-
- @Override
- final SSLEngine newEngine0(ByteBufAllocator alloc, String peerHost, int peerPort, boolean jdkCompatibilityMode) {
- return new OpenSslEngine(this, alloc, peerHost, peerPort, jdkCompatibilityMode);
- }
-
- @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/OpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
deleted file mode 100644
index a700dabf39..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBufAllocator;
-
-import javax.net.ssl.SSLEngine;
-
-/**
- * Implements a {@link SSLEngine} using
- * <a href="https://www.openssl.org/docs/crypto/BIO_s_bio.html#EXAMPLE">OpenSSL BIO abstractions</a>.
- * <p>
- * 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) {
- super(context, alloc, peerHost, peerPort, jdkCompatibilityMode, false);
- }
-
- @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 02131b4b26..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-interface OpenSslEngineMap {
-
- /**
- * 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 7acbf70cfe..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java
+++ /dev/null
@@ -1,127 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import javax.net.ssl.SSLException;
-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.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<String, String> KEY_TYPES = new HashMap<String, String>();
- 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) {
- return;
- }
- Set<String> aliases = new HashSet<String>(authMethods.length);
- for (String authMethod : authMethods) {
- String type = KEY_TYPES.get(authMethod);
- if (type != null) {
- String alias = chooseServerAlias(engine, type);
- if (alias != null && aliases.add(alias)) {
- if (!setKeyMaterial(engine, alias)) {
- return;
- }
- }
- }
- }
- }
-
- 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:
- // http://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 boolean setKeyMaterial(ReferenceCountedOpenSslEngine engine, String alias) throws SSLException {
- OpenSslKeyMaterial keyMaterial = null;
- try {
- keyMaterial = provider.chooseKeyMaterial(engine.alloc, alias);
- return keyMaterial == null || 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 f931fcfdbb..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.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 c2e4f108b7..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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 d9fc877269..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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 da342de0f2..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.internal.tcnative.SSL;
-
-import java.io.File;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-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.
- * <p>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<String> 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<String> ciphers, Iterable<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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());
- }
-
- OpenSslServerContext(
- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
- Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
- boolean enableOcsp, String keyStore) throws SSLException {
- this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
- cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls,
- enableOcsp, keyStore);
- }
-
- @SuppressWarnings("deprecation")
- private OpenSslServerContext(
- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
- Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
- boolean enableOcsp, String keyStore) throws SSLException {
- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
- clientAuth, protocols, startTls, enableOcsp);
-
- // 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);
- 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 691ee0b661..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslServerSessionContext.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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);
- }
-
- @Override
- public void setSessionTimeout(int seconds) {
- if (seconds < 0) {
- throw new IllegalArgumentException();
- }
- Lock writerLock = context.ctxLock.writeLock();
- writerLock.lock();
- try {
- SSLContext.setSessionCacheTimeout(context.ctx, seconds);
- } finally {
- writerLock.unlock();
- }
- }
-
- @Override
- public int getSessionTimeout() {
- Lock readerLock = context.ctxLock.readLock();
- readerLock.lock();
- try {
- return (int) SSLContext.getSessionCacheTimeout(context.ctx);
- } finally {
- readerLock.unlock();
- }
- }
-
- @Override
- public void setSessionCacheSize(int size) {
- if (size < 0) {
- throw new IllegalArgumentException();
- }
- Lock writerLock = context.ctxLock.writeLock();
- writerLock.lock();
- try {
- SSLContext.setSessionCacheSize(context.ctx, size);
- } finally {
- writerLock.unlock();
- }
- }
-
- @Override
- public int getSessionCacheSize() {
- Lock readerLock = context.ctxLock.readLock();
- readerLock.lock();
- try {
- return (int) SSLContext.getSessionCacheSize(context.ctx);
- } finally {
- readerLock.unlock();
- }
- }
-
- @Override
- public void setSessionCacheEnabled(boolean enabled) {
- long mode = enabled ? SSL.SSL_SESS_CACHE_SERVER : SSL.SSL_SESS_CACHE_OFF;
-
- Lock writerLock = context.ctxLock.writeLock();
- writerLock.lock();
- try {
- SSLContext.setSessionCacheMode(context.ctx, mode);
- } finally {
- writerLock.unlock();
- }
- }
-
- @Override
- public boolean isSessionCacheEnabled() {
- Lock readerLock = context.ctxLock.readLock();
- readerLock.lock();
- try {
- return SSLContext.getSessionCacheMode(context.ctx) == SSL.SSL_SESS_CACHE_SERVER;
- } finally {
- readerLock.unlock();
- }
- }
-
- /**
- * Set the context within which session be reused (server side only)
- * See <a href="http://www.openssl.org/docs/ssl/SSL_CTX_set_session_id_context.html">
- * man SSL_CTX_set_session_id_context</a>
- *
- * @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/OpenSslSessionContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java
deleted file mode 100644
index 5d471d34fb..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionContext.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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.NoSuchElementException;
-import java.util.concurrent.locks.Lock;
-
-/**
- * OpenSSL specific {@link SSLSessionContext} implementation.
- */
-public abstract class OpenSslSessionContext implements SSLSessionContext {
- private static final Enumeration<byte[]> EMPTY = new EmptyEnumeration();
-
- 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;
-
- // 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) {
- this.context = context;
- this.provider = provider;
- stats = new OpenSslSessionStats(context);
- }
-
- final boolean useKeyManager() {
- return provider != null;
- }
-
- @Override
- public SSLSession getSession(byte[] bytes) {
- ObjectUtil.checkNotNull(bytes, "bytes");
- return null;
- }
-
- @Override
- public Enumeration<byte[]> getIds() {
- return EMPTY;
- }
-
- /**
- * 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
- * <a href="https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#Session-tickets/">
- * BoringSSL</a> 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 abstract void setSessionCacheEnabled(boolean enabled);
-
- /**
- * Return {@code true} if caching of SSL sessions is enabled, {@code false} otherwise.
- */
- public abstract boolean isSessionCacheEnabled();
-
- /**
- * Returns the stats of this context.
- */
- public OpenSslSessionStats stats() {
- return stats;
- }
-
- final void destroy() {
- if (provider != null) {
- provider.destroy();
- }
- }
-
- private static final class EmptyEnumeration implements Enumeration<byte[]> {
- @Override
- public boolean hasMoreElements() {
- return false;
- }
-
- @Override
- public byte[] nextElement() {
- throw new NoSuchElementException();
- }
- }
-}
diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslSessionStats.java
deleted file mode 100644
index f49b95f3ba..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package io.netty.handler.ssl;
-
-import io.netty.internal.tcnative.SSLContext;
-
-import java.util.concurrent.locks.Lock;
-
-/**
- * Stats exposed by an OpenSSL session context.
- *
- * @see <a href="https://www.openssl.org/docs/manmaster/man3/SSL_CTX_sess_number.html">SSL_CTX_sess_number</a>
- */
-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 79f71a65a3..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.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/OpenSslTlsv13X509ExtendedTrustManager.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslTlsv13X509ExtendedTrustManager.java
deleted file mode 100644
index a5a84f2793..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslTlsv13X509ExtendedTrustManager.java
+++ /dev/null
@@ -1,240 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.util.internal.PlatformDependent;
-import io.netty.util.internal.SuppressJava6Requirement;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.X509ExtendedTrustManager;
-import java.net.Socket;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.List;
-
-/**
- * Provide a way to use {@code TLSv1.3} with Java versions prior to 11 by adding a
- * <a href="http://mail.openjdk.java.net/pipermail/security-dev/2018-September/018242.html>workaround</a> for the
- * default {@link X509ExtendedTrustManager} implementations provided by the JDK that can not handle a protocol version
- * of {@code TLSv1.3}.
- */
-@SuppressJava6Requirement(reason = "Usage guarded by java version check")
-final class OpenSslTlsv13X509ExtendedTrustManager extends X509ExtendedTrustManager {
-
- private final X509ExtendedTrustManager tm;
-
- private OpenSslTlsv13X509ExtendedTrustManager(X509ExtendedTrustManager tm) {
- this.tm = tm;
- }
-
- static X509ExtendedTrustManager wrap(X509ExtendedTrustManager tm) {
- if (PlatformDependent.javaVersion() < 11 && OpenSsl.isTlsv13Supported()) {
- return new OpenSslTlsv13X509ExtendedTrustManager(tm);
- }
- return tm;
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket)
- throws CertificateException {
- tm.checkClientTrusted(x509Certificates, s, socket);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket)
- throws CertificateException {
- tm.checkServerTrusted(x509Certificates, s, socket);
- }
-
- private static SSLEngine wrapEngine(final SSLEngine engine) {
- final SSLSession session = engine.getHandshakeSession();
- if (session != null && SslUtils.PROTOCOL_TLS_V1_3.equals(session.getProtocol())) {
- return new JdkSslEngine(engine) {
- @Override
- public String getNegotiatedApplicationProtocol() {
- if (engine instanceof ApplicationProtocolAccessor) {
- return ((ApplicationProtocolAccessor) engine).getNegotiatedApplicationProtocol();
- }
- return super.getNegotiatedApplicationProtocol();
- }
-
- @Override
- public SSLSession getHandshakeSession() {
- if (PlatformDependent.javaVersion() >= 7 && session instanceof ExtendedOpenSslSession) {
- final ExtendedOpenSslSession extendedOpenSslSession = (ExtendedOpenSslSession) session;
- return new ExtendedOpenSslSession(extendedOpenSslSession) {
- @Override
- public List getRequestedServerNames() {
- return extendedOpenSslSession.getRequestedServerNames();
- }
-
- @Override
- public String[] getPeerSupportedSignatureAlgorithms() {
- return extendedOpenSslSession.getPeerSupportedSignatureAlgorithms();
- }
-
- @Override
- public String getProtocol() {
- return SslUtils.PROTOCOL_TLS_V1_2;
- }
- };
- } else {
- return new SSLSession() {
- @Override
- public byte[] getId() {
- return session.getId();
- }
-
- @Override
- public SSLSessionContext getSessionContext() {
- return session.getSessionContext();
- }
-
- @Override
- public long getCreationTime() {
- return session.getCreationTime();
- }
-
- @Override
- public long getLastAccessedTime() {
- return session.getLastAccessedTime();
- }
-
- @Override
- public void invalidate() {
- session.invalidate();
- }
-
- @Override
- public boolean isValid() {
- return session.isValid();
- }
-
- @Override
- public void putValue(String s, Object o) {
- session.putValue(s, o);
- }
-
- @Override
- public Object getValue(String s) {
- return session.getValue(s);
- }
-
- @Override
- public void removeValue(String s) {
- session.removeValue(s);
- }
-
- @Override
- public String[] getValueNames() {
- return session.getValueNames();
- }
-
- @Override
- public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
- return session.getPeerCertificates();
- }
-
- @Override
- public Certificate[] getLocalCertificates() {
- return session.getLocalCertificates();
- }
-
- @Override
- public javax.security.cert.X509Certificate[] getPeerCertificateChain()
- throws SSLPeerUnverifiedException {
- return session.getPeerCertificateChain();
- }
-
- @Override
- public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
- return session.getPeerPrincipal();
- }
-
- @Override
- public Principal getLocalPrincipal() {
- return session.getLocalPrincipal();
- }
-
- @Override
- public String getCipherSuite() {
- return session.getCipherSuite();
- }
-
- @Override
- public String getProtocol() {
- return SslUtils.PROTOCOL_TLS_V1_2;
- }
-
- @Override
- public String getPeerHost() {
- return session.getPeerHost();
- }
-
- @Override
- public int getPeerPort() {
- return session.getPeerPort();
- }
-
- @Override
- public int getPacketBufferSize() {
- return session.getPacketBufferSize();
- }
-
- @Override
- public int getApplicationBufferSize() {
- return session.getApplicationBufferSize();
- }
- };
- }
- }
- };
- }
- return engine;
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] x509Certificates, final String s, SSLEngine sslEngine)
- throws CertificateException {
- tm.checkClientTrusted(x509Certificates, s, wrapEngine(sslEngine));
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine)
- throws CertificateException {
- tm.checkServerTrusted(x509Certificates, s, wrapEngine(sslEngine));
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
- tm.checkClientTrusted(x509Certificates, s);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
- tm.checkServerTrusted(x509Certificates, s);
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return tm.getAcceptedIssuers();
- }
-}
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 2a86332fe1..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslX509KeyManagerFactory.java
+++ /dev/null
@@ -1,413 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.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<String> aliases;
-
- ProviderFactory(X509KeyManager keyManager, String password, Iterable<String> 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<String, Object> materialMap;
-
- OpenSslPopulatedKeyMaterialProvider(
- X509KeyManager keyManager, String password, Iterable<String> aliases) {
- super(keyManager, password);
- materialMap = new HashMap<String, Object>();
- 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();
- }
- }
- if (materialMap.isEmpty()) {
- throw new IllegalArgumentException("aliases must be non-empty");
- }
- }
-
- @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
- * <a href="https://www.openssl.org/docs/man1.1.0/crypto/ENGINE_load_private_key.html">ENGINE_load_private_key</a>
- * 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
- * <a href="https://www.openssl.org/docs/man1.1.0/crypto/ENGINE_load_private_key.html">ENGINE_load_private_key</a>
- * function.
- */
- public static OpenSslX509KeyManagerFactory newEngineBased(X509Certificate[] certificateChain, String password)
- throws CertificateException, IOException,
- KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
- 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 {
- 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<String> 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 6b945506b9..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java
+++ /dev/null
@@ -1,343 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.internal.tcnative.CertificateCallback;
-import io.netty.util.internal.SuppressJava6Requirement;
-import io.netty.util.internal.SystemPropertyUtil;
-import io.netty.util.internal.logging.InternalLogger;
-import io.netty.util.internal.logging.InternalLoggerFactory;
-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.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.
- * <p>Instances of this class must be {@link #release() released} or else native memory will leak!
- *
- * <p>Instances of this class <strong>must not</strong> 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 InternalLogger logger =
- InternalLoggerFactory.getInstance(ReferenceCountedOpenSslClientContext.class);
- private static final Set<String> SUPPORTED_KEY_TYPES = Collections.unmodifiableSet(new LinkedHashSet<String>(
- 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 static final boolean ENABLE_SESSION_TICKET =
- SystemPropertyUtil.getBoolean("jdk.tls.client.enableSessionTicketExtension", false);
- private final OpenSslSessionContext sessionContext;
-
- ReferenceCountedOpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
- KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
- CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
- String[] protocols, long sessionCacheSize, long sessionTimeout,
- boolean enableOcsp, String keyStore) throws SSLException {
- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_CLIENT, keyCertChain,
- ClientAuth.NONE, protocols, false, enableOcsp, true);
- boolean success = false;
- try {
- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
- keyCertChain, key, keyPassword, keyManagerFactory, keyStore);
- if (ENABLE_SESSION_TICKET) {
- sessionContext.setTicketKeys();
- }
- 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) 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());
-
- // 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);
- 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));
- }
- }
-
- // No cache is currently supported for client side mode.
- static final class OpenSslClientSessionContext extends OpenSslSessionContext {
- OpenSslClientSessionContext(ReferenceCountedOpenSslContext context, OpenSslKeyMaterialProvider provider) {
- super(context, provider);
- }
-
- @Override
- public void setSessionTimeout(int seconds) {
- if (seconds < 0) {
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public int getSessionTimeout() {
- return 0;
- }
-
- @Override
- public void setSessionCacheSize(int size) {
- if (size < 0) {
- throw new IllegalArgumentException();
- }
- }
-
- @Override
- public int getSessionCacheSize() {
- return 0;
- }
-
- @Override
- public void setSessionCacheEnabled(boolean enabled) {
- // ignored
- }
-
- @Override
- public boolean isSessionCacheEnabled() {
- return false;
- }
- }
-
- 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 = OpenSslTlsv13X509ExtendedTrustManager.wrap(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<String> keyTypesSet = supportedClientKeyTypes(keyTypeBytes);
- final String[] keyTypes = keyTypesSet.toArray(new String[0]);
- 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) {
- logger.debug("request of key failed", cause);
- engine.initHandshakeException(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<String> supportedClientKeyTypes(byte[] clientCertificateTypes) {
- if (clientCertificateTypes == null) {
- // Try all of the supported key types.
- return SUPPORTED_KEY_TYPES;
- }
- Set<String> result = new HashSet<String>(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 http://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 27eb43574c..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java
+++ /dev/null
@@ -1,968 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.internal.tcnative.CertificateVerifier;
-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.internal.ObjectUtil;
-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.Arrays;
-import java.util.Collections;
-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.checkPositiveOrZero;
-
-/**
- * An implementation of {@link SslContext} which works with libraries that support the
- * <a href="https://www.openssl.org/">OpenSsl</a> C library API.
- * <p>Instances of this class must be {@link #release() released} or else native memory will leak!
- *
- * <p>Instances of this class <strong>must not</strong> 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));
- static final boolean USE_TASKS =
- SystemPropertyUtil.getBoolean("io.netty.handler.ssl.openssl.useTasks", false);
- private static final Integer DH_KEY_LENGTH;
- private static final ResourceLeakDetector<ReferenceCountedOpenSslContext> leakDetector =
- ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslContext.class);
-
- // TODO: Maybe make configurable ?
- protected static final int VERIFY_DEPTH = 10;
-
- /**
- * The OpenSSL SSL_CTX object.
- *
- * <strong>{@link #ctxLock} must be hold while using ctx!</strong>
- */
- protected long ctx;
- private final List<String> unmodifiableCiphers;
- private final long sessionCacheSize;
- private final long sessionTimeout;
- private final OpenSslApplicationProtocolNegotiator apn;
- private final int mode;
-
- // Reference Counting
- private final ResourceLeakTracker<ReferenceCountedOpenSslContext> 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 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<String> 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;
- }
-
- ReferenceCountedOpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
- ApplicationProtocolConfig apnCfg, long sessionCacheSize, long sessionTimeout,
- int mode, Certificate[] keyCertChain, ClientAuth clientAuth, String[] protocols,
- boolean startTls, boolean enableOcsp, boolean leakDetection) throws SSLException {
- this(ciphers, cipherFilter, toNegotiator(apnCfg), sessionCacheSize, sessionTimeout, mode, keyCertChain,
- clientAuth, protocols, startTls, enableOcsp, leakDetection);
- }
-
- ReferenceCountedOpenSslContext(Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
- OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize,
- long sessionTimeout, int mode, Certificate[] keyCertChain,
- ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp,
- boolean leakDetection) throws SSLException {
- super(startTls);
-
- 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");
- }
- leak = leakDetection ? leakDetector.track(this) : null;
- this.mode = mode;
- this.clientAuth = isServer() ? checkNotNull(clientAuth, "clientAuth") : ClientAuth.NONE;
- this.protocols = protocols;
- this.enableOcsp = enableOcsp;
-
- this.keyCertChain = keyCertChain == null ? null : keyCertChain.clone();
-
- unmodifiableCiphers = Arrays.asList(checkNotNull(cipherFilter, "cipherFilter").filterCipherSuites(
- ciphers, DEFAULT_CIPHERS, availableJavaCipherSuites()));
-
- this.apn = checkNotNull(apn, "apn");
-
- // Create a new SSL_CTX and configure it.
- boolean success = false;
- try {
- try {
- int protocolOpts = SSL.SSL_PROTOCOL_SSLV3 | SSL.SSL_PROTOCOL_TLSV1 |
- SSL.SSL_PROTOCOL_TLSV1_1 | SSL.SSL_PROTOCOL_TLSV1_2;
- if (OpenSsl.isTlsv13Supported()) {
- protocolOpts |= SSL.SSL_PROTOCOL_TLSV1_3;
- }
- ctx = SSLContext.make(protocolOpts, mode);
- } catch (Exception e) {
- throw new SSLException("failed to create an SSL_CTX", e);
- }
-
- boolean tlsv13Supported = OpenSsl.isTlsv13Supported();
- 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.
- SSLContext.setCipherSuite(ctx, cipherTLSv13Builder.toString(), 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.3 by default for now. Even if TLSv1.3 is not supported this will
- // work fine as in this case SSL_OP_NO_TLSv1_3 will be 0.
- SSL.SSL_OP_NO_TLSv1_3 |
-
- 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;
- }
-
- 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<String> nextProtoList = apn.protocols();
- /* Set next protocols for next protocol negotiation extension, if specified */
- if (!nextProtoList.isEmpty()) {
- String[] appProtocols = nextProtoList.toArray(new String[0]);
- 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();
- }
- }
-
- /* Set session cache size, if specified */
- if (sessionCacheSize <= 0) {
- // Get the default session cache size using SSLContext.setSessionCacheSize()
- sessionCacheSize = SSLContext.setSessionCacheSize(ctx, 20480);
- }
- this.sessionCacheSize = sessionCacheSize;
- SSLContext.setSessionCacheSize(ctx, sessionCacheSize);
-
- /* Set session timeout, if specified */
- if (sessionTimeout <= 0) {
- // Get the default session timeout using SSLContext.setSessionCacheTimeout()
- sessionTimeout = SSLContext.setSessionCacheTimeout(ctx, 300);
- }
- this.sessionTimeout = sessionTimeout;
- SSLContext.setSessionCacheTimeout(ctx, sessionTimeout);
-
- if (enableOcsp) {
- SSLContext.enableOcsp(ctx, isClient());
- }
-
- SSLContext.setUseTasks(ctx, USE_TASKS);
- 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<String> cipherSuites() {
- return unmodifiableCiphers;
- }
-
- @Override
- public final long sessionCacheSize() {
- return sessionCacheSize;
- }
-
- @Override
- public final long sessionTimeout() {
- return sessionTimeout;
- }
-
- @Override
- public ApplicationProtocolNegotiator applicationProtocolNegotiator() {
- return apn;
- }
-
- @Override
- public final boolean isClient() {
- return mode == SSL.SSL_MODE_CLIENT;
- }
-
- @Override
- public final SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) {
- return newEngine0(alloc, peerHost, peerPort, true);
- }
-
- @Override
- protected final SslHandler newHandler(ByteBufAllocator alloc, boolean startTls) {
- return new SslHandler(newEngine0(alloc, null, -1, false), startTls);
- }
-
- @Override
- protected final SslHandler newHandler(ByteBufAllocator alloc, String peerHost, int peerPort, boolean startTls) {
- return new SslHandler(newEngine0(alloc, peerHost, peerPort, false), startTls);
- }
-
- @Override
- protected SslHandler newHandler(ByteBufAllocator alloc, boolean startTls, Executor executor) {
- return new SslHandler(newEngine0(alloc, null, -1, false), startTls, executor);
- }
-
- @Override
- protected SslHandler newHandler(ByteBufAllocator alloc, String peerHost, int peerPort,
- boolean startTls, Executor executor) {
- return new SslHandler(newEngine0(alloc, peerHost, peerPort, false), executor);
- }
-
- SSLEngine newEngine0(ByteBufAllocator alloc, String peerHost, int peerPort, boolean jdkCompatibilityMode) {
- return new ReferenceCountedOpenSslEngine(this, alloc, peerHost, peerPort, jdkCompatibilityMode, true);
- }
-
- /**
- * 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.
- */
- @UnstableApi
- public final void setPrivateKeyMethod(OpenSslPrivateKeyMethod method) {
- ObjectUtil.checkNotNull(method, "method");
- Lock writerLock = ctxLock.writeLock();
- writerLock.lock();
- try {
- SSLContext.setPrivateKeyMethod(ctx, new PrivateKeyMethod(engineMap, method));
- } finally {
- writerLock.unlock();
- }
- }
-
- 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 OpenSslX509Certificate(chain[i]);
- }
- return peerCerts;
- }
-
- protected static X509TrustManager chooseTrustManager(TrustManager[] managers) {
- for (TrustManager m : managers) {
- if (m instanceof X509TrustManager) {
- if (PlatformDependent.javaVersion() >= 7) {
- return OpenSslX509TrustManagerWrapper.wrapIfNeeded((X509TrustManager) m);
- }
- return (X509TrustManager) m;
- }
- }
- 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<Long, ReferenceCountedOpenSslEngine> 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 <a href="https://www.openssl.org/docs/crypto/BIO_get_mem_ptr.html">in-memory BIO</a>
- * 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 <a href="https://www.openssl.org/docs/crypto/BIO_get_mem_ptr.html">in-memory BIO</a>
- * 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;
- }
-
- if (certChain.length == 0) {
- throw new IllegalArgumentException("certChain can't be empty");
- }
-
- 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 final class PrivateKeyMethod implements SSLPrivateKeyMethod {
-
- private final OpenSslEngineMap engineMap;
- private final OpenSslPrivateKeyMethod keyMethod;
- PrivateKeyMethod(OpenSslEngineMap engineMap, OpenSslPrivateKeyMethod keyMethod) {
- this.engineMap = engineMap;
- this.keyMethod = keyMethod;
- }
-
- private ReferenceCountedOpenSslEngine retrieveEngine(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;
- }
-
- @Override
- public byte[] sign(long ssl, int signatureAlgorithm, byte[] digest) throws Exception {
- ReferenceCountedOpenSslEngine engine = retrieveEngine(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(ssl);
- try {
- return verifyResult(keyMethod.decrypt(engine, input));
- } catch (Exception e) {
- engine.initHandshakeException(e);
- throw e;
- }
- }
-
- private static byte[] verifyResult(byte[] result) throws SignatureException {
- if (result == null) {
- throw new SignatureException();
- }
- return result;
- }
- }
-}
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 b404a1076b..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java
+++ /dev/null
@@ -1,2467 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.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.ObjectUtil;
-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.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-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.net.ssl.SSLSessionContext;
-import javax.security.cert.X509Certificate;
-
-import static io.netty.handler.ssl.OpenSsl.memoryAddress;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2_HELLO;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
-import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_3;
-import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
-import static io.netty.util.internal.ObjectUtil.checkNotNull;
-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
- * <a href="https://www.openssl.org/docs/crypto/BIO_s_bio.html#EXAMPLE">OpenSSL BIO abstractions</a>.
- * <p>Instances of this class must be {@link #release() released} or else native memory will leak!
- *
- * <p>Instances of this class <strong>must</strong> 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<ReferenceCountedOpenSslEngine> 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!
- */
- private 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;
-
- // Reference Counting
- private final ResourceLeakTracker<ReferenceCountedOpenSslEngine> 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 volatile ClientAuth clientAuth = ClientAuth.NONE;
- private volatile Certificate[] localCertificateChain;
-
- // Updated once a new handshake is started and so the SSLSession reused.
- private volatile long lastAccessed = -1;
-
- private String endPointIdentificationAlgorithm;
- // Store as object as AlgorithmConstraints only exists since java 7.
- private Object algorithmConstraints;
- private List<String> 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) {
- super(peerHost, peerPort);
- OpenSsl.ensureAvailability();
- this.alloc = checkNotNull(alloc, "alloc");
- apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator();
- clientMode = context.isClient();
- 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 = EmptyArrays.EMPTY_STRINGS;
- } else {
- String[] algs = SSL.getSigAlgs(ssl);
- if (algs == null) {
- peerSupportedSignatureAlgorithms = EmptyArrays.EMPTY_STRINGS;
- } else {
- Set<String> algorithmList = new LinkedHashSet<String>(algs.length);
- for (String alg: algs) {
- String converted = SignatureAlgorithmConverter.toJavaName(alg);
-
- if (converted != null) {
- algorithmList.add(converted);
- }
- }
- peerSupportedSignatureAlgorithms = algorithmList.toArray(new String[0]);
- }
- }
- }
- return peerSupportedSignatureAlgorithms.clone();
- }
- }
-
- @Override
- public List<byte[]> getStatusResponses() {
- byte[] ocspResponse = null;
- if (enableOcsp && clientMode) {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- if (!isDestroyed()) {
- ocspResponse = SSL.getOcspResponse(ssl);
- }
- }
- }
- return ocspResponse == null ?
- Collections.<byte[]>emptyList() : Collections.singletonList(ocspResponse);
- }
- };
- } else {
- session = new DefaultOpenSslSession(context.sessionContext());
- }
- engineMap = context.engineMap;
- enableOcsp = context.enableOcsp;
- if (!context.sessionContext().useKeyManager()) {
- // If we do not use the KeyManagerFactory we need to set localCertificateChain now.
- // When we use a KeyManagerFactory it will be set during setKeyMaterial(...).
- localCertificateChain = context.keyCertChain;
- }
-
- this.jdkCompatibilityMode = jdkCompatibilityMode;
- 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);
-
- if (context.protocols != null) {
- 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)) {
- 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);
- }
-
- // setMode may impact the overhead.
- calculateMaxWrapOverhead();
- } 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 EmptyArrays.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());
- }
- localCertificateChain = keyMaterial.certificateChain();
- return true;
- }
-
- final synchronized SecretKeySpec masterKey() {
- if (isDestroyed()) {
- return null;
- }
- return new SecretKeySpec(SSL.getMasterKey(ssl), "AES");
- }
-
- /**
- * 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);
- }
-
- @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;
- 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;
- }
-
- /**
- * Write encrypted data to the OpenSSL network BIO.
- */
- private ByteBuf writeEncryptedData(final ByteBuffer src, int len) {
- 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) {
- 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.
- */
- final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
- return (int) min(maxWrapBufferSize, 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
- if (srcs == null) {
- throw new IllegalArgumentException("srcs is null");
- }
- if (dst == null) {
- throw new IllegalArgumentException("dst is null");
- }
-
- if (offset >= srcs.length || offset + length > srcs.length) {
- throw new IndexOutOfBoundsException(
- "offset: " + offset + ", length: " + length +
- " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
- }
-
- if (dst.isReadOnly()) {
- throw new ReadOnlyBufferException();
- }
-
- 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;
- // 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) {
- 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 != FINISHED ? getHandshakeStatus() : FINISHED),
- bytesConsumed, bytesProduced);
- }
-
- private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
- SSLEngineResult.HandshakeStatus hs,
- int bytesConsumed, int bytesProduced) throws SSLException {
- return newResult(status, mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
- 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) {
- String errorString = SSL.getErrorString(error);
- if (logger.isDebugEnabled()) {
- logger.debug("{} failed with {}: OpenSSL error: {} {}",
- operation, sslError, error, errorString);
- }
-
- // There was an internal error -- shutdown
- shutdown();
- if (handshakeState == HandshakeState.FINISHED) {
- return new SSLException(errorString);
- }
-
- SSLHandshakeException exception = new SSLHandshakeException(errorString);
- // If we have a handshakeException stored already we should include it as well to help the user debug things.
- if (pendingException != null) {
- exception.initCause(pendingException);
- pendingException = null;
- }
- return exception;
- }
-
- 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
- ObjectUtil.checkNotNull(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 + "))");
- }
- if (dsts == null) {
- throw new IllegalArgumentException("dsts is null");
- }
- if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
- throw new IndexOutOfBoundsException(
- "offset: " + dstsOffset + ", length: " + dstsLength +
- " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
- }
- long capacity = 0;
- final int dstsEndOffset = dstsOffset + dstsLength;
- for (int i = dstsOffset; i < dstsEndOffset; i ++) {
- ByteBuffer dst = dsts[i];
- if (dst == null) {
- throw new IllegalArgumentException("dsts[" + i + "] is null");
- }
- 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 = srcs[i];
- if (src == null) {
- throw new IllegalArgumentException("srcs[" + i + "] is null");
- }
- len += src.remaining();
- }
-
- synchronized (this) {
- if (isInboundDone()) {
- return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
- }
-
- SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
- // 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 (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);
- bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
- }
- 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 = readPlaintextData(dst);
- // 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 SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced)
- throws SSLException {
- // 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 seems 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.
- String message = SSL.getErrorString(stackError);
- SSLException exception = handshakeState == HandshakeState.FINISHED ?
- new SSLException(message) : new SSLHandshakeException(message);
- if (pendingException == null) {
- pendingException = exception;
- } else {
- ThrowableUtil.addSuppressed(pendingException, exception);
- }
- // 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 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() && SSL.getHandshakeCount(ssl) > 1 &&
- // 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.
- !SslUtils.PROTOCOL_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();
- }
- }
-
- @Override
- public final synchronized Runnable getDelegatedTask() {
- if (isDestroyed()) {
- return null;
- }
- final Runnable task = SSL.getTask(ssl);
- if (task == null) {
- return null;
- }
- return new Runnable() {
- @Override
- public void run() {
- if (isDestroyed()) {
- // The engine was destroyed in the meantime, just return.
- return;
- }
- try {
- task.run();
- } finally {
- // The task was run, reset needTask to false so getHandshakeStatus() returns the correct value.
- needTask = false;
- }
- }
- };
- }
-
- @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 http://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(new String[0]);
- }
-
- @Override
- public final String[] getEnabledCipherSuites() {
- final String[] extraCiphers;
- final String[] enabled;
- synchronized (this) {
- if (!isDestroyed()) {
- enabled = SSL.getCiphers(ssl);
- int opts = SSL.getOptions(ssl);
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, PROTOCOL_TLS_V1_3)) {
- extraCiphers = OpenSsl.EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
- } else {
- extraCiphers = EmptyArrays.EMPTY_STRINGS;
- }
- } else {
- return EmptyArrays.EMPTY_STRINGS;
- }
- }
- if (enabled == null) {
- return EmptyArrays.EMPTY_STRINGS;
- } else {
- Set<String> enabledSet = new LinkedHashSet<String>(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 (!OpenSsl.isTlsv13Supported() && SslUtils.isTLSv13Cipher(cipher)) {
- continue;
- }
- enabledSet.add(cipher);
- }
- Collections.addAll(enabledSet, extraCiphers);
- }
- return enabledSet.toArray(new String[0]);
- }
- }
-
- @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) {
- if (!isDestroyed()) {
- // TODO: Should we also adjust the protocols based on if there are any ciphers left that can be used
- // for TLSv1.3 or for previor SSL/TLS versions ?
- try {
- // Set non TLSv1.3 ciphers.
- SSL.setCipherSuites(ssl, cipherSuiteSpec, false);
-
- if (OpenSsl.isTlsv13Supported()) {
- // Set TLSv1.3 ciphers.
- SSL.setCipherSuites(ssl, cipherSuiteSpecTLSv13, true);
- }
-
- } 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(new String[0]);
- }
-
- @Override
- public final String[] getEnabledProtocols() {
- List<String> enabled = new ArrayList<String>(6);
- // Seems like there is no way to explicit disable SSLv2Hello in openssl so it is always enabled
- enabled.add(PROTOCOL_SSL_V2_HELLO);
-
- int opts;
- synchronized (this) {
- if (!isDestroyed()) {
- opts = SSL.getOptions(ssl);
- } else {
- return enabled.toArray(new String[0]);
- }
- }
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1, PROTOCOL_TLS_V1)) {
- enabled.add(PROTOCOL_TLS_V1);
- }
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_1, PROTOCOL_TLS_V1_1)) {
- enabled.add(PROTOCOL_TLS_V1_1);
- }
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_2, PROTOCOL_TLS_V1_2)) {
- enabled.add(PROTOCOL_TLS_V1_2);
- }
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, PROTOCOL_TLS_V1_3)) {
- enabled.add(PROTOCOL_TLS_V1_3);
- }
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv2, PROTOCOL_SSL_V2)) {
- enabled.add(PROTOCOL_SSL_V2);
- }
- if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv3, PROTOCOL_SSL_V3)) {
- enabled.add(PROTOCOL_SSL_V3);
- }
- return enabled.toArray(new String[0]);
- }
-
- 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) {
- if (protocols == null) {
- // This is correct from the API docs
- throw new IllegalArgumentException();
- }
- 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(PROTOCOL_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(PROTOCOL_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(PROTOCOL_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(PROTOCOL_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(PROTOCOL_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 (p.equals(PROTOCOL_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;
- }
- }
- }
- synchronized (this) {
- 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 (lastAccessed == -1) {
- lastAccessed = System.currentTimeMillis();
- }
-
- 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;
- }
-
- // 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();
- return FINISHED;
- }
-
- private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
- throws SSLException {
- if (status == NOT_HANDSHAKING && 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();
- }
- 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 <a href="https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html">SSL_set_verify</a> 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) {
- sslParameters.setEndpointIdentificationAlgorithm(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<String> 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) {
- // 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);
- }
- }
- this.endPointIdentificationAlgorithm = endPointIdentificationAlgorithm;
- algorithmConstraints = sslParameters.getAlgorithmConstraints();
- }
- super.setSSLParameters(sslParameters);
- }
-
- 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);
- }
-
- 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 String protocol;
- private String cipher;
- private byte[] id;
- private long creationTime;
- private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
-
- // lazy init for memory reasons
- private Map<String, Object> values;
-
- DefaultOpenSslSession(OpenSslSessionContext sessionContext) {
- this.sessionContext = sessionContext;
- }
-
- private SSLSessionBindingEvent newSSLSessionBindingEvent(String name) {
- return new SSLSessionBindingEvent(session, name);
- }
-
- @Override
- public byte[] getId() {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- if (id == null) {
- return EmptyArrays.EMPTY_BYTES;
- }
- return id.clone();
- }
- }
-
- @Override
- public SSLSessionContext getSessionContext() {
- return sessionContext;
- }
-
- @Override
- public long getCreationTime() {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- if (creationTime == 0 && !isDestroyed()) {
- creationTime = SSL.getTime(ssl) * 1000L;
- }
- }
- return creationTime;
- }
-
- @Override
- public long getLastAccessedTime() {
- long lastAccessed = ReferenceCountedOpenSslEngine.this.lastAccessed;
- // if lastAccessed is -1 we will just return the creation time as the handshake was not started yet.
- return lastAccessed == -1 ? getCreationTime() : lastAccessed;
- }
-
- @Override
- public void invalidate() {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- if (!isDestroyed()) {
- SSL.setTimeout(ssl, 0);
- }
- }
- }
-
- @Override
- public boolean isValid() {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- if (!isDestroyed()) {
- return System.currentTimeMillis() - (SSL.getTimeout(ssl) * 1000L) < (SSL.getTime(ssl) * 1000L);
- }
- }
- return false;
- }
-
- @Override
- public void putValue(String name, Object value) {
- ObjectUtil.checkNotNull(name, "name");
- ObjectUtil.checkNotNull(value, "value");
-
- final Object old;
- synchronized (this) {
- Map<String, Object> values = this.values;
- if (values == null) {
- // Use size of 2 to keep the memory overhead small
- values = this.values = new HashMap<String, Object>(2);
- }
- old = values.put(name, value);
- }
-
- if (value instanceof SSLSessionBindingListener) {
- // Use newSSLSessionBindingEvent so we alway use the wrapper if needed.
- ((SSLSessionBindingListener) value).valueBound(newSSLSessionBindingEvent(name));
- }
- notifyUnbound(old, name);
- }
-
- @Override
- public Object getValue(String name) {
- ObjectUtil.checkNotNull(name, "name");
- synchronized (this) {
- if (values == null) {
- return null;
- }
- return values.get(name);
- }
- }
-
- @Override
- public void removeValue(String name) {
- ObjectUtil.checkNotNull(name, "name");
-
- final Object old;
- synchronized (this) {
- Map<String, Object> values = this.values;
- if (values == null) {
- return;
- }
- old = values.remove(name);
- }
-
- notifyUnbound(old, name);
- }
-
- @Override
- public String[] getValueNames() {
- synchronized (this) {
- Map<String, Object> values = this.values;
- if (values == null || values.isEmpty()) {
- return EmptyArrays.EMPTY_STRINGS;
- }
- return values.keySet().toArray(new String[0]);
- }
- }
-
- private void notifyUnbound(Object value, String name) {
- if (value instanceof SSLSessionBindingListener) {
- // Use newSSLSessionBindingEvent so we alway 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() throws SSLException {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- if (!isDestroyed()) {
- id = SSL.getSessionId(ssl);
- cipher = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
- protocol = SSL.getVersion(ssl);
-
- initPeerCerts();
- selectApplicationProtocol();
- calculateMaxWrapOverhead();
-
- handshakeState = HandshakeState.FINISHED;
- } else {
- throw new SSLException("Already closed");
- }
- }
- }
-
- /**
- * Init peer certificates that can be obtained via {@link #getPeerCertificateChain()}
- * and {@link #getPeerCertificates()}.
- */
- private void initPeerCerts() {
- // Return the full chain from the JNI layer.
- byte[][] chain = SSL.getPeerCertChain(ssl);
- if (clientMode) {
- if (isEmpty(chain)) {
- peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
- x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
- } else {
- peerCerts = new Certificate[chain.length];
- x509PeerCerts = new X509Certificate[chain.length];
- initCerts(chain, 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
- byte[] clientCert = SSL.getPeerCertificate(ssl);
- if (isEmpty(clientCert)) {
- peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
- x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
- } else {
- if (isEmpty(chain)) {
- peerCerts = new Certificate[] {new OpenSslX509Certificate(clientCert)};
- x509PeerCerts = new X509Certificate[] {new OpenSslJavaxX509Certificate(clientCert)};
- } else {
- peerCerts = new Certificate[chain.length + 1];
- x509PeerCerts = new X509Certificate[chain.length + 1];
- peerCerts[0] = new OpenSslX509Certificate(clientCert);
- x509PeerCerts[0] = new OpenSslJavaxX509Certificate(clientCert);
- initCerts(chain, 1);
- }
- }
- }
- }
-
- private void initCerts(byte[][] chain, int startPos) {
- for (int i = 0; i < chain.length; i++) {
- int certPos = startPos + i;
- peerCerts[certPos] = new OpenSslX509Certificate(chain[i]);
- x509PeerCerts[certPos] = new OpenSslJavaxX509Certificate(chain[i]);
- }
- }
-
- /**
- * Select the application protocol used.
- */
- private void selectApplicationProtocol() throws SSLException {
- ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
- List<String> 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<String> 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);
- }
- }
- }
- }
-
- @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 = ReferenceCountedOpenSslEngine.this.localCertificateChain;
- if (localCerts == null) {
- return null;
- }
- return localCerts.clone();
- }
-
- @Override
- public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
- synchronized (ReferenceCountedOpenSslEngine.this) {
- 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 = ReferenceCountedOpenSslEngine.this.localCertificateChain;
- if (local == null || local.length == 0) {
- return null;
- }
- return ((java.security.cert.X509Certificate) local[0]).getIssuerX500Principal();
- }
-
- @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 maxEncryptedPacketLength();
- }
-
- @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;
- }
- }
- }
-}
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 bac027a3b4..0000000000
--- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java
+++ /dev/null
@@ -1,286 +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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.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.SystemPropertyUtil;
-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 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.
- * <p>Instances of this class must be {@link #release() released} or else native memory will leak!
- *
- * <p>Instances of this class <strong>must not</strong> 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;
-
- private static final boolean ENABLE_SESSION_TICKET =
- SystemPropertyUtil.getBoolean("jdk.tls.server.enableSessionTicketExtension", false);
-
- ReferenceCountedOpenSslServerContext(
- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
- Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
- boolean enableOcsp, String keyStore) throws SSLException {
- this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers,
- cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls,
- enableOcsp, keyStore);
- }
-
- ReferenceCountedOpenSslServerContext(
- X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
- X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
- Iterable<String> ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn,
- long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
- boolean enableOcsp, String keyStore) throws SSLException {
- super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain,
- clientAuth, protocols, startTls, enableOcsp, true);
- // Create a new SSL_CTX and configure it.
- boolean success = false;
- try {
- sessionContext = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory,
- keyCertChain, key, keyPassword, keyManagerFactory, keyStore);
- if (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)
- 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());
-
- // 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);
-
- 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) {
- logger.debug("Failed to set the server-side key material", cause);
- engine.initHandshakeException(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 = OpenSslTlsv13X509ExtendedTrustManager.wrap(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 fef2702cfb..eb5110d145 100644
--- a/handler/src/main/java/io/netty/handler/ssl/SslContext.java
+++ b/handler/src/main/java/io/netty/handler/ssl/SslContext.java
@@ -120,11 +120,7 @@ public abstract class SslContext {
}
private static SslProvider defaultProvider() {
- if (OpenSsl.isAvailable()) {
- return SslProvider.OPENSSL;
- } else {
- return SslProvider.JDK;
- }
+ return SslProvider.JDK;
}
/**
@@ -466,18 +462,6 @@ public abstract class SslContext {
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
clientAuth, protocols, startTls, keyStoreType);
- case OPENSSL:
- verifyNullSslContextProvider(provider, sslContextProvider);
- return new OpenSslServerContext(
- trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
- keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
- clientAuth, protocols, startTls, enableOcsp, keyStoreType);
- 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);
default:
throw new Error(provider.toString());
}
@@ -822,18 +806,6 @@ public abstract class SslContext {
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize,
sessionTimeout, keyStoreType);
- case OPENSSL:
- verifyNullSslContextProvider(provider, sslContextProvider);
- return new OpenSslClientContext(
- trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
- keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout,
- enableOcsp, keyStoreType);
- case OPENSSL_REFCNT:
- verifyNullSslContextProvider(provider, sslContextProvider);
- return new ReferenceCountedOpenSslClientContext(
- trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
- keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, sessionTimeout,
- enableOcsp, keyStoreType);
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 8e11bbf4cc..56be212b09 100644
--- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java
+++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java
@@ -181,53 +181,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 readerIndex, 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(readerIndex, len), handler.singleBuffer);
- } finally {
- handler.singleBuffer[0] = null;
- }
- } else {
- result = handler.engine.unwrap(toByteBuffer(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)
- .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 readerIndex, int len, ByteBuf out)
@@ -280,7 +233,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) {
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 b1c710c841..44ef0456ed 100644
--- a/handler/src/main/java/io/netty/handler/ssl/SslMasterKeyHandler.java
+++ b/handler/src/main/java/io/netty/handler/ssl/SslMasterKeyHandler.java
@@ -138,9 +138,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 e72cfed8d9..5263314e7c 100644
--- a/handler/src/main/java/io/netty/handler/ssl/SslProvider.java
+++ b/handler/src/main/java/io/netty/handler/ssl/SslProvider.java
@@ -26,16 +26,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
@@ -45,9 +36,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);
}
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 c45c50e1e3..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl.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 2883ff48cf..0000000000
--- 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:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-/**
- * <a href="https://en.wikipedia.org/wiki/OCSP_stapling">OCSP stapling</a>,
- * 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;
diff --git a/pom.xml b/pom.xml
index bedd6d6903..75a2da328a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -465,16 +465,6 @@
<version>3.0.0-alpha-5</version>
</dependency>
- <!-- Our own Tomcat Native fork - completely optional, used for accelerating SSL with OpenSSL. -->
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>${tcnative.artifactId}</artifactId>
- <version>${tcnative.version}</version>
- <classifier>${tcnative.classifier}</classifier>
- <scope>compile</scope>
- <optional>true</optional>
- </dependency>
-
<!--
Bouncy Castle - completely optional, only needed when:
- you generate a temporary self-signed certificate using SelfSignedCertificate, and
--
2.26.2