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 static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 23 import android.net.wifi.EAPConstants; 24 import android.support.test.filters.SmallTest; 25 26 import com.android.server.wifi.IMSIParameter; 27 import com.android.server.wifi.hotspot2.anqp.CellularNetwork; 28 import com.android.server.wifi.hotspot2.anqp.DomainNameElement; 29 import com.android.server.wifi.hotspot2.anqp.NAIRealmData; 30 import com.android.server.wifi.hotspot2.anqp.NAIRealmElement; 31 import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; 32 import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; 33 import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; 34 import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; 35 import com.android.server.wifi.hotspot2.anqp.eap.InnerAuthEAP; 36 import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; 37 38 import org.junit.Test; 39 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.HashMap; 43 import java.util.HashSet; 44 import java.util.List; 45 import java.util.Map; 46 import java.util.Set; 47 48 /** 49 * Unit tests for {@link com.android.server.wifi.hotspot2.ANQPMatcher}. 50 */ 51 @SmallTest 52 public class ANQPMatcherTest { 53 /** 54 * Verify that domain name match will fail when a null Domain Name ANQP element is provided. 55 * 56 * @throws Exception 57 */ 58 @Test 59 public void matchDomainNameWithNullElement() throws Exception { 60 assertFalse(ANQPMatcher.matchDomainName(null, "test.com", null, null)); 61 } 62 63 /** 64 * Verify that domain name match will succeed when the specified FQDN matches a domain name 65 * in the Domain Name ANQP element. 66 * 67 * @throws Exception 68 */ 69 @Test 70 public void matchDomainNameUsingFQDN() throws Exception { 71 String fqdn = "test.com"; 72 String[] domains = new String[] {fqdn}; 73 DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); 74 assertTrue(ANQPMatcher.matchDomainName(element, fqdn, null, null)); 75 } 76 77 /** 78 * Verify that domain name match will succeed when the specified IMSI parameter and IMSI list 79 * matches a 3GPP network domain in the Domain Name ANQP element. 80 * 81 * @throws Exception 82 */ 83 @Test 84 public void matchDomainNameUsingIMSI() throws Exception { 85 IMSIParameter imsiParam = new IMSIParameter("1234", true); 86 List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); 87 // 3GPP network domain with MCC=123 and MNC=456. 88 String[] domains = new String[] {"wlan.mnc457.mcc123.3gppnetwork.org"}; 89 DomainNameElement element = new DomainNameElement(Arrays.asList(domains)); 90 assertTrue(ANQPMatcher.matchDomainName(element, null, imsiParam, simImsiList)); 91 } 92 93 /** 94 * Verify that roaming consortium match will fail when a null Roaming Consortium ANQP 95 * element is provided. 96 * 97 * @throws Exception 98 */ 99 @Test 100 public void matchRoamingConsortiumWithNullElement() throws Exception { 101 assertFalse(ANQPMatcher.matchRoamingConsortium(null, new long[0])); 102 } 103 104 /** 105 * Verify that a roaming consortium match will succeed when the specified OI matches 106 * an OI in the Roaming Consortium ANQP element. 107 * 108 * @throws Exception 109 */ 110 @Test 111 public void matchRoamingConsortium() throws Exception { 112 long oi = 0x1234L; 113 RoamingConsortiumElement element = 114 new RoamingConsortiumElement(Arrays.asList(new Long[] {oi})); 115 assertTrue(ANQPMatcher.matchRoamingConsortium(element, new long[] {oi})); 116 } 117 118 /** 119 * Verify that an indeterminate match will be returned when matching a null NAI Realm 120 * ANQP element. 121 * 122 * @throws Exception 123 */ 124 @Test 125 public void matchNAIRealmWithNullElement() throws Exception { 126 assertEquals(AuthMatch.INDETERMINATE, ANQPMatcher.matchNAIRealm(null, "test.com", 127 EAPConstants.EAP_TLS, new InnerAuthEAP(EAPConstants.EAP_TTLS))); 128 } 129 130 /** 131 * Verify that an indeterminate match will be returned when matching a NAI Realm 132 * ANQP element contained no NAI realm data. 133 * 134 * @throws Exception 135 */ 136 @Test 137 public void matchNAIRealmWithEmtpyRealmData() throws Exception { 138 NAIRealmElement element = new NAIRealmElement(new ArrayList<NAIRealmData>()); 139 assertEquals(AuthMatch.INDETERMINATE, ANQPMatcher.matchNAIRealm(element, "test.com", 140 EAPConstants.EAP_TLS, null)); 141 } 142 143 /** 144 * Verify that a realm match will be returned when the specified realm matches a realm 145 * in the NAI Realm ANQP element with no EAP methods. 146 * 147 * @throws Exception 148 */ 149 @Test 150 public void matchNAIRealmWithRealmMatch() throws Exception { 151 String realm = "test.com"; 152 NAIRealmData realmData = new NAIRealmData( 153 Arrays.asList(new String[] {realm}), new ArrayList<EAPMethod>()); 154 NAIRealmElement element = new NAIRealmElement( 155 Arrays.asList(new NAIRealmData[] {realmData})); 156 assertEquals(AuthMatch.REALM, ANQPMatcher.matchNAIRealm(element, realm, 157 EAPConstants.EAP_TLS, null)); 158 } 159 160 /** 161 * Verify that method match will be returned when the specified EAP 162 * method only matches a eap method in the NAI Realm ANQP element. 163 * 164 * @throws Exception 165 */ 166 @Test 167 public void matchNAIRealmWithMethodMatch() throws Exception { 168 // Test data. 169 String providerRealm = "test.com"; 170 String anqpRealm = "test2.com"; 171 int eapMethodID = EAPConstants.EAP_TLS; 172 173 // Setup NAI Realm element. 174 EAPMethod method = new EAPMethod(eapMethodID, new HashMap<Integer, Set<AuthParam>>()); 175 NAIRealmData realmData = new NAIRealmData( 176 Arrays.asList(new String[] {anqpRealm}), Arrays.asList(new EAPMethod[] {method})); 177 NAIRealmElement element = new NAIRealmElement( 178 Arrays.asList(new NAIRealmData[] {realmData})); 179 180 assertEquals(AuthMatch.METHOD, 181 ANQPMatcher.matchNAIRealm(element, providerRealm, eapMethodID, null)); 182 } 183 184 /** 185 * Verify that a realm and method match will be returned when the specified realm and EAP 186 * method matches a realm in the NAI Realm ANQP element. 187 * 188 * @throws Exception 189 */ 190 @Test 191 public void matchNAIRealmWithRealmMethodMatch() throws Exception { 192 // Test data. 193 String realm = "test.com"; 194 int eapMethodID = EAPConstants.EAP_TLS; 195 196 // Setup NAI Realm element. 197 EAPMethod method = new EAPMethod(eapMethodID, new HashMap<Integer, Set<AuthParam>>()); 198 NAIRealmData realmData = new NAIRealmData( 199 Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); 200 NAIRealmElement element = new NAIRealmElement( 201 Arrays.asList(new NAIRealmData[] {realmData})); 202 203 assertEquals(AuthMatch.REALM | AuthMatch.METHOD, 204 ANQPMatcher.matchNAIRealm(element, realm, eapMethodID, null)); 205 } 206 207 /** 208 * Verify that an exact match will be returned when the specified realm, EAP 209 * method, and the authentication parameter matches a realm with the associated EAP method and 210 * authentication parameter in the NAI Realm ANQP element. 211 * 212 * @throws Exception 213 */ 214 @Test 215 public void matchNAIRealmWithExactMatch() throws Exception { 216 // Test data. 217 String realm = "test.com"; 218 int eapMethodID = EAPConstants.EAP_TTLS; 219 NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP); 220 Set<AuthParam> authSet = new HashSet<>(); 221 authSet.add(authParam); 222 Map<Integer, Set<AuthParam>> authMap = new HashMap<>(); 223 authMap.put(authParam.getAuthTypeID(), authSet); 224 225 // Setup NAI Realm element. 226 EAPMethod method = new EAPMethod(eapMethodID, authMap); 227 NAIRealmData realmData = new NAIRealmData( 228 Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); 229 NAIRealmElement element = new NAIRealmElement( 230 Arrays.asList(new NAIRealmData[] {realmData})); 231 232 assertEquals(AuthMatch.EXACT, 233 ANQPMatcher.matchNAIRealm(element, realm, eapMethodID, authParam)); 234 } 235 236 /** 237 * Verify that a mismatch (AuthMatch.NONE) will be returned when the specified EAP method 238 * doesn't match with the corresponding EAP method in the NAI Realm ANQP element. 239 * 240 * @throws Exception 241 */ 242 @Test 243 public void matchNAIRealmWithEAPMethodMismatch() throws Exception { 244 // Test data. 245 String realm = "test.com"; 246 int eapMethodID = EAPConstants.EAP_TTLS; 247 NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP); 248 Set<AuthParam> authSet = new HashSet<>(); 249 authSet.add(authParam); 250 Map<Integer, Set<AuthParam>> authMap = new HashMap<>(); 251 authMap.put(authParam.getAuthTypeID(), authSet); 252 253 // Setup NAI Realm element. 254 EAPMethod method = new EAPMethod(eapMethodID, authMap); 255 NAIRealmData realmData = new NAIRealmData( 256 Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); 257 NAIRealmElement element = new NAIRealmElement( 258 Arrays.asList(new NAIRealmData[] {realmData})); 259 260 assertEquals(AuthMatch.NONE, 261 ANQPMatcher.matchNAIRealm(element, realm, EAPConstants.EAP_TLS, null)); 262 } 263 264 /** 265 * Verify that a mismatch (AuthMatch.NONE) will be returned when the specified authentication 266 * parameter doesn't match with the corresponding authentication parameter in the NAI Realm 267 * ANQP element. 268 * 269 * @throws Exception 270 */ 271 @Test 272 public void matchNAIRealmWithAuthTypeMismatch() throws Exception { 273 // Test data. 274 String realm = "test.com"; 275 int eapMethodID = EAPConstants.EAP_TTLS; 276 NonEAPInnerAuth authParam = new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAP); 277 Set<AuthParam> authSet = new HashSet<>(); 278 authSet.add(authParam); 279 Map<Integer, Set<AuthParam>> authMap = new HashMap<>(); 280 authMap.put(authParam.getAuthTypeID(), authSet); 281 282 // Setup NAI Realm element. 283 EAPMethod method = new EAPMethod(eapMethodID, authMap); 284 NAIRealmData realmData = new NAIRealmData( 285 Arrays.asList(new String[] {realm}), Arrays.asList(new EAPMethod[] {method})); 286 NAIRealmElement element = new NAIRealmElement( 287 Arrays.asList(new NAIRealmData[] {realmData})); 288 289 // Mismatch in authentication type. 290 assertEquals(AuthMatch.NONE, 291 ANQPMatcher.matchNAIRealm(element, realm, EAPConstants.EAP_TTLS, 292 new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_PAP))); 293 } 294 295 /** 296 * Verify that 3GPP Network match will fail when a null element is provided. 297 * 298 * @throws Exception 299 */ 300 @Test 301 public void matchThreeGPPNetworkWithNullElement() throws Exception { 302 IMSIParameter imsiParam = new IMSIParameter("1234", true); 303 List<String> simImsiList = Arrays.asList(new String[] {"123456789", "123498723"}); 304 assertFalse(ANQPMatcher.matchThreeGPPNetwork(null, imsiParam, simImsiList)); 305 } 306 307 /** 308 * Verify that 3GPP network will succeed when the given 3GPP Network ANQP element contained 309 * a MCC-MNC that matches the both IMSI parameter and an IMSI from the IMSI list. 310 * 311 * @throws Exception 312 */ 313 @Test 314 public void matchThreeGPPNetwork() throws Exception { 315 IMSIParameter imsiParam = new IMSIParameter("1234", true); 316 List<String> simImsiList = Arrays.asList(new String[] {"123456789", "123498723"}); 317 318 CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123456"})); 319 ThreeGPPNetworkElement element = 320 new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); 321 // The MCC-MNC provided in 3GPP Network ANQP element matches both IMSI parameter 322 // and an IMSI from the installed SIM card. 323 assertTrue(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsiList)); 324 } 325 326 /** 327 * Verify that 3GPP network will failed when the given 3GPP Network ANQP element contained 328 * a MCC-MNC that match the IMSI parameter but not the IMSI list. 329 * 330 * @throws Exception 331 */ 332 @Test 333 public void matchThreeGPPNetworkWithoutSimImsiMatch() throws Exception { 334 IMSIParameter imsiParam = new IMSIParameter("1234", true); 335 List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); 336 337 CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123456"})); 338 ThreeGPPNetworkElement element = 339 new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); 340 // The MCC-MNC provided in 3GPP Network ANQP element doesn't match any of the IMSIs 341 // from the installed SIM card. 342 assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsiList)); 343 } 344 345 /** 346 * Verify that 3GPP network will failed when the given 3GPP Network ANQP element contained 347 * a MCC-MNC that doesn't match with the IMSI parameter. 348 * 349 * @throws Exception 350 */ 351 @Test 352 public void matchThreeGPPNetworkWithImsiParamMismatch() throws Exception { 353 IMSIParameter imsiParam = new IMSIParameter("1234", true); 354 List<String> simImsiList = Arrays.asList(new String[] {"123457890", "123498723"}); 355 356 CellularNetwork network = new CellularNetwork(Arrays.asList(new String[] {"123356"})); 357 ThreeGPPNetworkElement element = 358 new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); 359 // The MCC-MNC provided in 3GPP Network ANQP element doesn't match the IMSI parameter. 360 assertFalse(ANQPMatcher.matchThreeGPPNetwork(element, imsiParam, simImsiList)); 361 } 362 } 363