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