• 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.annotation.UnsupportedAppUsage;
21 import android.app.AppOpsManager;
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.telephony.Rlog;
28 import android.util.Log;
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      * 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 message)61     public boolean checkCallingCanSendText(
62             boolean persistMessageForNonDefaultSmsApp, String callingPackage, 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, message);
75     }
76 
77 
78     /**
79      * Enforces that the caller is one of the following apps:
80      * <ul>
81      *     <li> IMS App
82      *     <li> Carrier App
83      * </ul>
84      */
enforceCallerIsImsAppOrCarrierApp(String message)85     public void enforceCallerIsImsAppOrCarrierApp(String message) {
86         int callingUid = Binder.getCallingUid();
87         String carrierImsPackage = CarrierSmsUtils.getCarrierImsPackageForIntent(mContext, mPhone,
88                 new Intent(CarrierMessagingService.SERVICE_INTERFACE));
89         try {
90             if (carrierImsPackage != null
91                     && callingUid == mContext.getPackageManager().getPackageUid(
92                     carrierImsPackage, 0)) {
93                 return;
94             }
95         } catch (PackageManager.NameNotFoundException e) {
96             if (Rlog.isLoggable("SMS", Log.DEBUG)) {
97                 log("Cannot find configured carrier ims package");
98             }
99         }
100 
101         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mPhone.getSubId(), message);
102     }
103 
104 
105     /**
106      * Check that the caller has SEND_SMS permissions. Can only be called during an IPC.
107      *
108      * @throws SecurityException if the caller is missing the permission declaration or has had the
109      *                           permission revoked at runtime.
110      * @return whether the caller has the OP_SEND_SMS AppOps bit.
111      */
checkCallingCanSendSms(String callingPackage, String message)112     public boolean checkCallingCanSendSms(String callingPackage, String message) {
113         mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, message);
114         return mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPackage)
115                 == AppOpsManager.MODE_ALLOWED;
116     }
117 
118     /**
119      * Check that the caller (or self, if this is not an IPC) has SEND_SMS permissions.
120      *
121      * @throws SecurityException if the caller is missing the permission declaration or has had the
122      *                           permission revoked at runtime.
123      * @return whether the caller has the OP_SEND_SMS AppOps bit.
124      */
checkCallingOrSelfCanSendSms(String callingPackage, String message)125     public boolean checkCallingOrSelfCanSendSms(String callingPackage, String message) {
126         mContext.enforceCallingOrSelfPermission(Manifest.permission.SEND_SMS, message);
127         return mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPackage)
128                 == AppOpsManager.MODE_ALLOWED;
129     }
130 
131     @UnsupportedAppUsage
log(String msg)132     protected void log(String msg) {
133         Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg);
134     }
135 }
136