Merge cherrypicks of ['googleplex-android-review.googlesource.com/28665239'] into udc-platform-release.

Change-Id: Ia691f471cbdce2b142d0b6b55d4a316da733e78a
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index 4f636cb..7642697 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -16,7 +16,11 @@
 
 package com.android.server.wifi;
 
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_NUM;
 import static android.net.wifi.WifiManager.ALL_ZEROS_MAC_ADDRESS;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_OI_VALUE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES;
 
 import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes;
 
@@ -31,6 +35,7 @@
 import android.net.wifi.WifiNetworkSpecifier;
 import android.net.wifi.WifiScanner;
 import android.net.wifi.WifiSsid;
+import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.PatternMatcher;
 import android.text.TextUtils;
 import android.util.Log;
@@ -46,8 +51,10 @@
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * WifiConfiguration utility for any {@link android.net.wifi.WifiConfiguration} related operations.
@@ -70,6 +77,7 @@
     private static final int PSK_SAE_HEX_LEN = 64;
     private static final int WEP104_KEY_BYTES_LEN = 13;
     private static final int WEP40_KEY_BYTES_LEN = 5;
+    private static final int MAX_STRING_LENGTH = 512;
 
     @VisibleForTesting
     public static final String PASSWORD_MASK = "*";
@@ -723,7 +731,8 @@
         if (!validateSsid(config.SSID, isAdd)) {
             return false;
         }
-        if (!validateBssid(config.BSSID)) {
+        if (!validateBssid(config.BSSID) || !validateBssid(config.dhcpServer)
+                || !validateBssid(config.defaultGwMacAddress)) {
             return false;
         }
         if (!validateBitSets(config)) {
@@ -732,9 +741,22 @@
         if (!validateKeyMgmt(config.allowedKeyManagement)) {
             return false;
         }
-        if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_WEP)
-                && config.wepKeys != null
-                && !validateWepKeys(config.wepKeys, config.wepTxKeyIndex, isAdd)) {
+        if (!validateSecurityParameters(config.getSecurityParamsList())) {
+            return false;
+        }
+        if (!validatePasspoint(config)) {
+            return false;
+        }
+        if (!validateNetworkSelectionStatus(config.getNetworkSelectionStatus())) {
+            return false;
+        }
+
+        if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_WEP)) {
+            if (config.wepKeys != null
+                    && !validateWepKeys(config.wepKeys, config.wepTxKeyIndex, isAdd)) {
+                return false;
+            }
+        } else if (!validateWepKeys(config.wepKeys, config.wepTxKeyIndex, false)) {
             return false;
         }
         if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)
@@ -766,10 +788,92 @@
         if (!validateIpConfiguration(config.getIpConfiguration())) {
             return false;
         }
+
+        if (config.getDppConnector().length > MAX_URL_BYTES
+                || config.getDppCSignKey().length > MAX_URL_BYTES
+                || config.getDppPrivateEcKey().length > MAX_URL_BYTES
+                || config.getDppNetAccessKey().length > MAX_URL_BYTES) {
+            return false;
+        }
         // TBD: Validate some enterprise params as well in the future here.
         return true;
     }
 
+    private static boolean validateStringField(String field, int maxLength) {
+        return field == null || field.length() <= maxLength;
+    }
+
+    private static boolean validatePasspoint(WifiConfiguration config) {
+        if (!validateStringField(config.FQDN, PasspointConfiguration.MAX_STRING_LENGTH)) {
+            return false;
+        }
+        if (!validateStringField(config.providerFriendlyName,
+                PasspointConfiguration.MAX_STRING_LENGTH)) {
+            return false;
+        }
+        if (!validateRoamingConsortiumIds(config.roamingConsortiumIds)) {
+            return false;
+        }
+        if (!validateUpdateIdentifier(config.updateIdentifier)) {
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean validateUpdateIdentifier(String updateIdentifier) {
+        if (TextUtils.isEmpty(updateIdentifier)) {
+            return true;
+        }
+        try {
+            Integer.valueOf(updateIdentifier);
+        } catch (NumberFormatException e) {
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean validateNetworkSelectionStatus(
+            WifiConfiguration.NetworkSelectionStatus status) {
+        if (status == null) {
+            return false;
+        }
+        return validateStringField(status.getConnectChoice(), MAX_STRING_LENGTH)
+                    && validateBssid(status.getNetworkSelectionBSSID());
+    }
+
+    private static boolean validateRoamingConsortiumIds(long[] roamingConsortiumIds) {
+        if (roamingConsortiumIds != null) {
+            if (roamingConsortiumIds.length > MAX_NUMBER_OF_OI) {
+                Log.d(TAG, "too many Roaming Consortium Organization Identifiers in the "
+                        + "profile");
+                return false;
+            }
+            for (long oi : roamingConsortiumIds) {
+                if (oi < 0 || oi > MAX_OI_VALUE) {
+                    Log.d(TAG, "Organization Identifiers is out of range");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static boolean validateSecurityParameters(List<SecurityParams> paramsList) {
+        Set<Integer> uniqueSecurityTypes = new HashSet<>(SECURITY_TYPE_NUM + 1);
+        for (SecurityParams params : paramsList) {
+            int securityType = params.getSecurityType();
+            if (securityType < 0 || securityType > SECURITY_TYPE_NUM) {
+                return false;
+            }
+            if (uniqueSecurityTypes.contains(securityType)) {
+                return false;
+            }
+            uniqueSecurityTypes.add(securityType);
+        }
+        return true;
+
+    }
+
     private static boolean validateBssidPattern(
             Pair<MacAddress, MacAddress> bssidPatternMatcher) {
         if (bssidPatternMatcher == null) return true;
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 83d737d..22396b6 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -3740,6 +3740,11 @@
         boolean isCamera = mWifiPermissionsUtil.checkCameraPermission(callingUid);
         boolean isSystem = mWifiPermissionsUtil.isSystem(packageName, callingUid);
         boolean isPrivileged = isPrivileged(callingPid, callingUid);
+        if (!isPrivileged && !isSystem && !isAdmin && config.getBssidAllowlistInternal() != null) {
+            mLog.info("addOrUpdateNetwork with allow bssid list is not allowed for uid=%")
+                    .c(callingUid).flush();
+            return -1;
+        }
 
         if (!isTargetSdkLessThanQOrPrivileged(packageName, callingPid, callingUid)) {
             mLog.info("addOrUpdateNetwork not allowed for uid=%").c(callingUid).flush();
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
index 0722d3e..1567ed4 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.wifi.WifiEnterpriseConfig.OCSP_NONE;
 import static android.net.wifi.WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -53,6 +54,7 @@
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 
+import java.nio.charset.StandardCharsets;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -77,6 +79,7 @@
             new UserInfo(CURRENT_USER_ID, "owner", 0),
             new UserInfo(CURRENT_USER_MANAGED_PROFILE_USER_ID, "managed profile", 0));
     private static final long SUPPORTED_FEATURES_ALL = Long.MAX_VALUE;
+    private final String mGeneratedString256 = "a".repeat(256);
 
     private MockitoSession mSession;
 
@@ -1592,4 +1595,76 @@
         assertTrue(WifiConfigurationUtil.isConfigLinkable(saeConfig));
         assertFalse(WifiConfigurationUtil.isConfigLinkable(saeDisabledConfig));
     }
+
+    @Test
+    public void testWepKeyOnNonWepConfig() {
+        WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
+        pskConfig.wepKeys = new String[4];
+        pskConfig.wepKeys[0] = mGeneratedString256;
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+    }
+
+    @Test
+    public void testInvalidFqdnAndFriendlyName() {
+        WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
+
+        pskConfig.FQDN = mGeneratedString256;
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+
+        pskConfig.FQDN = null;
+        pskConfig.providerFriendlyName = mGeneratedString256;
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+    }
+
+    @Test
+    public void testInvalidDhcpAndGtw() {
+        WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
+        pskConfig.dhcpServer = TEST_BSSID;
+        pskConfig.defaultGwMacAddress = TEST_BSSID;
+        assertTrue(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+        pskConfig.dhcpServer = mGeneratedString256;
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+        pskConfig.dhcpServer = TEST_BSSID;
+        pskConfig.defaultGwMacAddress = mGeneratedString256;
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+    }
+
+    @Test
+    public void testInvalidSecurityParameter() {
+        WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
+        List<SecurityParams> securityParamsList = new ArrayList<>();
+        securityParamsList.add(SecurityParams.createSecurityParamsBySecurityType(
+                WifiConfiguration.SECURITY_TYPE_PSK));
+        securityParamsList.add(SecurityParams.createSecurityParamsBySecurityType(
+                WifiConfiguration.SECURITY_TYPE_PSK));
+
+        pskConfig.setSecurityParams(securityParamsList);
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+    }
+
+    @Test
+    public void testInvalidUserConnectChoice() {
+        WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
+        String generatedString513 = "a".repeat(513);
+        pskConfig.getNetworkSelectionStatus().setConnectChoice(generatedString513);
+
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+    }
+
+    @Test
+    public void testInvalidDppConfig() {
+        WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork();
+        String generatedString = "a".repeat(MAX_URL_BYTES + 1);
+        pskConfig.setDppConfigurator(generatedString.getBytes(StandardCharsets.UTF_8));
+        assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL,
+                WifiConfigurationUtil.VALIDATE_FOR_ADD));
+    }
 }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index c06ae93..df32b92 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -6483,6 +6483,31 @@
     }
 
     /**
+     * Verify that add or update networks is allowed for apps targeting below Q SDK.
+     */
+    @Test
+    public void testAddOrUpdateNetworkWithBssidAllowListIsNotAllowedForAppsNotPrivileged()
+            throws Exception {
+        doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager)
+                .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME);
+        when(mWifiConfigManager.addOrUpdateNetwork(any(),  anyInt(), any(), eq(false))).thenReturn(
+                new NetworkUpdateResult(0));
+        when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
+                eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true);
+
+        WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
+        config.setBssidAllowlist(Collections.emptyList());
+        mLooper.startAutoDispatch();
+        assertEquals(-1,
+                mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME, mAttribution));
+        mLooper.stopAutoDispatchAndIgnoreExceptions();
+
+        verifyCheckChangePermission(TEST_PACKAGE_NAME);
+        verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(),  anyInt(), any(), eq(false));
+        verify(mWifiMetrics, never()).incrementNumAddOrUpdateNetworkCalls();
+    }
+
+    /**
      * Verify that add or update networks is not allowed for apps targeting below Q SDK
      * when DISALLOW_ADD_WIFI_CONFIG user restriction is set.
      */