diff --git a/core/java/android/security/net/config/NetworkSecurityTrustManager.java b/core/java/android/security/net/config/NetworkSecurityTrustManager.java index f2c718cde1b1a..3c292ca54578b 100644 --- a/core/java/android/security/net/config/NetworkSecurityTrustManager.java +++ b/core/java/android/security/net/config/NetworkSecurityTrustManager.java @@ -20,6 +20,7 @@ import com.android.org.conscrypt.TrustManagerImpl; import android.util.ArrayMap; import java.io.IOException; +import java.net.Socket; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.GeneralSecurityException; @@ -29,14 +30,15 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.X509ExtendedTrustManager; /** - * {@link X509TrustManager} that implements the trust anchor and pinning for a + * {@link X509ExtendedTrustManager} that implements the trust anchor and pinning for a * given {@link NetworkSecurityConfig}. * @hide */ -public class NetworkSecurityTrustManager implements X509TrustManager { +public class NetworkSecurityTrustManager extends X509ExtendedTrustManager { // TODO: Replace this with a general X509TrustManager and use duck-typing. private final TrustManagerImpl mDelegate; private final NetworkSecurityConfig mNetworkSecurityConfig; @@ -67,10 +69,38 @@ public class NetworkSecurityTrustManager implements X509TrustManager { mDelegate.checkClientTrusted(chain, authType); } + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType, Socket socket) + throws CertificateException { + mDelegate.checkClientTrusted(certs, authType, socket); + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType, SSLEngine engine) + throws CertificateException { + mDelegate.checkClientTrusted(certs, authType, engine); + } + @Override public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { - checkServerTrusted(certs, authType, null); + checkServerTrusted(certs, authType, (String) null); + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType, Socket socket) + throws CertificateException { + List trustedChain = + mDelegate.getTrustedChainForServer(certs, authType, socket); + checkPins(trustedChain); + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType, SSLEngine engine) + throws CertificateException { + List trustedChain = + mDelegate.getTrustedChainForServer(certs, authType, engine); + checkPins(trustedChain); } /** diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java index b4e58e6e9da6e..19f688787abe8 100644 --- a/core/java/android/security/net/config/RootTrustManager.java +++ b/core/java/android/security/net/config/RootTrustManager.java @@ -16,24 +16,28 @@ package android.security.net.config; +import java.net.Socket; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.List; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSession; +import javax.net.ssl.X509ExtendedTrustManager; /** - * {@link X509TrustManager} based on an {@link ApplicationConfig}. + * {@link X509ExtendedTrustManager} based on an {@link ApplicationConfig}. * - *

This {@code X509TrustManager} delegates to the specific trust manager for the hostname - * being used for the connection (See {@link ApplicationConfig#getConfigForHostname(String)} and + *

This trust manager delegates to the specific trust manager for the hostname being used for + * the connection (See {@link ApplicationConfig#getConfigForHostname(String)} and * {@link NetworkSecurityTrustManager}).

* * Note that if the {@code ApplicationConfig} has per-domain configurations the hostname aware * {@link #checkServerTrusted(X509Certificate[], String String)} must be used instead of the normal * non-aware call. * @hide */ -public class RootTrustManager implements X509TrustManager { +public class RootTrustManager extends X509ExtendedTrustManager { private final ApplicationConfig mConfig; public RootTrustManager(ApplicationConfig config) { @@ -52,6 +56,54 @@ public class RootTrustManager implements X509TrustManager { config.getTrustManager().checkClientTrusted(chain, authType); } + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType, Socket socket) + throws CertificateException { + // Use the default configuration for all client authentication. Domain specific configs are + // only for use in checking server trust not client trust. + NetworkSecurityConfig config = mConfig.getConfigForHostname(""); + config.getTrustManager().checkClientTrusted(certs, authType, socket); + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType, SSLEngine engine) + throws CertificateException { + // Use the default configuration for all client authentication. Domain specific configs are + // only for use in checking server trust not client trust. + NetworkSecurityConfig config = mConfig.getConfigForHostname(""); + config.getTrustManager().checkClientTrusted(certs, authType, engine); + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType, Socket socket) + throws CertificateException { + if (socket instanceof SSLSocket) { + SSLSocket sslSocket = (SSLSocket) socket; + SSLSession session = sslSocket.getHandshakeSession(); + if (session == null) { + throw new CertificateException("Not in handshake; no session available"); + } + String host = session.getPeerHost(); + NetworkSecurityConfig config = mConfig.getConfigForHostname(host); + config.getTrustManager().checkServerTrusted(certs, authType, socket); + } else { + // Not an SSLSocket, use the hostname unaware checkServerTrusted. + checkServerTrusted(certs, authType); + } + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType, SSLEngine engine) + throws CertificateException { + SSLSession session = engine.getHandshakeSession(); + if (session == null) { + throw new CertificateException("Not in handshake; no session available"); + } + String host = session.getPeerHost(); + NetworkSecurityConfig config = mConfig.getConfigForHostname(host); + config.getTrustManager().checkServerTrusted(certs, authType, engine); + } + @Override public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {