diff options
author | lucaslin <lucaslin@google.com> | 2020-04-10 03:28:12 +0000 |
---|---|---|
committer | Remi NGUYEN VAN <reminv@google.com> | 2020-04-10 08:38:51 +0000 |
commit | c3d9f7160011ae95ce948cad815cdf6377d1c2da (patch) | |
tree | ea75c983da3188ad5c4017a7d3fa388f1ea6736f /src | |
parent | 6fb2a069f996e86c31998e0e0088cba5d311c7db (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-x | src/com/android/server/connectivity/NetworkMonitor.java | 85 |
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); |