1 /* 2 * Copyright (C) 2019 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.internal.telephony; 18 19 import android.Manifest; 20 import android.app.AppOpsManager; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.Binder; 25 import android.os.Build; 26 import android.service.carrier.CarrierMessagingService; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.telephony.Rlog; 30 31 /** 32 * Permissions checks for SMS functionality 33 */ 34 public class SmsPermissions { 35 static final String LOG_TAG = "SmsPermissions"; 36 37 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 38 private final Phone mPhone; 39 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 40 private final Context mContext; 41 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 42 private final AppOpsManager mAppOps; 43 SmsPermissions(Phone phone, Context context, AppOpsManager appOps)44 public SmsPermissions(Phone phone, Context context, AppOpsManager appOps) { 45 mPhone = phone; 46 mContext = context; 47 mAppOps = appOps; 48 } 49 50 /** 51 * Check that the caller can send text messages. 52 * 53 * For persisted messages, the caller just needs the SEND_SMS permission. For unpersisted 54 * messages, the caller must either be the IMS app or a carrier-privileged app, or they must 55 * have both the MODIFY_PHONE_STATE and SEND_SMS permissions. 56 * 57 * @throws SecurityException if the caller is missing all necessary permission declaration or 58 * has had a necessary runtime permission revoked. 59 * @return true unless the caller has all necessary permissions but has a revoked AppOps bit. 60 */ checkCallingCanSendText( boolean persistMessageForNonDefaultSmsApp, String callingPackage, String callingAttributionTag, String message)61 public boolean checkCallingCanSendText( 62 boolean persistMessageForNonDefaultSmsApp, String callingPackage, 63 String callingAttributionTag, String message) { 64 // TODO(b/75978989): Should we allow IMS/carrier apps for persisted messages as well? 65 if (!persistMessageForNonDefaultSmsApp) { 66 try { 67 enforceCallerIsImsAppOrCarrierApp(message); 68 // No need to also check SEND_SMS. 69 return true; 70 } catch (SecurityException e) { 71 mContext.enforceCallingPermission( 72 android.Manifest.permission.MODIFY_PHONE_STATE, message); 73 } 74 } 75 return checkCallingCanSendSms(callingPackage, callingAttributionTag, message); 76 } 77 78 /** 79 * Enforces that the caller is one of the following apps: 80 * <ul> 81 * <li> IMS App determined by telephony to implement RCS features 82 * <li> Carrier App 83 * </ul> 84 */ enforceCallerIsImsAppOrCarrierApp(String message)85 public void enforceCallerIsImsAppOrCarrierApp(String message) { 86 String imsRcsPackage = CarrierSmsUtils.getImsRcsPackageForIntent(mContext, 87 mPhone, new Intent(CarrierMessagingService.SERVICE_INTERFACE)); 88 if (imsRcsPackage != null && packageNameMatchesCallingUid(imsRcsPackage)) { 89 return; 90 } 91 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege( 92 mContext, mPhone.getSubId(), message); 93 } 94 95 /** 96 * Check that the caller has SEND_SMS permissions. Can only be called during an IPC. 97 * 98 * @throws SecurityException if the caller is missing the permission declaration or has had the 99 * permission revoked at runtime. 100 * @return whether the caller has the OP_SEND_SMS AppOps bit. 101 */ checkCallingCanSendSms(String callingPackage, String callingAttributionTag, String message)102 public boolean checkCallingCanSendSms(String callingPackage, String callingAttributionTag, 103 String message) { 104 mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, message); 105 return mAppOps.noteOp(AppOpsManager.OPSTR_SEND_SMS, Binder.getCallingUid(), callingPackage, 106 callingAttributionTag, null) == AppOpsManager.MODE_ALLOWED; 107 } 108 109 /** 110 * Check that the caller (or self, if this is not an IPC) has SEND_SMS permissions. 111 * 112 * @throws SecurityException if the caller is missing the permission declaration or has had the 113 * permission revoked at runtime. 114 * @return whether the caller has the OP_SEND_SMS AppOps bit. 115 */ checkCallingOrSelfCanSendSms(String callingPackage, String callingAttributionTag, String message)116 public boolean checkCallingOrSelfCanSendSms(String callingPackage, String callingAttributionTag, 117 String message) { 118 mContext.enforceCallingOrSelfPermission(Manifest.permission.SEND_SMS, message); 119 return mAppOps.noteOp(AppOpsManager.OPSTR_SEND_SMS, Binder.getCallingUid(), callingPackage, 120 callingAttributionTag, null) 121 == AppOpsManager.MODE_ALLOWED; 122 } 123 124 /** 125 * Check that the caller (or self, if this is not an IPC) can get SMSC address from (U)SIM. 126 * 127 * The default SMS application can get SMSC address, otherwise the caller must have 128 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or carrier privileges. 129 * 130 * @return true if the caller is default SMS app or has the required permission and privileges. 131 * Otherwise, false; 132 */ checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message)133 public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { 134 // Allow it to the default SMS app always. 135 if (!isCallerDefaultSmsPackage(callingPackage)) { 136 TelephonyPermissions 137 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( 138 mContext, mPhone.getSubId(), message); 139 } 140 return true; 141 } 142 143 /** 144 * Check that the caller (or self, if this is not an IPC) can set SMSC address on (U)SIM. 145 * 146 * The default SMS application can set SMSC address, otherwise the caller must have 147 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier privileges. 148 * 149 * @return true if the caller is default SMS app or has the required permission and privileges. 150 * Otherwise, false. 151 */ checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message)152 public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { 153 // Allow it to the default SMS app always. 154 if (!isCallerDefaultSmsPackage(callingPackage)) { 155 // Allow it with MODIFY_PHONE_STATE or Carrier Privileges 156 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( 157 mContext, mPhone.getSubId(), message); 158 } 159 return true; 160 } 161 162 /** Check if a package is default SMS app. */ 163 @VisibleForTesting isCallerDefaultSmsPackage(String packageName)164 public boolean isCallerDefaultSmsPackage(String packageName) { 165 if (packageNameMatchesCallingUid(packageName)) { 166 return SmsApplication.isDefaultSmsApplication(mContext, packageName); 167 } 168 return false; 169 } 170 171 /** 172 * Check if the passed in packageName belongs to the calling uid. 173 * @param packageName name of the package to check 174 * @return true if package belongs to calling uid, false otherwise 175 */ 176 @VisibleForTesting packageNameMatchesCallingUid(String packageName)177 public boolean packageNameMatchesCallingUid(String packageName) { 178 try { 179 ((AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE)) 180 .checkPackage(Binder.getCallingUid(), packageName); 181 // If checkPackage doesn't throw an exception then we are the given package 182 return true; 183 } catch (SecurityException e) { 184 return false; 185 } 186 } 187 188 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) log(String msg)189 protected void log(String msg) { 190 Rlog.d(LOG_TAG, msg); 191 } 192 loge(String msg)193 protected void loge(String msg) { 194 Rlog.e(LOG_TAG, msg); 195 } 196 loge(String msg, Throwable e)197 protected void loge(String msg, Throwable e) { 198 Rlog.e(LOG_TAG, msg, e); 199 } 200 } 201