summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHai Shalom <haishalom@google.com>2020-03-17 23:48:54 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-03-17 23:48:54 +0000
commit95d7544a87272802f591dd44640a18ab1c6d6edd (patch)
tree4123f2693db7c1c73ad7ae5fcab5c1d63d60554d
parent47622333f37484d6cf2ebae422e245e0d002d832 (diff)
parent4354285b8de3345d5146f68ce2d17be83b4f34a4 (diff)
Merge "[Passpoint] Fix Passpoint matching algorithm for Home networks" into qt-qpr1-dev
-rw-r--r--service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java63
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointManager.java6
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointProvider.java174
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java127
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java189
5 files changed, 421 insertions, 138 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java
index d95ab3831..69f98b0ef 100644
--- a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java
+++ b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java
@@ -75,10 +75,11 @@ public class ANQPMatcher {
*
* @param element The Roaming Consortium ANQP element
* @param providerOIs The roaming consortium OIs of the provider
+ * @param matchAll Indicates if a match with all OIs must be done
* @return true if a match is found
*/
public static boolean matchRoamingConsortium(RoamingConsortiumElement element,
- long[] providerOIs) {
+ long[] providerOIs, boolean matchAll) {
if (element == null) {
return false;
}
@@ -88,10 +89,14 @@ public class ANQPMatcher {
List<Long> rcOIs = element.getOIs();
for (long oi : providerOIs) {
if (rcOIs.contains(oi)) {
- return true;
+ if (!matchAll) {
+ return true;
+ }
+ } else if (matchAll) {
+ return false;
}
}
- return false;
+ return matchAll;
}
/**
@@ -100,27 +105,19 @@ public class ANQPMatcher {
*
* @param element The NAI Realm ANQP element
* @param realm The realm of the provider's credential
- * @param eapMethodID The EAP Method ID of the provider's credential
- * @param authParam The authentication parameter of the provider's credential
* @return an integer indicating the match status
*/
- public static int matchNAIRealm(NAIRealmElement element, String realm, int eapMethodID,
- AuthParam authParam) {
+ public static boolean matchNAIRealm(NAIRealmElement element, String realm) {
if (element == null || element.getRealmDataList().isEmpty()) {
- return AuthMatch.INDETERMINATE;
+ return false;
}
- int bestMatch = AuthMatch.NONE;
for (NAIRealmData realmData : element.getRealmDataList()) {
- int match = matchNAIRealmData(realmData, realm, eapMethodID, authParam);
- if (match > bestMatch) {
- bestMatch = match;
- if (bestMatch == AuthMatch.EXACT) {
- break;
- }
+ if (matchNAIRealmData(realmData, realm)) {
+ return true;
}
}
- return bestMatch;
+ return false;
}
/**
@@ -172,42 +169,16 @@ public class ANQPMatcher {
*
* @param realmData The NAI Realm data
* @param realm The realm of the provider's credential
- * @param eapMethodID The EAP Method ID of the provider's credential
- * @param authParam The authentication parameter of the provider's credential
- * @return an integer indicating the match status
+ * @return true if a match is found
*/
- private static int matchNAIRealmData(NAIRealmData realmData, String realm, int eapMethodID,
- AuthParam authParam) {
+ private static boolean matchNAIRealmData(NAIRealmData realmData, String realm) {
// Check for realm domain name match.
- int realmMatch = AuthMatch.NONE;
for (String realmStr : realmData.getRealms()) {
if (DomainMatcher.arg2SubdomainOfArg1(realm, realmStr)) {
- realmMatch = AuthMatch.REALM;
- break;
- }
- }
-
- if (realmData.getEAPMethods().isEmpty()) {
- return realmMatch;
- }
-
- // Check for EAP method match.
- int eapMethodMatch = AuthMatch.NONE;
- for (EAPMethod eapMethod : realmData.getEAPMethods()) {
- eapMethodMatch = matchEAPMethod(eapMethod, eapMethodID, authParam);
- if (eapMethodMatch != AuthMatch.NONE) {
- break;
+ return true;
}
}
-
- if (eapMethodMatch == AuthMatch.NONE) {
- return AuthMatch.NONE;
- }
-
- if (realmMatch == AuthMatch.NONE) {
- return eapMethodMatch;
- }
- return realmMatch | eapMethodMatch;
+ return false;
}
private static int getEapMethodForNAIRealmWithCarrier(String realm,
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index c46873761..172d1a13d 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -217,6 +217,7 @@ public class PasspointManager {
public void setProviders(List<PasspointProvider> providers) {
mProviders.clear();
for (PasspointProvider provider : providers) {
+ provider.enableVerboseLogging(mVerboseLoggingEnabled ? 1 : 0);
mProviders.put(provider.getConfig().getHomeSp().getFqdn(), provider);
if (provider.getPackageName() != null) {
startTrackingAppOpsChange(provider.getPackageName(),
@@ -377,6 +378,9 @@ public class PasspointManager {
public void enableVerboseLogging(int verbose) {
mVerboseLoggingEnabled = (verbose > 0) ? true : false;
mPasspointProvisioner.enableVerboseLogging(verbose);
+ for (PasspointProvider provider : mProviders.values()) {
+ provider.enableVerboseLogging(verbose);
+ }
}
/**
@@ -433,6 +437,7 @@ public class PasspointManager {
mProviders.get(config.getHomeSp().getFqdn()).uninstallCertsAndKeys();
mProviders.remove(config.getHomeSp().getFqdn());
}
+ newProvider.enableVerboseLogging(mVerboseLoggingEnabled ? 1 : 0);
mProviders.put(config.getHomeSp().getFqdn(), newProvider);
mWifiConfigManager.saveToStore(true /* forceWrite */);
if (newProvider.getPackageName() != null) {
@@ -1165,6 +1170,7 @@ public class PasspointManager {
Arrays.asList(enterpriseConfig.getCaCertificateAlias()),
enterpriseConfig.getClientCertificateAlias(),
enterpriseConfig.getClientCertificateAlias(), null, false, false);
+ provider.enableVerboseLogging(mVerboseLoggingEnabled ? 1 : 0);
mProviders.put(passpointConfig.getHomeSp().getFqdn(), provider);
return true;
}
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
index ca9814aa6..8db71d3e6 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
@@ -95,6 +95,7 @@ public class PasspointProvider {
private boolean mHasEverConnected;
private boolean mIsShared;
+ private boolean mVerboseLoggingEnabled;
/**
* This is a flag to indicate if the Provider is created temporarily.
@@ -327,39 +328,53 @@ public class PasspointProvider {
* Return the matching status with the given AP, based on the ANQP elements from the AP.
*
* @param anqpElements ANQP elements from the AP
- * @param roamingConsortium Roaming Consortium information element from the AP
+ * @param roamingConsortiumFromAp Roaming Consortium information element from the AP
* @return {@link PasspointMatch}
*/
public PasspointMatch match(Map<ANQPElementType, ANQPElement> anqpElements,
- RoamingConsortium roamingConsortium) {
- PasspointMatch providerMatch = matchProviderExceptFor3GPP(anqpElements, roamingConsortium);
+ RoamingConsortium roamingConsortiumFromAp) {
+ // Match FQDN for Home provider or RCOI(s) for Roaming provider
+ // For SIM credential, the FQDN is in the format of wlan.mnc*.mcc*.3gppnetwork.org
+ PasspointMatch providerMatch = matchFqdnAndRcoi(anqpElements, roamingConsortiumFromAp);
// 3GPP Network matching.
if (providerMatch == PasspointMatch.None && ANQPMatcher.matchThreeGPPNetwork(
(ThreeGPPNetworkElement) anqpElements.get(ANQPElementType.ANQP3GPPNetwork),
mImsiParameter, mMatchingSIMImsiList)) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Final RoamingProvider match with "
+ + anqpElements.get(ANQPElementType.ANQP3GPPNetwork));
+ }
return PasspointMatch.RoamingProvider;
}
- // Perform authentication match against the NAI Realm.
- int authMatch = ANQPMatcher.matchNAIRealm(
+ // Perform NAI Realm matching
+ boolean realmMatch = ANQPMatcher.matchNAIRealm(
(NAIRealmElement) anqpElements.get(ANQPElementType.ANQPNAIRealm),
- mConfig.getCredential().getRealm(), mEAPMethodID, mAuthParam);
-
- // In case of Auth mismatch, demote provider match.
- if (authMatch == AuthMatch.NONE) {
- return PasspointMatch.None;
- }
+ mConfig.getCredential().getRealm());
// In case of no realm match, return provider match as is.
- if ((authMatch & AuthMatch.REALM) == 0) {
+ if (!realmMatch) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "No NAI realm match, final match: " + providerMatch);
+ }
return providerMatch;
}
- // Promote the provider match to roaming provider if provider match is not found, but NAI
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "NAI realm match with " + mConfig.getCredential().getRealm());
+ }
+
+ // Promote the provider match to RoamingProvider if provider match is not found, but NAI
// realm is matched.
- return providerMatch == PasspointMatch.None ? PasspointMatch.RoamingProvider
- : providerMatch;
+ if (providerMatch == PasspointMatch.None) {
+ providerMatch = PasspointMatch.RoamingProvider;
+ }
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Final match: " + providerMatch);
+ }
+ return providerMatch;
}
/**
@@ -570,42 +585,129 @@ public class PasspointProvider {
}
/**
+ * Match given OIs to the Roaming Consortium OIs
+ *
+ * @param providerOis Provider OIs to match against
+ * @param roamingConsortiumElement RCOIs in the ANQP element
+ * @param roamingConsortiumFromAp RCOIs in the AP scan results
+ * @param matchAll Indicates if all providerOis must match the RCOIs elements
+ * @return {@code true} if there is a match, {@code false} otherwise.
+ */
+ private boolean matchOis(long[] providerOis,
+ RoamingConsortiumElement roamingConsortiumElement,
+ RoamingConsortium roamingConsortiumFromAp,
+ boolean matchAll) {
+
+
+ // ANQP Roaming Consortium OI matching.
+ if (ANQPMatcher.matchRoamingConsortium(roamingConsortiumElement, providerOis, matchAll)) {
+ if (mVerboseLoggingEnabled) {
+ Log.e(TAG, "ANQP RCOI match " + roamingConsortiumElement);
+ }
+ return true;
+ }
+
+ // AP Roaming Consortium OI matching.
+ long[] apRoamingConsortiums = roamingConsortiumFromAp.getRoamingConsortiums();
+ if (apRoamingConsortiums == null || providerOis == null) {
+ return false;
+ }
+ // Roaming Consortium OI information element matching.
+ for (long apOi: apRoamingConsortiums) {
+ boolean matched = false;
+ for (long providerOi: providerOis) {
+ if (apOi == providerOi) {
+ if (mVerboseLoggingEnabled) {
+ Log.e(TAG, "AP RCOI match: " + apOi);
+ }
+ if (!matchAll) {
+ return true;
+ } else {
+ matched = true;
+ break;
+ }
+ }
+ }
+ if (matchAll && !matched) {
+ return false;
+ }
+ }
+ return matchAll;
+ }
+
+ /**
* Perform a provider match based on the given ANQP elements except for matching 3GPP Network.
*
* @param anqpElements List of ANQP elements
- * @param roamingConsortium Roaming Consortium information element from the AP
+ * @param roamingConsortiumFromAp Roaming Consortium information element from the AP
* @return {@link PasspointMatch}
*/
- private PasspointMatch matchProviderExceptFor3GPP(
+ private PasspointMatch matchFqdnAndRcoi(
Map<ANQPElementType, ANQPElement> anqpElements,
- RoamingConsortium roamingConsortium) {
+ RoamingConsortium roamingConsortiumFromAp) {
// Domain name matching.
if (ANQPMatcher.matchDomainName(
(DomainNameElement) anqpElements.get(ANQPElementType.ANQPDomName),
mConfig.getHomeSp().getFqdn(), mImsiParameter, mMatchingSIMImsiList)) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Domain name " + mConfig.getHomeSp().getFqdn()
+ + " match: HomeProvider");
+ }
return PasspointMatch.HomeProvider;
}
- // ANQP Roaming Consortium OI matching.
- long[] providerOIs = mConfig.getHomeSp().getRoamingConsortiumOis();
- if (ANQPMatcher.matchRoamingConsortium(
- (RoamingConsortiumElement) anqpElements.get(ANQPElementType.ANQPRoamingConsortium),
- providerOIs)) {
- return PasspointMatch.RoamingProvider;
+ // Other Home Partners matching.
+ if (mConfig.getHomeSp().getOtherHomePartners() != null) {
+ for (String otherHomePartner : mConfig.getHomeSp().getOtherHomePartners()) {
+ if (ANQPMatcher.matchDomainName(
+ (DomainNameElement) anqpElements.get(ANQPElementType.ANQPDomName),
+ otherHomePartner, null, null)) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Other Home Partner " + otherHomePartner
+ + " match: HomeProvider");
+ }
+ return PasspointMatch.HomeProvider;
+ }
+ }
}
- long[] roamingConsortiums = roamingConsortium.getRoamingConsortiums();
- // Roaming Consortium OI information element matching.
- if (roamingConsortiums != null && providerOIs != null) {
- for (long sta_oi: roamingConsortiums) {
- for (long ap_oi: providerOIs) {
- if (sta_oi == ap_oi) {
- return PasspointMatch.RoamingProvider;
- }
+ // HomeOI matching
+ if (mConfig.getHomeSp().getMatchAllOis() != null) {
+ // Ensure that every HomeOI whose corresponding HomeOIRequired value is true shall match
+ // an OI in the Roaming Consortium advertised by the hotspot operator.
+ if (matchOis(mConfig.getHomeSp().getMatchAllOis(), (RoamingConsortiumElement)
+ anqpElements.get(ANQPElementType.ANQPRoamingConsortium),
+ roamingConsortiumFromAp, true)) {
+ if (mVerboseLoggingEnabled) {
+ Log.e(TAG, "All HomeOI RCOI match: HomeProvider");
+ }
+ return PasspointMatch.HomeProvider;
+ }
+ } else if (mConfig.getHomeSp().getMatchAnyOis() != null) {
+ // Ensure that any HomeOI whose corresponding HomeOIRequired value is false shall match
+ // an OI in the Roaming Consortium advertised by the hotspot operator.
+ if (matchOis(mConfig.getHomeSp().getMatchAnyOis(), (RoamingConsortiumElement)
+ anqpElements.get(ANQPElementType.ANQPRoamingConsortium),
+ roamingConsortiumFromAp, false)) {
+ if (mVerboseLoggingEnabled) {
+ Log.e(TAG, "Any HomeOI RCOI match: HomeProvider");
}
+ return PasspointMatch.HomeProvider;
}
}
+ // Roaming Consortium OI matching.
+ if (matchOis(mConfig.getHomeSp().getRoamingConsortiumOis(), (RoamingConsortiumElement)
+ anqpElements.get(ANQPElementType.ANQPRoamingConsortium),
+ roamingConsortiumFromAp, false)) {
+ if (mVerboseLoggingEnabled) {
+ Log.e(TAG, "ANQP RCOI match: RoamingProvider");
+ }
+ return PasspointMatch.RoamingProvider;
+ }
+ if (mVerboseLoggingEnabled) {
+ Log.e(TAG, "No domain name or RCOI match");
+ }
return PasspointMatch.None;
}
@@ -768,4 +870,12 @@ public class PasspointProvider {
simCredential.setEapType(eapType);
return simCredential;
}
+
+ /**
+ * Enable verbose logging
+ * @param verbose more than 0 enables verbose logging
+ */
+ public void enableVerboseLogging(int verbose) {
+ mVerboseLoggingEnabled = (verbose > 0) ? true : false;
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java
index 4d4ea4487..df9c332a3 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/ANQPMatcherTest.java
@@ -33,7 +33,6 @@ import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement;
import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement;
import com.android.server.wifi.hotspot2.anqp.eap.AuthParam;
import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod;
-import com.android.server.wifi.hotspot2.anqp.eap.InnerAuthEAP;
import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth;
import org.junit.Test;
@@ -102,7 +101,7 @@ public class ANQPMatcherTest {
*/
@Test
public void matchRoamingConsortiumWithNullElement() throws Exception {
- assertFalse(ANQPMatcher.matchRoamingConsortium(null, new long[0]));
+ assertFalse(ANQPMatcher.matchRoamingConsortium(null, new long[0], false));
}
/**
@@ -116,23 +115,22 @@ public class ANQPMatcherTest {
long oi = 0x1234L;
RoamingConsortiumElement element =
new RoamingConsortiumElement(Arrays.asList(new Long[] {oi}));
- assertTrue(ANQPMatcher.matchRoamingConsortium(element, new long[] {oi}));
+ assertTrue(ANQPMatcher.matchRoamingConsortium(element, new long[] {oi}, false));
}
/**
- * Verify that an indeterminate match will be returned when matching a null NAI Realm
+ * Verify that no match will be returned when matching a null NAI Realm
* ANQP element.
*
* @throws Exception
*/
@Test
public void matchNAIRealmWithNullElement() throws Exception {
- assertEquals(AuthMatch.INDETERMINATE, ANQPMatcher.matchNAIRealm(null, "test.com",
- EAPConstants.EAP_TLS, new InnerAuthEAP(EAPConstants.EAP_TTLS)));
+ assertFalse(ANQPMatcher.matchNAIRealm(null, "test.com"));
}
/**
- * Verify that an indeterminate match will be returned when matching a NAI Realm
+ * Verify that no match will be returned when matching a NAI Realm
* ANQP element contained no NAI realm data.
*
* @throws Exception
@@ -140,8 +138,7 @@ public class ANQPMatcherTest {
@Test
public void matchNAIRealmWithEmtpyRealmData() throws Exception {
NAIRealmElement element = new NAIRealmElement(new ArrayList<NAIRealmData>());
- assertEquals(AuthMatch.INDETERMINATE, ANQPMatcher.matchNAIRealm(element, "test.com",
- EAPConstants.EAP_TLS, null));
+ assertFalse(ANQPMatcher.matchNAIRealm(element, "test.com"));
}
/**
@@ -157,38 +154,11 @@ public class ANQPMatcherTest {
Arrays.asList(new String[] {realm}), new ArrayList<EAPMethod>());
NAIRealmElement element = new NAIRealmElement(
Arrays.asList(new NAIRealmData[] {realmData}));
- assertEquals(AuthMatch.REALM, ANQPMatcher.matchNAIRealm(element, realm,
- EAPConstants.EAP_TLS, null));
+ assertTrue(ANQPMatcher.matchNAIRealm(element, realm));
}
/**
- * Verify that method match will be returned when the specified EAP
- * method only matches a eap method in the NAI Realm ANQP element if the element does not have
- * auth params.
- *
- * @throws Exception
- */
- @Test
- public void matchNAIRealmWithMethodMatch() throws Exception {
- // Test data.
- String providerRealm = "test.com";
- String anqpRealm = "test2.com";
- NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP);
- int eapMethodID = EAPConstants.EAP_TLS;
-
- // Setup NAI Realm element that has EAP method and no auth params.
- EAPMethod method = new EAPMethod(eapMethodID, new HashMap<Integer, Set<AuthParam>>());
- NAIRealmData realmData = new NAIRealmData(
- Arrays.asList(new String[]{anqpRealm}), Arrays.asList(new EAPMethod[]{method}));
- NAIRealmElement element = new NAIRealmElement(
- Arrays.asList(new NAIRealmData[]{realmData}));
-
- assertEquals(AuthMatch.METHOD,
- ANQPMatcher.matchNAIRealm(element, providerRealm, eapMethodID, authParam));
- }
-
- /**
- * Verify that a realm and method match will be returned when the specified realm and EAP
+ * Verify that a realm match will be returned when the specified realm and EAP
* method matches a realm in the NAI Realm ANQP element.
*
* @throws Exception
@@ -206,12 +176,11 @@ public class ANQPMatcherTest {
NAIRealmElement element = new NAIRealmElement(
Arrays.asList(new NAIRealmData[] {realmData}));
- assertEquals(AuthMatch.REALM | AuthMatch.METHOD,
- ANQPMatcher.matchNAIRealm(element, realm, eapMethodID, null));
+ assertTrue(ANQPMatcher.matchNAIRealm(element, realm));
}
/**
- * Verify that an exact match will be returned when the specified realm, EAP
+ * Verify that a realm match will be returned when the specified realm, EAP
* method, and the authentication parameter matches a realm with the associated EAP method and
* authentication parameter in the NAI Realm ANQP element.
*
@@ -235,12 +204,11 @@ public class ANQPMatcherTest {
NAIRealmElement element = new NAIRealmElement(
Arrays.asList(new NAIRealmData[] {realmData}));
- assertEquals(AuthMatch.EXACT,
- ANQPMatcher.matchNAIRealm(element, realm, eapMethodID, authParam));
+ assertTrue(ANQPMatcher.matchNAIRealm(element, realm));
}
/**
- * Verify that a mismatch (AuthMatch.NONE) will be returned when the specified EAP method
+ * Verify that a realm match will be returned when the specified EAP method
* doesn't match with the corresponding EAP method in the NAI Realm ANQP element.
*
* @throws Exception
@@ -263,12 +231,11 @@ public class ANQPMatcherTest {
NAIRealmElement element = new NAIRealmElement(
Arrays.asList(new NAIRealmData[] {realmData}));
- assertEquals(AuthMatch.NONE,
- ANQPMatcher.matchNAIRealm(element, realm, EAPConstants.EAP_TLS, null));
+ assertTrue(ANQPMatcher.matchNAIRealm(element, realm));
}
/**
- * Verify that a mismatch (AuthMatch.NONE) will be returned when the specified authentication
+ * Verify that a realm match will be returned when the specified authentication
* parameter doesn't match with the corresponding authentication parameter in the NAI Realm
* ANQP element.
*
@@ -292,10 +259,8 @@ public class ANQPMatcherTest {
NAIRealmElement element = new NAIRealmElement(
Arrays.asList(new NAIRealmData[] {realmData}));
- // Mismatch in authentication type.
- assertEquals(AuthMatch.NONE,
- ANQPMatcher.matchNAIRealm(element, realm, EAPConstants.EAP_TTLS,
- new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_PAP)));
+ // Mismatch in authentication type which we ignore.
+ assertTrue(ANQPMatcher.matchNAIRealm(element, realm));
}
/**
@@ -458,4 +423,64 @@ public class ANQPMatcherTest {
assertEquals(-1,
ANQPMatcher.getCarrierEapMethodFromMatchingNAIRealm(TEST_3GPP_FQDN, element));
}
+
+ /**
+ * Verify that match is found when HomeOI contains some of the RCOIs advertised by an AP marked
+ * as not required.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAnyHomeOi() throws Exception {
+ long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL};
+ Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xdeadL, 0xf0cdL};
+ RoamingConsortiumElement element =
+ new RoamingConsortiumElement(Arrays.asList(anqpOis));
+ assertTrue(ANQPMatcher.matchRoamingConsortium(element, providerOis, false));
+ }
+
+ /**
+ * Verify that no match is found when HomeOI does not contain any of the RCOIs advertised by an
+ * AP marked as not required.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAnyHomeOiNegative() throws Exception {
+ long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL};
+ Long[] anqpOis = new Long[] {0xabc2L, 0x1232L};
+ RoamingConsortiumElement element =
+ new RoamingConsortiumElement(Arrays.asList(anqpOis));
+ assertFalse(ANQPMatcher.matchRoamingConsortium(element, providerOis, false));
+ }
+
+ /**
+ * Verify that match is found when HomeOI contains all of the RCOIs advertised by an AP marked
+ * as required.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAllHomeOi() throws Exception {
+ long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL};
+ Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xabcdL, 0xdeadL, 0xf0cdL};
+ RoamingConsortiumElement element =
+ new RoamingConsortiumElement(Arrays.asList(anqpOis));
+ assertTrue(ANQPMatcher.matchRoamingConsortium(element, providerOis, true));
+ }
+
+ /**
+ * Verify that match is not found when HomeOI does not contain all of the RCOIs advertised by an
+ * AP marked as required.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAllHomeOiNegative() throws Exception {
+ long[] providerOis = new long[] {0x1234L, 0x5678L, 0xabcdL};
+ Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xdeadL, 0xf0cdL};
+ RoamingConsortiumElement element =
+ new RoamingConsortiumElement(Arrays.asList(anqpOis));
+ assertFalse(ANQPMatcher.matchRoamingConsortium(element, providerOis, true));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
index 31229c562..c35d67301 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
@@ -478,9 +478,10 @@ public class PasspointProviderTest {
}
/**
- * Verify that there is no match when the provider's FQDN matches a domain name in the
- * Domain Name ANQP element but the provider's credential doesn't match the authentication
- * method provided in the NAI realm.
+ * Verify that Home provider is matched even when the provider's FQDN matches a domain name in
+ * the Domain Name ANQP element but the provider's credential doesn't match the authentication
+ * method provided in the NAI realm. This can happen when the infrastructure provider is not
+ * the identity provider, and authentication method matching is not required in the spec.
*
* @throws Exception
*/
@@ -509,7 +510,8 @@ public class PasspointProviderTest {
anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
createNAIRealmElement(testRealm, EAPConstants.EAP_TLS, null));
- assertEquals(PasspointMatch.None, mProvider.match(anqpElementMap, mRoamingConsortium));
+ assertEquals(PasspointMatch.HomeProvider,
+ mProvider.match(anqpElementMap, mRoamingConsortium));
}
/**
@@ -657,8 +659,8 @@ public class PasspointProviderTest {
}
/**
- * Verify that there is no match when a roaming consortium OI matches an OI
- * in the roaming consortium ANQP element and but NAI realm is not matched.
+ * Verify that there is Roaming provider match when a roaming consortium OI matches an OI
+ * in the roaming consortium ANQP element and regardless of NAI realm mismatch.
*
* @throws Exception
*/
@@ -689,7 +691,7 @@ public class PasspointProviderTest {
anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
createNAIRealmElement(testRealm, EAPConstants.EAP_TLS, null));
- assertEquals(PasspointMatch.None,
+ assertEquals(PasspointMatch.RoamingProvider,
mProvider.match(anqpElementMap, mRoamingConsortium));
}
@@ -766,8 +768,14 @@ public class PasspointProviderTest {
}
/**
- * Verify that there is no match when a roaming consortium OI matches an OI
+ * Verify that there is Roaming provider match when a roaming consortium OI matches an OI
* in the roaming consortium information element, but NAI realm is not matched.
+ * This can happen in roaming federation where the infrastructure provider is not the
+ * identity provider.
+ * Page 133 in the Hotspot2.0 specification states:
+ * Per subclause 11.25.8 of [2], if the value of HomeOI matches an OI in the Roaming
+ * Consortium advertised by a hotspot operator, successful authentication with that hotspot
+ * is possible.
*
* @throws Exception
*/
@@ -799,7 +807,7 @@ public class PasspointProviderTest {
anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
createNAIRealmElement(testRealm, EAPConstants.EAP_TLS, null));
- assertEquals(PasspointMatch.None,
+ assertEquals(PasspointMatch.RoamingProvider,
mProvider.match(anqpElementMap, mRoamingConsortium));
}
@@ -1354,4 +1362,167 @@ public class PasspointProviderTest {
mProvider.setHasEverConnected(true);
assertTrue(mProvider.getHasEverConnected());
}
+
+ /**
+ * Verify that an expected WifiConfiguration will be returned for a Passpoint provider
+ * with a user credential.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchOtherPartnersDomainName() throws Exception {
+ // Setup test provider.
+ PasspointConfiguration config = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test1.com");
+ homeSp.setOtherHomePartners(new String [] {"test3.com"});
+ config.setHomeSp(homeSp);
+ Credential credential = new Credential();
+ credential.setUserCredential(new Credential.UserCredential());
+ config.setCredential(credential);
+ mProvider = createProvider(config);
+ verifyInstalledConfig(config, true);
+
+ // Setup Domain Name ANQP element to test2.com and test3.com
+ Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
+ anqpElementMap.put(ANQPElementType.ANQPDomName,
+ createDomainNameElement(new String[] {"test2.com", "test3.com"}));
+
+ assertEquals(PasspointMatch.HomeProvider,
+ mProvider.match(anqpElementMap, mRoamingConsortium));
+ }
+
+ /**
+ * Verify that matching Any HomeOI results in a Home Provider match
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAnyHomeOi() throws Exception {
+ // Setup test provider.
+ PasspointConfiguration config = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test1.com");
+ homeSp.setMatchAnyOis(new long[] {0x1234L, 0x2345L});
+ homeSp.setRoamingConsortiumOis(null);
+ config.setHomeSp(homeSp);
+ Credential credential = new Credential();
+ credential.setUserCredential(new Credential.UserCredential());
+ config.setCredential(credential);
+ mProvider = createProvider(config);
+ verifyInstalledConfig(config, true);
+ Long[] anqpOis = new Long[] {0x1234L, 0xdeadL, 0xf0cdL};
+
+ // Setup Domain Name ANQP element to test2.com and test3.com
+ Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
+ anqpElementMap.put(ANQPElementType.ANQPDomName,
+ createDomainNameElement(new String[] {"test2.com", "test3.com"}));
+ // Setup RCOIs advertised by the AP
+ anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
+ createRoamingConsortiumElement(anqpOis));
+
+ assertEquals(PasspointMatch.HomeProvider,
+ mProvider.match(anqpElementMap, mRoamingConsortium));
+ }
+
+ /**
+ * Verify that non-matching Any HomeOI results in a None Provider match
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAnyHomeOiNegative() throws Exception {
+ // Setup test provider.
+ PasspointConfiguration config = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test1.com");
+ homeSp.setMatchAnyOis(new long[] {0x1234L, 0x2345L});
+ homeSp.setRoamingConsortiumOis(null);
+ config.setHomeSp(homeSp);
+ Credential credential = new Credential();
+ credential.setUserCredential(new Credential.UserCredential());
+ config.setCredential(credential);
+ mProvider = createProvider(config);
+ verifyInstalledConfig(config, true);
+ Long[] anqpOis = new Long[] {0x12a4L, 0xceadL, 0xf0cdL};
+
+ // Setup Domain Name ANQP element to test2.com and test3.com
+ Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
+ anqpElementMap.put(ANQPElementType.ANQPDomName,
+ createDomainNameElement(new String[] {"test2.com", "test3.com"}));
+ // Setup RCOIs advertised by the AP
+ anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
+ createRoamingConsortiumElement(anqpOis));
+
+ assertEquals(PasspointMatch.None,
+ mProvider.match(anqpElementMap, mRoamingConsortium));
+ }
+
+ /**
+ * Verify that matching All HomeOI results in a Home Provider match
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAllHomeOi() throws Exception {
+ // Setup test provider.
+ PasspointConfiguration config = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test1.com");
+ homeSp.setMatchAllOis(new long[] {0x1234L, 0x2345L});
+ homeSp.setRoamingConsortiumOis(null);
+ config.setHomeSp(homeSp);
+ Credential credential = new Credential();
+ credential.setUserCredential(new Credential.UserCredential());
+ config.setCredential(credential);
+ mProvider = createProvider(config);
+ verifyInstalledConfig(config, true);
+ Long[] anqpOis = new Long[] {0x1234L, 0x2345L, 0xabcdL, 0xdeadL, 0xf0cdL};
+
+ // Setup Domain Name ANQP element to test2.com and test3.com
+ Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
+ anqpElementMap.put(ANQPElementType.ANQPDomName,
+ createDomainNameElement(new String[] {"test2.com", "test3.com"}));
+ // Setup RCOIs advertised by the AP
+ anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
+ createRoamingConsortiumElement(anqpOis));
+
+ assertEquals(PasspointMatch.HomeProvider,
+ mProvider.match(anqpElementMap, mRoamingConsortium));
+ }
+
+ /**
+ * Verify that non-matching All HomeOI results in a None Provider match
+ *
+ * @throws Exception
+ */
+ @Test
+ public void matchAllHomeOiNegative() throws Exception {
+ // Setup test provider.
+ PasspointConfiguration config = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test1.com");
+ homeSp.setMatchAllOis(new long[] {0x1234L, 0x2345L});
+ homeSp.setRoamingConsortiumOis(null);
+ config.setHomeSp(homeSp);
+ Credential credential = new Credential();
+ credential.setUserCredential(new Credential.UserCredential());
+ config.setCredential(credential);
+ mProvider = createProvider(config);
+ verifyInstalledConfig(config, true);
+
+ // 0x1234 matches, but 0x2345 does not
+ Long[] anqpOis = new Long[] {0x1234L, 0x5678L, 0xdeadL, 0xf0cdL};
+
+ // Setup Domain Name ANQP element to test2.com and test3.com
+ Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
+ anqpElementMap.put(ANQPElementType.ANQPDomName,
+ createDomainNameElement(new String[] {"test2.com", "test3.com"}));
+ // Setup RCOIs advertised by the AP
+ anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
+ createRoamingConsortiumElement(anqpOis));
+
+ assertEquals(PasspointMatch.None,
+ mProvider.match(anqpElementMap, mRoamingConsortium));
+ }
}