[Passpoint] Add more check to limit the config size
Bug: 245299920
Test: atest con.android.server.wifi
Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d
Change-Id: I97522ce3607547c10025caa107cd1a40455a9c5d
(cherry picked from commit 73285e50d507f1e0099dc18010bd1c7c724cc4ce)
Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d
diff --git a/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 239f406..60c8133 100644
--- a/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -70,8 +70,42 @@
/**
* Maximum bytes for URL string.
+ * @hide
*/
- private static final int MAX_URL_BYTES = 1023;
+ public static final int MAX_URL_BYTES = 2048;
+
+ /**
+ * Maximum size for match entry, just to limit the size of the Passpoint config.
+ * @hide
+ */
+ public static final int MAX_NUMBER_OF_ENTRIES = 16;
+
+ /**
+ * Maximum size for OI entry.
+ * The spec allows a string of up to 255 characters, with comma delimited numbers like
+ * 001122,334455. So with minimum OI size of 7, the maximum amount of OIs is 36.
+ * @hide
+ */
+ public static final int MAX_NUMBER_OF_OI = 36;
+
+
+ /**
+ * Maximum bytes for a string entry like FQDN and friendly name.
+ * @hide
+ */
+ public static final int MAX_STRING_LENGTH = 255;
+
+ /**
+ * HESSID is 48 bit.
+ * @hide
+ */
+ public static final long MAX_HESSID_VALUE = ((long) 1 << 48) - 1;
+
+ /**
+ * Organization Identifiers is 3 or 5 Octets. 24 or 36 bit.
+ * @hide
+ */
+ public static final long MAX_OI_VALUE = ((long) 1 << 40) - 1;
/**
* Integer value used for indicating null value in the Parcel.
@@ -954,14 +988,49 @@
return false;
}
// Optional: DecoratedIdentityPrefix
- if (!TextUtils.isEmpty(mDecoratedIdentityPrefix)
- && !mDecoratedIdentityPrefix.endsWith("!")) {
- EventLog.writeEvent(0x534e4554, "246539931", -1,
+ if (!TextUtils.isEmpty(mDecoratedIdentityPrefix)) {
+ if (!mDecoratedIdentityPrefix.endsWith("!")) {
+ EventLog.writeEvent(0x534e4554, "246539931", -1,
"Invalid decorated identity prefix");
- return false;
+ return false;
+ }
+ String[] decoratedIdentityPrefixArray = mDecoratedIdentityPrefix.split("!");
+ if (decoratedIdentityPrefixArray.length > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "too many decoratedIdentityPrefix");
+ return false;
+ }
+ for (String prefix : decoratedIdentityPrefixArray) {
+ if (prefix.length() > MAX_STRING_LENGTH) {
+ Log.d(TAG, "The decoratedIdentityPrefix is too long: " + prefix);
+ return false;
+ }
+ }
+ }
+
+ if (mAaaServerTrustedNames != null) {
+ if (mAaaServerTrustedNames.length > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "Too many AaaServerTrustedNames");
+ return false;
+ }
+ for (String fqdn : mAaaServerTrustedNames) {
+ if (fqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "AaaServerTrustedNames is too long");
+ return false;
+ }
+ }
+ }
+ if (mSubscriptionType != null) {
+ if (mSubscriptionType.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "SubscriptionType is too long");
+ return false;
+ }
}
if (mTrustRootCertList != null) {
+ if (mTrustRootCertList.size() > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "Too many TrustRootCert");
+ return false;
+ }
for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
String url = entry.getKey();
byte[] certFingerprint = entry.getValue();
diff --git a/framework/java/android/net/wifi/hotspot2/pps/Credential.java b/framework/java/android/net/wifi/hotspot2/pps/Credential.java
index 282757a..4ca724a 100644
--- a/framework/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/framework/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -16,6 +16,8 @@
package android.net.wifi.hotspot2.pps;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
+
import android.net.wifi.EAPConstants;
import android.net.wifi.ParcelUtil;
import android.os.Parcel;
@@ -413,6 +415,13 @@
+ mPassword.getBytes(StandardCharsets.UTF_8).length);
return false;
}
+ if (mSoftTokenApp != null) {
+ if (mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "app name exceeding maximum length: "
+ + mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length);
+ return false;
+ }
+ }
// Only supports EAP-TTLS for user credential.
if (mEapType != EAPConstants.EAP_TTLS) {
diff --git a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 64aad61..34aff6c 100644
--- a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -16,6 +16,13 @@
package android.net.wifi.hotspot2.pps;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_HESSID_VALUE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES;
+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_STRING_LENGTH;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -404,16 +411,86 @@
Log.d(TAG, "Missing FQDN");
return false;
}
+ if (mFqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "FQDN is too long");
+ return false;
+ }
if (TextUtils.isEmpty(mFriendlyName)) {
Log.d(TAG, "Missing friendly name");
return false;
}
+ if (mFriendlyName.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "Friendly name is too long");
+ return false;
+ }
// Verify SSIDs specified in the NetworkID
if (mHomeNetworkIds != null) {
+ if (mHomeNetworkIds.size() > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "too many SSID in HomeNetworkIDs");
+ return false;
+ }
for (Map.Entry<String, Long> entry : mHomeNetworkIds.entrySet()) {
if (entry.getKey() == null ||
entry.getKey().getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
- Log.d(TAG, "Invalid SSID in HomeNetworkIDs");
+ Log.d(TAG, "SSID is too long in HomeNetworkIDs");
+ return false;
+ }
+ if (entry.getValue() != null
+ && (entry.getValue() > MAX_HESSID_VALUE || entry.getValue() < 0)) {
+ Log.d(TAG, "HESSID is out of range");
+ return false;
+ }
+ }
+ }
+ if (mIconUrl != null && mIconUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
+ Log.d(TAG, "Icon URL is too long");
+ return false;
+ }
+ if (mMatchAllOis != null) {
+ if (mMatchAllOis.length > MAX_NUMBER_OF_OI) {
+ Log.d(TAG, "too many match all Organization Identifiers in the profile");
+ return false;
+ }
+ for (long oi : mMatchAllOis) {
+ if (oi > MAX_OI_VALUE || oi < 0) {
+ Log.d(TAG, "Organization Identifiers is out of range");
+ return false;
+ }
+ }
+ }
+ if (mMatchAnyOis != null) {
+ if (mMatchAnyOis.length > MAX_NUMBER_OF_OI) {
+ Log.d(TAG, "too many match any Organization Identifiers in the profile");
+ return false;
+ }
+ for (long oi : mMatchAnyOis) {
+ if (oi > MAX_OI_VALUE || oi < 0) {
+ Log.d(TAG, "Organization Identifiers is out of range");
+ return false;
+ }
+ }
+ }
+ if (mRoamingConsortiumOis != null) {
+ if (mRoamingConsortiumOis.length > MAX_NUMBER_OF_OI) {
+ Log.d(TAG, "too many Roaming Consortium Organization Identifiers in the "
+ + "profile");
+ return false;
+ }
+ for (long oi : mRoamingConsortiumOis) {
+ if (oi > MAX_OI_VALUE || oi < 0) {
+ Log.d(TAG, "Organization Identifiers is out of range");
+ return false;
+ }
+ }
+ }
+ if (mOtherHomePartners != null) {
+ if (mOtherHomePartners.length > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "too many other home partners in the profile");
+ return false;
+ }
+ for (String fqdn : mOtherHomePartners) {
+ if (fqdn.length() > MAX_STRING_LENGTH) {
+ Log.d(TAG, "FQDN is too long in OtherHomePartners");
return false;
}
}
diff --git a/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index d8393f9..8318de3 100644
--- a/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -17,6 +17,9 @@
package android.net.wifi.hotspot2;
import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
import static junit.framework.Assert.assertNull;
@@ -36,6 +39,8 @@
import com.android.modules.utils.build.SdkLevel;
+import com.google.common.base.Strings;
+
import org.junit.Test;
import java.nio.charset.StandardCharsets;
@@ -44,8 +49,10 @@
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -53,7 +60,7 @@
*/
@SmallTest
public class PasspointConfigurationTest {
- private static final int MAX_URL_BYTES = 1023;
+ private static final int MAX_URL_BYTES = 2048;
private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
private static final String TEST_DECORATED_IDENTITY_PREFIX = "androidwifi.dev!";
private static final long SUBSCRIPTION_EXPIRATION_TIME_MS = 1643996661000L;
@@ -674,4 +681,65 @@
assertEquals(SUBSCRIPTION_EXPIRATION_TIME_MS,
passpointConfiguration.getSubscriptionExpirationTimeMillis());
}
+
+ @Test
+ public void testValidatePasspointConfig() {
+ PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn(Strings.repeat("A", MAX_STRING_LENGTH));
+ homeSp.setFriendlyName(Strings.repeat("A", MAX_STRING_LENGTH));
+ List<String> homePartnersList = new ArrayList<>();
+ for (int h = 0; h < MAX_NUMBER_OF_ENTRIES; h++) {
+ homePartnersList.add(Strings.repeat("A", MAX_STRING_LENGTH));
+ }
+ homeSp.setOtherHomePartnersList(homePartnersList);
+ homeSp.setIconUrl(Strings.repeat("A", MAX_URL_BYTES));
+
+ Credential credential = new Credential();
+ credential.setRealm("example.com");
+ Credential.UserCredential userCredential = new Credential.UserCredential();
+ userCredential.setUsername("username");
+ userCredential.setPassword("password");
+ userCredential.setEapType(21);
+ userCredential.setNonEapInnerMethod("MS-CHAP");
+ credential.setUserCredential(userCredential);
+ passpointConfiguration.setCredential(credential);
+ passpointConfiguration.setHomeSp(homeSp);
+ assertTrue(passpointConfiguration.validate());
+
+ // FQDN exceed the limit
+ homeSp.setFqdn(Strings.repeat("A", MAX_STRING_LENGTH + 1));
+ passpointConfiguration.setHomeSp(homeSp);
+ assertFalse(passpointConfiguration.validate());
+ homeSp.setFqdn(Strings.repeat("A", MAX_STRING_LENGTH));
+ // Friendly name exceed the limit
+ homeSp.setFriendlyName(Strings.repeat("A", MAX_STRING_LENGTH + 1));
+ passpointConfiguration.setHomeSp(homeSp);
+ assertFalse(passpointConfiguration.validate());
+ homeSp.setFriendlyName(Strings.repeat("A", MAX_STRING_LENGTH));
+ // Icon url exceed the limit
+ homeSp.setIconUrl(Strings.repeat("A", MAX_URL_BYTES + 1));
+ passpointConfiguration.setHomeSp(homeSp);
+ assertFalse(passpointConfiguration.validate());
+ homeSp.setIconUrl(Strings.repeat("A", MAX_URL_BYTES));
+ // AAA service trusted names exceed the limit
+ String[] aaaServerTrustedNames = new String[MAX_NUMBER_OF_ENTRIES + 1];
+ passpointConfiguration.setAaaServerTrustedNames(aaaServerTrustedNames);
+ passpointConfiguration.setHomeSp(homeSp);
+ assertFalse(passpointConfiguration.validate());
+ passpointConfiguration.setAaaServerTrustedNames(null);
+ // Match all OIs exceed the limit
+ long[] ois = new long[MAX_NUMBER_OF_OI + 1];
+ homeSp.setMatchAllOis(ois);
+ assertFalse(homeSp.validate());
+ homeSp.setMatchAllOis(null);
+ // Match any OIs exceed the limit
+ homeSp.setMatchAnyOis(ois);
+ assertFalse(homeSp.validate());
+ homeSp.setMatchAnyOis(null);
+ // Roaming Consortium OIs exceed the limit
+ homeSp.setRoamingConsortiumOis(ois);
+ assertFalse(homeSp.validate());
+ homeSp.setRoamingConsortiumOis(null);
+ }
}