• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 package com.android.internal.telephony;
17 
18 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
19 
20 import android.Manifest;
21 import android.annotation.Nullable;
22 import android.app.AppOpsManager;
23 import android.content.Context;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.PackageManager;
26 import android.os.Binder;
27 import android.os.Build;
28 import android.os.Process;
29 import android.os.UserHandle;
30 import android.permission.LegacyPermissionManager;
31 import android.telephony.SubscriptionManager;
32 import android.telephony.TelephonyManager;
33 import android.util.Log;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.Map;
40 import java.util.Set;
41 
42 /** Utility class for Telephony permission enforcement. */
43 public final class TelephonyPermissions {
44     private static final String LOG_TAG = "TelephonyPermissions";
45 
46     private static final boolean DBG = false;
47 
48     /**
49      * Whether to disable the new device identifier access restrictions.
50      */
51     private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED =
52             "device_identifier_access_restrictions_disabled";
53 
54     // Contains a mapping of packages that did not meet the new requirements to access device
55     // identifiers and the methods they were attempting to invoke; used to prevent duplicate
56     // reporting of packages / methods.
57     private static final Map<String, Set<String>> sReportedDeviceIDPackages;
58     static {
59         sReportedDeviceIDPackages = new HashMap<>();
60     }
61 
TelephonyPermissions()62     private TelephonyPermissions() {}
63 
64     /**
65      * Check whether the caller (or self, if not processing an IPC) can read phone state.
66      *
67      * <p>This method behaves in one of the following ways:
68      * <ul>
69      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
70      *       READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
71      *   <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
72      *       apps which support runtime permissions, if the caller does not currently have any of
73      *       these permissions.
74      *   <li>return false: if the caller lacks all of these permissions and doesn't support runtime
75      *       permissions. This implies that the user revoked the ability to read phone state
76      *       manually (via AppOps). In this case we can't throw as it would break app compatibility,
77      *       so we return false to indicate that the calling function should return placeholder
78      *       data.
79      * </ul>
80      *
81      * <p>Note: for simplicity, this method always returns false for callers using legacy
82      * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
83      * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
84      * devices.
85      *
86      * @param subId the subId of the relevant subscription; used to check carrier privileges. May be
87      *              {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases
88      *              where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave
89      *              inaccesible to carrier-privileged apps).
90      */
checkCallingOrSelfReadPhoneState( Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message)91     public static boolean checkCallingOrSelfReadPhoneState(
92             Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
93             String message) {
94         return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
95                 callingPackage, callingFeatureId, message);
96     }
97 
98     /** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
checkCallingOrSelfReadPhoneStateNoThrow( Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message)99     public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
100             Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
101             String message) {
102         try {
103             return checkCallingOrSelfReadPhoneState(context, subId, callingPackage,
104                     callingFeatureId, message);
105         } catch (SecurityException se) {
106             return false;
107         }
108     }
109 
110     /**
111      * Check whether the app with the given pid/uid can read phone state.
112      *
113      * <p>This method behaves in one of the following ways:
114      * <ul>
115      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
116      *       READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
117      *   <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
118      *       apps which support runtime permissions, if the caller does not currently have any of
119      *       these permissions.
120      *   <li>return false: if the caller lacks all of these permissions and doesn't support runtime
121      *       permissions. This implies that the user revoked the ability to read phone state
122      *       manually (via AppOps). In this case we can't throw as it would break app compatibility,
123      *       so we return false to indicate that the calling function should return placeholder
124      *       data.
125      * </ul>
126      *
127      * <p>Note: for simplicity, this method always returns false for callers using legacy
128      * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
129      * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
130      * devices.
131      */
checkReadPhoneState( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message)132     public static boolean checkReadPhoneState(
133             Context context, int subId, int pid, int uid, String callingPackage,
134             @Nullable  String callingFeatureId, String message) {
135         try {
136             context.enforcePermission(
137                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
138 
139             // SKIP checking for run-time permission since caller has PRIVILEGED permission
140             return true;
141         } catch (SecurityException privilegedPhoneStateException) {
142             try {
143                 context.enforcePermission(
144                         android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
145             } catch (SecurityException phoneStateException) {
146                 // If we don't have the runtime permission, but do have carrier privileges, that
147                 // suffices for reading phone state.
148                 if (SubscriptionManager.isValidSubscriptionId(subId)) {
149                     enforceCarrierPrivilege(context, subId, uid, message);
150                     return true;
151                 }
152                 throw phoneStateException;
153             }
154         }
155 
156         // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
157         // revoked.
158         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
159         return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage,
160                 callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
161     }
162 
163     /**
164      * Check whether the calling packages has carrier privileges for the passing subscription.
165      * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
166      */
checkCarrierPrivilegeForSubId(Context context, int subId)167     public static boolean checkCarrierPrivilegeForSubId(Context context, int subId) {
168         if (SubscriptionManager.isValidSubscriptionId(subId)
169                 && getCarrierPrivilegeStatus(context, subId, Binder.getCallingUid())
170                 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
171             return true;
172         }
173         return false;
174     }
175 
176     /**
177      * Check whether the app with the given pid/uid can read phone state, or has carrier
178      * privileges on any active subscription.
179      *
180      * <p>If the app does not have carrier privilege, this method will return {@code false} instead
181      * of throwing a SecurityException. Therefore, the callers cannot tell the difference
182      * between M+ apps which declare the runtime permission but do not have it, and pre-M apps
183      * which declare the static permission but had access revoked via AppOps. Apps in the former
184      * category expect SecurityExceptions; apps in the latter don't. So this method is suitable for
185      * use only if the behavior in both scenarios is meant to be identical.
186      *
187      * @return {@code true} if the app can read phone state or has carrier privilege;
188      *         {@code false} otherwise.
189      */
checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message)190     public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid,
191             String callingPackage, @Nullable String callingFeatureId, String message) {
192         try {
193             context.enforcePermission(
194                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
195 
196             // SKIP checking for run-time permission since caller has PRIVILEGED permission
197             return true;
198         } catch (SecurityException privilegedPhoneStateException) {
199             try {
200                 context.enforcePermission(
201                         android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
202             } catch (SecurityException phoneStateException) {
203                 // If we don't have the runtime permission, but do have carrier privileges, that
204                 // suffices for reading phone state.
205                 return checkCarrierPrivilegeForAnySubId(context, uid);
206             }
207         }
208 
209         // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
210         // revoked.
211         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
212         return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage,
213                 callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
214     }
215 
216     /**
217      * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
218      *
219      * <p>This method behaves in one of the following ways:
220      * <ul>
221      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
222      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
223      *       access check, or the calling package has carrier privileges on any active subscription.
224     *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
225      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
226      *       or carrier privileges of any active subscription.
227      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
228      *       permission. In this case the caller would expect to have access to the device
229      *       identifiers so false is returned instead of throwing a SecurityException to indicate
230      *       the calling function should return placeholder data.
231      * </ul>
232      */
checkCallingOrSelfReadDeviceIdentifiers(Context context, String callingPackage, @Nullable String callingFeatureId, String message)233     public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
234             String callingPackage, @Nullable String callingFeatureId, String message) {
235         return checkCallingOrSelfReadDeviceIdentifiers(context,
236                 SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, callingFeatureId,
237                 message);
238     }
239 
240     /**
241      * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
242      *
243      * <p>This method behaves in one of the following ways:
244      * <ul>
245      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
246      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
247      *       access check, or the calling package has carrier privileges on any active
248      *       subscription, or the calling package has the {@link
249      *       Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
250      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
251      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
252      *       or carrier privileges of any active subscription.
253      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
254      *       permission or carrier privileges. In this case the caller would expect to have access
255      *       to the device identifiers so false is returned instead of throwing a SecurityException
256      *       to indicate the calling function should return placeholder data.
257      * </ul>
258      */
checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message)259     public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
260             String callingPackage, @Nullable String callingFeatureId, String message) {
261         if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
262                 callingFeatureId, message)) {
263             return true;
264         }
265         return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
266                 context, subId, callingPackage, callingFeatureId, message, true, true);
267     }
268 
269     /**
270      * Check whether the caller (or self, if not processing an IPC) can read subscriber identifiers.
271      *
272      * <p>This method behaves in one of the following ways:
273      * <ul>
274      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
275      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
276      *       access check, or the calling package has carrier privileges on specified subscription,
277      *       or the calling package has the {@link
278      *       Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission.
279      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
280      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
281      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
282      *       permission. In this case the caller would expect to have access to the device
283      *       identifiers so false is returned instead of throwing a SecurityException to indicate
284      *       the calling function should return placeholder data.
285      * </ul>
286      */
checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message)287     public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
288             String callingPackage, @Nullable String callingFeatureId, String message) {
289         return checkCallingOrSelfReadSubscriberIdentifiers(context, subId, callingPackage,
290                 callingFeatureId, message, true);
291     }
292 
293     /**
294      * Same as {@link #checkCallingOrSelfReadSubscriberIdentifiers(Context, int, String, String,
295      * String)} except this allows an additional parameter reportFailure. Caller may not want to
296      * report a failure when this is an internal/intermediate check, for example,
297      * SubscriptionController calls this with an INVALID_SUBID to check if caller has the required
298      * permissions to bypass carrier privilege checks.
299      * @param reportFailure Indicates if failure should be reported.
300      */
checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message, boolean reportFailure)301     public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
302             String callingPackage, @Nullable String callingFeatureId, String message,
303             boolean reportFailure) {
304         if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage,
305                 callingFeatureId, message)) {
306             return true;
307         }
308         return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
309                 context, subId, callingPackage, callingFeatureId, message, false, reportFailure);
310     }
311     /**
312      * Checks whether the app with the given pid/uid can read device identifiers.
313      *
314      * <p>This method behaves in one of the following ways:
315      * <ul>
316      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
317      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
318      *       access check; or the calling package has carrier privileges on the specified
319      *       subscription; or allowCarrierPrivilegeOnAnySub is true and has carrier privilege on
320      *       any active subscription.
321      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
322      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
323      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
324      *       permission. In this case the caller would expect to have access to the device
325      *       identifiers so false is returned instead of throwing a SecurityException to indicate
326      *       the calling function should return placeholder data.
327      * </ul>
328      */
checkPrivilegedReadPermissionOrCarrierPrivilegePermission( Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message, boolean allowCarrierPrivilegeOnAnySub, boolean reportFailure)329     private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
330             Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
331             String message, boolean allowCarrierPrivilegeOnAnySub, boolean reportFailure) {
332         int uid = Binder.getCallingUid();
333         int pid = Binder.getCallingPid();
334 
335         // If the calling package has carrier privileges for specified sub, then allow access.
336         if (checkCarrierPrivilegeForSubId(context, subId)) return true;
337 
338         // If the calling package has carrier privileges for any subscription
339         // and allowCarrierPrivilegeOnAnySub is set true, then allow access.
340         if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) {
341             return true;
342         }
343 
344         LegacyPermissionManager permissionManager = (LegacyPermissionManager)
345                 context.getSystemService(Context.LEGACY_PERMISSION_SERVICE);
346         if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
347                 pid, uid) == PackageManager.PERMISSION_GRANTED) {
348             return true;
349         }
350 
351         if (reportFailure) {
352             return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
353                     message);
354         } else {
355             return false;
356         }
357     }
358 
359     /**
360      * Reports a failure when the app with the given pid/uid cannot access the requested identifier.
361      *
362      * @returns false if the caller is targeting pre-Q and does have the READ_PHONE_STATE
363      * permission or carrier privileges.
364      * @throws SecurityException if the caller does not meet any of the requirements for the
365      *                           requested identifier and is targeting Q or is targeting pre-Q
366      *                           and does not have the READ_PHONE_STATE permission or carrier
367      *                           privileges.
368      */
reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid, int uid, String callingPackage, String message)369     private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
370             int uid, String callingPackage, String message) {
371         ApplicationInfo callingPackageInfo = null;
372         try {
373             callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser(
374                     callingPackage, 0, UserHandle.getUserHandleForUid(uid));
375         } catch (PackageManager.NameNotFoundException e) {
376             // If the application info for the calling package could not be found then assume the
377             // calling app is a non-preinstalled app to detect any issues with the check
378             Log.e(LOG_TAG, "Exception caught obtaining package info for package " + callingPackage,
379                     e);
380         }
381         // The current package should only be reported in StatsLog if it has not previously been
382         // reported for the currently invoked device identifier method.
383         boolean packageReported = sReportedDeviceIDPackages.containsKey(callingPackage);
384         if (!packageReported || !sReportedDeviceIDPackages.get(callingPackage).contains(
385                 message)) {
386             Set invokedMethods;
387             if (!packageReported) {
388                 invokedMethods = new HashSet<String>();
389                 sReportedDeviceIDPackages.put(callingPackage, invokedMethods);
390             } else {
391                 invokedMethods = sReportedDeviceIDPackages.get(callingPackage);
392             }
393             invokedMethods.add(message);
394             TelephonyCommonStatsLog.write(TelephonyCommonStatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED,
395                     callingPackage, message, /* isPreinstalled= */ false, false);
396         }
397         Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message + ":"
398                 + subId);
399         // if the target SDK is pre-Q then check if the calling package would have previously
400         // had access to device identifiers.
401         if (callingPackageInfo != null && (
402                 callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q)) {
403             if (context.checkPermission(
404                     android.Manifest.permission.READ_PHONE_STATE,
405                     pid,
406                     uid) == PackageManager.PERMISSION_GRANTED) {
407                 return false;
408             }
409             if (checkCarrierPrivilegeForSubId(context, subId)) {
410                 return false;
411             }
412         }
413         throw new SecurityException(message + ": The user " + uid
414                 + " does not meet the requirements to access device identifiers.");
415     }
416 
417     /**
418      * Check whether the caller (or self, if not processing an IPC) has {@link
419      * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} AppOp permission.
420      *
421      * <p>With the permission, the caller can access device/subscriber identifiers and use ICC
422      * authentication like EAP-AKA.
423      */
checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context, String callingPackage, String callingFeatureId, String message)424     public static boolean checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context,
425             String callingPackage, String callingFeatureId, String message) {
426         // The implementation follows PermissionChecker.checkAppOpPermission, but it cannot be
427         // used directly: because it uses noteProxyOpNoThrow which requires the phone process
428         // having the permission, which doesn't make sense since phone process is the ower of
429         // data/action.
430         // Cannot perform appop check if the calling package is null
431         if (callingPackage == null) {
432             return false;
433         }
434         int callingUid = Binder.getCallingUid();
435         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
436         int opMode = appOps.noteOpNoThrow(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
437                 callingUid, callingPackage, callingFeatureId, message);
438         switch (opMode) {
439             case AppOpsManager.MODE_ALLOWED:
440             case AppOpsManager.MODE_FOREGROUND:
441                 return true;
442             case AppOpsManager.MODE_DEFAULT:
443                 return context.checkCallingOrSelfPermission(
444                             Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER)
445                         == PERMISSION_GRANTED;
446             default:
447                 return false;
448         }
449     }
450 
451     /**
452      * Check whether the app with the given pid/uid can read the call log.
453      * @return {@code true} if the specified app has the read call log permission and AppOpp granted
454      *      to it, {@code false} otherwise.
455      */
checkReadCallLog( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingPackageName)456     public static boolean checkReadCallLog(
457             Context context, int subId, int pid, int uid, String callingPackage,
458             @Nullable String callingPackageName) {
459         if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
460                 != PERMISSION_GRANTED) {
461             // If we don't have the runtime permission, but do have carrier privileges, that
462             // suffices for being able to see the call phone numbers.
463             if (SubscriptionManager.isValidSubscriptionId(subId)) {
464                 enforceCarrierPrivilege(context, subId, uid, "readCallLog");
465                 return true;
466             }
467             return false;
468         }
469 
470         // We have READ_CALL_LOG permission, so return true as long as the AppOps bit hasn't been
471         // revoked.
472         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
473         return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage,
474                 callingPackageName, null) == AppOpsManager.MODE_ALLOWED;
475     }
476 
477     /**
478      * Returns whether the caller can read phone numbers.
479      *
480      * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}
481      * (only prior to R), the default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS
482      * can also read phone numbers.
483      */
checkCallingOrSelfReadPhoneNumber( Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message)484     public static boolean checkCallingOrSelfReadPhoneNumber(
485             Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
486             String message) {
487         return checkReadPhoneNumber(
488                 context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
489                 callingPackage, callingFeatureId, message);
490     }
491 
492     /**
493      * Returns whether the caller can read phone numbers.
494      *
495      * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}
496      * (only prior to R), the default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS
497      * can also read phone numbers.
498      */
499     @VisibleForTesting
checkReadPhoneNumber( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message)500     public static boolean checkReadPhoneNumber(
501             Context context, int subId, int pid, int uid,
502             String callingPackage, @Nullable String callingFeatureId, String message) {
503         LegacyPermissionManager permissionManager = (LegacyPermissionManager)
504                 context.getSystemService(Context.LEGACY_PERMISSION_SERVICE);
505         // Apps with target SDK version < R can have the READ_PHONE_STATE permission granted with
506         // the appop denied. If PERMISSION_GRANTED is not received then check if the caller has
507         // carrier privileges; if not and the permission result is MODE_IGNORED then return false
508         // to return null data to the caller.
509         int permissionResult = permissionManager.checkPhoneNumberAccess(callingPackage, message,
510                 callingFeatureId, pid, uid);
511         if (permissionResult == PackageManager.PERMISSION_GRANTED) {
512             return true;
513         }
514         if (SubscriptionManager.isValidSubscriptionId(subId)) {
515             if (TelephonyPermissions.getCarrierPrivilegeStatus(context, subId, uid)
516                     == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
517                 return true;
518             }
519         }
520         if (permissionResult == AppOpsManager.MODE_IGNORED) {
521             return false;
522         }
523 
524         throw new SecurityException(message + ": Neither user " + uid
525                 + " nor current process has " + android.Manifest.permission.READ_PHONE_STATE
526                 + ", " + android.Manifest.permission.READ_SMS + ", or "
527                 + android.Manifest.permission.READ_PHONE_NUMBERS);
528     }
529 
530     /**
531      * Ensure the caller (or self, if not processing an IPC) has MODIFY_PHONE_STATE (and is thus a
532      * privileged app) or carrier privileges.
533      *
534      * @throws SecurityException if the caller does not have the required permission/privileges
535      */
enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( Context context, int subId, String message)536     public static void enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
537             Context context, int subId, String message) {
538         if (context.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
539                 == PERMISSION_GRANTED) {
540             return;
541         }
542 
543         if (DBG) Log.d(LOG_TAG, "No modify permission, check carrier privilege next.");
544         enforceCallingOrSelfCarrierPrivilege(context, subId, message);
545     }
546 
547     /**
548      * Ensure the caller (or self, if not processing an IPC) has
549      * {@link android.Manifest.permission#READ_PHONE_STATE} or carrier privileges.
550      *
551      * @throws SecurityException if the caller does not have the required permission/privileges
552      */
enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege( Context context, int subId, String message)553     public static void enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
554             Context context, int subId, String message) {
555         if (context.checkCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE)
556                 == PERMISSION_GRANTED) {
557             return;
558         }
559 
560         if (DBG) {
561             Log.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next.");
562         }
563 
564         enforceCallingOrSelfCarrierPrivilege(context, subId, message);
565     }
566 
567     /**
568      * Ensure the caller (or self, if not processing an IPC) has
569      * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or carrier privileges.
570      *
571      * @throws SecurityException if the caller does not have the required permission/privileges
572      */
enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( Context context, int subId, String message)573     public static void enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
574             Context context, int subId, String message) {
575         if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
576                 == PERMISSION_GRANTED) {
577             return;
578         }
579 
580         if (DBG) {
581             Log.d(LOG_TAG, "No READ_PRIVILEGED_PHONE_STATE permission, "
582                     + "check carrier privilege next.");
583         }
584 
585         enforceCallingOrSelfCarrierPrivilege(context, subId, message);
586     }
587 
588     /**
589      * Ensure the caller (or self, if not processing an IPC) has
590      * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
591      * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or carrier privileges.
592      *
593      * @throws SecurityException if the caller does not have the required permission/privileges
594      */
enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege( Context context, int subId, String message)595     public static void enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
596             Context context, int subId, String message) {
597         if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
598                 == PERMISSION_GRANTED) {
599             return;
600         }
601 
602         if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
603                 == PERMISSION_GRANTED) {
604             return;
605         }
606 
607         if (DBG) {
608             Log.d(LOG_TAG, "No READ_PRIVILEGED_PHONE_STATE nor READ_PRECISE_PHONE_STATE permission"
609                     + ", check carrier privilege next.");
610         }
611 
612         enforceCallingOrSelfCarrierPrivilege(context, subId, message);
613     }
614 
615     /**
616      * Make sure the caller (or self, if not processing an IPC) has carrier privileges.
617      *
618      * @throws SecurityException if the caller does not have the required privileges
619      */
enforceCallingOrSelfCarrierPrivilege( Context context, int subId, String message)620     public static void enforceCallingOrSelfCarrierPrivilege(
621             Context context, int subId, String message) {
622         // NOTE: It's critical that we explicitly pass the calling UID here rather than call
623         // TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from
624         // the phone process. When called from another process, it will check whether that process
625         // has carrier privileges instead.
626         enforceCarrierPrivilege(context, subId, Binder.getCallingUid(), message);
627     }
628 
enforceCarrierPrivilege( Context context, int subId, int uid, String message)629     private static void enforceCarrierPrivilege(
630             Context context, int subId, int uid, String message) {
631         if (getCarrierPrivilegeStatus(context, subId, uid)
632                 != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
633             if (DBG) Log.e(LOG_TAG, "No Carrier Privilege.");
634             throw new SecurityException(message);
635         }
636     }
637 
638     /** Returns whether the provided uid has carrier privileges for any active subscription ID. */
checkCarrierPrivilegeForAnySubId(Context context, int uid)639     private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) {
640         SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
641                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
642         int[] activeSubIds = sm.getCompleteActiveSubscriptionIdList();
643         for (int activeSubId : activeSubIds) {
644             if (getCarrierPrivilegeStatus(context, activeSubId, uid)
645                     == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
646                 return true;
647             }
648         }
649         return false;
650     }
651 
getCarrierPrivilegeStatus(Context context, int subId, int uid)652     private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) {
653         if (uid == Process.SYSTEM_UID || uid == Process.PHONE_UID) {
654             // Skip the check if it's one of these special uids
655             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
656         }
657         final long identity = Binder.clearCallingIdentity();
658         try {
659             TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
660                 Context.TELEPHONY_SERVICE);
661             return telephonyManager.createForSubscriptionId(subId).getCarrierPrivilegeStatus(uid);
662         } finally {
663             Binder.restoreCallingIdentity(identity);
664         }
665     }
666 
667     /**
668      * Given a list of permissions, check to see if the caller has at least one of them. If the
669      * caller has none of these permissions, throw a SecurityException.
670      */
enforceAnyPermissionGranted(Context context, int uid, String message, String... permissions)671     public static void enforceAnyPermissionGranted(Context context, int uid, String message,
672             String... permissions) {
673         if (permissions.length == 0) return;
674         boolean isGranted = false;
675         for (String perm : permissions) {
676             if (context.checkCallingOrSelfPermission(perm) == PERMISSION_GRANTED) {
677                 isGranted = true;
678                 break;
679             }
680         }
681 
682         if (isGranted) return;
683 
684         StringBuilder b = new StringBuilder(message);
685         b.append(": Neither user ");
686         b.append(uid);
687         b.append(" nor current process has ");
688         b.append(permissions[0]);
689         for (int i = 1; i < permissions.length; i++) {
690             b.append(" or ");
691             b.append(permissions[i]);
692         }
693         throw new SecurityException(b.toString());
694     }
695 
696     /**
697      * Given a list of permissions, check to see if the caller has at least one of them granted. If
698      * not, check to see if the caller has carrier privileges. If the caller does not have any  of
699      * these permissions, throw a SecurityException.
700      */
enforceAnyPermissionGrantedOrCarrierPrivileges(Context context, int subId, int uid, String message, String... permissions)701     public static void enforceAnyPermissionGrantedOrCarrierPrivileges(Context context, int subId,
702             int uid, String message, String... permissions) {
703         if (permissions.length == 0) return;
704         boolean isGranted = false;
705         for (String perm : permissions) {
706             if (context.checkCallingOrSelfPermission(perm) == PERMISSION_GRANTED) {
707                 isGranted = true;
708                 break;
709             }
710         }
711 
712         if (isGranted) return;
713         if (checkCarrierPrivilegeForSubId(context, subId)) return;
714 
715         StringBuilder b = new StringBuilder(message);
716         b.append(": Neither user ");
717         b.append(uid);
718         b.append(" nor current process has ");
719         b.append(permissions[0]);
720         for (int i = 1; i < permissions.length; i++) {
721             b.append(" or ");
722             b.append(permissions[i]);
723         }
724         b.append(" or carrier privileges");
725         throw new SecurityException(b.toString());
726     }
727 
728     /**
729      * Throws if the caller is not of a shell (or root) UID.
730      *
731      * @param callingUid pass Binder.callingUid().
732      */
enforceShellOnly(int callingUid, String message)733     public static void enforceShellOnly(int callingUid, String message) {
734         if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
735             return; // okay
736         }
737 
738         throw new SecurityException(message + ": Only shell user can call it");
739     }
740 
741     /**
742      * Returns the target SDK version number for a given package name.
743      *
744      * This call MUST be invoked before clearing the calling UID.
745      *
746      * @return target SDK if the package is found or INT_MAX.
747      */
getTargetSdk(Context c, String packageName)748     public static int getTargetSdk(Context c, String packageName) {
749         try {
750             final ApplicationInfo ai = c.getPackageManager().getApplicationInfoAsUser(
751                     packageName, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
752             if (ai != null) return ai.targetSdkVersion;
753         } catch (PackageManager.NameNotFoundException unexpected) {
754             Log.e(LOG_TAG, "Failed to get package info for pkg="
755                     + packageName + ", uid=" + Binder.getCallingUid());
756         }
757         return Integer.MAX_VALUE;
758     }
759 }
760