1 /* 2 * Copyright (C) 2021 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; 18 19 import static android.Manifest.permission.NETWORK_STACK; 20 21 import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageManager.NameNotFoundException; 31 import android.net.ConnectivityManager; 32 import android.net.INetd; 33 import android.net.IVpnManager; 34 import android.net.LinkProperties; 35 import android.net.Network; 36 import android.net.NetworkStack; 37 import android.net.UnderlyingNetworkInfo; 38 import android.net.Uri; 39 import android.net.VpnManager; 40 import android.net.VpnService; 41 import android.net.util.NetdService; 42 import android.os.Binder; 43 import android.os.Build; 44 import android.os.Handler; 45 import android.os.HandlerThread; 46 import android.os.INetworkManagementService; 47 import android.os.ParcelFileDescriptor; 48 import android.os.Process; 49 import android.os.ServiceManager; 50 import android.os.UserHandle; 51 import android.os.UserManager; 52 import android.security.Credentials; 53 import android.text.TextUtils; 54 import android.util.Log; 55 import android.util.SparseArray; 56 57 import com.android.internal.annotations.GuardedBy; 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.internal.net.LegacyVpnInfo; 60 import com.android.internal.net.VpnConfig; 61 import com.android.internal.net.VpnProfile; 62 import com.android.internal.util.DumpUtils; 63 import com.android.internal.util.IndentingPrintWriter; 64 import com.android.server.connectivity.Vpn; 65 import com.android.server.connectivity.VpnProfileStore; 66 import com.android.server.net.LockdownVpnTracker; 67 68 import java.io.FileDescriptor; 69 import java.io.PrintWriter; 70 import java.util.List; 71 72 /** 73 * Service that tracks and manages VPNs, and backs the VpnService and VpnManager APIs. 74 * @hide 75 */ 76 public class VpnManagerService extends IVpnManager.Stub { 77 private static final String TAG = VpnManagerService.class.getSimpleName(); 78 79 @VisibleForTesting 80 protected final HandlerThread mHandlerThread; 81 private final Handler mHandler; 82 83 private final Context mContext; 84 private final Context mUserAllContext; 85 86 private final Dependencies mDeps; 87 88 private final ConnectivityManager mCm; 89 private final VpnProfileStore mVpnProfileStore; 90 private final INetworkManagementService mNMS; 91 private final INetd mNetd; 92 private final UserManager mUserManager; 93 94 @VisibleForTesting 95 @GuardedBy("mVpns") 96 protected final SparseArray<Vpn> mVpns = new SparseArray<>(); 97 98 // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by 99 // a direct call to LockdownVpnTracker.isEnabled(). 100 @GuardedBy("mVpns") 101 private boolean mLockdownEnabled; 102 @GuardedBy("mVpns") 103 private LockdownVpnTracker mLockdownTracker; 104 105 /** 106 * Dependencies of VpnManager, for injection in tests. 107 */ 108 @VisibleForTesting 109 public static class Dependencies { 110 /** Returns the calling UID of an IPC. */ getCallingUid()111 public int getCallingUid() { 112 return Binder.getCallingUid(); 113 } 114 115 /** Creates a HandlerThread to be used by this class. */ makeHandlerThread()116 public HandlerThread makeHandlerThread() { 117 return new HandlerThread("VpnManagerService"); 118 } 119 120 /** Return the VpnProfileStore to be used by this class */ getVpnProfileStore()121 public VpnProfileStore getVpnProfileStore() { 122 return new VpnProfileStore(); 123 } 124 getNetd()125 public INetd getNetd() { 126 return NetdService.getInstance(); 127 } 128 getINetworkManagementService()129 public INetworkManagementService getINetworkManagementService() { 130 return INetworkManagementService.Stub.asInterface( 131 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); 132 } 133 } 134 VpnManagerService(Context context, Dependencies deps)135 public VpnManagerService(Context context, Dependencies deps) { 136 mContext = context; 137 mDeps = deps; 138 mHandlerThread = mDeps.makeHandlerThread(); 139 mHandlerThread.start(); 140 mHandler = mHandlerThread.getThreadHandler(); 141 mVpnProfileStore = mDeps.getVpnProfileStore(); 142 mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); 143 mCm = mContext.getSystemService(ConnectivityManager.class); 144 mNMS = mDeps.getINetworkManagementService(); 145 mNetd = mDeps.getNetd(); 146 mUserManager = mContext.getSystemService(UserManager.class); 147 registerReceivers(); 148 log("VpnManagerService starting up"); 149 } 150 151 /** Creates a new VpnManagerService */ create(Context context)152 public static VpnManagerService create(Context context) { 153 return new VpnManagerService(context, new Dependencies()); 154 } 155 156 /** Informs the service that the system is ready. */ systemReady()157 public void systemReady() { 158 // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait 159 // for user to unlock device too. 160 updateLockdownVpn(); 161 } 162 163 @Override 164 /** Dumps service state. */ dump(@onNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args)165 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, 166 @Nullable String[] args) { 167 if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; 168 IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 169 pw.println("VPNs:"); 170 pw.increaseIndent(); 171 synchronized (mVpns) { 172 for (int i = 0; i < mVpns.size(); i++) { 173 pw.println(mVpns.keyAt(i) + ": " + mVpns.valueAt(i).getPackage()); 174 } 175 pw.decreaseIndent(); 176 } 177 } 178 179 /** 180 * Prepare for a VPN application. 181 * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, 182 * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. 183 * 184 * @param oldPackage Package name of the application which currently controls VPN, which will 185 * be replaced. If there is no such application, this should should either be 186 * {@code null} or {@link VpnConfig.LEGACY_VPN}. 187 * @param newPackage Package name of the application which should gain control of VPN, or 188 * {@code null} to disable. 189 * @param userId User for whom to prepare the new VPN. 190 * 191 * @hide 192 */ 193 @Override prepareVpn(@ullable String oldPackage, @Nullable String newPackage, int userId)194 public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, 195 int userId) { 196 enforceCrossUserPermission(userId); 197 198 synchronized (mVpns) { 199 throwIfLockdownEnabled(); 200 Vpn vpn = mVpns.get(userId); 201 if (vpn != null) { 202 return vpn.prepare(oldPackage, newPackage, VpnManager.TYPE_VPN_SERVICE); 203 } else { 204 return false; 205 } 206 } 207 } 208 209 /** 210 * Set whether the VPN package has the ability to launch VPNs without user intervention. This 211 * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn} 212 * class. If the caller is not {@code userId}, {@link 213 * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. 214 * 215 * @param packageName The package for which authorization state should change. 216 * @param userId User for whom {@code packageName} is installed. 217 * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN 218 * permissions should be granted. When unauthorizing an app, {@link 219 * VpnManager.TYPE_VPN_NONE} should be used. 220 * @hide 221 */ 222 @Override setVpnPackageAuthorization( String packageName, int userId, @VpnManager.VpnType int vpnType)223 public void setVpnPackageAuthorization( 224 String packageName, int userId, @VpnManager.VpnType int vpnType) { 225 enforceCrossUserPermission(userId); 226 227 synchronized (mVpns) { 228 Vpn vpn = mVpns.get(userId); 229 if (vpn != null) { 230 vpn.setPackageAuthorization(packageName, vpnType); 231 } 232 } 233 } 234 235 /** 236 * Configure a TUN interface and return its file descriptor. Parameters 237 * are encoded and opaque to this class. This method is used by VpnBuilder 238 * and not available in VpnManager. Permissions are checked in 239 * Vpn class. 240 * @hide 241 */ 242 @Override establishVpn(VpnConfig config)243 public ParcelFileDescriptor establishVpn(VpnConfig config) { 244 int user = UserHandle.getUserId(mDeps.getCallingUid()); 245 synchronized (mVpns) { 246 throwIfLockdownEnabled(); 247 return mVpns.get(user).establish(config); 248 } 249 } 250 251 @Override addVpnAddress(String address, int prefixLength)252 public boolean addVpnAddress(String address, int prefixLength) { 253 int user = UserHandle.getUserId(mDeps.getCallingUid()); 254 synchronized (mVpns) { 255 throwIfLockdownEnabled(); 256 return mVpns.get(user).addAddress(address, prefixLength); 257 } 258 } 259 260 @Override removeVpnAddress(String address, int prefixLength)261 public boolean removeVpnAddress(String address, int prefixLength) { 262 int user = UserHandle.getUserId(mDeps.getCallingUid()); 263 synchronized (mVpns) { 264 throwIfLockdownEnabled(); 265 return mVpns.get(user).removeAddress(address, prefixLength); 266 } 267 } 268 269 @Override setUnderlyingNetworksForVpn(Network[] networks)270 public boolean setUnderlyingNetworksForVpn(Network[] networks) { 271 int user = UserHandle.getUserId(mDeps.getCallingUid()); 272 final boolean success; 273 synchronized (mVpns) { 274 success = mVpns.get(user).setUnderlyingNetworks(networks); 275 } 276 return success; 277 } 278 279 /** 280 * Stores the given VPN profile based on the provisioning package name. 281 * 282 * <p>If there is already a VPN profile stored for the provisioning package, this call will 283 * overwrite the profile. 284 * 285 * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed 286 * exclusively by the Settings app, and passed into the platform at startup time. 287 * 288 * @return {@code true} if user consent has already been granted, {@code false} otherwise. 289 * @hide 290 */ 291 @Override provisionVpnProfile(@onNull VpnProfile profile, @NonNull String packageName)292 public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) { 293 final int user = UserHandle.getUserId(mDeps.getCallingUid()); 294 synchronized (mVpns) { 295 return mVpns.get(user).provisionVpnProfile(packageName, profile); 296 } 297 } 298 299 /** 300 * Deletes the stored VPN profile for the provisioning package 301 * 302 * <p>If there are no profiles for the given package, this method will silently succeed. 303 * 304 * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed 305 * exclusively by the Settings app, and passed into the platform at startup time. 306 * 307 * @hide 308 */ 309 @Override deleteVpnProfile(@onNull String packageName)310 public void deleteVpnProfile(@NonNull String packageName) { 311 final int user = UserHandle.getUserId(mDeps.getCallingUid()); 312 synchronized (mVpns) { 313 mVpns.get(user).deleteVpnProfile(packageName); 314 } 315 } 316 317 // TODO : Move to a static lib to factorize with Vpn.java getAppUid(final String app, final int userId)318 private int getAppUid(final String app, final int userId) { 319 final PackageManager pm = mContext.getPackageManager(); 320 final long token = Binder.clearCallingIdentity(); 321 try { 322 return pm.getPackageUidAsUser(app, userId); 323 } catch (NameNotFoundException e) { 324 return -1; 325 } finally { 326 Binder.restoreCallingIdentity(token); 327 } 328 } 329 verifyCallingUidAndPackage(String packageName, int callingUid)330 private void verifyCallingUidAndPackage(String packageName, int callingUid) { 331 final int userId = UserHandle.getUserId(callingUid); 332 if (getAppUid(packageName, userId) != callingUid) { 333 throw new SecurityException(packageName + " does not belong to uid " + callingUid); 334 } 335 } 336 337 /** 338 * Starts the VPN based on the stored profile for the given package 339 * 340 * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed 341 * exclusively by the Settings app, and passed into the platform at startup time. 342 * 343 * @throws IllegalArgumentException if no profile was found for the given package name. 344 * @hide 345 */ 346 @Override startVpnProfile(@onNull String packageName)347 public void startVpnProfile(@NonNull String packageName) { 348 final int callingUid = Binder.getCallingUid(); 349 verifyCallingUidAndPackage(packageName, callingUid); 350 final int user = UserHandle.getUserId(callingUid); 351 synchronized (mVpns) { 352 throwIfLockdownEnabled(); 353 mVpns.get(user).startVpnProfile(packageName); 354 } 355 } 356 357 /** 358 * Stops the Platform VPN if the provided package is running one. 359 * 360 * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed 361 * exclusively by the Settings app, and passed into the platform at startup time. 362 * 363 * @hide 364 */ 365 @Override stopVpnProfile(@onNull String packageName)366 public void stopVpnProfile(@NonNull String packageName) { 367 final int callingUid = Binder.getCallingUid(); 368 verifyCallingUidAndPackage(packageName, callingUid); 369 final int user = UserHandle.getUserId(callingUid); 370 synchronized (mVpns) { 371 mVpns.get(user).stopVpnProfile(packageName); 372 } 373 } 374 375 /** 376 * Start legacy VPN, controlling native daemons as needed. Creates a 377 * secondary thread to perform connection work, returning quickly. 378 * 379 * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the 380 * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be 381 * thrown. 382 */ 383 @SuppressWarnings("AndroidFrameworkCompatChange") // This is not an app-visible API. 384 @Override startLegacyVpn(VpnProfile profile)385 public void startLegacyVpn(VpnProfile profile) { 386 if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.S 387 && VpnProfile.isLegacyType(profile.type)) { 388 throw new UnsupportedOperationException("Legacy VPN is deprecated"); 389 } 390 int user = UserHandle.getUserId(mDeps.getCallingUid()); 391 // Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID), 392 // the code might not work well since getActiveNetwork might return null if the uid is 393 // blocked by NetworkPolicyManagerService. 394 final LinkProperties egress = mCm.getLinkProperties(mCm.getActiveNetwork()); 395 if (egress == null) { 396 throw new IllegalStateException("Missing active network connection"); 397 } 398 synchronized (mVpns) { 399 throwIfLockdownEnabled(); 400 mVpns.get(user).startLegacyVpn(profile, null /* underlying */, egress); 401 } 402 } 403 404 /** 405 * Return the information of the ongoing legacy VPN. This method is used 406 * by VpnSettings and not available in ConnectivityManager. Permissions 407 * are checked in Vpn class. 408 */ 409 @Override getLegacyVpnInfo(int userId)410 public LegacyVpnInfo getLegacyVpnInfo(int userId) { 411 enforceCrossUserPermission(userId); 412 413 synchronized (mVpns) { 414 return mVpns.get(userId).getLegacyVpnInfo(); 415 } 416 } 417 418 /** 419 * Returns the information of the ongoing VPN for {@code userId}. This method is used by 420 * VpnDialogs and not available in ConnectivityManager. 421 * Permissions are checked in Vpn class. 422 * @hide 423 */ 424 @Override getVpnConfig(int userId)425 public VpnConfig getVpnConfig(int userId) { 426 enforceCrossUserPermission(userId); 427 synchronized (mVpns) { 428 Vpn vpn = mVpns.get(userId); 429 if (vpn != null) { 430 return vpn.getVpnConfig(); 431 } else { 432 return null; 433 } 434 } 435 } 436 isLockdownVpnEnabled()437 private boolean isLockdownVpnEnabled() { 438 return mVpnProfileStore.get(Credentials.LOCKDOWN_VPN) != null; 439 } 440 441 @Override updateLockdownVpn()442 public boolean updateLockdownVpn() { 443 // Allow the system UID for the system server and for Settings. 444 // Also, for unit tests, allow the process that ConnectivityService is running in. 445 if (mDeps.getCallingUid() != Process.SYSTEM_UID 446 && Binder.getCallingPid() != Process.myPid()) { 447 logw("Lockdown VPN only available to system process or AID_SYSTEM"); 448 return false; 449 } 450 451 synchronized (mVpns) { 452 // Tear down existing lockdown if profile was removed 453 mLockdownEnabled = isLockdownVpnEnabled(); 454 if (!mLockdownEnabled) { 455 setLockdownTracker(null); 456 return true; 457 } 458 459 byte[] profileTag = mVpnProfileStore.get(Credentials.LOCKDOWN_VPN); 460 if (profileTag == null) { 461 loge("Lockdown VPN configured but cannot be read from keystore"); 462 return false; 463 } 464 String profileName = new String(profileTag); 465 final VpnProfile profile = VpnProfile.decode( 466 profileName, mVpnProfileStore.get(Credentials.VPN + profileName)); 467 if (profile == null) { 468 loge("Lockdown VPN configured invalid profile " + profileName); 469 setLockdownTracker(null); 470 return true; 471 } 472 int user = UserHandle.getUserId(mDeps.getCallingUid()); 473 Vpn vpn = mVpns.get(user); 474 if (vpn == null) { 475 logw("VPN for user " + user + " not ready yet. Skipping lockdown"); 476 return false; 477 } 478 setLockdownTracker( 479 new LockdownVpnTracker(mContext, mHandler, vpn, profile)); 480 } 481 482 return true; 483 } 484 485 /** 486 * Internally set new {@link LockdownVpnTracker}, shutting down any existing 487 * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown. 488 */ 489 @GuardedBy("mVpns") setLockdownTracker(LockdownVpnTracker tracker)490 private void setLockdownTracker(LockdownVpnTracker tracker) { 491 // Shutdown any existing tracker 492 final LockdownVpnTracker existing = mLockdownTracker; 493 // TODO: Add a trigger when the always-on VPN enable/disable to reevaluate and send the 494 // necessary onBlockedStatusChanged callbacks. 495 mLockdownTracker = null; 496 if (existing != null) { 497 existing.shutdown(); 498 } 499 500 if (tracker != null) { 501 mLockdownTracker = tracker; 502 mLockdownTracker.init(); 503 } 504 } 505 506 /** 507 * Throws if there is any currently running, always-on Legacy VPN. 508 * 509 * <p>The LockdownVpnTracker and mLockdownEnabled both track whether an always-on Legacy VPN is 510 * running across the entire system. Tracking for app-based VPNs is done on a per-user, 511 * per-package basis in Vpn.java 512 */ 513 @GuardedBy("mVpns") throwIfLockdownEnabled()514 private void throwIfLockdownEnabled() { 515 if (mLockdownEnabled) { 516 throw new IllegalStateException("Unavailable in lockdown mode"); 517 } 518 } 519 520 /** 521 * Starts the always-on VPN {@link VpnService} for user {@param userId}, which should perform 522 * some setup and then call {@code establish()} to connect. 523 * 524 * @return {@code true} if the service was started, the service was already connected, or there 525 * was no always-on VPN to start. {@code false} otherwise. 526 */ startAlwaysOnVpn(int userId)527 private boolean startAlwaysOnVpn(int userId) { 528 synchronized (mVpns) { 529 Vpn vpn = mVpns.get(userId); 530 if (vpn == null) { 531 // Shouldn't happen as all code paths that point here should have checked the Vpn 532 // exists already. 533 Log.wtf(TAG, "User " + userId + " has no Vpn configuration"); 534 return false; 535 } 536 537 return vpn.startAlwaysOnVpn(); 538 } 539 } 540 541 @Override isAlwaysOnVpnPackageSupported(int userId, String packageName)542 public boolean isAlwaysOnVpnPackageSupported(int userId, String packageName) { 543 enforceSettingsPermission(); 544 enforceCrossUserPermission(userId); 545 546 synchronized (mVpns) { 547 Vpn vpn = mVpns.get(userId); 548 if (vpn == null) { 549 logw("User " + userId + " has no Vpn configuration"); 550 return false; 551 } 552 return vpn.isAlwaysOnPackageSupported(packageName); 553 } 554 } 555 556 @Override setAlwaysOnVpnPackage( int userId, String packageName, boolean lockdown, List<String> lockdownAllowlist)557 public boolean setAlwaysOnVpnPackage( 558 int userId, String packageName, boolean lockdown, List<String> lockdownAllowlist) { 559 enforceControlAlwaysOnVpnPermission(); 560 enforceCrossUserPermission(userId); 561 562 synchronized (mVpns) { 563 // Can't set always-on VPN if legacy VPN is already in lockdown mode. 564 if (isLockdownVpnEnabled()) { 565 return false; 566 } 567 568 Vpn vpn = mVpns.get(userId); 569 if (vpn == null) { 570 logw("User " + userId + " has no Vpn configuration"); 571 return false; 572 } 573 if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownAllowlist)) { 574 return false; 575 } 576 if (!startAlwaysOnVpn(userId)) { 577 vpn.setAlwaysOnPackage(null, false, null); 578 return false; 579 } 580 } 581 return true; 582 } 583 584 @Override getAlwaysOnVpnPackage(int userId)585 public String getAlwaysOnVpnPackage(int userId) { 586 enforceControlAlwaysOnVpnPermission(); 587 enforceCrossUserPermission(userId); 588 589 synchronized (mVpns) { 590 Vpn vpn = mVpns.get(userId); 591 if (vpn == null) { 592 logw("User " + userId + " has no Vpn configuration"); 593 return null; 594 } 595 return vpn.getAlwaysOnPackage(); 596 } 597 } 598 599 @Override isVpnLockdownEnabled(int userId)600 public boolean isVpnLockdownEnabled(int userId) { 601 enforceControlAlwaysOnVpnPermission(); 602 enforceCrossUserPermission(userId); 603 604 synchronized (mVpns) { 605 Vpn vpn = mVpns.get(userId); 606 if (vpn == null) { 607 logw("User " + userId + " has no Vpn configuration"); 608 return false; 609 } 610 return vpn.getLockdown(); 611 } 612 } 613 614 @Override getVpnLockdownAllowlist(int userId)615 public List<String> getVpnLockdownAllowlist(int userId) { 616 enforceControlAlwaysOnVpnPermission(); 617 enforceCrossUserPermission(userId); 618 619 synchronized (mVpns) { 620 Vpn vpn = mVpns.get(userId); 621 if (vpn == null) { 622 logw("User " + userId + " has no Vpn configuration"); 623 return null; 624 } 625 return vpn.getLockdownAllowlist(); 626 } 627 } 628 629 @GuardedBy("mVpns") getVpnIfOwner()630 private Vpn getVpnIfOwner() { 631 return getVpnIfOwner(mDeps.getCallingUid()); 632 } 633 634 // TODO: stop calling into Vpn.java and get this information from data in this class. 635 @GuardedBy("mVpns") getVpnIfOwner(int uid)636 private Vpn getVpnIfOwner(int uid) { 637 final int user = UserHandle.getUserId(uid); 638 639 final Vpn vpn = mVpns.get(user); 640 if (vpn == null) { 641 return null; 642 } else { 643 final UnderlyingNetworkInfo info = vpn.getUnderlyingNetworkInfo(); 644 return (info == null || info.getOwnerUid() != uid) ? null : vpn; 645 } 646 } 647 registerReceivers()648 private void registerReceivers() { 649 // Set up the listener for user state for creating user VPNs. 650 // Should run on mHandler to avoid any races. 651 IntentFilter intentFilter = new IntentFilter(); 652 intentFilter.addAction(Intent.ACTION_USER_STARTED); 653 intentFilter.addAction(Intent.ACTION_USER_STOPPED); 654 intentFilter.addAction(Intent.ACTION_USER_ADDED); 655 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 656 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); 657 658 mUserAllContext.registerReceiver( 659 mIntentReceiver, 660 intentFilter, 661 null /* broadcastPermission */, 662 mHandler); 663 mContext.createContextAsUser(UserHandle.SYSTEM, 0 /* flags */).registerReceiver( 664 mUserPresentReceiver, 665 new IntentFilter(Intent.ACTION_USER_PRESENT), 666 null /* broadcastPermission */, 667 mHandler /* scheduler */); 668 669 // Listen to package add and removal events for all users. 670 intentFilter = new IntentFilter(); 671 intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 672 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 673 intentFilter.addDataScheme("package"); 674 mUserAllContext.registerReceiver( 675 mIntentReceiver, 676 intentFilter, 677 null /* broadcastPermission */, 678 mHandler); 679 680 // Listen to lockdown VPN reset. 681 intentFilter = new IntentFilter(); 682 intentFilter.addAction(LockdownVpnTracker.ACTION_LOCKDOWN_RESET); 683 mUserAllContext.registerReceiver( 684 mIntentReceiver, intentFilter, NETWORK_STACK, mHandler); 685 } 686 687 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 688 @Override 689 public void onReceive(Context context, Intent intent) { 690 ensureRunningOnHandlerThread(); 691 final String action = intent.getAction(); 692 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 693 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 694 final Uri packageData = intent.getData(); 695 final String packageName = 696 packageData != null ? packageData.getSchemeSpecificPart() : null; 697 698 if (LockdownVpnTracker.ACTION_LOCKDOWN_RESET.equals(action)) { 699 onVpnLockdownReset(); 700 } 701 702 // UserId should be filled for below intents, check the existence. 703 if (userId == UserHandle.USER_NULL) return; 704 705 if (Intent.ACTION_USER_STARTED.equals(action)) { 706 onUserStarted(userId); 707 } else if (Intent.ACTION_USER_STOPPED.equals(action)) { 708 onUserStopped(userId); 709 } else if (Intent.ACTION_USER_ADDED.equals(action)) { 710 onUserAdded(userId); 711 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 712 onUserRemoved(userId); 713 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { 714 onUserUnlocked(userId); 715 } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) { 716 onPackageReplaced(packageName, uid); 717 } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { 718 final boolean isReplacing = intent.getBooleanExtra( 719 Intent.EXTRA_REPLACING, false); 720 onPackageRemoved(packageName, uid, isReplacing); 721 } else { 722 Log.wtf(TAG, "received unexpected intent: " + action); 723 } 724 } 725 }; 726 727 private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() { 728 @Override 729 public void onReceive(Context context, Intent intent) { 730 ensureRunningOnHandlerThread(); 731 // Try creating lockdown tracker, since user present usually means 732 // unlocked keystore. 733 updateLockdownVpn(); 734 // Use the same context that registered receiver before to unregister it. Because use 735 // different context to unregister receiver will cause exception. 736 context.unregisterReceiver(this); 737 } 738 }; 739 onUserStarted(int userId)740 private void onUserStarted(int userId) { 741 synchronized (mVpns) { 742 Vpn userVpn = mVpns.get(userId); 743 if (userVpn != null) { 744 loge("Starting user already has a VPN"); 745 return; 746 } 747 userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, 748 new VpnProfileStore()); 749 mVpns.put(userId, userVpn); 750 if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { 751 updateLockdownVpn(); 752 } 753 } 754 } 755 onUserStopped(int userId)756 private void onUserStopped(int userId) { 757 synchronized (mVpns) { 758 Vpn userVpn = mVpns.get(userId); 759 if (userVpn == null) { 760 loge("Stopped user has no VPN"); 761 return; 762 } 763 userVpn.onUserStopped(); 764 mVpns.delete(userId); 765 } 766 } 767 768 @Override isCallerCurrentAlwaysOnVpnApp()769 public boolean isCallerCurrentAlwaysOnVpnApp() { 770 synchronized (mVpns) { 771 Vpn vpn = getVpnIfOwner(); 772 return vpn != null && vpn.getAlwaysOn(); 773 } 774 } 775 776 @Override isCallerCurrentAlwaysOnVpnLockdownApp()777 public boolean isCallerCurrentAlwaysOnVpnLockdownApp() { 778 synchronized (mVpns) { 779 Vpn vpn = getVpnIfOwner(); 780 return vpn != null && vpn.getLockdown(); 781 } 782 } 783 784 onUserAdded(int userId)785 private void onUserAdded(int userId) { 786 synchronized (mVpns) { 787 final int vpnsSize = mVpns.size(); 788 for (int i = 0; i < vpnsSize; i++) { 789 Vpn vpn = mVpns.valueAt(i); 790 vpn.onUserAdded(userId); 791 } 792 } 793 } 794 onUserRemoved(int userId)795 private void onUserRemoved(int userId) { 796 synchronized (mVpns) { 797 final int vpnsSize = mVpns.size(); 798 for (int i = 0; i < vpnsSize; i++) { 799 Vpn vpn = mVpns.valueAt(i); 800 vpn.onUserRemoved(userId); 801 } 802 } 803 } 804 onPackageReplaced(String packageName, int uid)805 private void onPackageReplaced(String packageName, int uid) { 806 if (TextUtils.isEmpty(packageName) || uid < 0) { 807 Log.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid); 808 return; 809 } 810 final int userId = UserHandle.getUserId(uid); 811 synchronized (mVpns) { 812 final Vpn vpn = mVpns.get(userId); 813 if (vpn == null) { 814 return; 815 } 816 // Legacy always-on VPN won't be affected since the package name is not set. 817 if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) { 818 log("Restarting always-on VPN package " + packageName + " for user " 819 + userId); 820 vpn.startAlwaysOnVpn(); 821 } 822 } 823 } 824 onPackageRemoved(String packageName, int uid, boolean isReplacing)825 private void onPackageRemoved(String packageName, int uid, boolean isReplacing) { 826 if (TextUtils.isEmpty(packageName) || uid < 0) { 827 Log.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid); 828 return; 829 } 830 831 final int userId = UserHandle.getUserId(uid); 832 synchronized (mVpns) { 833 final Vpn vpn = mVpns.get(userId); 834 if (vpn == null) { 835 return; 836 } 837 // Legacy always-on VPN won't be affected since the package name is not set. 838 if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) { 839 log("Removing always-on VPN package " + packageName + " for user " 840 + userId); 841 vpn.setAlwaysOnPackage(null, false, null); 842 } 843 } 844 } 845 onUserUnlocked(int userId)846 private void onUserUnlocked(int userId) { 847 synchronized (mVpns) { 848 // User present may be sent because of an unlock, which might mean an unlocked keystore. 849 if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { 850 updateLockdownVpn(); 851 } else { 852 startAlwaysOnVpn(userId); 853 } 854 } 855 } 856 onVpnLockdownReset()857 private void onVpnLockdownReset() { 858 synchronized (mVpns) { 859 if (mLockdownTracker != null) mLockdownTracker.reset(); 860 } 861 } 862 863 864 @Override factoryReset()865 public void factoryReset() { 866 enforceSettingsPermission(); 867 868 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET) 869 || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { 870 return; 871 } 872 873 // Remove always-on package 874 final int userId = UserHandle.getCallingUserId(); 875 synchronized (mVpns) { 876 final String alwaysOnPackage = getAlwaysOnVpnPackage(userId); 877 if (alwaysOnPackage != null) { 878 setAlwaysOnVpnPackage(userId, null, false, null); 879 setVpnPackageAuthorization(alwaysOnPackage, userId, VpnManager.TYPE_VPN_NONE); 880 } 881 882 // Turn Always-on VPN off 883 if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) { 884 final long ident = Binder.clearCallingIdentity(); 885 try { 886 mVpnProfileStore.remove(Credentials.LOCKDOWN_VPN); 887 mLockdownEnabled = false; 888 setLockdownTracker(null); 889 } finally { 890 Binder.restoreCallingIdentity(ident); 891 } 892 } 893 894 // Turn VPN off 895 VpnConfig vpnConfig = getVpnConfig(userId); 896 if (vpnConfig != null) { 897 if (vpnConfig.legacy) { 898 prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); 899 } else { 900 // Prevent this app (packagename = vpnConfig.user) from initiating 901 // VPN connections in the future without user intervention. 902 setVpnPackageAuthorization( 903 vpnConfig.user, userId, VpnManager.TYPE_VPN_NONE); 904 905 prepareVpn(null, VpnConfig.LEGACY_VPN, userId); 906 } 907 } 908 } 909 } 910 ensureRunningOnHandlerThread()911 private void ensureRunningOnHandlerThread() { 912 if (mHandler.getLooper().getThread() != Thread.currentThread()) { 913 throw new IllegalStateException( 914 "Not running on VpnManagerService thread: " 915 + Thread.currentThread().getName()); 916 } 917 } 918 enforceControlAlwaysOnVpnPermission()919 private void enforceControlAlwaysOnVpnPermission() { 920 mContext.enforceCallingOrSelfPermission( 921 android.Manifest.permission.CONTROL_ALWAYS_ON_VPN, 922 "VpnManagerService"); 923 } 924 925 /** 926 * Require that the caller is either in the same user or has appropriate permission to interact 927 * across users. 928 * 929 * @param userId Target user for whatever operation the current IPC is supposed to perform. 930 */ enforceCrossUserPermission(int userId)931 private void enforceCrossUserPermission(int userId) { 932 if (userId == UserHandle.getCallingUserId()) { 933 // Not a cross-user call. 934 return; 935 } 936 mContext.enforceCallingOrSelfPermission( 937 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, 938 "VpnManagerService"); 939 } 940 enforceSettingsPermission()941 private void enforceSettingsPermission() { 942 enforceAnyPermissionOf(mContext, 943 android.Manifest.permission.NETWORK_SETTINGS, 944 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); 945 } 946 log(String s)947 private static void log(String s) { 948 Log.d(TAG, s); 949 } 950 logw(String s)951 private static void logw(String s) { 952 Log.w(TAG, s); 953 } 954 loge(String s)955 private static void loge(String s) { 956 Log.e(TAG, s); 957 } 958 } 959