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