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 17package com.android.server.wifi.util; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertTrue; 22import static org.junit.Assert.fail; 23import static org.mockito.Matchers.anyInt; 24import static org.mockito.Matchers.anyString; 25import static org.mockito.Mockito.doAnswer; 26import static org.mockito.Mockito.doThrow; 27import static org.mockito.Mockito.when; 28 29import android.Manifest; 30import android.app.AppOpsManager; 31import android.content.ComponentName; 32import android.content.ContentResolver; 33import android.content.Context; 34import android.content.pm.ApplicationInfo; 35import android.content.pm.PackageManager; 36import android.content.pm.UserInfo; 37import android.net.NetworkScoreManager; 38import android.net.NetworkScorerAppData; 39import android.net.wifi.WifiConfiguration; 40import android.os.Build; 41import android.os.RemoteException; 42import android.os.UserHandle; 43import android.os.UserManager; 44import android.provider.Settings; 45 46import com.android.server.wifi.BinderUtil; 47import com.android.server.wifi.FakeWifiLog; 48import com.android.server.wifi.FrameworkFacade; 49import com.android.server.wifi.WifiInjector; 50import com.android.server.wifi.WifiSettingsStore; 51 52import org.junit.Before; 53import org.junit.Test; 54import org.junit.runner.RunWith; 55import org.junit.runners.JUnit4; 56import org.mockito.Mock; 57import org.mockito.MockitoAnnotations; 58import org.mockito.Spy; 59import org.mockito.invocation.InvocationOnMock; 60import org.mockito.stubbing.Answer; 61 62import java.util.Arrays; 63import java.util.HashMap; 64 65/** Unit tests for {@link WifiPermissionsUtil}. */ 66@RunWith(JUnit4.class) 67public class WifiPermissionsUtilTest { 68 public static final String TAG = "WifiPermissionsUtilTest"; 69 70 // Mock objects for testing 71 @Mock private WifiPermissionsWrapper mMockPermissionsWrapper; 72 @Mock private Context mMockContext; 73 @Mock private PackageManager mMockPkgMgr; 74 @Mock private ApplicationInfo mMockApplInfo; 75 @Mock private AppOpsManager mMockAppOps; 76 @Mock private UserInfo mMockUserInfo; 77 @Mock private UserManager mMockUserManager; 78 @Mock private WifiSettingsStore mMockWifiSettingsStore; 79 @Mock private ContentResolver mMockContentResolver; 80 @Mock private NetworkScoreManager mMockNetworkScoreManager; 81 @Mock private WifiInjector mMockWifiInjector; 82 @Mock private FrameworkFacade mMockFrameworkFacade; 83 @Mock private WifiConfiguration mMockWifiConfig; 84 @Spy private FakeWifiLog mWifiLog; 85 86 private static final String TEST_PACKAGE_NAME = "com.google.somePackage"; 87 private static final String INVALID_PACKAGE = "BAD_PACKAGE"; 88 private static final int MANAGED_PROFILE_UID = 1100000; 89 private static final int OTHER_USER_UID = 1200000; 90 91 private final int mCallingUser = UserHandle.USER_CURRENT_OR_SELF; 92 private final String mMacAddressPermission = "android.permission.PEERS_MAC_ADDRESS"; 93 private final String mInteractAcrossUsersFullPermission = 94 "android.permission.INTERACT_ACROSS_USERS_FULL"; 95 private final String mManifestStringCoarse = 96 Manifest.permission.ACCESS_COARSE_LOCATION; 97 98 // Test variables 99 private int mWifiScanAllowApps; 100 private int mUid; 101 private int mCoarseLocationPermission; 102 private int mAllowCoarseLocationApps; 103 private String mPkgNameOfTopActivity; 104 private int mCurrentUser; 105 private int mLocationModeSetting; 106 private boolean mThrowSecurityException; 107 private int mTargetVersion; 108 private boolean mActiveNwScorer; 109 private Answer<Integer> mReturnPermission; 110 private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>(); 111 private String mUseOpenWifiPackage; 112 private NetworkScorerAppData mNetworkScorerAppData; 113 private boolean mGetActiveScorerThrowsSecurityException; 114 private boolean mConfigIsOpen; 115 116 /** 117 * Set up Mockito tests 118 */ 119 @Before 120 public void setUp() { 121 MockitoAnnotations.initMocks(this); 122 initTestVars(); 123 } 124 125 private void setupTestCase() throws Exception { 126 setupMocks(); 127 setupMockInterface(); 128 } 129 130 /** 131 * Verify we return true when the UID does have the override config permission 132 */ 133 @Test 134 public void testCheckConfigOverridePermissionApproved() throws Exception { 135 mUid = MANAGED_PROFILE_UID; // do not really care about this value 136 setupTestCase(); 137 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 138 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 139 mMockWifiInjector); 140 when(mMockPermissionsWrapper.getOverrideWifiConfigPermission(anyInt())) 141 .thenReturn(PackageManager.PERMISSION_GRANTED); 142 assertTrue(codeUnderTest.checkConfigOverridePermission(mUid)); 143 } 144 145 /** 146 * Verify we return false when the UID does not have the override config permission. 147 */ 148 @Test 149 public void testCheckConfigOverridePermissionDenied() throws Exception { 150 mUid = OTHER_USER_UID; // do not really care about this value 151 setupTestCase(); 152 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 153 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 154 mMockWifiInjector); 155 when(mMockPermissionsWrapper.getOverrideWifiConfigPermission(anyInt())) 156 .thenReturn(PackageManager.PERMISSION_DENIED); 157 assertFalse(codeUnderTest.checkConfigOverridePermission(mUid)); 158 } 159 160 /** 161 * Verify we return false when the override config permission check throws a RemoteException. 162 */ 163 @Test 164 public void testCheckConfigOverridePermissionWithException() throws Exception { 165 mUid = OTHER_USER_UID; // do not really care about this value 166 setupTestCase(); 167 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 168 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 169 mMockWifiInjector); 170 doThrow(new RemoteException("Failed to check permissions for " + mUid)) 171 .when(mMockPermissionsWrapper).getOverrideWifiConfigPermission(mUid); 172 assertFalse(codeUnderTest.checkConfigOverridePermission(mUid)); 173 } 174 175 /** 176 * Test case setting: Package is valid 177 * Caller can read peers mac address 178 * This App has permission to request WIFI_SCAN 179 * User is current 180 * Validate result is true 181 * - User has all the permissions 182 */ 183 @Test 184 public void testCanReadPeersMacAddressCurrentUserAndAllPermissions() throws Exception { 185 boolean output = false; 186 mThrowSecurityException = false; 187 mUid = MANAGED_PROFILE_UID; 188 mPermissionsList.put(mMacAddressPermission, mUid); 189 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 190 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 191 setupTestCase(); 192 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 193 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 194 mMockWifiInjector); 195 try { 196 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 197 } catch (SecurityException e) { 198 throw e; 199 } 200 assertEquals(output, true); 201 } 202 203 /** 204 * Test case setting: Package is valid 205 * Caller can read peers mac address 206 * This App has permission to request WIFI_SCAN 207 * User profile is current 208 * Validate result is true 209 * - User has all the permissions 210 */ 211 @Test 212 public void testCanReadPeersMacAddressCurrentProfileAndAllPermissions() throws Exception { 213 boolean output = false; 214 mThrowSecurityException = false; 215 mUid = MANAGED_PROFILE_UID; 216 mPermissionsList.put(mMacAddressPermission, mUid); 217 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 218 mMockUserInfo.id = mCallingUser; 219 setupTestCase(); 220 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 221 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 222 mMockWifiInjector); 223 try { 224 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 225 } catch (SecurityException e) { 226 throw e; 227 } 228 assertEquals(output, true); 229 } 230 231 /** 232 * Test case setting: Package is valid 233 * Caller can read peers mac address 234 * Validate result is false 235 * - This App doesn't have permission to request Wifi Scan 236 */ 237 @Test 238 public void testCannotAccessScanResult_AppNotAllowed() throws Exception { 239 boolean output = true; 240 mThrowSecurityException = false; 241 mPermissionsList.put(mMacAddressPermission, mUid); 242 setupTestCase(); 243 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 244 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 245 mMockWifiInjector); 246 try { 247 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 248 } catch (SecurityException e) { 249 throw e; 250 } 251 assertEquals(output, false); 252 } 253 254 /** 255 * Test case setting: Package is valid 256 * Caller can read peers mac address 257 * This App has permission to request WIFI_SCAN 258 * User or profile is not current but the uid has 259 * permission to INTERACT_ACROSS_USERS_FULL 260 * Validate result is true 261 * - User has all the permissions 262 */ 263 @Test 264 public void testCanAccessScanResults_UserOrProfileNotCurrent() throws Exception { 265 boolean output = false; 266 mThrowSecurityException = false; 267 mUid = MANAGED_PROFILE_UID; 268 mPermissionsList.put(mMacAddressPermission, mUid); 269 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 270 mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); 271 setupTestCase(); 272 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 273 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 274 mMockWifiInjector); 275 try { 276 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 277 } catch (SecurityException e) { 278 throw e; 279 } 280 assertEquals(output, true); 281 } 282 283 /** 284 * Test case setting: Package is valid 285 * Caller can read peers mac address 286 * This App has permission to request WIFI_SCAN 287 * User or profile is not Current 288 * Validate result is false 289 * - Calling uid doesn't have INTERACT_ACROSS_USERS_FULL permission 290 */ 291 @Test 292 public void testCannotAccessScanResults_NoInteractAcrossUsersFullPermission() throws Exception { 293 boolean output = true; 294 mThrowSecurityException = false; 295 mUid = MANAGED_PROFILE_UID; 296 mPermissionsList.put(mMacAddressPermission, mUid); 297 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 298 setupTestCase(); 299 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 300 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 301 mMockWifiInjector); 302 try { 303 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 304 } catch (SecurityException e) { 305 throw e; 306 } 307 assertEquals(output, false); 308 } 309 310 /** 311 * Test case setting: Package is valid 312 * Caller is active network scorer 313 * This App has permission to request WIFI_SCAN 314 * User is current 315 * Validate result is true 316 */ 317 @Test 318 public void testCanAccessScanResults_CallerIsActiveNwScorer() throws Exception { 319 boolean output = false; 320 mThrowSecurityException = false; 321 mActiveNwScorer = true; 322 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 323 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 324 setupTestCase(); 325 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 326 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 327 mMockWifiInjector); 328 try { 329 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 330 } catch (SecurityException e) { 331 throw e; 332 } 333 assertEquals(output, true); 334 } 335 336 /** 337 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 338 * User is current 339 * The current config is for an open network. 340 * Validate result is true 341 */ 342 @Test 343 public void testCanAccessFullConnectionInfo_PackageIsUseOpenWifiPackage() throws Exception { 344 final boolean output; 345 mThrowSecurityException = false; 346 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 347 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 348 ComponentName useOpenWifiComponent = new ComponentName(TEST_PACKAGE_NAME, "TestClass"); 349 mNetworkScorerAppData = new NetworkScorerAppData(0 /*packageUid*/, 350 null /*recommendationServiceComp*/, null /*recommendationServiceLabel*/, 351 useOpenWifiComponent, null /*networkAvailableNotificationChannelId*/); 352 setupTestCase(); 353 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 354 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 355 mMockWifiInjector); 356 357 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 358 mUid, mTargetVersion); 359 360 assertEquals(true, output); 361 } 362 363 /** 364 * Test case setting: Package is valid because the caller has access to scan results. 365 * Location mode is ON 366 * User is current 367 * The current config is not for an open network. 368 * Validate result is true 369 */ 370 @Test 371 public void testCanAccessFullConnectionInfo_HasAccessToScanResults() throws Exception { 372 final boolean output; 373 mThrowSecurityException = false; 374 mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; 375 mLocationModeSetting = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 376 mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; 377 mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; 378 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 379 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 380 mConfigIsOpen = false; 381 382 setupTestCase(); 383 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 384 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 385 mMockWifiInjector); 386 387 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 388 mUid, mTargetVersion); 389 390 assertEquals(true, output); 391 } 392 393 /** 394 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 395 * User or profile is not current but the uid has 396 * permission to INTERACT_ACROSS_USERS_FULL 397 * The current config is for an open network. 398 * Validate result is true 399 */ 400 @Test 401 public void testCanAccessFullConnectionInfo_UserNotCurrentButHasInteractAcrossUsers() 402 throws Exception { 403 final boolean output; 404 mThrowSecurityException = false; 405 mUid = MANAGED_PROFILE_UID; 406 mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); 407 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 408 ComponentName useOpenWifiComponent = new ComponentName(TEST_PACKAGE_NAME, "TestClass"); 409 mNetworkScorerAppData = new NetworkScorerAppData(0 /*packageUid*/, 410 null /*recommendationServiceComp*/, null /*recommendationServiceLabel*/, 411 useOpenWifiComponent, null /*networkAvailableNotificationChannelId*/); 412 setupTestCase(); 413 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 414 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 415 mMockWifiInjector); 416 417 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 418 mUid, mTargetVersion); 419 420 assertEquals(true, output); 421 } 422 423 /** 424 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 425 * User or profile is NOT current 426 * INTERACT_ACROSS_USERS_FULL NOT granted 427 * The current config is for an open network. 428 * Validate result is false 429 */ 430 @Test 431 public void testCanAccessFullConnectionInfo_UserNotCurrentNoInteractAcrossUsers() 432 throws Exception { 433 final boolean output; 434 mThrowSecurityException = false; 435 mUid = MANAGED_PROFILE_UID; 436 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 437 setupTestCase(); 438 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 439 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 440 mMockWifiInjector); 441 442 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 443 mUid, mTargetVersion); 444 445 assertEquals(false, output); 446 } 447 448 /** 449 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 450 * User is current 451 * The current config is NULL. 452 * Validate result is false 453 */ 454 @Test 455 public void testCanAccessFullConnectionInfo_WiFiConfigIsNull() throws Exception { 456 final boolean output; 457 mThrowSecurityException = false; 458 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 459 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 460 ComponentName useOpenWifiComponent = new ComponentName(TEST_PACKAGE_NAME, "TestClass"); 461 mNetworkScorerAppData = new NetworkScorerAppData(0 /*packageUid*/, 462 null /*recommendationServiceComp*/, null /*recommendationServiceLabel*/, 463 useOpenWifiComponent, null /*networkAvailableNotificationChannelId*/); 464 setupTestCase(); 465 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 466 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 467 mMockWifiInjector); 468 469 output = codeUnderTest.canAccessFullConnectionInfo(null /*config*/, TEST_PACKAGE_NAME, 470 mUid, mTargetVersion); 471 472 assertEquals(false, output); 473 } 474 475 /** 476 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 477 * User is current 478 * The current config is not for an open network. 479 * Validate result is false 480 */ 481 @Test 482 public void testCanAccessFullConnectionInfo_WiFiConfigIsNotOpen() throws Exception { 483 final boolean output; 484 mThrowSecurityException = false; 485 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 486 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 487 ComponentName useOpenWifiComponent = new ComponentName(TEST_PACKAGE_NAME, "TestClass"); 488 mNetworkScorerAppData = new NetworkScorerAppData(0 /*packageUid*/, 489 null /*recommendationServiceComp*/, null /*recommendationServiceLabel*/, 490 useOpenWifiComponent, null /*networkAvailableNotificationChannelId*/); 491 mConfigIsOpen = false; 492 setupTestCase(); 493 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 494 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 495 mMockWifiInjector); 496 497 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 498 mUid, mTargetVersion); 499 500 assertEquals(false, output); 501 } 502 503 /** 504 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 505 * User is current 506 * The current config is for an open network. 507 * There is no active scorer 508 * Validate result is false 509 */ 510 @Test 511 public void testCanAccessFullConnectionInfo_UseOpenWifiPackageIsSetButNoActiveScorer() 512 throws Exception { 513 final boolean output; 514 mThrowSecurityException = false; 515 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 516 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 517 mNetworkScorerAppData = null; // getActiveScorer() will return null 518 setupTestCase(); 519 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 520 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 521 mMockWifiInjector); 522 523 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 524 mUid, mTargetVersion); 525 526 assertEquals(false, output); 527 } 528 529 /** 530 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 531 * User is current 532 * The current config is for an open network. 533 * The scorer is active but the useOpenWiFi component name doesn't match 534 * the provided package. 535 * Validate result is false 536 */ 537 @Test 538 public void testCanAccessFullConnectionInfo_MismatchBetweenUseOpenWifiPackages() 539 throws Exception { 540 final boolean output; 541 mThrowSecurityException = false; 542 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 543 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 544 ComponentName useOpenWifiComponent = 545 new ComponentName(mUseOpenWifiPackage + ".nomatch", "TestClass"); 546 mNetworkScorerAppData = new NetworkScorerAppData(0 /*packageUid*/, 547 null /*recommendationServiceComp*/, null /*recommendationServiceLabel*/, 548 useOpenWifiComponent, null /*networkAvailableNotificationChannelId*/); 549 setupTestCase(); 550 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 551 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 552 mMockWifiInjector); 553 554 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 555 mUid, mTargetVersion); 556 557 assertEquals(false, output); 558 } 559 560 /** 561 * Test case setting: Package is valid because it matches the USE_OPEN_WIFI_PACKAGE. 562 * User is current 563 * The current config is for an open network. 564 * The scorer is active but the useOpenWiFi component name is null. 565 * Validate result is false 566 */ 567 @Test 568 public void testCanAccessFullConnectionInfo_UseOpenWifiPackageFromScorerIsNull() 569 throws Exception { 570 final boolean output; 571 mThrowSecurityException = false; 572 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 573 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 574 mNetworkScorerAppData = new NetworkScorerAppData(0 /*packageUid*/, 575 null /*recommendationServiceComp*/, null /*recommendationServiceLabel*/, 576 null /*useOpenWifiComponent*/, null /*networkAvailableNotificationChannelId*/); 577 setupTestCase(); 578 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 579 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 580 mMockWifiInjector); 581 582 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 583 mUid, mTargetVersion); 584 585 assertEquals(false, output); 586 } 587 588 /** 589 * Test case setting: Package is invalid because USE_OPEN_WIFI_PACKAGE is an empty string. 590 * Location mode is ON 591 * User is current 592 * The current config is for an open network. 593 * Validate result is false 594 */ 595 @Test 596 public void testCanAccessFullConnectionInfo_UseOpenWifiPackageIsEmpty() throws Exception { 597 final boolean output; 598 mThrowSecurityException = false; 599 mLocationModeSetting = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 600 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 601 mUseOpenWifiPackage = ""; 602 setupTestCase(); 603 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 604 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 605 mMockWifiInjector); 606 607 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 608 mUid, mTargetVersion); 609 610 assertEquals(false, output); 611 } 612 613 /** 614 * Test case setting: Package is invalid because it does not match the USE_OPEN_WIFI_PACKAGE. 615 * User is current 616 * The current config is for an open network. 617 * Validate result is false 618 */ 619 @Test 620 public void testCanAccessFullConnectionInfo_DoesNotMatchUseOpenWifiPackage() throws Exception { 621 final boolean output; 622 mThrowSecurityException = false; 623 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 624 mUseOpenWifiPackage = TEST_PACKAGE_NAME + ".nomatch"; 625 setupTestCase(); 626 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 627 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 628 mMockWifiInjector); 629 630 output = codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, 631 mUid, mTargetVersion); 632 633 assertEquals(false, output); 634 } 635 636 /** 637 * Test case setting: The caller is invalid because its UID does not match the provided package. 638 * 639 * Validate a SecurityException is thrown. 640 */ 641 @Test 642 public void testCanAccessFullConnectionInfo_UidPackageCheckFails() throws Exception { 643 mThrowSecurityException = true; 644 setupTestCase(); 645 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 646 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 647 mMockWifiInjector); 648 649 try { 650 codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, mUid, 651 mTargetVersion); 652 fail("SecurityException not thrown."); 653 } catch (SecurityException e) { 654 // expected 655 } 656 } 657 658 /** 659 * Test case setting: The getActiveScorer() call fails with a SecurityException. 660 * 661 * Validate a SecurityException is thrown. 662 */ 663 @Test 664 public void testCanAccessFullConnectionInfo_GetActiveScorerFails() throws Exception { 665 mThrowSecurityException = false; 666 mGetActiveScorerThrowsSecurityException = true; 667 mLocationModeSetting = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 668 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 669 mUseOpenWifiPackage = TEST_PACKAGE_NAME; 670 setupTestCase(); 671 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 672 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 673 mMockWifiInjector); 674 675 try { 676 codeUnderTest.canAccessFullConnectionInfo(mMockWifiConfig, TEST_PACKAGE_NAME, mUid, 677 mTargetVersion); 678 fail("SecurityException not thrown."); 679 } catch (SecurityException e) { 680 // expected 681 } 682 } 683 684 /** 685 * Test case Setting: Package is valid 686 * Legacy App 687 * Foreground 688 * This App has permission to request WIFI_SCAN 689 * User is current 690 * Validate result is true - has all permissions 691 */ 692 @Test 693 public void testLegacyForegroundAppAndAllPermissions() throws Exception { 694 boolean output = false; 695 mThrowSecurityException = false; 696 mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; 697 mPkgNameOfTopActivity = TEST_PACKAGE_NAME; 698 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 699 mUid = MANAGED_PROFILE_UID; 700 mCurrentUser = UserHandle.USER_CURRENT_OR_SELF; 701 setupTestCase(); 702 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 703 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 704 mMockWifiInjector); 705 try { 706 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 707 } catch (SecurityException e) { 708 throw e; 709 } 710 assertEquals(output, true); 711 } 712 713 /** 714 * Test case Setting: Package is valid 715 * Legacy App 716 * Location Mode Enabled 717 * Coarse Location Access 718 * This App has permission to request WIFI_SCAN 719 * User profile is current 720 * Validate result is true - has all permissions 721 */ 722 @Test 723 public void testLegacyAppHasLocationAndAllPermissions() throws Exception { 724 boolean output = false; 725 mThrowSecurityException = false; 726 mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; 727 mLocationModeSetting = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 728 mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; 729 mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; 730 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 731 mUid = MANAGED_PROFILE_UID; 732 mMockUserInfo.id = mCallingUser; 733 setupTestCase(); 734 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 735 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 736 mMockWifiInjector); 737 try { 738 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 739 } catch (SecurityException e) { 740 throw e; 741 } 742 assertEquals(output, true); 743 } 744 745 /** 746 * Test case setting: Package is valid 747 * Location Mode Enabled 748 * Validate result is false 749 * - Doesn't have Peer Mac Address read permission 750 * - Uid is not an active network scorer 751 * - Location Mode is enabled but the uid 752 * - doesn't have Coarse Location Access 753 * - which implies No Location Permission 754 */ 755 @Test 756 public void testCannotAccessScanResults_NoCoarseLocationPermission() throws Exception { 757 boolean output = true; 758 mThrowSecurityException = false; 759 mLocationModeSetting = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 760 setupTestCase(); 761 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 762 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 763 mMockWifiInjector); 764 try { 765 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 766 } catch (SecurityException e) { 767 throw e; 768 } 769 assertEquals(output, false); 770 } 771 772 /** 773 * Test case setting: Invalid Package 774 * Expect a securityException 775 */ 776 @Test (expected = SecurityException.class) 777 public void testInvalidPackage() throws Exception { 778 boolean output = false; 779 setupTestCase(); 780 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 781 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 782 mMockWifiInjector); 783 try { 784 output = codeUnderTest.canAccessScanResults(TEST_PACKAGE_NAME, mUid, mTargetVersion); 785 } catch (SecurityException e) { 786 throw e; 787 } 788 } 789 790 /** 791 * Test case setting: caller does have Location permission. 792 * A SecurityException should not be thrown. 793 */ 794 @Test 795 public void testEnforceLocationPermission() throws Exception { 796 mThrowSecurityException = false; 797 mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; 798 mLocationModeSetting = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 799 mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; 800 mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; 801 mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; 802 mUid = MANAGED_PROFILE_UID; 803 mMockUserInfo.id = mCallingUser; 804 setupTestCase(); 805 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 806 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 807 mMockWifiInjector); 808 codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, mUid); 809 } 810 811 /** 812 * Test case setting: caller does not have Location permission. 813 * Expect a SecurityException 814 */ 815 @Test(expected = SecurityException.class) 816 public void testEnforceLocationPermissionExpectSecurityException() throws Exception { 817 setupTestCase(); 818 WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, 819 mMockContext, mMockWifiSettingsStore, mMockUserManager, mMockNetworkScoreManager, 820 mMockWifiInjector); 821 codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, mUid); 822 } 823 824 private Answer<Integer> createPermissionAnswer() { 825 return new Answer<Integer>() { 826 @Override 827 public Integer answer(InvocationOnMock invocation) { 828 int myUid = (int) invocation.getArguments()[1]; 829 String myPermission = (String) invocation.getArguments()[0]; 830 mPermissionsList.get(myPermission); 831 if (mPermissionsList.containsKey(myPermission)) { 832 int uid = mPermissionsList.get(myPermission); 833 if (myUid == uid) { 834 return PackageManager.PERMISSION_GRANTED; 835 } 836 } 837 return PackageManager.PERMISSION_DENIED; 838 } 839 }; 840 } 841 842 private void setupMocks() throws Exception { 843 when(mMockPkgMgr.getApplicationInfo(TEST_PACKAGE_NAME, 0)) 844 .thenReturn(mMockApplInfo); 845 when(mMockContext.getPackageManager()).thenReturn(mMockPkgMgr); 846 when(mMockAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, mUid, TEST_PACKAGE_NAME)) 847 .thenReturn(mWifiScanAllowApps); 848 when(mMockAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, mUid, TEST_PACKAGE_NAME)) 849 .thenReturn(mAllowCoarseLocationApps); 850 if (mThrowSecurityException) { 851 doThrow(new SecurityException("Package " + TEST_PACKAGE_NAME + " doesn't belong" 852 + " to application bound to user " + mUid)) 853 .when(mMockAppOps).checkPackage(mUid, TEST_PACKAGE_NAME); 854 } 855 when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)) 856 .thenReturn(mMockAppOps); 857 when(mMockUserManager.getProfiles(mCurrentUser)) 858 .thenReturn(Arrays.asList(mMockUserInfo)); 859 when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); 860 when(mMockContext.getSystemService(Context.USER_SERVICE)) 861 .thenReturn(mMockUserManager); 862 when(mMockWifiInjector.makeLog(anyString())).thenReturn(mWifiLog); 863 when(mMockWifiInjector.getFrameworkFacade()).thenReturn(mMockFrameworkFacade); 864 if (mGetActiveScorerThrowsSecurityException) { 865 when(mMockNetworkScoreManager.getActiveScorer()).thenThrow( 866 new SecurityException("Caller is neither the system process nor a " 867 + "score requester.")); 868 } else { 869 when(mMockNetworkScoreManager.getActiveScorer()).thenReturn(mNetworkScorerAppData); 870 } 871 } 872 873 private void initTestVars() { 874 mPermissionsList.clear(); 875 mReturnPermission = createPermissionAnswer(); 876 mWifiScanAllowApps = AppOpsManager.MODE_ERRORED; 877 mUid = OTHER_USER_UID; 878 mThrowSecurityException = true; 879 mMockUserInfo.id = UserHandle.USER_NULL; 880 mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M; 881 mTargetVersion = Build.VERSION_CODES.M; 882 mPkgNameOfTopActivity = INVALID_PACKAGE; 883 mLocationModeSetting = Settings.Secure.LOCATION_MODE_OFF; 884 mCurrentUser = UserHandle.USER_SYSTEM; 885 mCoarseLocationPermission = PackageManager.PERMISSION_DENIED; 886 mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; 887 mActiveNwScorer = false; 888 mUseOpenWifiPackage = null; 889 mNetworkScorerAppData = null; 890 mGetActiveScorerThrowsSecurityException = false; 891 mConfigIsOpen = true; 892 } 893 894 private void setupMockInterface() { 895 BinderUtil.setUid(mUid); 896 doAnswer(mReturnPermission).when(mMockPermissionsWrapper).getUidPermission( 897 anyString(), anyInt()); 898 doAnswer(mReturnPermission).when(mMockPermissionsWrapper).getUidPermission( 899 anyString(), anyInt()); 900 when(mMockPermissionsWrapper.getCallingUserId(mUid)).thenReturn(mCallingUser); 901 when(mMockPermissionsWrapper.getCurrentUser()).thenReturn(mCurrentUser); 902 when(mMockNetworkScoreManager.isCallerActiveScorer(mUid)).thenReturn(mActiveNwScorer); 903 when(mMockPermissionsWrapper.getUidPermission(mManifestStringCoarse, mUid)) 904 .thenReturn(mCoarseLocationPermission); 905 when(mMockWifiSettingsStore.getLocationModeSetting(mMockContext)) 906 .thenReturn(mLocationModeSetting); 907 when(mMockPermissionsWrapper.getTopPkgName()).thenReturn(mPkgNameOfTopActivity); 908 when(mMockFrameworkFacade.getStringSetting(mMockContext, 909 Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(mUseOpenWifiPackage); 910 when(mMockWifiConfig.isOpenNetwork()).thenReturn(mConfigIsOpen); 911 } 912} 913