• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi.hotspot2;
18 
19 import android.text.TextUtils;
20 
21 import com.android.server.wifi.IMSIParameter;
22 import com.android.server.wifi.hotspot2.anqp.CellularNetwork;
23 import com.android.server.wifi.hotspot2.anqp.DomainNameElement;
24 import com.android.server.wifi.hotspot2.anqp.NAIRealmData;
25 import com.android.server.wifi.hotspot2.anqp.NAIRealmElement;
26 import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement;
27 import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement;
28 
29 import java.util.List;
30 
31 /**
32  * Utility class for providing matching functions against ANQP elements.
33  */
34 public class ANQPMatcher {
35     /**
36      * Match the domain names in the ANQP element against the provider's FQDN and SIM credential.
37      * The Domain Name ANQP element might contain domains for 3GPP network (e.g.
38      * wlan.mnc*.mcc*.3gppnetwork.org), so we should match that against the provider's SIM
39      * credential if one is provided.
40      *
41      * @param element The Domain Name ANQP element
42      * @param fqdn The FQDN to compare against
43      * @param imsiParam The IMSI parameter of the provider (needed only for IMSI matching)
44      * @param simImsi The IMSI from the installed SIM cards that best matched provider's
45      *                    IMSI parameter (needed only for IMSI matching)
46      * @return true if a match is found
47      */
matchDomainName(DomainNameElement element, String fqdn, IMSIParameter imsiParam, String simImsi)48     public static boolean matchDomainName(DomainNameElement element, String fqdn,
49             IMSIParameter imsiParam, String simImsi) {
50         if (element == null) {
51             return false;
52         }
53 
54         for (String domain : element.getDomains()) {
55             if (DomainMatcher.arg2SubdomainOfArg1(fqdn, domain)) {
56                 return true;
57             }
58 
59             if (imsiParam == null || simImsi == null) {
60                 continue;
61             }
62 
63             // Try to retrieve the MCC-MNC string from the domain (for 3GPP network domain) and
64             // match against the provider's SIM credential.
65             if (matchMccMnc(Utils.getMccMnc(Utils.splitDomain(domain)), imsiParam, simImsi)) {
66                 return true;
67             }
68         }
69         return false;
70     }
71 
72     /**
73      * Match the roaming consortium OIs in the ANQP element against the roaming consortium OIs
74      * of a provider.
75      *
76      * @param element The Roaming Consortium ANQP element
77      * @param providerOIs The roaming consortium OIs of the provider
78      * @param matchAll Indicates if a match with all OIs must be done
79      * @return true if a match is found
80      */
matchRoamingConsortium(RoamingConsortiumElement element, long[] providerOIs, boolean matchAll)81     public static boolean matchRoamingConsortium(RoamingConsortiumElement element,
82             long[] providerOIs, boolean matchAll) {
83         if (element == null) {
84             return false;
85         }
86         if (providerOIs == null) {
87             return false;
88         }
89         List<Long> rcOIs = element.getOIs();
90         for (long oi : providerOIs) {
91             if (rcOIs.contains(oi)) {
92                 if (!matchAll) {
93                     return true;
94                 }
95             } else if (matchAll) {
96                 return false;
97             }
98         }
99         return matchAll;
100     }
101 
102     /**
103      * Match the NAI realm in the ANQP element against the realm and authentication method of
104      * a provider.
105      *
106      * @param element The NAI Realm ANQP element
107      * @param realm The realm of the provider's credential
108      * @return true if there is a NAI Realm match, false otherwise
109      */
matchNAIRealm(NAIRealmElement element, String realm)110     public static boolean matchNAIRealm(NAIRealmElement element, String realm) {
111         if (element == null || element.getRealmDataList().isEmpty()) {
112             return false;
113         }
114 
115         for (NAIRealmData realmData : element.getRealmDataList()) {
116             if (matchNAIRealmData(realmData, realm)) {
117                 return true;
118             }
119         }
120         return false;
121     }
122 
123     /**
124      * Match the 3GPP Network in the ANQP element against the SIM credential of a provider.
125      *
126      * @param element 3GPP Network ANQP element
127      * @param imsiParam The IMSI parameter of the provider's SIM credential
128      * @param simImsi The IMSI from the installed SIM cards that best matched provider's
129      *                    IMSI parameter
130      * @return true if a match is found
131      */
matchThreeGPPNetwork(ThreeGPPNetworkElement element, IMSIParameter imsiParam, String simImsi)132     public static  boolean matchThreeGPPNetwork(ThreeGPPNetworkElement element,
133             IMSIParameter imsiParam, String simImsi) {
134         if (element == null) {
135             return false;
136         }
137         for (CellularNetwork network : element.getNetworks()) {
138             if (matchCellularNetwork(network, imsiParam, simImsi)) {
139                 return true;
140             }
141         }
142         return false;
143     }
144 
145     /**
146      * Match the given NAI Realm data against the realm and authentication method of a provider.
147      *
148      * @param realmData The NAI Realm data
149      * @param realm The realm of the provider's credential
150      * @return true if a match is found
151      */
matchNAIRealmData(NAIRealmData realmData, String realm)152     private static boolean matchNAIRealmData(NAIRealmData realmData, String realm) {
153         // Check for realm domain name match.
154         for (String realmStr : realmData.getRealms()) {
155             if (DomainMatcher.arg2SubdomainOfArg1(realm, realmStr)) {
156                 return true;
157             }
158         }
159         return false;
160     }
161 
162     /**
163      * Match a cellular network information in the 3GPP Network ANQP element against the SIM
164      * credential of a provider.
165      *
166      * @param network The cellular network that contained list of PLMNs
167      * @param imsiParam IMSI parameter of the provider
168      * @param simImsi The IMSI from the installed SIM cards that best matched provider's
169      *                    IMSI parameter
170      * @return true if a match is found
171      */
matchCellularNetwork(CellularNetwork network, IMSIParameter imsiParam, String simImsi)172     private static boolean matchCellularNetwork(CellularNetwork network, IMSIParameter imsiParam,
173             String simImsi) {
174         for (String plmn : network.getPlmns()) {
175             if (matchMccMnc(plmn, imsiParam, simImsi)) {
176                 return true;
177             }
178         }
179 
180         return false;
181     }
182 
183     /**
184      * Match a MCC-MNC against the SIM credential of a provider.
185      *
186      * @param mccMnc The string containing MCC-MNC
187      * @param imsiParam The IMSI parameter of the provider
188      * @param simImsi The IMSI from the installed SIM cards that best matched provider's
189      *                    IMSI parameter
190      * @return true if a match is found
191      */
matchMccMnc(String mccMnc, IMSIParameter imsiParam, String simImsi)192     private static boolean matchMccMnc(String mccMnc, IMSIParameter imsiParam,
193             String simImsi) {
194         if (imsiParam == null || TextUtils.isEmpty(simImsi) || mccMnc == null) {
195             return false;
196         }
197         // Match against the IMSI parameter in the provider.
198         if (!imsiParam.matchesMccMnc(mccMnc)) {
199             return false;
200         }
201         // Additional check for verifying the match with IMSI from the SIM card, since the IMSI
202         // parameter might not contain the full 6-digit MCC MNC (e.g. IMSI parameter is an IMSI
203         // prefix that contained less than 6-digit of numbers "12345*").
204         return simImsi.startsWith(mccMnc);
205     }
206 }
207