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.util; 18 19 import android.Manifest; 20 import android.annotation.Nullable; 21 import android.app.AppOpsManager; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.pm.PackageManager; 26 import android.location.LocationManager; 27 import android.net.NetworkStack; 28 import android.os.Binder; 29 import android.os.Build; 30 import android.os.UserHandle; 31 import android.os.UserManager; 32 import android.provider.Settings; 33 import android.util.EventLog; 34 import android.util.Log; 35 36 import com.android.internal.annotations.GuardedBy; 37 import com.android.server.wifi.FrameworkFacade; 38 import com.android.server.wifi.WifiInjector; 39 import com.android.server.wifi.WifiLog; 40 41 /** 42 * A wifi permissions utility assessing permissions 43 * for getting scan results by a package. 44 */ 45 public class WifiPermissionsUtil { 46 private static final String TAG = "WifiPermissionsUtil"; 47 private final WifiPermissionsWrapper mWifiPermissionsWrapper; 48 private final Context mContext; 49 private final FrameworkFacade mFrameworkFacade; 50 private final AppOpsManager mAppOps; 51 private final UserManager mUserManager; 52 private final Object mLock = new Object(); 53 @GuardedBy("mLock") 54 private LocationManager mLocationManager; 55 private WifiLog mLog; 56 WifiPermissionsUtil(WifiPermissionsWrapper wifiPermissionsWrapper, Context context, UserManager userManager, WifiInjector wifiInjector)57 public WifiPermissionsUtil(WifiPermissionsWrapper wifiPermissionsWrapper, 58 Context context, UserManager userManager, WifiInjector wifiInjector) { 59 mWifiPermissionsWrapper = wifiPermissionsWrapper; 60 mContext = context; 61 mFrameworkFacade = wifiInjector.getFrameworkFacade(); 62 mUserManager = userManager; 63 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 64 mLog = wifiInjector.makeLog(TAG); 65 } 66 67 /** 68 * Checks if the app has the permission to override Wi-Fi network configuration or not. 69 * 70 * @param uid uid of the app. 71 * @return true if the app does have the permission, false otherwise. 72 */ checkConfigOverridePermission(int uid)73 public boolean checkConfigOverridePermission(int uid) { 74 int permission = mWifiPermissionsWrapper.getOverrideWifiConfigPermission(uid); 75 return permission == PackageManager.PERMISSION_GRANTED; 76 } 77 78 /** 79 * Check and enforce Coarse or Fine Location permission (depending on target SDK). 80 * 81 * @param pkgName PackageName of the application requesting access 82 * @param featureId The feature in the package 83 * @param uid The uid of the package 84 */ enforceLocationPermission(String pkgName, @Nullable String featureId, int uid)85 public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid) { 86 if (!checkCallersLocationPermission(pkgName, featureId, 87 uid, /* coarseForTargetSdkLessThanQ */ true, null)) { 88 throw new SecurityException( 89 "UID " + uid + " does not have Coarse/Fine Location permission"); 90 } 91 } 92 93 /** 94 * Checks whether than the target SDK of the package is less than the specified version code. 95 */ isTargetSdkLessThan(String packageName, int versionCode, int callingUid)96 public boolean isTargetSdkLessThan(String packageName, int versionCode, int callingUid) { 97 long ident = Binder.clearCallingIdentity(); 98 try { 99 if (mContext.getPackageManager().getApplicationInfoAsUser( 100 packageName, 0, 101 UserHandle.getUserHandleForUid(callingUid)).targetSdkVersion 102 < versionCode) { 103 return true; 104 } 105 } catch (PackageManager.NameNotFoundException e) { 106 // In case of exception, assume unknown app (more strict checking) 107 // Note: This case will never happen since checkPackage is 108 // called to verify validity before checking App's version. 109 } finally { 110 Binder.restoreCallingIdentity(ident); 111 } 112 return false; 113 } 114 115 /** 116 * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION or 117 * android.Manifest.permission.ACCESS_FINE_LOCATION (depending on config/targetSDK leve) 118 * and a corresponding app op is allowed for this package and uid. 119 * 120 * @param pkgName PackageName of the application requesting access 121 * @param featureId The feature in the package 122 * @param uid The uid of the package 123 * @param coarseForTargetSdkLessThanQ If true and the targetSDK < Q then will check for COARSE 124 * else (false or targetSDK >= Q) then will check for FINE 125 * @param message A message describing why the permission was checked. Only needed if this is 126 * not inside of a two-way binder call from the data receiver 127 */ checkCallersLocationPermission(String pkgName, @Nullable String featureId, int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message)128 public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId, 129 int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) { 130 boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid); 131 132 String permissionType = Manifest.permission.ACCESS_FINE_LOCATION; 133 if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { 134 // Having FINE permission implies having COARSE permission (but not the reverse) 135 permissionType = Manifest.permission.ACCESS_COARSE_LOCATION; 136 } 137 if (mWifiPermissionsWrapper.getUidPermission(permissionType, uid) 138 == PackageManager.PERMISSION_DENIED) { 139 return false; 140 } 141 142 // Always checking FINE - even if will not enforce. This will record the request for FINE 143 // so that a location request by the app is surfaced to the user. 144 boolean isFineLocationAllowed = noteAppOpAllowed( 145 AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, message); 146 if (isFineLocationAllowed) { 147 return true; 148 } 149 if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) { 150 return noteAppOpAllowed(AppOpsManager.OPSTR_COARSE_LOCATION, pkgName, featureId, uid, 151 message); 152 } 153 return false; 154 } 155 156 /** 157 * Check and enforce Fine Location permission. 158 * 159 * @param pkgName PackageName of the application requesting access 160 * @param featureId The feature in the package 161 * @param uid The uid of the package 162 */ enforceFineLocationPermission(String pkgName, @Nullable String featureId, int uid)163 public void enforceFineLocationPermission(String pkgName, @Nullable String featureId, 164 int uid) { 165 if (!checkCallersFineLocationPermission(pkgName, featureId, uid, false)) { 166 throw new SecurityException("UID " + uid + " does not have Fine Location permission"); 167 } 168 } 169 170 /** 171 * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION 172 * and a corresponding app op is allowed for this package and uid. 173 * 174 * @param pkgName PackageName of the application requesting access 175 * @param featureId The feature in the package 176 * @param uid The uid of the package 177 * @param hideFromAppOps True to invoke {@link AppOpsManager#checkOp(int, int, String)}, false 178 * to invoke {@link AppOpsManager#noteOp(String, int, String, String, 179 * String)}. 180 */ checkCallersFineLocationPermission(String pkgName, @Nullable String featureId, int uid, boolean hideFromAppOps)181 private boolean checkCallersFineLocationPermission(String pkgName, @Nullable String featureId, 182 int uid, boolean hideFromAppOps) { 183 // Having FINE permission implies having COARSE permission (but not the reverse) 184 if (mWifiPermissionsWrapper.getUidPermission( 185 Manifest.permission.ACCESS_FINE_LOCATION, uid) 186 == PackageManager.PERMISSION_DENIED) { 187 return false; 188 } 189 if (hideFromAppOps) { 190 // Don't note the operation, just check if the app is allowed to perform the operation. 191 return checkAppOpAllowed(AppOpsManager.OPSTR_FINE_LOCATION, pkgName, uid); 192 } else { 193 return noteAppOpAllowed(AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, 194 null); 195 } 196 } 197 198 /** 199 * Checks that calling process has android.Manifest.permission.LOCATION_HARDWARE. 200 * 201 * @param uid The uid of the package 202 */ checkCallersHardwareLocationPermission(int uid)203 private boolean checkCallersHardwareLocationPermission(int uid) { 204 return mWifiPermissionsWrapper.getUidPermission(Manifest.permission.LOCATION_HARDWARE, uid) 205 == PackageManager.PERMISSION_GRANTED; 206 } 207 208 /** 209 * API to determine if the caller has permissions to get scan results. Throws SecurityException 210 * if the caller has no permission. 211 * @param pkgName package name of the application requesting access 212 * @param featureId The feature in the package 213 * @param uid The uid of the package 214 * @param message A message describing why the permission was checked. Only needed if this is 215 * not inside of a two-way binder call from the data receiver 216 */ enforceCanAccessScanResults(String pkgName, @Nullable String featureId, int uid, @Nullable String message)217 public void enforceCanAccessScanResults(String pkgName, @Nullable String featureId, int uid, 218 @Nullable String message) 219 throws SecurityException { 220 checkPackage(uid, pkgName); 221 222 // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_MANAGED_PROVISIONING, 223 // NETWORK_STACK & MAINLINE_NETWORK_STACK, RADIO_SCAN_WITHOUT_LOCATION are granted a bypass. 224 if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid) 225 || checkNetworkManagedProvisioningPermission(uid) 226 || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid) 227 || checkScanWithoutLocationPermission(uid)) { 228 return; 229 } 230 231 // Location mode must be enabled 232 if (!isLocationModeEnabled()) { 233 // Location mode is disabled, scan results cannot be returned 234 throw new SecurityException("Location mode is disabled for the device"); 235 } 236 237 // Check if the calling Uid has CAN_READ_PEER_MAC_ADDRESS permission. 238 boolean canCallingUidAccessLocation = checkCallerHasPeersMacAddressPermission(uid); 239 // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to 240 // location information. 241 boolean canAppPackageUseLocation = checkCallersLocationPermission(pkgName, featureId, 242 uid, /* coarseForTargetSdkLessThanQ */ true, message); 243 244 // If neither caller or app has location access, there is no need to check 245 // any other permissions. Deny access to scan results. 246 if (!canCallingUidAccessLocation && !canAppPackageUseLocation) { 247 throw new SecurityException("UID " + uid + " has no location permission"); 248 } 249 // Check if Wifi Scan request is an operation allowed for this App. 250 if (!isScanAllowedbyApps(pkgName, featureId, uid)) { 251 throw new SecurityException("UID " + uid + " has no wifi scan permission"); 252 } 253 // If the User or profile is current, permission is granted 254 // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission. 255 if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) { 256 throw new SecurityException("UID " + uid + " profile not permitted"); 257 } 258 } 259 260 /** 261 * API to determine if the caller has permissions to get scan results. Throws SecurityException 262 * if the caller has no permission. 263 * @param pkgName package name of the application requesting access 264 * @param featureId The feature in the package 265 * @param uid The uid of the package 266 * @param ignoreLocationSettings Whether this request can bypass location settings. 267 * @param hideFromAppOps Whether to note the request in app-ops logging or not. 268 * 269 * Note: This is to be used for checking permissions in the internal WifiScanner API surface 270 * for requests coming from system apps. 271 */ enforceCanAccessScanResultsForWifiScanner(String pkgName, @Nullable String featureId, int uid, boolean ignoreLocationSettings, boolean hideFromAppOps)272 public void enforceCanAccessScanResultsForWifiScanner(String pkgName, 273 @Nullable String featureId, int uid, boolean ignoreLocationSettings, 274 boolean hideFromAppOps) throws SecurityException { 275 checkPackage(uid, pkgName); 276 277 // Location mode must be enabled 278 if (!isLocationModeEnabled()) { 279 if (ignoreLocationSettings) { 280 mLog.w("Request from " + pkgName + " violated location settings"); 281 } else { 282 // Location mode is disabled, scan results cannot be returned 283 throw new SecurityException("Location mode is disabled for the device"); 284 } 285 } 286 // LocationAccess by App: caller must have fine & hardware Location permission to have 287 // access to location information. 288 if (!checkCallersFineLocationPermission(pkgName, featureId, uid, hideFromAppOps) 289 || !checkCallersHardwareLocationPermission(uid)) { 290 throw new SecurityException("UID " + uid + " has no location permission"); 291 } 292 // Check if Wifi Scan request is an operation allowed for this App. 293 if (!isScanAllowedbyApps(pkgName, featureId, uid)) { 294 throw new SecurityException("UID " + uid + " has no wifi scan permission"); 295 } 296 } 297 298 /** 299 * 300 * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION 301 * and a corresponding app op is allowed for this package and uid 302 * 303 * @param pkgName package name of the application requesting access 304 * @param featureId The feature in the package 305 * @param uid The uid of the package 306 * @param needLocationModeEnabled indicates location mode must be enabled. 307 * 308 * @return true if caller has permission, false otherwise 309 */ checkCanAccessWifiDirect(String pkgName, @Nullable String featureId, int uid, boolean needLocationModeEnabled)310 public boolean checkCanAccessWifiDirect(String pkgName, @Nullable String featureId, int uid, 311 boolean needLocationModeEnabled) { 312 try { 313 checkPackage(uid, pkgName); 314 } catch (SecurityException se) { 315 Log.e(TAG, "Package check exception - " + se); 316 return false; 317 } 318 319 // Apps with NETWORK_SETTINGS are granted a bypass. 320 if (checkNetworkSettingsPermission(uid)) { 321 return true; 322 } 323 324 // Location mode must be enabled if needed. 325 if (needLocationModeEnabled && !isLocationModeEnabled()) { 326 Log.e(TAG, "Location mode is disabled for the device"); 327 return false; 328 } 329 330 // LocationAccess by App: caller must have Fine Location permission to have access to 331 // location information. 332 if (!checkCallersLocationPermission(pkgName, featureId, uid, 333 /* coarseForTargetSdkLessThanQ */ false, null)) { 334 Log.e(TAG, "UID " + uid + " has no location permission"); 335 return false; 336 } 337 return true; 338 } 339 340 /** 341 * API to check to validate if a package name belongs to a UID. Throws SecurityException 342 * if pkgName does not belongs to a UID 343 * 344 * @param pkgName package name of the application requesting access 345 * @param uid The uid of the package 346 * 347 */ checkPackage(int uid, String pkgName)348 public void checkPackage(int uid, String pkgName) throws SecurityException { 349 if (pkgName == null) { 350 throw new SecurityException("Checking UID " + uid + " but Package Name is Null"); 351 } 352 mAppOps.checkPackage(uid, pkgName); 353 } 354 355 /** 356 * Returns true if the caller holds PEERS_MAC_ADDRESS permission. 357 */ checkCallerHasPeersMacAddressPermission(int uid)358 private boolean checkCallerHasPeersMacAddressPermission(int uid) { 359 return mWifiPermissionsWrapper.getUidPermission( 360 android.Manifest.permission.PEERS_MAC_ADDRESS, uid) 361 == PackageManager.PERMISSION_GRANTED; 362 } 363 364 /** 365 * Returns true if Wifi scan operation is allowed for this caller 366 * and package. 367 */ isScanAllowedbyApps(String pkgName, @Nullable String featureId, int uid)368 private boolean isScanAllowedbyApps(String pkgName, @Nullable String featureId, int uid) { 369 return noteAppOpAllowed(AppOpsManager.OPSTR_WIFI_SCAN, pkgName, featureId, uid, null); 370 } 371 372 /** 373 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL. 374 */ checkInteractAcrossUsersFull(int uid)375 private boolean checkInteractAcrossUsersFull(int uid) { 376 return mWifiPermissionsWrapper.getUidPermission( 377 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid) 378 == PackageManager.PERMISSION_GRANTED; 379 } 380 381 /** 382 * Returns true if the calling user is the current one or a profile of the 383 * current user. 384 */ isCurrentProfile(int uid)385 private boolean isCurrentProfile(int uid) { 386 UserHandle currentUser = UserHandle.of(mWifiPermissionsWrapper.getCurrentUser()); 387 UserHandle callingUser = UserHandle.getUserHandleForUid(uid); 388 return currentUser.equals(callingUser) 389 || mUserManager.isSameProfileGroup(currentUser, callingUser); 390 } 391 noteAppOpAllowed(String op, String pkgName, @Nullable String featureId, int uid, @Nullable String message)392 private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId, 393 int uid, @Nullable String message) { 394 return mAppOps.noteOp(op, uid, pkgName, featureId, message) == AppOpsManager.MODE_ALLOWED; 395 } 396 checkAppOpAllowed(String op, String pkgName, int uid)397 private boolean checkAppOpAllowed(String op, String pkgName, int uid) { 398 return mAppOps.unsafeCheckOp(op, uid, pkgName) == AppOpsManager.MODE_ALLOWED; 399 } 400 retrieveLocationManagerIfNecessary()401 private boolean retrieveLocationManagerIfNecessary() { 402 // This is going to be accessed by multiple threads. 403 synchronized (mLock) { 404 if (mLocationManager == null) { 405 mLocationManager = 406 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 407 } 408 } 409 return mLocationManager != null; 410 } 411 412 /** 413 * Retrieves a handle to LocationManager (if not already done) and check if location is enabled. 414 */ isLocationModeEnabled()415 public boolean isLocationModeEnabled() { 416 if (!retrieveLocationManagerIfNecessary()) return false; 417 try { 418 return mLocationManager.isLocationEnabledForUser(UserHandle.of( 419 mWifiPermissionsWrapper.getCurrentUser())); 420 } catch (Exception e) { 421 Log.e(TAG, "Failure to get location mode via API, falling back to settings", e); 422 return mFrameworkFacade.getIntegerSetting( 423 mContext, Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 424 == Settings.Secure.LOCATION_MODE_ON; 425 } 426 } 427 428 /** 429 * Returns true if the |uid| holds NETWORK_SETTINGS permission. 430 */ checkNetworkSettingsPermission(int uid)431 public boolean checkNetworkSettingsPermission(int uid) { 432 return mWifiPermissionsWrapper.getUidPermission( 433 android.Manifest.permission.NETWORK_SETTINGS, uid) 434 == PackageManager.PERMISSION_GRANTED; 435 } 436 437 /** 438 * Returns true if the |uid| holds RADIO_SCAN_WITHOUT_LOCATION permission. 439 */ checkScanWithoutLocationPermission(int uid)440 public boolean checkScanWithoutLocationPermission(int uid) { 441 return mWifiPermissionsWrapper.getUidPermission( 442 android.Manifest.permission.RADIO_SCAN_WITHOUT_LOCATION, uid) 443 == PackageManager.PERMISSION_GRANTED; 444 } 445 446 /** 447 * Returns true if the |uid| holds LOCAL_MAC_ADDRESS permission. 448 */ checkLocalMacAddressPermission(int uid)449 public boolean checkLocalMacAddressPermission(int uid) { 450 return mWifiPermissionsWrapper.getUidPermission( 451 android.Manifest.permission.LOCAL_MAC_ADDRESS, uid) 452 == PackageManager.PERMISSION_GRANTED; 453 } 454 455 /** 456 * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission. 457 */ checkNetworkSetupWizardPermission(int uid)458 public boolean checkNetworkSetupWizardPermission(int uid) { 459 return mWifiPermissionsWrapper.getUidPermission( 460 android.Manifest.permission.NETWORK_SETUP_WIZARD, uid) 461 == PackageManager.PERMISSION_GRANTED; 462 } 463 464 /** 465 * Returns true if the |uid| holds NETWORK_STACK permission. 466 */ checkNetworkStackPermission(int uid)467 public boolean checkNetworkStackPermission(int uid) { 468 return mWifiPermissionsWrapper.getUidPermission( 469 android.Manifest.permission.NETWORK_STACK, uid) 470 == PackageManager.PERMISSION_GRANTED; 471 } 472 473 /** 474 * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission. 475 */ checkMainlineNetworkStackPermission(int uid)476 public boolean checkMainlineNetworkStackPermission(int uid) { 477 return mWifiPermissionsWrapper.getUidPermission( 478 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid) 479 == PackageManager.PERMISSION_GRANTED; 480 } 481 482 /** 483 * Returns true if the |uid| holds NETWORK_MANAGED_PROVISIONING permission. 484 */ checkNetworkManagedProvisioningPermission(int uid)485 public boolean checkNetworkManagedProvisioningPermission(int uid) { 486 return mWifiPermissionsWrapper.getUidPermission( 487 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, uid) 488 == PackageManager.PERMISSION_GRANTED; 489 } 490 491 /** 492 * Returns true if the |uid| holds NETWORK_CARRIER_PROVISIONING permission. 493 */ checkNetworkCarrierProvisioningPermission(int uid)494 public boolean checkNetworkCarrierProvisioningPermission(int uid) { 495 return mWifiPermissionsWrapper.getUidPermission( 496 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING, uid) 497 == PackageManager.PERMISSION_GRANTED; 498 } 499 500 /** 501 * Returns true if the |uid| holds READ_WIFI_CREDENTIAL permission. 502 */ checkReadWifiCredentialPermission(int uid)503 public boolean checkReadWifiCredentialPermission(int uid) { 504 return mWifiPermissionsWrapper.getUidPermission( 505 android.Manifest.permission.READ_WIFI_CREDENTIAL, uid) 506 == PackageManager.PERMISSION_GRANTED; 507 } 508 509 /** 510 * Returns true if the |callingUid|/\callingPackage| holds SYSTEM_ALERT_WINDOW permission. 511 */ checkSystemAlertWindowPermission(int callingUid, String callingPackage)512 public boolean checkSystemAlertWindowPermission(int callingUid, String callingPackage) { 513 final int mode = mAppOps.noteOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, callingUid, 514 callingPackage, null, null); 515 if (mode == AppOpsManager.MODE_DEFAULT) { 516 return mWifiPermissionsWrapper.getUidPermission( 517 Manifest.permission.SYSTEM_ALERT_WINDOW, callingUid) 518 == PackageManager.PERMISSION_GRANTED; 519 } 520 return mode == AppOpsManager.MODE_ALLOWED; 521 } 522 retrieveDevicePolicyManagerFromContext(Context context)523 private static DevicePolicyManager retrieveDevicePolicyManagerFromContext(Context context) { 524 DevicePolicyManager devicePolicyManager = 525 context.getSystemService(DevicePolicyManager.class); 526 if (devicePolicyManager == null 527 && context.getPackageManager().hasSystemFeature( 528 PackageManager.FEATURE_DEVICE_ADMIN)) { 529 Log.w(TAG, "Error retrieving DPM service"); 530 } 531 return devicePolicyManager; 532 } 533 retrieveDevicePolicyManagerFromUserContext(int uid)534 private DevicePolicyManager retrieveDevicePolicyManagerFromUserContext(int uid) { 535 Context userContext = null; 536 try { 537 userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, 538 UserHandle.getUserHandleForUid(uid)); 539 } catch (PackageManager.NameNotFoundException e) { 540 Log.e(TAG, "Unknown package name"); 541 return null; 542 } 543 if (userContext == null) { 544 Log.e(TAG, "Unable to retrieve user context for " + uid); 545 return null; 546 } 547 return retrieveDevicePolicyManagerFromContext(userContext); 548 } 549 550 /** 551 * Returns true if the |callingUid|/\callingPackage| is the device owner. 552 */ isDeviceOwner(int uid, @Nullable String packageName)553 public boolean isDeviceOwner(int uid, @Nullable String packageName) { 554 // Cannot determine if the app is DO/PO if packageName is null. So, will return false to be 555 // safe. 556 if (packageName == null) { 557 Log.e(TAG, "isDeviceOwner: packageName is null, returning false"); 558 return false; 559 } 560 DevicePolicyManager devicePolicyManager = 561 retrieveDevicePolicyManagerFromContext(mContext); 562 if (devicePolicyManager == null) return false; 563 long ident = Binder.clearCallingIdentity(); 564 UserHandle deviceOwnerUser = null; 565 ComponentName deviceOwnerComponent = null; 566 try { 567 deviceOwnerUser = devicePolicyManager.getDeviceOwnerUser(); 568 deviceOwnerComponent = devicePolicyManager.getDeviceOwnerComponentOnAnyUser(); 569 } finally { 570 Binder.restoreCallingIdentity(ident); 571 } 572 // no device owner 573 if (deviceOwnerUser == null || deviceOwnerComponent == null) return false; 574 return deviceOwnerUser.equals(UserHandle.getUserHandleForUid(uid)) 575 && deviceOwnerComponent.getPackageName().equals(packageName); 576 } 577 578 /** 579 * Returns true if the |callingUid|/\callingPackage| is the profile owner. 580 */ isProfileOwner(int uid, @Nullable String packageName)581 public boolean isProfileOwner(int uid, @Nullable String packageName) { 582 // Cannot determine if the app is DO/PO if packageName is null. So, will return false to be 583 // safe. 584 if (packageName == null) { 585 Log.e(TAG, "isProfileOwner: packageName is null, returning false"); 586 return false; 587 } 588 DevicePolicyManager devicePolicyManager = 589 retrieveDevicePolicyManagerFromUserContext(uid); 590 if (devicePolicyManager == null) return false; 591 return devicePolicyManager.isProfileOwnerApp(packageName); 592 } 593 594 /** 595 * Check if the given UID belongs to the current foreground user. This is 596 * used to prevent apps running in background users from modifying network 597 * configurations. 598 * <p> 599 * UIDs belonging to system internals (such as SystemUI) are always allowed, 600 * since they always run as {@link UserHandle#USER_SYSTEM}. 601 * 602 * @param uid uid of the app. 603 * @return true if the given UID belongs to the current foreground user, 604 * otherwise false. 605 */ doesUidBelongToCurrentUser(int uid)606 public boolean doesUidBelongToCurrentUser(int uid) { 607 if (uid == android.os.Process.SYSTEM_UID 608 // UIDs with the NETWORK_SETTINGS permission are always allowed since they are 609 // acting on behalf of the user. 610 || checkNetworkSettingsPermission(uid)) { 611 return true; 612 } 613 boolean isCurrentProfile = isCurrentProfile(uid); 614 if (!isCurrentProfile) { 615 // Fix for b/174749461 616 EventLog.writeEvent(0x534e4554, "174749461", -1, 617 "Non foreground user trying to modify wifi configuration"); 618 } 619 return isCurrentProfile; 620 } 621 } 622