diff --git a/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java b/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java
index 69a6125d17..184845a9fe 100644
--- a/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java
+++ b/handler/src/main/java/io/netty/handler/ssl/ExtendedOpenSslSession.java
@@ -42,7 +42,6 @@ abstract class ExtendedOpenSslSession extends ExtendedSSLSession implements Open
private final OpenSslSession wrapped;
ExtendedOpenSslSession(OpenSslSession wrapped) {
- assert !(wrapped instanceof ExtendedSSLSession);
this.wrapped = wrapped;
}
@@ -153,7 +152,7 @@ abstract class ExtendedOpenSslSession extends ExtendedSSLSession implements Open
}
@Override
- public final String getProtocol() {
+ public String getProtocol() {
return wrapped.getProtocol();
}
diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
index 955404b25e..073c855a4a 100644
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
+++ b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
@@ -31,7 +31,6 @@ import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
-import javax.net.ssl.SSLException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
@@ -40,16 +39,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import static io.netty.handler.ssl.SslUtils.DEFAULT_CIPHER_SUITES;
-import static io.netty.handler.ssl.SslUtils.addIfSupported;
-import static io.netty.handler.ssl.SslUtils.useFallbackCiphersIfDefaultIsEmpty;
-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.*;
/**
* Tells if {@code netty-tcnative} and its OpenSSL support
@@ -154,14 +144,13 @@ public final class OpenSsl {
long certBio = 0;
SelfSignedCertificate cert = null;
try {
- if (PlatformDependent.javaVersion() >= 11) {
- try {
- SSLContext.setCipherSuite(sslCtx, TLSV13_CIPHERS, true);
- tlsv13Supported = true;
- } catch (Exception ignore) {
- tlsv13Supported = false;
- }
+ try {
+ SSLContext.setCipherSuite(sslCtx, TLSV13_CIPHERS, true);
+ tlsv13Supported = true;
+ } catch (Exception ignore) {
+ tlsv13Supported = false;
}
+
SSLContext.setCipherSuite(sslCtx, "ALL", false);
final long ssl = SSL.newSSL(sslCtx, true);
@@ -231,6 +220,8 @@ public final class OpenSsl {
}
addIfSupported(availableJavaCipherSuites, defaultCiphers, DEFAULT_CIPHER_SUITES);
+ addIfSupported(availableJavaCipherSuites, defaultCiphers, TLSV13_CIPHER_SUITES);
+
useFallbackCiphersIfDefaultIsEmpty(defaultCiphers, availableJavaCipherSuites);
DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers);
@@ -266,11 +257,7 @@ public final class OpenSsl {
}
// This is only supported by java11 and later.
- if (tlsv13Supported && doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_OP_NO_TLSv1_3)
- && PlatformDependent.javaVersion() >= 11) {
- // We can only support TLS1.3 when using Java 11 or higher as otherwise it will fail to create the
- // internal instance of an sun.security.ssl.ProtocolVersion as can not parse the version string :/
- // See http://mail.openjdk.java.net/pipermail/security-dev/2018-September/018242.html
+ if (tlsv13Supported && doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_OP_NO_TLSv1_3)) {
protocols.add(PROTOCOL_TLS_V1_3);
TLSV13_SUPPORTED = true;
} else {
diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslTlsv13X509ExtendedTrustManager.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslTlsv13X509ExtendedTrustManager.java
new file mode 100644
index 0000000000..e145c05c08
--- /dev/null
+++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslTlsv13X509ExtendedTrustManager.java
@@ -0,0 +1,498 @@
+/*
+ * 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.EmptyArrays;
+import io.netty.util.internal.PlatformDependent;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLException;
+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.nio.ByteBuffer;
+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
+ * = 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();
+ }
+
+ private static final class DummySSLEngine extends SSLEngine {
+
+ private final boolean client;
+
+ DummySSLEngine(boolean client) {
+ this.client = client;
+ }
+
+ @Override
+ public SSLSession getHandshakeSession() {
+ return new SSLSession() {
+ @Override
+ public byte[] getId() {
+ return EmptyArrays.EMPTY_BYTES;
+ }
+
+ @Override
+ public SSLSessionContext getSessionContext() {
+ return null;
+ }
+
+ @Override
+ public long getCreationTime() {
+ return 0;
+ }
+
+ @Override
+ public long getLastAccessedTime() {
+ return 0;
+ }
+
+ @Override
+ public void invalidate() {
+ // NOOP
+ }
+
+ @Override
+ public boolean isValid() {
+ return false;
+ }
+
+ @Override
+ public void putValue(String s, Object o) {
+ // NOOP
+ }
+
+ @Override
+ public Object getValue(String s) {
+ return null;
+ }
+
+ @Override
+ public void removeValue(String s) {
+ // NOOP
+ }
+
+ @Override
+ public String[] getValueNames() {
+ return EmptyArrays.EMPTY_STRINGS;
+ }
+
+ @Override
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
+ return EmptyArrays.EMPTY_CERTIFICATES;
+ }
+
+ @Override
+ public Certificate[] getLocalCertificates() {
+ return EmptyArrays.EMPTY_CERTIFICATES;
+ }
+
+ @Override
+ public javax.security.cert.X509Certificate[] getPeerCertificateChain()
+ throws SSLPeerUnverifiedException {
+ return EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
+ }
+
+ @Override
+ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+ return null;
+ }
+
+ @Override
+ public Principal getLocalPrincipal() {
+ return null;
+ }
+
+ @Override
+ public String getCipherSuite() {
+ return null;
+ }
+
+ @Override
+ public String getProtocol() {
+ return SslUtils.PROTOCOL_TLS_V1_3;
+ }
+
+ @Override
+ public String getPeerHost() {
+ return null;
+ }
+
+ @Override
+ public int getPeerPort() {
+ return 0;
+ }
+
+ @Override
+ public int getPacketBufferSize() {
+ return 0;
+ }
+
+ @Override
+ public int getApplicationBufferSize() {
+ return 0;
+ }
+ };
+ }
+
+ @Override
+ public SSLEngineResult wrap(ByteBuffer[] byteBuffers, int i, int i1, ByteBuffer byteBuffer)
+ throws SSLException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SSLEngineResult unwrap(ByteBuffer byteBuffer, ByteBuffer[] byteBuffers, int i, int i1)
+ throws SSLException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Runnable getDelegatedTask() {
+ return null;
+ }
+
+ @Override
+ public void closeInbound() throws SSLException {
+ // NOOP
+ }
+
+ @Override
+ public boolean isInboundDone() {
+ return true;
+ }
+
+ @Override
+ public void closeOutbound() {
+ // NOOP
+ }
+
+ @Override
+ public boolean isOutboundDone() {
+ return true;
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return EmptyArrays.EMPTY_STRINGS;
+ }
+
+ @Override
+ public String[] getEnabledCipherSuites() {
+ return EmptyArrays.EMPTY_STRINGS;
+ }
+
+ @Override
+ public void setEnabledCipherSuites(String[] strings) {
+ // NOOP
+ }
+
+ @Override
+ public String[] getSupportedProtocols() {
+ return new String[] { SslUtils.PROTOCOL_TLS_V1_3 };
+ }
+
+ @Override
+ public String[] getEnabledProtocols() {
+ return new String[] { SslUtils.PROTOCOL_TLS_V1_3 };
+ }
+
+ @Override
+ public void setEnabledProtocols(String[] strings) {
+ // NOOP
+ }
+
+ @Override
+ public SSLSession getSession() {
+ return getHandshakeSession();
+ }
+
+ @Override
+ public void beginHandshake() throws SSLException {
+ // NOOP
+ }
+
+ @Override
+ public HandshakeStatus getHandshakeStatus() {
+ return HandshakeStatus.NEED_TASK;
+ }
+
+ @Override
+ public void setUseClientMode(boolean b) {
+ // NOOP
+ }
+
+ @Override
+ public boolean getUseClientMode() {
+ return client;
+ }
+
+ @Override
+ public void setNeedClientAuth(boolean b) {
+ // NOOP
+ }
+
+ @Override
+ public boolean getNeedClientAuth() {
+ return false;
+ }
+
+ @Override
+ public void setWantClientAuth(boolean b) {
+ // NOOP
+ }
+
+ @Override
+ public boolean getWantClientAuth() {
+ return false;
+ }
+
+ @Override
+ public void setEnableSessionCreation(boolean b) {
+ // NOOP
+ }
+
+ @Override
+ public boolean getEnableSessionCreation() {
+ return false;
+ }
+ }
+}
diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java
index 4972905baa..f508971f01 100644
--- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java
+++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslClientContext.java
@@ -233,7 +233,7 @@ public final class ReferenceCountedOpenSslClientContext extends ReferenceCounted
ExtendedTrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509ExtendedTrustManager manager) {
super(engineMap);
- this.manager = manager;
+ this.manager = OpenSslTlsv13X509ExtendedTrustManager.wrap(manager, true);
}
@Override
diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java
index 1dbae15dd3..e901aebb38 100644
--- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java
+++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslServerContext.java
@@ -239,7 +239,7 @@ public final class ReferenceCountedOpenSslServerContext extends ReferenceCounted
ExtendedTrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509ExtendedTrustManager manager) {
super(engineMap);
- this.manager = manager;
+ this.manager = OpenSslTlsv13X509ExtendedTrustManager.wrap(manager, false);
}
@Override
diff --git a/handler/src/main/java/io/netty/handler/ssl/SslUtils.java b/handler/src/main/java/io/netty/handler/ssl/SslUtils.java
index f1f000fa8f..492c4f2b7d 100644
--- a/handler/src/main/java/io/netty/handler/ssl/SslUtils.java
+++ b/handler/src/main/java/io/netty/handler/ssl/SslUtils.java
@@ -97,10 +97,11 @@ final class SslUtils {
static final String[] DEFAULT_CIPHER_SUITES;
static final String[] DEFAULT_TLSV13_CIPHER_SUITES;
+ static final String[] TLSV13_CIPHER_SUITES = { "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384" };
static {
if (PlatformDependent.javaVersion() >= 11) {
- DEFAULT_TLSV13_CIPHER_SUITES = new String[] { "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384" };
+ DEFAULT_TLSV13_CIPHER_SUITES = TLSV13_CIPHER_SUITES;
} else {
DEFAULT_TLSV13_CIPHER_SUITES = EmptyArrays.EMPTY_STRINGS;
}
diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java
index 630de226d6..1ae88ebdfb 100644
--- a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java
+++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java
@@ -73,7 +73,7 @@ public class OpenSslEngineTest extends SSLEngineTest {
for (BufferType type: BufferType.values()) {
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
- if (PlatformDependent.javaVersion() >= 11 && OpenSsl.isTlsv13Supported()) {
+ if (OpenSsl.isTlsv13Supported()) {
params.add(new Object[] { type, ProtocolCipherCombo.tlsv13() });
}
}
diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslTest.java
index 4fd8491099..0a9d19db65 100644
--- a/handler/src/test/java/io/netty/handler/ssl/OpenSslTest.java
+++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslTest.java
@@ -22,7 +22,9 @@ public class OpenSslTest {
@Test
public void testDefaultCiphers() {
- Assert.assertTrue(
- OpenSsl.DEFAULT_CIPHERS.size() <= SslUtils.DEFAULT_CIPHER_SUITES.length);
+ if (!OpenSsl.isTlsv13Supported()) {
+ Assert.assertTrue(
+ OpenSsl.DEFAULT_CIPHERS.size() <= SslUtils.DEFAULT_CIPHER_SUITES.length);
+ }
}
}
diff --git a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java
index 0094c92d3e..fd8c9b8fc3 100644
--- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java
+++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java
@@ -1201,6 +1201,7 @@ public abstract class SSLEngineTest {
@Test(timeout = 30000)
public void clientInitiatedRenegotiationWithFatalAlertDoesNotInfiniteLoopServer()
throws CertificateException, SSLException, InterruptedException, ExecutionException {
+ Assume.assumeTrue(PlatformDependent.javaVersion() >= 11);
final SelfSignedCertificate ssc = new SelfSignedCertificate();
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
.sslProvider(sslServerProvider())