From e3aae40d07bae209c7b7dd608175563857f67ba6 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 11 Jan 2017 16:23:26 +0900 Subject: [PATCH] Captive portal: better detect empty responses The captive portal detection logic treats empty http responses with a Content-Length of 0 as not coming from a portal. However when the Content-Length is missing from the response header, the empty response is not detected as such and is classified as a captive portal answer. When this happens for the http probe, the portal detection logic will short circuit the detection and wrongly report a portal. The system validates the network in such conditions only if the https probe returns a successful connection faster than the http probe. This patch attempts to better detect empty responses by trying to read the first byte from the response body when the Content-Length is missing for 200 responses. Test: build, flashed + manual tests. Bug: 33498325 (cherry picked from commit cb4aa4d412c7940386df9b8dd681e0d2efebfd1d) Change-Id: Ibb9914cba72a4dab3ae76746d8889bbf083be812 --- .../server/connectivity/NetworkMonitor.java | 33 +++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 9ffe2b78a095..c40780e0d588 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -809,19 +809,26 @@ public class NetworkMonitor extends StateMachine { // portal. If it is considered a captive portal, a different sign-in URL // is needed (i.e. can't browse a 204). This could be the result of an HTTP // proxy server. - - // Consider 200 response with "Content-length=0" to not be a captive portal. - // There's no point in considering this a captive portal as the user cannot - // sign-in to an empty page. Probably the result of a broken transparent proxy. - // See http://b/9972012. - if (httpResponseCode == 200 && urlConnection.getContentLength() == 0) { - validationLog("Empty 200 response interpreted as 204 response."); - httpResponseCode = 204; - } - - if (httpResponseCode == 200 && probeType == ValidationProbeEvent.PROBE_PAC) { - validationLog("PAC fetch 200 response interpreted as 204 response."); - httpResponseCode = 204; + if (httpResponseCode == 200) { + if (probeType == ValidationProbeEvent.PROBE_PAC) { + validationLog("PAC fetch 200 response interpreted as 204 response."); + httpResponseCode = 204; + } else if (urlConnection.getContentLengthLong() == 0) { + // Consider 200 response with "Content-length=0" to not be a captive portal. + // There's no point in considering this a captive portal as the user cannot + // sign-in to an empty page. Probably the result of a broken transparent proxy. + // See http://b/9972012. + validationLog( + "200 response with Content-length=0 interpreted as 204 response."); + httpResponseCode = 204; + } else if (urlConnection.getContentLengthLong() == -1) { + // When no Content-length (default value == -1), attempt to read a byte from the + // response. Do not use available() as it is unreliable. See http://b/33498325. + if (urlConnection.getInputStream().read() == -1) { + validationLog("Empty 200 response interpreted as 204 response."); + httpResponseCode = 204; + } + } } } catch (IOException e) { validationLog("Probably not a portal: exception " + e); -- 2.11.0