• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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