diff options
author | Alex Klyubin <klyubin@google.com> | 2015-03-27 08:50:03 -0700 |
---|---|---|
committer | Alex Klyubin <klyubin@google.com> | 2015-03-27 10:40:30 -0700 |
commit | 23c78a7d649e632852abb1f73ee36c117097c5c0 (patch) | |
tree | 6e0509d81ec004f816619d3a5ce5b767deb32aa4 | |
parent | 1cbd67d91edfcedbfd28aac75c1c616ced66ab4a (diff) | |
download | android_external_apache-http-23c78a7d649e632852abb1f73ee36c117097c5c0.tar.gz android_external_apache-http-23c78a7d649e632852abb1f73ee36c117097c5c0.tar.bz2 android_external_apache-http-23c78a7d649e632852abb1f73ee36c117097c5c0.zip |
Honor NetworkSecurityPolicy regarding cleartext traffic.
This makes HttpClient instances honor the process-wide policy about
cleartext network traffic. If cleartext network traffic is not
permitted, then attempts to send a cleartext HTTP request will throw
an IOException.
This change is needed despite platform-provided HttpClient being
deprecated because a large fraction of applications still use this
HttpClient library to generate HTTP traffic instead of using
URLConnection.
HttpClient is modular -- most of its parts can be replaced with
alternative implementations. Thus, this CL enforces the cleartext
traffic policy in DefaultRequestDirector because RequestDirector is
least commonly replaced (if ever) and there are no other
RequestDirector implementations provided by the library.
The cleartext policy is enforced pretty late in the process of
emitting a request to give time for any HttpRequestInterceptor
instances to see the request. This is because some apps use a
HttpRequestInterceptor to enforce their own policies about cleartext
HTTP such as catching accidental use of cleartext HTTP and reporting
it to their servers for analysis.
Bug: 19215516
Change-Id: I03687123080475581e7196d9bb8c0d006502d056
-rw-r--r-- | src/org/apache/http/impl/client/DefaultRequestDirector.java | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/org/apache/http/impl/client/DefaultRequestDirector.java b/src/org/apache/http/impl/client/DefaultRequestDirector.java index 9aafa85..6f9dcd0 100644 --- a/src/org/apache/http/impl/client/DefaultRequestDirector.java +++ b/src/org/apache/http/impl/client/DefaultRequestDirector.java @@ -33,6 +33,7 @@ package org.apache.http.impl.client; import java.io.IOException; import java.io.InterruptedIOException; +import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.util.Locale; @@ -430,6 +431,12 @@ public class DefaultRequestDirector implements RequestDirector { if (this.log.isDebugEnabled()) { this.log.debug("Attempt " + execCount + " to execute request"); } + // BEGIN android-added + if ((!route.isSecure()) && (!isCleartextTrafficPermitted())) { + throw new IOException( + "Cleartext traffic not permitted: " + route.getTargetHost()); + } + // END android-added response = requestExec.execute(wrapper, managedConn, context); retrying = false; @@ -1121,4 +1128,40 @@ public class DefaultRequestDirector implements RequestDirector { authState.setCredentials(creds); } + // BEGIN android-added + /** Cached instance of android.security.NetworkSecurityPolicy. */ + private static Object networkSecurityPolicy; + + /** Cached android.security.NetworkSecurityPolicy.isCleartextTrafficPermitted method. */ + private static Method cleartextTrafficPermittedMethod; + + private static boolean isCleartextTrafficPermitted() { + // TODO: Remove this method once NetworkSecurityPolicy can be accessed without Reflection. + // This method invokes NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted + // via Reflection API. + // Because of the way external/apache-http is built, in the near term it can't invoke new + // Android framework API directly. + try { + Object policy; + Method method; + synchronized (DefaultRequestDirector.class) { + if (cleartextTrafficPermittedMethod == null) { + Class<?> cls = Class.forName("android.security.NetworkSecurityPolicy"); + Method getInstanceMethod = cls.getMethod("getInstance"); + networkSecurityPolicy = getInstanceMethod.invoke(null); + cleartextTrafficPermittedMethod = cls.getMethod("isCleartextTrafficPermitted"); + } + policy = networkSecurityPolicy; + method = cleartextTrafficPermittedMethod; + } + return (Boolean) method.invoke(policy); + } catch (ReflectiveOperationException e) { + // Can't access the Android framework NetworkSecurityPolicy. To be backward compatible, + // assume that cleartext traffic is permitted. Android CTS will take care of ensuring + // this issue doesn't occur on new Android platforms. + return true; + } + } + // END android-added + } // class DefaultClientRequestDirector |