diff options
author | Remi NGUYEN VAN <reminv@google.com> | 2020-04-10 08:20:10 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-04-10 08:20:10 +0000 |
commit | 6fb2a069f996e86c31998e0e0088cba5d311c7db (patch) | |
tree | a0e25db1b52988018ab2eb26c5c67bdc0dfe217d /src | |
parent | 9eebee7583b30df25b180c161260c46df9a66d06 (diff) | |
parent | 75e9d9014f3c76135068eef2b12401774a9f98e3 (diff) |
Merge "Do not detect portals when DNS returns private IPs" into rvc-dev
Diffstat (limited to 'src')
-rwxr-xr-x[-rw-r--r--] | src/android/net/util/NetworkStackUtils.java | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/server/connectivity/NetworkMonitor.java | 65 |
2 files changed, 68 insertions, 6 deletions
diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java index bc41549..2de18de 100644..100755 --- a/src/android/net/util/NetworkStackUtils.java +++ b/src/android/net/util/NetworkStackUtils.java @@ -172,6 +172,15 @@ public class NetworkStackUtils { public static final String DISMISS_PORTAL_IN_VALIDATED_NETWORK = "dismiss_portal_in_validated_network"; + /** + * Experiment flag to enable considering DNS probes returning private IP addresses as failed + * when attempting to detect captive portals. + * + * This flag is enabled if !=0 and less than the module APK version. + */ + public static final String DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION = + "dns_probe_private_ip_no_internet"; + static { System.loadLibrary("networkstackutilsjni"); } diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java index 7ea61fa..0540258 100644..100755 --- a/src/com/android/server/connectivity/NetworkMonitor.java +++ b/src/com/android/server/connectivity/NetworkMonitor.java @@ -70,6 +70,7 @@ import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS; import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_HTTP_URLS; import static android.net.util.NetworkStackUtils.DISMISS_PORTAL_IN_VALIDATED_NETWORK; +import static android.net.util.NetworkStackUtils.DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION; import static android.net.util.NetworkStackUtils.isEmpty; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; @@ -423,6 +424,8 @@ public class NetworkMonitor extends StateMachine { private boolean mAcceptPartialConnectivity = false; private final EvaluationState mEvaluationState = new EvaluationState(); + private final boolean mPrivateIpNotPortalEnabled; + private int getCallbackVersion(INetworkMonitorCallbacks cb) { int version; try { @@ -484,6 +487,7 @@ public class NetworkMonitor extends StateMachine { // CHECKSTYLE:ON IndentationCheck mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); + mPrivateIpNotPortalEnabled = getIsPrivateIpNotPortalEnabled(); mUseHttps = getUseHttpsValidation(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls(); @@ -1434,6 +1438,12 @@ public class NetworkMonitor extends StateMachine { return mode != CAPTIVE_PORTAL_MODE_IGNORE; } + private boolean getIsPrivateIpNotPortalEnabled() { + return mDependencies.isFeatureEnabled(mContext, DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION) + || mContext.getResources().getBoolean( + R.bool.config_force_dns_probe_private_ip_no_internet); + } + private boolean getUseHttpsValidation() { return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_USE_HTTPS, 1) == 1; @@ -1877,7 +1887,13 @@ public class NetworkMonitor extends StateMachine { // state machine thread. Reporting results here would cause races and potentially send // information to callers that does not make sense because the state machine has already // changed state. - sendDnsProbe(host); + final InetAddress[] resolvedAddr = sendDnsProbe(host); + // The private IP logic only applies to the HTTP probe, not the HTTPS probe (which would + // fail anyway) or the PAC probe. + if (mPrivateIpNotPortalEnabled && probeType == ValidationProbeEvent.PROBE_HTTP + && (proxy == null) && hasPrivateIpAddress(resolvedAddr)) { + return CaptivePortalProbeResult.PRIVATE_IP; + } return sendHttpProbe(url, probeType, null); } @@ -1891,23 +1907,41 @@ public class NetworkMonitor extends StateMachine { } /** Do a DNS resolution of the given server. */ - private void sendDnsProbe(String host) { + private InetAddress[] sendDnsProbe(String host) { if (TextUtils.isEmpty(host)) { - return; + return null; } - final String name = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS); final Stopwatch watch = new Stopwatch().start(); int result; - String connectInfo; + InetAddress[] addresses; try { - InetAddress[] addresses = sendDnsProbeWithTimeout(host, getDnsProbeTimeout()); + addresses = sendDnsProbeWithTimeout(host, getDnsProbeTimeout()); result = ValidationProbeEvent.DNS_SUCCESS; } catch (UnknownHostException e) { + addresses = null; result = ValidationProbeEvent.DNS_FAILURE; } final long latency = watch.stop(); logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result); + return addresses; + } + + /** + * Check if any of the provided IP addresses include a private IP, as defined by + * {@link com.android.server.util.NetworkStackConstants#PRIVATE_IPV4_RANGES}. + * @return true if an IP address is private. + */ + private static boolean hasPrivateIpAddress(@Nullable InetAddress[] addresses) { + if (addresses == null) { + return false; + } + for (InetAddress address : addresses) { + if (address.isLinkLocalAddress() || address.isSiteLocalAddress()) { + return true; + } + } + return false; } /** @@ -2230,6 +2264,15 @@ public class NetworkMonitor extends StateMachine { reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTPS, httpsResult); return httpsResult; } + // Consider a DNS response with a private IP address on the HTTP probe as an indication that + // the network is not connected to the Internet, and have the whole evaluation fail in that + // case. + // This only applies if the DNS probe completed within PROBE_TIMEOUT_MS, as the fallback + // probe should not be delayed by this check. + if (mPrivateIpNotPortalEnabled && (httpResult.isDnsPrivateIpResponse())) { + validationLog("DNS response to the URL is private IP"); + return CaptivePortalProbeResult.FAILED; + } // If a fallback method exists, use it to retry portal detection. // If we have new-style probe specs, use those. Otherwise, use the fallback URLs. final CaptivePortalProbeSpec probeSpec = nextFallbackSpec(); @@ -2449,6 +2492,16 @@ public class NetworkMonitor extends StateMachine { } /** + * Check whether or not one experimental feature in the connectivity namespace is + * enabled. + * @param name Flag name of the experiment in the connectivity namespace. + * @see NetworkStackUtils#isFeatureEnabled(Context, String, String) + */ + public boolean isFeatureEnabled(@NonNull Context context, @NonNull String name) { + return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name); + } + + /** * Send a broadcast indicating network conditions. */ public void sendNetworkConditionsBroadcast(@NonNull Context context, |