summaryrefslogtreecommitdiffstats
path: root/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java
diff options
context:
space:
mode:
Diffstat (limited to 'service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java')
-rw-r--r--service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java257
1 files changed, 257 insertions, 0 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java
new file mode 100644
index 000000000..649534662
--- /dev/null
+++ b/service/java/com/android/server/wifi/hotspot2/ANQPMatcher.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.hotspot2;
+
+import com.android.server.wifi.IMSIParameter;
+import com.android.server.wifi.hotspot2.anqp.CellularNetwork;
+import com.android.server.wifi.hotspot2.anqp.DomainNameElement;
+import com.android.server.wifi.hotspot2.anqp.NAIRealmData;
+import com.android.server.wifi.hotspot2.anqp.NAIRealmElement;
+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 java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility class for providing matching functions against ANQP elements.
+ */
+public class ANQPMatcher {
+ /**
+ * Match the domain names in the ANQP element against the provider's FQDN and SIM credential.
+ * The Domain Name ANQP element might contain domains for 3GPP network (e.g.
+ * wlan.mnc*.mcc*.3gppnetwork.org), so we should match that against the provider's SIM
+ * credential if one is provided.
+ *
+ * @param element The Domain Name ANQP element
+ * @param fqdn The FQDN to compare against
+ * @param imsiParam The IMSI parameter of the provider
+ * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
+ * IMSI parameter
+ * @return true if a match is found
+ */
+ public static boolean matchDomainName(DomainNameElement element, String fqdn,
+ IMSIParameter imsiParam, List<String> simImsiList) {
+ if (element == null) {
+ return false;
+ }
+
+ for (String domain : element.getDomains()) {
+ if (DomainMatcher.arg2SubdomainOfArg1(fqdn, domain)) {
+ return true;
+ }
+
+ // Try to retrieve the MCC-MNC string from the domain (for 3GPP network domain) and
+ // match against the provider's SIM credential.
+ if (matchMccMnc(Utils.getMccMnc(Utils.splitDomain(domain)), imsiParam, simImsiList)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Match the roaming consortium OIs in the ANQP element against the roaming consortium OIs
+ * of a provider.
+ *
+ * @param element The Roaming Consortium ANQP element
+ * @param providerOIs The roaming consortium OIs of the provider
+ * @return true if a match is found
+ */
+ public static boolean matchRoamingConsortium(RoamingConsortiumElement element,
+ long[] providerOIs) {
+ if (element == null) {
+ return false;
+ }
+ if (providerOIs == null) {
+ return false;
+ }
+ List<Long> rcOIs = element.getOIs();
+ for (long oi : providerOIs) {
+ if (rcOIs.contains(oi)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Match the NAI realm in the ANQP element against the realm and authentication method of
+ * a provider.
+ *
+ * @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) {
+ if (element == null || element.getRealmDataList().isEmpty()) {
+ return AuthMatch.INDETERMINATE;
+ }
+
+ 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;
+ }
+ }
+ }
+ return bestMatch;
+ }
+
+ /**
+ * Match the 3GPP Network in the ANQP element against the SIM credential of a provider.
+ *
+ * @param element 3GPP Network ANQP element
+ * @param imsiParam The IMSI parameter of the provider's SIM credential
+ * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
+ * IMSI parameter
+ * @return true if a matched is found
+ */
+ public static boolean matchThreeGPPNetwork(ThreeGPPNetworkElement element,
+ IMSIParameter imsiParam, List<String> simImsiList) {
+ if (element == null) {
+ return false;
+ }
+ for (CellularNetwork network : element.getNetworks()) {
+ if (matchCellularNetwork(network, imsiParam, simImsiList)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Match the given NAI Realm data against the realm and authentication method of a provider.
+ *
+ * @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
+ */
+ private static int matchNAIRealmData(NAIRealmData realmData, String realm, int eapMethodID,
+ AuthParam authParam) {
+ // 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 (realmMatch == AuthMatch.NONE || 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;
+ }
+ }
+
+ if (eapMethodMatch == AuthMatch.NONE) {
+ return AuthMatch.NONE;
+ }
+ return realmMatch | eapMethodMatch;
+ }
+
+ /**
+ * Match the given EAPMethod against the authentication method of a provider.
+ *
+ * @param method The EAP Method
+ * @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
+ */
+ private static int matchEAPMethod(EAPMethod method, int eapMethodID, AuthParam authParam) {
+ if (method.getEAPMethodID() != eapMethodID) {
+ return AuthMatch.NONE;
+ }
+ // Check for authentication parameter match.
+ if (authParam != null) {
+ Map<Integer, Set<AuthParam>> authParams = method.getAuthParams();
+ Set<AuthParam> paramSet = authParams.get(authParam.getAuthTypeID());
+ if (paramSet == null || !paramSet.contains(authParam)) {
+ return AuthMatch.NONE;
+ }
+ return AuthMatch.METHOD_PARAM;
+ }
+ return AuthMatch.METHOD;
+ }
+
+ /**
+ * Match a cellular network information in the 3GPP Network ANQP element against the SIM
+ * credential of a provider.
+ *
+ * @param network The cellular network that contained list of PLMNs
+ * @param imsiParam IMSI parameter of the provider
+ * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
+ * IMSI parameter
+ * @return true if a match is found
+ */
+ private static boolean matchCellularNetwork(CellularNetwork network, IMSIParameter imsiParam,
+ List<String> simImsiList) {
+ for (String plmn : network.getPlmns()) {
+ if (matchMccMnc(plmn, imsiParam, simImsiList)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Match a MCC-MNC against the SIM credential of a provider.
+ *
+ * @param mccMnc The string containing MCC-MNC
+ * @param imsiParam The IMSI parameter of the provider
+ * @param simImsiList The list of IMSI from the installed SIM cards that matched provider's
+ * IMSI parameter
+ * @return true if a match is found
+ */
+ private static boolean matchMccMnc(String mccMnc, IMSIParameter imsiParam,
+ List<String> simImsiList) {
+ if (imsiParam == null || simImsiList == null) {
+ return false;
+ }
+ // Match against the IMSI parameter in the provider.
+ if (!imsiParam.matchesMccMnc(mccMnc)) {
+ return false;
+ }
+ // Additional check for verifying the match with IMSIs from the SIM cards, since the IMSI
+ // parameter might not contain the full 6-digit MCC MNC (e.g. IMSI parameter is an IMSI
+ // prefix that contained less than 6-digit of numbers "12345*").
+ for (String imsi : simImsiList) {
+ if (imsi.startsWith(mccMnc)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}