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.app.AppOpsManager; 22 import android.content.Context; 23 import android.content.pm.PackageManager; 24 import android.os.Binder; 25 import android.os.RemoteException; 26 import android.os.ServiceManager; 27 import android.telephony.Rlog; 28 import android.telephony.SubscriptionManager; 29 import android.telephony.TelephonyManager; 30 31 import com.android.internal.annotations.VisibleForTesting; 32 33 import java.util.function.Supplier; 34 35 /** Utility class for Telephony permission enforcement. */ 36 public final class TelephonyPermissions { 37 private static final String LOG_TAG = "TelephonyPermissions"; 38 39 private static final boolean DBG = false; 40 41 private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () -> 42 ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); 43 44 private TelephonyPermissions() {} 45 46 /** 47 * Check whether the caller (or self, if not processing an IPC) can read phone state. 48 * 49 * <p>This method behaves in one of the following ways: 50 * <ul> 51 * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the 52 * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId. 53 * <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for 54 * apps which support runtime permissions, if the caller does not currently have any of 55 * these permissions. 56 * <li>return false: if the caller lacks all of these permissions and doesn't support runtime 57 * permissions. This implies that the user revoked the ability to read phone state 58 * manually (via AppOps). In this case we can't throw as it would break app compatibility, 59 * so we return false to indicate that the calling function should return dummy data. 60 * </ul> 61 * 62 * <p>Note: for simplicity, this method always returns false for callers using legacy 63 * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged. 64 * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+ 65 * devices. 66 * 67 * @param subId the subId of the relevant subscription; used to check carrier privileges. May be 68 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases 69 * where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave 70 * inaccesible to carrier-privileged apps). 71 */ 72 public static boolean checkCallingOrSelfReadPhoneState( 73 Context context, int subId, String callingPackage, String message) { 74 return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(), 75 callingPackage, message); 76 } 77 78 /** 79 * Check whether the app with the given pid/uid can read phone state. 80 * 81 * <p>This method behaves in one of the following ways: 82 * <ul> 83 * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the 84 * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId. 85 * <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for 86 * apps which support runtime permissions, if the caller does not currently have any of 87 * these permissions. 88 * <li>return false: if the caller lacks all of these permissions and doesn't support runtime 89 * permissions. This implies that the user revoked the ability to read phone state 90 * manually (via AppOps). In this case we can't throw as it would break app compatibility, 91 * so we return false to indicate that the calling function should return dummy data. 92 * </ul> 93 * 94 * <p>Note: for simplicity, this method always returns false for callers using legacy 95 * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged. 96 * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+ 97 * devices. 98 */ 99 public static boolean checkReadPhoneState( 100 Context context, int subId, int pid, int uid, String callingPackage, String message) { 101 return checkReadPhoneState( 102 context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message); 103 } 104 105 @VisibleForTesting 106 public static boolean checkReadPhoneState( 107 Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, 108 String callingPackage, String message) { 109 try { 110 context.enforcePermission( 111 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message); 112 113 // SKIP checking for run-time permission since caller has PRIVILEGED permission 114 return true; 115 } catch (SecurityException privilegedPhoneStateException) { 116 try { 117 context.enforcePermission( 118 android.Manifest.permission.READ_PHONE_STATE, pid, uid, message); 119 } catch (SecurityException phoneStateException) { 120 // If we don't have the runtime permission, but do have carrier privileges, that 121 // suffices for reading phone state. 122 if (SubscriptionManager.isValidSubscriptionId(subId)) { 123 enforceCarrierPrivilege(telephonySupplier, subId, uid, message); 124 return true; 125 } 126 throw phoneStateException; 127 } 128 } 129 130 // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been 131 // revoked. 132 AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 133 return appOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, uid, callingPackage) == 134 AppOpsManager.MODE_ALLOWED; 135 } 136 137 /** 138 * Check whether the app with the given pid/uid can read the call log. 139 * @return {@code true} if the specified app has the read call log permission and AppOpp granted 140 * to it, {@code false} otherwise. 141 */ 142 public static boolean checkReadCallLog( 143 Context context, int subId, int pid, int uid, String callingPackage) { 144 return checkReadCallLog( 145 context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage); 146 } 147 148 @VisibleForTesting 149 public static boolean checkReadCallLog( 150 Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, 151 String callingPackage) { 152 153 if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid) 154 != PERMISSION_GRANTED) { 155 // If we don't have the runtime permission, but do have carrier privileges, that 156 // suffices for being able to see the call phone numbers. 157 if (SubscriptionManager.isValidSubscriptionId(subId)) { 158 enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog"); 159 return true; 160 } 161 return false; 162 } 163 164 // We have READ_CALL_LOG permission, so return true as long as the AppOps bit hasn't been 165 // revoked. 166 AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 167 return appOps.noteOp(AppOpsManager.OP_READ_CALL_LOG, uid, callingPackage) == 168 AppOpsManager.MODE_ALLOWED; 169 } 170 171 /** 172 * Returns whether the caller can read phone numbers. 173 * 174 * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}, the 175 * default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers. 176 */ 177 public static boolean checkCallingOrSelfReadPhoneNumber( 178 Context context, int subId, String callingPackage, String message) { 179 return checkReadPhoneNumber( 180 context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(), 181 callingPackage, message); 182 } 183 184 @VisibleForTesting 185 public static boolean checkReadPhoneNumber( 186 Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, 187 String callingPackage, String message) { 188 // Default SMS app can always read it. 189 AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 190 if (appOps.noteOp(AppOpsManager.OP_WRITE_SMS, uid, callingPackage) == 191 AppOpsManager.MODE_ALLOWED) { 192 return true; 193 } 194 195 // NOTE(b/73308711): If an app has one of the following AppOps bits explicitly revoked, they 196 // will be denied access, even if they have another permission and AppOps bit if needed. 197 198 // First, check if we can read the phone state. 199 try { 200 return checkReadPhoneState( 201 context, telephonySupplier, subId, pid, uid, callingPackage, message); 202 } catch (SecurityException readPhoneStateSecurityException) { 203 } 204 // Can be read with READ_SMS too. 205 try { 206 context.enforcePermission(android.Manifest.permission.READ_SMS, pid, uid, message); 207 int opCode = AppOpsManager.permissionToOpCode(android.Manifest.permission.READ_SMS); 208 if (opCode != AppOpsManager.OP_NONE) { 209 return appOps.noteOp(opCode, uid, callingPackage) == AppOpsManager.MODE_ALLOWED; 210 } else { 211 return true; 212 } 213 } catch (SecurityException readSmsSecurityException) { 214 } 215 // Can be read with READ_PHONE_NUMBERS too. 216 try { 217 context.enforcePermission(android.Manifest.permission.READ_PHONE_NUMBERS, pid, uid, 218 message); 219 int opCode = AppOpsManager.permissionToOpCode( 220 android.Manifest.permission.READ_PHONE_NUMBERS); 221 if (opCode != AppOpsManager.OP_NONE) { 222 return appOps.noteOp(opCode, uid, callingPackage) == AppOpsManager.MODE_ALLOWED; 223 } else { 224 return true; 225 } 226 } catch (SecurityException readPhoneNumberSecurityException) { 227 } 228 229 throw new SecurityException(message + ": Neither user " + uid + 230 " nor current process has " + android.Manifest.permission.READ_PHONE_STATE + 231 ", " + android.Manifest.permission.READ_SMS + ", or " + 232 android.Manifest.permission.READ_PHONE_NUMBERS); 233 } 234 235 /** 236 * Ensure the caller (or self, if not processing an IPC) has MODIFY_PHONE_STATE (and is thus a 237 * privileged app) or carrier privileges. 238 * 239 * @throws SecurityException if the caller does not have the required permission/privileges 240 */ 241 public static void enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( 242 Context context, int subId, String message) { 243 if (context.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) == 244 PERMISSION_GRANTED) { 245 return; 246 } 247 248 if (DBG) Rlog.d(LOG_TAG, "No modify permission, check carrier privilege next."); 249 enforceCallingOrSelfCarrierPrivilege(subId, message); 250 } 251 252 /** 253 * Make sure the caller (or self, if not processing an IPC) has carrier privileges. 254 * 255 * @throws SecurityException if the caller does not have the required privileges 256 */ 257 public static void enforceCallingOrSelfCarrierPrivilege(int subId, String message) { 258 // NOTE: It's critical that we explicitly pass the calling UID here rather than call 259 // TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from 260 // the phone process. When called from another process, it will check whether that process 261 // has carrier privileges instead. 262 enforceCarrierPrivilege(subId, Binder.getCallingUid(), message); 263 } 264 265 private static void enforceCarrierPrivilege(int subId, int uid, String message) { 266 enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message); 267 } 268 269 private static void enforceCarrierPrivilege( 270 Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) { 271 if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) != 272 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 273 if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege."); 274 throw new SecurityException(message); 275 } 276 } 277 278 private static int getCarrierPrivilegeStatus( 279 Supplier<ITelephony> telephonySupplier, int subId, int uid) { 280 ITelephony telephony = telephonySupplier.get(); 281 try { 282 if (telephony != null) { 283 return telephony.getCarrierPrivilegeStatusForUid(subId, uid); 284 } 285 } catch (RemoteException e) { 286 // Fallback below. 287 } 288 Rlog.e(LOG_TAG, "Phone process is down, cannot check carrier privileges"); 289 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 290 } 291 } 292