From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "Nate(Qiang) Jiang" Date: Wed, 26 Oct 2022 21:52:34 +0000 Subject: [PATCH] Passpoint Add more check to limit the config size Bug: 245299920 Test: atest con.android.server.wifi (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e1a80210f3f0391c989a2a86fd4aef739bf2574c) Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d Change-Id: I97522ce3607547c10025caa107cd1a40455a9c5d Change-Id: Id95fc30cb9f22276114ecef543d7a7e9e0c3459b --- .../wifi/hotspot2/PasspointConfiguration.java | 47 ++++++++++- .../net/wifi/hotspot2/pps/Credential.java | 10 ++- .../android/net/wifi/hotspot2/pps/HomeSp.java | 79 ++++++++++++++++++- .../hotspot2/PasspointConfigurationTest.java | 2 +- 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java index 9095b5d927a2..f88d6f6ca25a 100644 --- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java @@ -52,8 +52,42 @@ public final class PasspointConfiguration implements Parcelable { /** * Maximum bytes for URL string. + * @hide + */ + 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 */ - private static final int MAX_URL_BYTES = 1023; + 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. @@ -572,7 +606,18 @@ public final class PasspointConfiguration implements Parcelable { 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 entry : mTrustRootCertList.entrySet()) { String url = entry.getKey(); byte[] certFingerprint = entry.getValue(); diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java index 9409c03c614d..6d12ccef29ae 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java +++ b/wifi/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,7 +415,13 @@ public final class Credential implements Parcelable { + 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) { Log.d(TAG, "Invalid EAP Type for user credential: " + mEapType); diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java index 49a76c33d209..cdb9ec5cec3c 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java +++ b/wifi/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.os.Parcelable; import android.os.Parcel; import android.text.TextUtils; @@ -328,16 +335,86 @@ public final class HomeSp implements Parcelable { 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 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/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java index fc03e7eb6176..6b4f7b0cc51e 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java @@ -43,7 +43,7 @@ import java.util.Map; */ @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; /**