diff options
| author | 2015-11-12 19:28:21 +0000 | |
|---|---|---|
| committer | 2015-11-12 19:28:21 +0000 | |
| commit | 9c3982f75da19e2c0e146e7f251514a44412da0c (patch) | |
| tree | 9b503e90b8caafaa4fcc745fa7cba2b8da15fc03 | |
| parent | 8f87949340e858ff4e24615709080978b017f644 (diff) | |
| parent | bfcd67f71eedcefd269e63e72219ac6a3435626e (diff) | |
Merge "Use duck typing in X509TrustManagerExtensions"
| -rw-r--r-- | core/java/android/net/http/X509TrustManagerExtensions.java | 73 | 
1 files changed, 66 insertions, 7 deletions
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java index eb4cedab83b7..7c23c2319f4d 100644 --- a/core/java/android/net/http/X509TrustManagerExtensions.java +++ b/core/java/android/net/http/X509TrustManagerExtensions.java @@ -18,6 +18,9 @@ package android.net.http;  import com.android.org.conscrypt.TrustManagerImpl; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method;  import java.security.cert.CertificateException;  import java.security.cert.X509Certificate;  import java.util.List; @@ -34,7 +37,11 @@ import javax.net.ssl.X509TrustManager;   */  public class X509TrustManagerExtensions { -    final TrustManagerImpl mDelegate; +    private final TrustManagerImpl mDelegate; +    // Methods to use when mDelegate is not a TrustManagerImpl and duck typing is being used. +    private final X509TrustManager mTrustManager; +    private final Method mCheckServerTrusted; +    private final Method mIsUserAddedCertificate;      /**       * Constructs a new X509TrustManagerExtensions wrapper. @@ -45,10 +52,31 @@ public class X509TrustManagerExtensions {      public X509TrustManagerExtensions(X509TrustManager tm) throws IllegalArgumentException {          if (tm instanceof TrustManagerImpl) {              mDelegate = (TrustManagerImpl) tm; -        } else { -            mDelegate = null; -            throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() + -                    " which is not a supported type of X509TrustManager"); +            mTrustManager = null; +            mCheckServerTrusted = null; +            mIsUserAddedCertificate = null; +            return; +        } +        // Use duck typing if possible. +        mDelegate = null; +        mTrustManager = tm; +        // Check that the hostname aware checkServerTrusted is present. +        try { +            mCheckServerTrusted = tm.getClass().getMethod("checkServerTrusted", +                    X509Certificate[].class, +                    String.class, +                    String.class); +        } catch (NoSuchMethodException e) { +            throw new IllegalArgumentException("Required method" +                    + " checkServerTrusted(X509Certificate[], String, String, String) missing"); +        } +        // Check that isUserAddedCertificate is present. +        try { +            mIsUserAddedCertificate = tm.getClass().getMethod("isUserAddedCertificate", +                    X509Certificate.class); +        } catch (NoSuchMethodException e) { +            throw new IllegalArgumentException( +                    "Required method isUserAddedCertificate(X509Certificate) missing");          }      } @@ -64,7 +92,24 @@ public class X509TrustManagerExtensions {       */      public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType,                                                      String host) throws CertificateException { -        return mDelegate.checkServerTrusted(chain, authType, host); +        if (mDelegate != null) { +            return mDelegate.checkServerTrusted(chain, authType, host); +        } else { +            try { +                return (List<X509Certificate>) mCheckServerTrusted.invoke(mTrustManager, chain, +                        authType, host); +            } catch (IllegalAccessException e) { +                throw new CertificateException("Failed to call checkServerTrusted", e); +            } catch (InvocationTargetException e) { +                if (e.getCause() instanceof CertificateException) { +                    throw (CertificateException) e.getCause(); +                } +                if (e.getCause() instanceof RuntimeException) { +                    throw (RuntimeException) e.getCause(); +                } +                throw new CertificateException("checkServerTrusted failed", e.getCause()); +            } +        }      }      /** @@ -78,6 +123,20 @@ public class X509TrustManagerExtensions {       * otherwise.       */      public boolean isUserAddedCertificate(X509Certificate cert) { -        return mDelegate.isUserAddedCertificate(cert); +        if (mDelegate != null) { +            return mDelegate.isUserAddedCertificate(cert); +        } else { +            try { +                return (Boolean) mIsUserAddedCertificate.invoke(mTrustManager, cert); +            } catch (IllegalAccessException e) { +                throw new RuntimeException("Failed to call isUserAddedCertificate", e); +            } catch (InvocationTargetException e) { +                if (e.getCause() instanceof RuntimeException) { +                    throw (RuntimeException) e.getCause(); +                } else { +                    throw new RuntimeException("isUserAddedCertificate failed", e.getCause()); +                } +            } +        }      }  }  |