summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlucaslin <lucaslin@google.com>2020-04-10 03:28:12 +0000
committerRemi NGUYEN VAN <reminv@google.com>2020-04-10 08:38:51 +0000
commitc3d9f7160011ae95ce948cad815cdf6377d1c2da (patch)
treeea75c983da3188ad5c4017a7d3fa388f1ea6736f /src
parent6fb2a069f996e86c31998e0e0088cba5d311c7db (diff)
Matches the URL content by regular expression
This patch provides a way to configure the regular expression which is used for matching the URL content. Once the result is matching, then NetworkMonitor will treat the validation result as fail or success. Bug: 141406258 Test: 1. Build pass 2. atest NetworkStackTests Merged-In: I77747b34fad895565d42ea4c017759c256d61489 Change-Id: I77747b34fad895565d42ea4c017759c256d61489
Diffstat (limited to 'src')
-rwxr-xr-xsrc/com/android/server/connectivity/NetworkMonitor.java85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index 0540258..4aba4f9 100755
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -142,6 +142,7 @@ import android.util.Pair;
import androidx.annotation.ArrayRes;
import androidx.annotation.BoolRes;
+import androidx.annotation.IntegerRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@@ -167,6 +168,7 @@ import com.android.server.NetworkStackService.NetworkStackServiceManager;
import org.json.JSONException;
import org.json.JSONObject;
+import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -193,6 +195,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
/**
* {@hide}
@@ -1504,7 +1507,7 @@ public class NetworkMonitor extends StateMachine {
@VisibleForTesting
protected Context getContextByMccIfNoSimCardOrDefault() {
final boolean useNeighborResource =
- getResBooleanConfig(mContext, R.bool.config_no_sim_card_uses_neighbor_mcc);
+ getResBooleanConfig(mContext, R.bool.config_no_sim_card_uses_neighbor_mcc, false);
if (!useNeighborResource
|| TelephonyManager.SIM_STATE_READY == mTelephonyManager.getSimState()) {
return mContext;
@@ -1552,13 +1555,41 @@ public class NetworkMonitor extends StateMachine {
}
@VisibleForTesting
- protected boolean getResBooleanConfig(@NonNull final Context context,
- @BoolRes int configResource) {
+ boolean getResBooleanConfig(@NonNull final Context context,
+ @BoolRes int configResource, final boolean defaultValue) {
final Resources res = context.getResources();
try {
return res.getBoolean(configResource);
} catch (Resources.NotFoundException e) {
- return false;
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Gets integer config from resources.
+ */
+ @VisibleForTesting
+ int getResIntConfig(@NonNull final Context context,
+ @IntegerRes final int configResource, final int defaultValue) {
+ final Resources res = context.getResources();
+ try {
+ return res.getInteger(configResource);
+ } catch (Resources.NotFoundException e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Gets string config from resources.
+ */
+ @VisibleForTesting
+ String getResStringConfig(@NonNull final Context context,
+ @StringRes final int configResource, @Nullable final String defaultValue) {
+ final Resources res = context.getResources();
+ try {
+ return res.getString(configResource);
+ } catch (Resources.NotFoundException e) {
+ return defaultValue;
}
}
@@ -1999,6 +2030,24 @@ public class NetworkMonitor extends StateMachine {
"Empty 200 response interpreted as failed response.");
httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
}
+ } else if (matchesHttpContentLength(contentLength)) {
+ final InputStream is = new BufferedInputStream(urlConnection.getInputStream());
+ final String content = readAsString(is, (int) contentLength,
+ extractCharset(urlConnection.getContentType()));
+ if (matchesHttpContent(content,
+ R.string.config_network_validation_failed_content_regexp)) {
+ httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
+ } else if (matchesHttpContent(content,
+ R.string.config_network_validation_success_content_regexp)) {
+ httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
+ }
+
+ if (httpResponseCode != 200) {
+ validationLog(probeType, url, "200 response with Content-length ="
+ + contentLength + ", content matches custom regexp, interpreted"
+ + " as " + httpResponseCode
+ + " response.");
+ }
} else if (contentLength <= 4) {
// Consider 200 response with "Content-length <= 4" to not be a captive
// portal. There's no point in considering this a captive portal as the
@@ -2029,6 +2078,34 @@ public class NetworkMonitor extends StateMachine {
}
}
+ @VisibleForTesting
+ boolean matchesHttpContent(final String content, @StringRes final int configResource) {
+ final String resString = getResStringConfig(mContext, configResource, "");
+ try {
+ return content.matches(resString);
+ } catch (PatternSyntaxException e) {
+ Log.e(TAG, "Pattern syntax exception occurs when matching the resource=" + resString,
+ e);
+ return false;
+ }
+ }
+
+ @VisibleForTesting
+ boolean matchesHttpContentLength(final long contentLength) {
+ // Consider that the Resources#getInteger() is returning an integer, so if the contentLength
+ // is lower or equal to 0 or higher than Integer.MAX_VALUE, then it's an invalid value.
+ if (contentLength <= 0) return false;
+ if (contentLength > Integer.MAX_VALUE) {
+ logw("matchesHttpContentLength : Get invalid contentLength = " + contentLength);
+ return false;
+ }
+ return (contentLength > getResIntConfig(mContext,
+ R.integer.config_min_matches_http_content_length, Integer.MAX_VALUE)
+ &&
+ contentLength < getResIntConfig(mContext,
+ R.integer.config_max_matches_http_content_length, 0));
+ }
+
private HttpURLConnection makeProbeConnection(URL url, boolean followRedirects)
throws IOException {
final HttpURLConnection conn = (HttpURLConnection) mCleartextDnsNetwork.openConnection(url);