From 0b7bf49c165e682644a53279f75a44ba084201cd Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Wed, 12 Oct 2016 14:30:32 +0900 Subject: [PATCH] Convert X509TrustManager into X509ExtendedTrustManager for Java 7+ Motivation: Since Java 7, X509TrustManager implementation is wrapped by a JDK class called AbstractTrustManagerWrapper, which performs an additional certificate validation for Socket or SSLEngine-backed connections. This makes the TrustManager implementations provided by InsecureTrustManagerFactory and FingerprintTrustManagerFactory not insecure enough, where their certificate validation fails even when it should pass. Modifications: - Add X509TrustManagerWrapper which adapts an X509TrustManager into an X509ExtendedTrustManager - Make SimpleTrustManagerFactory wrap an X509TrustManager with X509TrustManagerWrapper is the provided TrustManager does not extend X509ExtendedTrustManager Result: - InsecureTrustManagerFactory and FingerprintTrustManagerFactory are now insecure as expected. - Fixes #5910 --- .../ssl/util/SimpleTrustManagerFactory.java | 19 ++++- .../ssl/util/X509TrustManagerWrapper.java | 73 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 handler/src/main/java/io/netty/handler/ssl/util/X509TrustManagerWrapper.java diff --git a/handler/src/main/java/io/netty/handler/ssl/util/SimpleTrustManagerFactory.java b/handler/src/main/java/io/netty/handler/ssl/util/SimpleTrustManagerFactory.java index 05fbc46151..a11cede558 100644 --- a/handler/src/main/java/io/netty/handler/ssl/util/SimpleTrustManagerFactory.java +++ b/handler/src/main/java/io/netty/handler/ssl/util/SimpleTrustManagerFactory.java @@ -17,11 +17,14 @@ package io.netty.handler.ssl.util; import io.netty.util.concurrent.FastThreadLocal; +import io.netty.util.internal.PlatformDependent; import javax.net.ssl.ManagerFactoryParameters; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactorySpi; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -98,6 +101,7 @@ public abstract class SimpleTrustManagerFactory extends TrustManagerFactory { static final class SimpleTrustManagerFactorySpi extends TrustManagerFactorySpi { private SimpleTrustManagerFactory parent; + private volatile TrustManager[] trustManagers; void init(SimpleTrustManagerFactory parent) { this.parent = parent; @@ -128,7 +132,20 @@ public abstract class SimpleTrustManagerFactory extends TrustManagerFactory { @Override protected TrustManager[] engineGetTrustManagers() { - return parent.engineGetTrustManagers(); + TrustManager[] trustManagers = this.trustManagers; + if (trustManagers == null) { + trustManagers = parent.engineGetTrustManagers(); + if (PlatformDependent.javaVersion() >= 7) { + for (int i = 0; i < trustManagers.length; i++) { + final TrustManager tm = trustManagers[i]; + if (tm instanceof X509TrustManager && !(tm instanceof X509ExtendedTrustManager)) { + trustManagers[i] = new X509TrustManagerWrapper((X509TrustManager) tm); + } + } + } + this.trustManagers = trustManagers; + } + return trustManagers.clone(); } } } diff --git a/handler/src/main/java/io/netty/handler/ssl/util/X509TrustManagerWrapper.java b/handler/src/main/java/io/netty/handler/ssl/util/X509TrustManagerWrapper.java new file mode 100644 index 0000000000..1b70b97122 --- /dev/null +++ b/handler/src/main/java/io/netty/handler/ssl/util/X509TrustManagerWrapper.java @@ -0,0 +1,73 @@ +/* + * 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.util; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; +import java.net.Socket; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import static io.netty.util.internal.ObjectUtil.*; + +final class X509TrustManagerWrapper extends X509ExtendedTrustManager { + + private final X509TrustManager delegate; + + X509TrustManagerWrapper(X509TrustManager delegate) { + this.delegate = checkNotNull(delegate, "delegate"); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String s) throws CertificateException { + delegate.checkClientTrusted(chain, s); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String s, Socket socket) + throws CertificateException { + delegate.checkClientTrusted(chain, s); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String s, SSLEngine sslEngine) + throws CertificateException { + delegate.checkClientTrusted(chain, s); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String s) throws CertificateException { + delegate.checkServerTrusted(chain, s); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String s, Socket socket) + throws CertificateException { + delegate.checkServerTrusted(chain, s); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String s, SSLEngine sslEngine) + throws CertificateException { + delegate.checkServerTrusted(chain, s); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return delegate.getAcceptedIssuers(); + } +}