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.networkstack.tethering; 18 19 import static android.Manifest.permission.ACCESS_NETWORK_STATE; 20 import static android.Manifest.permission.NETWORK_STACK; 21 import static android.Manifest.permission.TETHER_PRIVILEGED; 22 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 23 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; 24 import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION; 25 import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; 26 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; 27 import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; 28 import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR; 29 30 import android.app.Service; 31 import android.bluetooth.BluetoothAdapter; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.net.IIntResultListener; 35 import android.net.INetworkStackConnector; 36 import android.net.ITetheringConnector; 37 import android.net.ITetheringEventCallback; 38 import android.net.NetworkCapabilities; 39 import android.net.NetworkRequest; 40 import android.net.NetworkStack; 41 import android.net.TetheringRequestParcel; 42 import android.net.dhcp.DhcpServerCallbacks; 43 import android.net.dhcp.DhcpServingParamsParcel; 44 import android.net.ip.IpServer; 45 import android.os.Binder; 46 import android.os.HandlerThread; 47 import android.os.IBinder; 48 import android.os.Looper; 49 import android.os.RemoteException; 50 import android.os.ResultReceiver; 51 import android.provider.Settings; 52 import android.util.Log; 53 54 import androidx.annotation.NonNull; 55 import androidx.annotation.Nullable; 56 57 import com.android.internal.annotations.VisibleForTesting; 58 59 import java.io.FileDescriptor; 60 import java.io.PrintWriter; 61 62 /** 63 * Android service used to manage tethering. 64 * 65 * <p>The service returns a binder for the system server to communicate with the tethering. 66 */ 67 public class TetheringService extends Service { 68 private static final String TAG = TetheringService.class.getSimpleName(); 69 70 private TetheringConnector mConnector; 71 72 @Override onCreate()73 public void onCreate() { 74 final TetheringDependencies deps = makeTetheringDependencies(); 75 // The Tethering object needs a fully functional context to start, so this can't be done 76 // in the constructor. 77 mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this); 78 } 79 80 /** 81 * Make a reference to Tethering object. 82 */ 83 @VisibleForTesting makeTethering(TetheringDependencies deps)84 public Tethering makeTethering(TetheringDependencies deps) { 85 System.loadLibrary("tetherutilsjni"); 86 return new Tethering(deps); 87 } 88 89 @NonNull 90 @Override onBind(Intent intent)91 public IBinder onBind(Intent intent) { 92 return mConnector; 93 } 94 95 private static class TetheringConnector extends ITetheringConnector.Stub { 96 private final TetheringService mService; 97 private final Tethering mTethering; 98 TetheringConnector(Tethering tether, TetheringService service)99 TetheringConnector(Tethering tether, TetheringService service) { 100 mTethering = tether; 101 mService = service; 102 } 103 104 @Override tether(String iface, String callerPkg, String callingAttributionTag, IIntResultListener listener)105 public void tether(String iface, String callerPkg, String callingAttributionTag, 106 IIntResultListener listener) { 107 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 108 109 try { 110 listener.onResult(mTethering.tether(iface)); 111 } catch (RemoteException e) { } 112 } 113 114 @Override untether(String iface, String callerPkg, String callingAttributionTag, IIntResultListener listener)115 public void untether(String iface, String callerPkg, String callingAttributionTag, 116 IIntResultListener listener) { 117 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 118 119 try { 120 listener.onResult(mTethering.untether(iface)); 121 } catch (RemoteException e) { } 122 } 123 124 @Override setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag, IIntResultListener listener)125 public void setUsbTethering(boolean enable, String callerPkg, String callingAttributionTag, 126 IIntResultListener listener) { 127 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 128 129 try { 130 listener.onResult(mTethering.setUsbTethering(enable)); 131 } catch (RemoteException e) { } 132 } 133 134 @Override startTethering(TetheringRequestParcel request, String callerPkg, String callingAttributionTag, IIntResultListener listener)135 public void startTethering(TetheringRequestParcel request, String callerPkg, 136 String callingAttributionTag, IIntResultListener listener) { 137 if (checkAndNotifyCommonError(callerPkg, 138 callingAttributionTag, 139 request.exemptFromEntitlementCheck /* onlyAllowPrivileged */, 140 listener)) { 141 return; 142 } 143 144 mTethering.startTethering(request, listener); 145 } 146 147 @Override stopTethering(int type, String callerPkg, String callingAttributionTag, IIntResultListener listener)148 public void stopTethering(int type, String callerPkg, String callingAttributionTag, 149 IIntResultListener listener) { 150 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 151 152 try { 153 mTethering.stopTethering(type); 154 listener.onResult(TETHER_ERROR_NO_ERROR); 155 } catch (RemoteException e) { } 156 } 157 158 @Override requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, boolean showEntitlementUi, String callerPkg, String callingAttributionTag)159 public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, 160 boolean showEntitlementUi, String callerPkg, String callingAttributionTag) { 161 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, receiver)) return; 162 163 mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi); 164 } 165 166 @Override registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg)167 public void registerTetheringEventCallback(ITetheringEventCallback callback, 168 String callerPkg) { 169 try { 170 if (!hasTetherAccessPermission()) { 171 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); 172 return; 173 } 174 mTethering.registerTetheringEventCallback(callback); 175 } catch (RemoteException e) { } 176 } 177 178 @Override unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg)179 public void unregisterTetheringEventCallback(ITetheringEventCallback callback, 180 String callerPkg) { 181 try { 182 if (!hasTetherAccessPermission()) { 183 callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION); 184 return; 185 } 186 mTethering.unregisterTetheringEventCallback(callback); 187 } catch (RemoteException e) { } 188 } 189 190 @Override stopAllTethering(String callerPkg, String callingAttributionTag, IIntResultListener listener)191 public void stopAllTethering(String callerPkg, String callingAttributionTag, 192 IIntResultListener listener) { 193 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 194 195 try { 196 mTethering.untetherAll(); 197 listener.onResult(TETHER_ERROR_NO_ERROR); 198 } catch (RemoteException e) { } 199 } 200 201 @Override isTetheringSupported(String callerPkg, String callingAttributionTag, IIntResultListener listener)202 public void isTetheringSupported(String callerPkg, String callingAttributionTag, 203 IIntResultListener listener) { 204 if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return; 205 206 try { 207 listener.onResult(TETHER_ERROR_NO_ERROR); 208 } catch (RemoteException e) { } 209 } 210 211 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args)212 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, 213 @Nullable String[] args) { 214 mTethering.dump(fd, writer, args); 215 } 216 checkAndNotifyCommonError(final String callerPkg, final String callingAttributionTag, final IIntResultListener listener)217 private boolean checkAndNotifyCommonError(final String callerPkg, 218 final String callingAttributionTag, final IIntResultListener listener) { 219 return checkAndNotifyCommonError(callerPkg, callingAttributionTag, 220 false /* onlyAllowPrivileged */, listener); 221 } 222 checkAndNotifyCommonError(final String callerPkg, final String callingAttributionTag, final boolean onlyAllowPrivileged, final IIntResultListener listener)223 private boolean checkAndNotifyCommonError(final String callerPkg, 224 final String callingAttributionTag, final boolean onlyAllowPrivileged, 225 final IIntResultListener listener) { 226 try { 227 if (!hasTetherChangePermission(callerPkg, callingAttributionTag, 228 onlyAllowPrivileged)) { 229 listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 230 return true; 231 } 232 if (!mTethering.isTetheringSupported()) { 233 listener.onResult(TETHER_ERROR_UNSUPPORTED); 234 return true; 235 } 236 } catch (RemoteException e) { 237 return true; 238 } 239 240 return false; 241 } 242 checkAndNotifyCommonError(final String callerPkg, final String callingAttributionTag, final ResultReceiver receiver)243 private boolean checkAndNotifyCommonError(final String callerPkg, 244 final String callingAttributionTag, final ResultReceiver receiver) { 245 if (!hasTetherChangePermission(callerPkg, callingAttributionTag, 246 false /* onlyAllowPrivileged */)) { 247 receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null); 248 return true; 249 } 250 if (!mTethering.isTetheringSupported()) { 251 receiver.send(TETHER_ERROR_UNSUPPORTED, null); 252 return true; 253 } 254 255 return false; 256 } 257 hasNetworkStackPermission()258 private boolean hasNetworkStackPermission() { 259 return checkCallingOrSelfPermission(NETWORK_STACK) 260 || checkCallingOrSelfPermission(PERMISSION_MAINLINE_NETWORK_STACK); 261 } 262 hasTetherPrivilegedPermission()263 private boolean hasTetherPrivilegedPermission() { 264 return checkCallingOrSelfPermission(TETHER_PRIVILEGED); 265 } 266 checkCallingOrSelfPermission(final String permission)267 private boolean checkCallingOrSelfPermission(final String permission) { 268 return mService.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; 269 } 270 hasTetherChangePermission(final String callerPkg, final String callingAttributionTag, final boolean onlyAllowPrivileged)271 private boolean hasTetherChangePermission(final String callerPkg, 272 final String callingAttributionTag, final boolean onlyAllowPrivileged) { 273 if (onlyAllowPrivileged && !hasNetworkStackPermission()) return false; 274 275 if (hasTetherPrivilegedPermission()) return true; 276 277 if (mTethering.isTetherProvisioningRequired()) return false; 278 279 int uid = Binder.getCallingUid(); 280 281 // If callerPkg's uid is not same as Binder.getCallingUid(), 282 // checkAndNoteWriteSettingsOperation will return false and the operation will be 283 // denied. 284 return mService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg, 285 callingAttributionTag, false /* throwException */); 286 } 287 hasTetherAccessPermission()288 private boolean hasTetherAccessPermission() { 289 if (hasTetherPrivilegedPermission()) return true; 290 291 return mService.checkCallingOrSelfPermission( 292 ACCESS_NETWORK_STATE) == PERMISSION_GRANTED; 293 } 294 } 295 296 /** 297 * Check if the package is a allowed to write settings. This also accounts that such an access 298 * happened. 299 * 300 * @return {@code true} iff the package is allowed to write settings. 301 */ 302 @VisibleForTesting checkAndNoteWriteSettingsOperation(@onNull Context context, int uid, @NonNull String callingPackage, @Nullable String callingAttributionTag, boolean throwException)303 boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, 304 @NonNull String callingPackage, @Nullable String callingAttributionTag, 305 boolean throwException) { 306 return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage, 307 throwException); 308 } 309 310 /** 311 * An injection method for testing. 312 */ 313 @VisibleForTesting makeTetheringDependencies()314 public TetheringDependencies makeTetheringDependencies() { 315 return new TetheringDependencies() { 316 @Override 317 public NetworkRequest getDefaultNetworkRequest() { 318 // TODO: b/147280869, add a proper system API to replace this. 319 final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder() 320 .clearCapabilities() 321 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 322 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 323 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 324 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 325 .build(); 326 return trackDefaultRequest; 327 } 328 329 @Override 330 public Looper getTetheringLooper() { 331 final HandlerThread tetherThread = new HandlerThread("android.tethering"); 332 tetherThread.start(); 333 return tetherThread.getLooper(); 334 } 335 336 @Override 337 public Context getContext() { 338 return TetheringService.this; 339 } 340 341 @Override 342 public IpServer.Dependencies getIpServerDependencies() { 343 return new IpServer.Dependencies() { 344 @Override 345 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, 346 DhcpServerCallbacks cb) { 347 try { 348 final INetworkStackConnector service = getNetworkStackConnector(); 349 if (service == null) return; 350 351 service.makeDhcpServer(ifName, params, cb); 352 } catch (RemoteException e) { 353 Log.e(TAG, "Fail to make dhcp server"); 354 try { 355 cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null); 356 } catch (RemoteException re) { } 357 } 358 } 359 }; 360 } 361 362 // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring 363 // networkStackClient. 364 static final int NETWORKSTACK_TIMEOUT_MS = 60_000; 365 private INetworkStackConnector getNetworkStackConnector() { 366 IBinder connector; 367 try { 368 final long before = System.currentTimeMillis(); 369 while ((connector = NetworkStack.getService()) == null) { 370 if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { 371 Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector"); 372 return null; 373 } 374 Thread.sleep(200); 375 } 376 } catch (InterruptedException e) { 377 Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector"); 378 return null; 379 } 380 return INetworkStackConnector.Stub.asInterface(connector); 381 } 382 383 @Override 384 public BluetoothAdapter getBluetoothAdapter() { 385 return BluetoothAdapter.getDefaultAdapter(); 386 } 387 }; 388 } 389 } 390