summaryrefslogtreecommitdiff
path: root/service
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 /service
parent47622333f37484d6cf2ebae422e245e0d002d832 (diff)
parent4354285b8de3345d5146f68ce2d17be83b4f34a4 (diff)
Merge "[Passpoint] Fix Passpoint matching algorithm for Home networks" into qt-qpr1-dev
Diffstat (limited to 'service')
-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
3 files changed, 165 insertions, 78 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;
+ }
}