diff options
author | Hai Shalom <haishalom@google.com> | 2020-03-17 23:48:54 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-03-17 23:48:54 +0000 |
commit | 95d7544a87272802f591dd44640a18ab1c6d6edd (patch) | |
tree | 4123f2693db7c1c73ad7ae5fcab5c1d63d60554d /service | |
parent | 47622333f37484d6cf2ebae422e245e0d002d832 (diff) | |
parent | 4354285b8de3345d5146f68ce2d17be83b4f34a4 (diff) |
Merge "[Passpoint] Fix Passpoint matching algorithm for Home networks" into qt-qpr1-dev
Diffstat (limited to 'service')
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; + } } |