• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.server.connectivity;
18 
19 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
20 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
21 
22 import android.annotation.NonNull;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.PackageManager;
29 import android.net.NetworkCapabilities;
30 import android.net.NetworkSpecifier;
31 import android.net.TelephonyNetworkSpecifier;
32 import android.os.Handler;
33 import android.os.HandlerThread;
34 import android.os.Process;
35 import android.telephony.SubscriptionManager;
36 import android.telephony.TelephonyManager;
37 import android.util.Log;
38 
39 import com.android.internal.annotations.GuardedBy;
40 import com.android.internal.annotations.VisibleForTesting;
41 import com.android.modules.utils.HandlerExecutor;
42 import com.android.networkstack.apishim.TelephonyManagerShimImpl;
43 import com.android.networkstack.apishim.common.TelephonyManagerShim;
44 import com.android.networkstack.apishim.common.TelephonyManagerShim.CarrierPrivilegesListenerShim;
45 import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
46 
47 import java.util.ArrayList;
48 import java.util.List;
49 import java.util.concurrent.Executor;
50 
51 /**
52  * Tracks the uid of the carrier privileged app that provides the carrier config.
53  * Authenticates if the caller has same uid as
54  * carrier privileged app that provides the carrier config
55  * @hide
56  */
57 public class CarrierPrivilegeAuthenticator extends BroadcastReceiver {
58     private static final String TAG = CarrierPrivilegeAuthenticator.class.getSimpleName();
59     private static final boolean DBG = true;
60 
61     // The context is for the current user (system server)
62     private final Context mContext;
63     private final TelephonyManagerShim mTelephonyManagerShim;
64     private final TelephonyManager mTelephonyManager;
65     @GuardedBy("mLock")
66     private int[] mCarrierServiceUid;
67     @GuardedBy("mLock")
68     private int mModemCount = 0;
69     private final Object mLock = new Object();
70     private final HandlerThread mThread;
71     private final Handler mHandler;
72     @NonNull
73     private final List<CarrierPrivilegesListenerShim> mCarrierPrivilegesChangedListeners =
74             new ArrayList<>();
75 
CarrierPrivilegeAuthenticator(@onNull final Context c, @NonNull final TelephonyManager t, @NonNull final TelephonyManagerShimImpl telephonyManagerShim)76     public CarrierPrivilegeAuthenticator(@NonNull final Context c,
77             @NonNull final TelephonyManager t,
78             @NonNull final TelephonyManagerShimImpl telephonyManagerShim) {
79         mContext = c;
80         mTelephonyManager = t;
81         mTelephonyManagerShim = telephonyManagerShim;
82         mThread = new HandlerThread(TAG);
83         mThread.start();
84         mHandler = new Handler(mThread.getLooper()) {};
85         synchronized (mLock) {
86             mModemCount = mTelephonyManager.getActiveModemCount();
87             registerForCarrierChanges();
88             updateCarrierServiceUid();
89         }
90     }
91 
CarrierPrivilegeAuthenticator(@onNull final Context c, @NonNull final TelephonyManager t)92     public CarrierPrivilegeAuthenticator(@NonNull final Context c,
93             @NonNull final TelephonyManager t) {
94         mContext = c;
95         mTelephonyManager = t;
96         mTelephonyManagerShim = TelephonyManagerShimImpl.newInstance(mTelephonyManager);
97         mThread = new HandlerThread(TAG);
98         mThread.start();
99         mHandler = new Handler(mThread.getLooper()) {};
100         synchronized (mLock) {
101             mModemCount = mTelephonyManager.getActiveModemCount();
102             registerForCarrierChanges();
103             updateCarrierServiceUid();
104         }
105     }
106 
107     /**
108      * Broadcast receiver for ACTION_MULTI_SIM_CONFIG_CHANGED
109      *
110      * <p>The broadcast receiver is registered with mHandler
111      */
112     @Override
onReceive(Context context, Intent intent)113     public void onReceive(Context context, Intent intent) {
114         switch (intent.getAction()) {
115             case TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED:
116                 handleActionMultiSimConfigChanged(context, intent);
117                 break;
118             default:
119                 Log.d(TAG, "Unknown intent received with action: " + intent.getAction());
120         }
121     }
122 
handleActionMultiSimConfigChanged(Context context, Intent intent)123     private void handleActionMultiSimConfigChanged(Context context, Intent intent) {
124         unregisterCarrierPrivilegesListeners();
125         synchronized (mLock) {
126             mModemCount = mTelephonyManager.getActiveModemCount();
127         }
128         registerCarrierPrivilegesListeners();
129         updateCarrierServiceUid();
130     }
131 
registerForCarrierChanges()132     private void registerForCarrierChanges() {
133         final IntentFilter filter = new IntentFilter();
134         filter.addAction(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
135         mContext.registerReceiver(this, filter, null, mHandler);
136         registerCarrierPrivilegesListeners();
137     }
138 
registerCarrierPrivilegesListeners()139     private void registerCarrierPrivilegesListeners() {
140         final HandlerExecutor executor = new HandlerExecutor(mHandler);
141         int modemCount;
142         synchronized (mLock) {
143             modemCount = mModemCount;
144         }
145         try {
146             for (int i = 0; i < modemCount; i++) {
147                 CarrierPrivilegesListenerShim carrierPrivilegesListener =
148                         new CarrierPrivilegesListenerShim() {
149                             @Override
150                             public void onCarrierPrivilegesChanged(
151                                     @NonNull List<String> privilegedPackageNames,
152                                     @NonNull int[] privilegedUids) {
153                                 // Re-trigger the synchronous check (which is also very cheap due
154                                 // to caching in CarrierPrivilegesTracker). This allows consistency
155                                 // with the onSubscriptionsChangedListener and broadcasts.
156                                 updateCarrierServiceUid();
157                             }
158                         };
159                 addCarrierPrivilegesListener(i, executor, carrierPrivilegesListener);
160                 mCarrierPrivilegesChangedListeners.add(carrierPrivilegesListener);
161             }
162         } catch (IllegalArgumentException e) {
163             Log.e(TAG, "Encountered exception registering carrier privileges listeners", e);
164         }
165     }
166 
addCarrierPrivilegesListener(int logicalSlotIndex, Executor executor, CarrierPrivilegesListenerShim listener)167     private void addCarrierPrivilegesListener(int logicalSlotIndex, Executor executor,
168             CarrierPrivilegesListenerShim listener) {
169         try {
170             mTelephonyManagerShim.addCarrierPrivilegesListener(
171                     logicalSlotIndex, executor, listener);
172         } catch (UnsupportedApiLevelException unsupportedApiLevelException) {
173             // Should not happen since CarrierPrivilegeAuthenticator is only used on T+
174             Log.e(TAG, "addCarrierPrivilegesListener API is not available");
175         }
176     }
177 
removeCarrierPrivilegesListener(CarrierPrivilegesListenerShim listener)178     private void removeCarrierPrivilegesListener(CarrierPrivilegesListenerShim listener) {
179         try {
180             mTelephonyManagerShim.removeCarrierPrivilegesListener(listener);
181         } catch (UnsupportedApiLevelException unsupportedApiLevelException) {
182             // Should not happen since CarrierPrivilegeAuthenticator is only used on T+
183             Log.e(TAG, "removeCarrierPrivilegesListener API is not available");
184         }
185     }
186 
getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex)187     private String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
188         try {
189             return mTelephonyManagerShim.getCarrierServicePackageNameForLogicalSlot(
190                     logicalSlotIndex);
191         } catch (UnsupportedApiLevelException unsupportedApiLevelException) {
192             // Should not happen since CarrierPrivilegeAuthenticator is only used on T+
193             Log.e(TAG, "getCarrierServicePackageNameForLogicalSlot API is not available");
194         }
195         return null;
196     }
197 
unregisterCarrierPrivilegesListeners()198     private void unregisterCarrierPrivilegesListeners() {
199         for (CarrierPrivilegesListenerShim carrierPrivilegesListener :
200                 mCarrierPrivilegesChangedListeners) {
201             removeCarrierPrivilegesListener(carrierPrivilegesListener);
202         }
203         mCarrierPrivilegesChangedListeners.clear();
204     }
205 
206     /**
207      * Check if a UID is the carrier service app of the subscription ID in the provided capabilities
208      *
209      * This returns whether the passed UID is the carrier service package for the subscription ID
210      * stored in the telephony network specifier in the passed network capabilities.
211      * If the capabilities don't code for a cellular network, or if they don't have the
212      * subscription ID in their specifier, this returns false.
213      *
214      * This method can be used to check that a network request for {@link NET_CAPABILITY_CBS} is
215      * allowed for the UID of a caller, which must hold carrier privilege and provide the carrier
216      * config.
217      * It can also be used to check that a factory is entitled to grant access to a given network
218      * to a given UID on grounds that it is the carrier service package.
219      *
220      * @param callingUid uid of the app claimed to be the carrier service package.
221      * @param networkCapabilities the network capabilities for which carrier privilege is checked.
222      * @return true if uid provides the relevant carrier config else false.
223      */
hasCarrierPrivilegeForNetworkCapabilities(int callingUid, @NonNull NetworkCapabilities networkCapabilities)224     public boolean hasCarrierPrivilegeForNetworkCapabilities(int callingUid,
225             @NonNull NetworkCapabilities networkCapabilities) {
226         if (callingUid == Process.INVALID_UID) return false;
227         if (!networkCapabilities.hasSingleTransport(TRANSPORT_CELLULAR)) return false;
228         final int subId = getSubIdFromNetworkSpecifier(networkCapabilities.getNetworkSpecifier());
229         if (SubscriptionManager.INVALID_SUBSCRIPTION_ID == subId) return false;
230         return callingUid == getCarrierServiceUidForSubId(subId);
231     }
232 
233     @VisibleForTesting
updateCarrierServiceUid()234     void updateCarrierServiceUid() {
235         synchronized (mLock) {
236             mCarrierServiceUid = new int[mModemCount];
237             for (int i = 0; i < mModemCount; i++) {
238                 mCarrierServiceUid[i] = getCarrierServicePackageUidForSlot(i);
239             }
240         }
241     }
242 
243     @VisibleForTesting
getCarrierServiceUidForSubId(int subId)244     int getCarrierServiceUidForSubId(int subId) {
245         final int slotId = getSlotIndex(subId);
246         synchronized (mLock) {
247             if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX && slotId < mModemCount) {
248                 return mCarrierServiceUid[slotId];
249             }
250         }
251         return Process.INVALID_UID;
252     }
253 
254     @VisibleForTesting
getSlotIndex(int subId)255     protected int getSlotIndex(int subId) {
256         return SubscriptionManager.getSlotIndex(subId);
257     }
258 
259     @VisibleForTesting
getSubIdFromNetworkSpecifier(NetworkSpecifier specifier)260     int getSubIdFromNetworkSpecifier(NetworkSpecifier specifier) {
261         if (specifier instanceof TelephonyNetworkSpecifier) {
262             return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
263         }
264         return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
265     }
266 
267     @VisibleForTesting
getUidForPackage(String pkgName)268     int getUidForPackage(String pkgName) {
269         if (pkgName == null) {
270             return Process.INVALID_UID;
271         }
272         try {
273             PackageManager pm = mContext.getPackageManager();
274             if (pm != null) {
275                 ApplicationInfo applicationInfo = pm.getApplicationInfo(pkgName, 0);
276                 if (applicationInfo != null) {
277                     return applicationInfo.uid;
278                 }
279             }
280         } catch (PackageManager.NameNotFoundException exception) {
281             // Didn't find package. Try other users
282             Log.i(TAG, "Unable to find uid for package " + pkgName);
283         }
284         return Process.INVALID_UID;
285     }
286 
287     @VisibleForTesting
getCarrierServicePackageUidForSlot(int slotId)288     int getCarrierServicePackageUidForSlot(int slotId) {
289         return getUidForPackage(getCarrierServicePackageNameForLogicalSlot(slotId));
290     }
291 }
292