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 android.net.wifi.hotspot2; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertTrue; 21 22 import android.net.wifi.EAPConstants; 23 import android.net.wifi.hotspot2.pps.Credential; 24 import android.net.wifi.hotspot2.pps.HomeSp; 25 import android.net.wifi.hotspot2.pps.Policy; 26 import android.net.wifi.hotspot2.pps.UpdateParameter; 27 import android.os.Parcel; 28 import android.support.test.filters.SmallTest; 29 import android.util.Base64; 30 31 import org.junit.Test; 32 33 import java.nio.charset.StandardCharsets; 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.HashMap; 37 import java.util.List; 38 import java.util.Map; 39 40 /** 41 * Unit tests for {@link android.net.wifi.hotspot2.PasspointConfiguration}. 42 */ 43 @SmallTest 44 public class PasspointConfigurationTest { 45 private static final int MAX_URL_BYTES = 1023; 46 private static final int CERTIFICATE_FINGERPRINT_BYTES = 32; 47 48 /** 49 * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}. 50 * 51 * @return {@link android.net.wifi.hotspot2.pps.HomeSP} 52 */ 53 private static HomeSp createHomeSp() { 54 HomeSp homeSp = new HomeSp(); 55 homeSp.setFqdn("fqdn"); 56 homeSp.setFriendlyName("friendly name"); 57 homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66}); 58 return homeSp; 59 } 60 61 /** 62 * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}. 63 * 64 * @return {@link android.net.wifi.hotspot2.pps.Credential} 65 */ 66 private static Credential createCredential() { 67 Credential cred = new Credential(); 68 cred.setRealm("realm"); 69 cred.setUserCredential(null); 70 cred.setCertCredential(null); 71 cred.setSimCredential(new Credential.SimCredential()); 72 cred.getSimCredential().setImsi("1234*"); 73 cred.getSimCredential().setEapType(EAPConstants.EAP_SIM); 74 cred.setCaCertificate(null); 75 cred.setClientCertificateChain(null); 76 cred.setClientPrivateKey(null); 77 return cred; 78 } 79 80 /** 81 * Helper function for creating a {@link Policy} for testing. 82 * 83 * @return {@link Policy} 84 */ 85 private static Policy createPolicy() { 86 Policy policy = new Policy(); 87 policy.setMinHomeDownlinkBandwidth(123); 88 policy.setMinHomeUplinkBandwidth(345); 89 policy.setMinRoamingDownlinkBandwidth(567); 90 policy.setMinRoamingUplinkBandwidth(789); 91 policy.setMaximumBssLoadValue(12); 92 policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"}); 93 HashMap<Integer, String> requiredProtoPortMap = new HashMap<>(); 94 requiredProtoPortMap.put(12, "23,342,123"); 95 requiredProtoPortMap.put(23, "789,372,1235"); 96 policy.setRequiredProtoPortMap(requiredProtoPortMap); 97 98 List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>(); 99 Policy.RoamingPartner partner1 = new Policy.RoamingPartner(); 100 partner1.setFqdn("partner1.com"); 101 partner1.setFqdnExactMatch(true); 102 partner1.setPriority(12); 103 partner1.setCountries("us,jp"); 104 Policy.RoamingPartner partner2 = new Policy.RoamingPartner(); 105 partner2.setFqdn("partner2.com"); 106 partner2.setFqdnExactMatch(false); 107 partner2.setPriority(42); 108 partner2.setCountries("ca,fr"); 109 preferredRoamingPartnerList.add(partner1); 110 preferredRoamingPartnerList.add(partner2); 111 policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList); 112 113 UpdateParameter policyUpdate = new UpdateParameter(); 114 policyUpdate.setUpdateIntervalInMinutes(1712); 115 policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM); 116 policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP); 117 policyUpdate.setServerUri("policy.update.com"); 118 policyUpdate.setUsername("username"); 119 policyUpdate.setBase64EncodedPassword( 120 Base64.encodeToString("password".getBytes(), Base64.DEFAULT)); 121 policyUpdate.setTrustRootCertUrl("trust.cert.com"); 122 policyUpdate.setTrustRootCertSha256Fingerprint( 123 new byte[CERTIFICATE_FINGERPRINT_BYTES]); 124 policy.setPolicyUpdate(policyUpdate); 125 126 return policy; 127 } 128 129 private static UpdateParameter createSubscriptionUpdate() { 130 UpdateParameter subUpdate = new UpdateParameter(); 131 subUpdate.setUpdateIntervalInMinutes(9021); 132 subUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP); 133 subUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER); 134 subUpdate.setServerUri("subscription.update.com"); 135 subUpdate.setUsername("subUsername"); 136 subUpdate.setBase64EncodedPassword( 137 Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT)); 138 subUpdate.setTrustRootCertUrl("subscription.trust.cert.com"); 139 subUpdate.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_FINGERPRINT_BYTES]); 140 return subUpdate; 141 } 142 /** 143 * Helper function for creating a {@link PasspointConfiguration} for testing. 144 * 145 * @return {@link PasspointConfiguration} 146 */ 147 private static PasspointConfiguration createConfig() { 148 PasspointConfiguration config = new PasspointConfiguration(); 149 config.setHomeSp(createHomeSp()); 150 config.setCredential(createCredential()); 151 config.setPolicy(createPolicy()); 152 config.setSubscriptionUpdate(createSubscriptionUpdate()); 153 Map<String, byte[]> trustRootCertList = new HashMap<>(); 154 trustRootCertList.put("trustRoot.cert1.com", 155 new byte[CERTIFICATE_FINGERPRINT_BYTES]); 156 trustRootCertList.put("trustRoot.cert2.com", 157 new byte[CERTIFICATE_FINGERPRINT_BYTES]); 158 config.setTrustRootCertList(trustRootCertList); 159 config.setUpdateIdentifier(1); 160 config.setCredentialPriority(120); 161 config.setSubscriptionCreationTimeInMillis(231200); 162 config.setSubscriptionExpirationTimeInMillis(2134232); 163 config.setSubscriptionType("Gold"); 164 config.setUsageLimitUsageTimePeriodInMinutes(3600); 165 config.setUsageLimitStartTimeInMillis(124214213); 166 config.setUsageLimitDataLimit(14121); 167 config.setUsageLimitTimeLimitInMinutes(78912); 168 return config; 169 } 170 171 /** 172 * Verify parcel write and read consistency for the given configuration. 173 * 174 * @param writeConfig The configuration to verify 175 * @throws Exception 176 */ 177 private static void verifyParcel(PasspointConfiguration writeConfig) throws Exception { 178 Parcel parcel = Parcel.obtain(); 179 writeConfig.writeToParcel(parcel, 0); 180 181 parcel.setDataPosition(0); // Rewind data position back to the beginning for read. 182 PasspointConfiguration readConfig = 183 PasspointConfiguration.CREATOR.createFromParcel(parcel); 184 assertTrue(readConfig.equals(writeConfig)); 185 } 186 187 /** 188 * Verify parcel read/write for a default configuration. 189 * 190 * @throws Exception 191 */ 192 @Test 193 public void verifyParcelWithDefault() throws Exception { 194 verifyParcel(new PasspointConfiguration()); 195 } 196 197 /** 198 * Verify parcel read/write for a configuration that contained the full configuration. 199 * 200 * @throws Exception 201 */ 202 @Test 203 public void verifyParcelWithFullConfiguration() throws Exception { 204 verifyParcel(createConfig()); 205 } 206 207 /** 208 * Verify parcel read/write for a configuration that doesn't contain HomeSP. 209 * 210 * @throws Exception 211 */ 212 @Test 213 public void verifyParcelWithoutHomeSP() throws Exception { 214 PasspointConfiguration config = createConfig(); 215 config.setHomeSp(null); 216 verifyParcel(config); 217 } 218 219 /** 220 * Verify parcel read/write for a configuration that doesn't contain Credential. 221 * 222 * @throws Exception 223 */ 224 @Test 225 public void verifyParcelWithoutCredential() throws Exception { 226 PasspointConfiguration config = createConfig(); 227 config.setCredential(null); 228 verifyParcel(config); 229 } 230 231 /** 232 * Verify parcel read/write for a configuration that doesn't contain Policy. 233 * 234 * @throws Exception 235 */ 236 @Test 237 public void verifyParcelWithoutPolicy() throws Exception { 238 PasspointConfiguration config = createConfig(); 239 config.setPolicy(null); 240 verifyParcel(config); 241 } 242 243 /** 244 * Verify parcel read/write for a configuration that doesn't contain subscription update. 245 * 246 * @throws Exception 247 */ 248 @Test 249 public void verifyParcelWithoutSubscriptionUpdate() throws Exception { 250 PasspointConfiguration config = createConfig(); 251 config.setSubscriptionUpdate(null); 252 verifyParcel(config); 253 } 254 255 /** 256 * Verify parcel read/write for a configuration that doesn't contain trust root certificate 257 * list. 258 * 259 * @throws Exception 260 */ 261 @Test 262 public void verifyParcelWithoutTrustRootCertList() throws Exception { 263 PasspointConfiguration config = createConfig(); 264 config.setTrustRootCertList(null); 265 verifyParcel(config); 266 } 267 268 /** 269 * Verify that a default/empty configuration is invalid. 270 * 271 * @throws Exception 272 */ 273 @Test 274 public void validateDefaultConfig() throws Exception { 275 PasspointConfiguration config = new PasspointConfiguration(); 276 assertFalse(config.validate()); 277 } 278 279 /** 280 * Verify that a configuration contained all fields is valid. 281 * 282 * @throws Exception 283 */ 284 @Test 285 public void validateFullConfig() throws Exception { 286 PasspointConfiguration config = createConfig(); 287 assertTrue(config.validate()); 288 } 289 290 /** 291 * Verify that a configuration without Credential is invalid. 292 * 293 * @throws Exception 294 */ 295 @Test 296 public void validateConfigWithoutCredential() throws Exception { 297 PasspointConfiguration config = createConfig(); 298 config.setCredential(null); 299 assertFalse(config.validate()); 300 } 301 302 /** 303 * Verify that a configuration without HomeSP is invalid. 304 * 305 * @throws Exception 306 */ 307 @Test 308 public void validateConfigWithoutHomeSp() throws Exception { 309 PasspointConfiguration config = createConfig(); 310 config.setHomeSp(null); 311 assertFalse(config.validate()); 312 } 313 314 /** 315 * Verify that a configuration without Policy is valid, since Policy configurations 316 * are optional (applied for Hotspot 2.0 Release only). 317 * 318 * @throws Exception 319 */ 320 @Test 321 public void validateConfigWithoutPolicy() throws Exception { 322 PasspointConfiguration config = createConfig(); 323 config.setPolicy(null); 324 assertTrue(config.validate()); 325 } 326 327 /** 328 * Verify that a configuration without subscription update is valid, since subscription 329 * update configurations are optional (applied for Hotspot 2.0 Release only). 330 * 331 * @throws Exception 332 */ 333 @Test 334 public void validateConfigWithoutSubscriptionUpdate() throws Exception { 335 PasspointConfiguration config = createConfig(); 336 config.setSubscriptionUpdate(null); 337 assertTrue(config.validate()); 338 } 339 340 /** 341 * Verify that a configuration with a trust root certificate URL exceeding the max size 342 * is invalid. 343 * 344 * @throws Exception 345 */ 346 @Test 347 public void validateConfigWithInvalidTrustRootCertUrl() throws Exception { 348 PasspointConfiguration config = createConfig(); 349 byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1]; 350 Map<String, byte[]> trustRootCertList = new HashMap<>(); 351 Arrays.fill(rawUrlBytes, (byte) 'a'); 352 trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8), 353 new byte[CERTIFICATE_FINGERPRINT_BYTES]); 354 config.setTrustRootCertList(trustRootCertList); 355 assertFalse(config.validate()); 356 357 trustRootCertList = new HashMap<>(); 358 trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]); 359 config.setTrustRootCertList(trustRootCertList); 360 assertFalse(config.validate()); 361 } 362 363 /** 364 * Verify that a configuration with an invalid trust root certificate fingerprint is invalid. 365 * 366 * @throws Exception 367 */ 368 @Test 369 public void validateConfigWithInvalidTrustRootCertFingerprint() throws Exception { 370 PasspointConfiguration config = createConfig(); 371 Map<String, byte[]> trustRootCertList = new HashMap<>(); 372 trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES + 1]); 373 config.setTrustRootCertList(trustRootCertList); 374 assertFalse(config.validate()); 375 376 trustRootCertList = new HashMap<>(); 377 trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES - 1]); 378 config.setTrustRootCertList(trustRootCertList); 379 assertFalse(config.validate()); 380 381 trustRootCertList = new HashMap<>(); 382 trustRootCertList.put("test.cert.com", null); 383 config.setTrustRootCertList(trustRootCertList); 384 assertFalse(config.validate()); 385 } 386 387 /** 388 * Verify that copy constructor works when pass in a null source. 389 * 390 * @throws Exception 391 */ 392 @Test 393 public void validateCopyConstructorWithNullSource() throws Exception { 394 PasspointConfiguration copyConfig = new PasspointConfiguration(null); 395 PasspointConfiguration defaultConfig = new PasspointConfiguration(); 396 assertTrue(copyConfig.equals(defaultConfig)); 397 } 398 399 /** 400 * Verify that copy constructor works when pass in a valid source. 401 * 402 * @throws Exception 403 */ 404 @Test 405 public void validateCopyConstructorWithValidSource() throws Exception { 406 PasspointConfiguration sourceConfig = createConfig(); 407 PasspointConfiguration copyConfig = new PasspointConfiguration(sourceConfig); 408 assertTrue(copyConfig.equals(sourceConfig)); 409 } 410 } 411