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