Vpn.java revision 05542603dd4f1e0ea47a3dca01de3999a9a329a9
1/* 2 * Copyright (C) 2011 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 17package com.android.server.connectivity; 18 19import static android.Manifest.permission.BIND_VPN_SERVICE; 20import static android.system.OsConstants.AF_INET; 21import static android.system.OsConstants.AF_INET6; 22 23import android.app.AppGlobals; 24import android.app.AppOpsManager; 25import android.content.BroadcastReceiver; 26import android.content.ComponentName; 27import android.content.Context; 28import android.content.Intent; 29import android.content.IntentFilter; 30import android.content.ServiceConnection; 31import android.content.pm.ApplicationInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.PackageManager.NameNotFoundException; 34import android.content.pm.ResolveInfo; 35import android.content.pm.UserInfo; 36import android.net.ConnectivityManager; 37import android.net.IConnectivityManager; 38import android.net.INetworkManagementEventObserver; 39import android.net.LinkAddress; 40import android.net.LinkProperties; 41import android.net.LocalSocket; 42import android.net.LocalSocketAddress; 43import android.net.NetworkAgent; 44import android.net.NetworkCapabilities; 45import android.net.NetworkInfo; 46import android.net.NetworkInfo.DetailedState; 47import android.net.NetworkMisc; 48import android.net.RouteInfo; 49import android.net.UidRange; 50import android.os.Binder; 51import android.os.FileUtils; 52import android.os.IBinder; 53import android.os.INetworkManagementService; 54import android.os.Looper; 55import android.os.Parcel; 56import android.os.ParcelFileDescriptor; 57import android.os.Process; 58import android.os.RemoteException; 59import android.os.SystemClock; 60import android.os.SystemService; 61import android.os.UserHandle; 62import android.os.UserManager; 63import android.security.Credentials; 64import android.security.KeyStore; 65import android.util.Log; 66 67import com.android.internal.annotations.GuardedBy; 68import com.android.internal.net.LegacyVpnInfo; 69import com.android.internal.net.VpnConfig; 70import com.android.internal.net.VpnProfile; 71import com.android.server.net.BaseNetworkObserver; 72 73import libcore.io.IoUtils; 74 75import java.io.File; 76import java.io.IOException; 77import java.io.InputStream; 78import java.io.OutputStream; 79import java.net.Inet4Address; 80import java.net.Inet6Address; 81import java.net.InetAddress; 82import java.nio.charset.StandardCharsets; 83import java.util.ArrayList; 84import java.util.Arrays; 85import java.util.List; 86import java.util.concurrent.atomic.AtomicInteger; 87 88/** 89 * @hide 90 */ 91public class Vpn { 92 private static final String NETWORKTYPE = "VPN"; 93 private static final String TAG = "Vpn"; 94 private static final boolean LOGD = true; 95 96 // TODO: create separate trackers for each unique VPN to support 97 // automated reconnection 98 99 private Context mContext; 100 private NetworkInfo mNetworkInfo; 101 private String mPackage; 102 private int mOwnerUID; 103 private String mInterface; 104 private boolean mAllowIPv4; 105 private boolean mAllowIPv6; 106 private Connection mConnection; 107 private LegacyVpnRunner mLegacyVpnRunner; 108 private volatile boolean mEnableTeardown = true; 109 private final IConnectivityManager mConnService; 110 private final INetworkManagementService mNetd; 111 private VpnConfig mConfig; 112 private NetworkAgent mNetworkAgent; 113 private final Looper mLooper; 114 private final NetworkCapabilities mNetworkCapabilities; 115 116 /* list of users using this VPN. */ 117 @GuardedBy("this") 118 private List<UidRange> mVpnUsers = null; 119 private BroadcastReceiver mUserIntentReceiver = null; 120 121 private final int mUserId; 122 123 public Vpn(Looper looper, Context context, INetworkManagementService netService, 124 IConnectivityManager connService, int userId) { 125 mContext = context; 126 mNetd = netService; 127 mConnService = connService; 128 mUserId = userId; 129 mLooper = looper; 130 131 mPackage = VpnConfig.LEGACY_VPN; 132 mOwnerUID = getAppUid(mPackage); 133 134 try { 135 netService.registerObserver(mObserver); 136 } catch (RemoteException e) { 137 Log.wtf(TAG, "Problem registering observer", e); 138 } 139 if (userId == UserHandle.USER_OWNER) { 140 // Owner's VPN also needs to handle restricted users 141 mUserIntentReceiver = new BroadcastReceiver() { 142 @Override 143 public void onReceive(Context context, Intent intent) { 144 final String action = intent.getAction(); 145 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 146 UserHandle.USER_NULL); 147 if (userId == UserHandle.USER_NULL) return; 148 149 if (Intent.ACTION_USER_ADDED.equals(action)) { 150 onUserAdded(userId); 151 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 152 onUserRemoved(userId); 153 } 154 } 155 }; 156 157 IntentFilter intentFilter = new IntentFilter(); 158 intentFilter.addAction(Intent.ACTION_USER_ADDED); 159 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 160 mContext.registerReceiverAsUser( 161 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); 162 } 163 164 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, ""); 165 // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332 166 mNetworkCapabilities = new NetworkCapabilities(); 167 mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); 168 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); 169 } 170 171 /** 172 * Set if this object is responsible for watching for {@link NetworkInfo} 173 * teardown. When {@code false}, teardown is handled externally by someone 174 * else. 175 */ 176 public void setEnableTeardown(boolean enableTeardown) { 177 mEnableTeardown = enableTeardown; 178 } 179 180 /** 181 * Update current state, dispaching event to listeners. 182 */ 183 private void updateState(DetailedState detailedState, String reason) { 184 if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); 185 mNetworkInfo.setDetailedState(detailedState, reason, null); 186 if (mNetworkAgent != null) { 187 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 188 } 189 } 190 191 /** 192 * Prepare for a VPN application. This method is designed to solve 193 * race conditions. It first compares the current prepared package 194 * with {@code oldPackage}. If they are the same, the prepared 195 * package is revoked and replaced with {@code newPackage}. If 196 * {@code oldPackage} is {@code null}, the comparison is omitted. 197 * If {@code newPackage} is the same package or {@code null}, the 198 * revocation is omitted. This method returns {@code true} if the 199 * operation is succeeded. 200 * 201 * Legacy VPN is handled specially since it is not a real package. 202 * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and 203 * it can be revoked by itself. 204 * 205 * @param oldPackage The package name of the old VPN application. 206 * @param newPackage The package name of the new VPN application. 207 * @return true if the operation is succeeded. 208 */ 209 public synchronized boolean prepare(String oldPackage, String newPackage) { 210 // Return false if the package does not match. 211 if (oldPackage != null && !oldPackage.equals(mPackage)) { 212 // The package doesn't match. If this VPN was not previously authorized, return false 213 // to force user authorization. Otherwise, revoke the VPN anyway. 214 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) { 215 long token = Binder.clearCallingIdentity(); 216 try { 217 // This looks bizarre, but it is what ConfirmDialog in VpnDialogs is doing when 218 // the user clicks through to allow the VPN to consent. So we are emulating the 219 // action of the dialog without actually showing it. 220 prepare(null, oldPackage); 221 } finally { 222 Binder.restoreCallingIdentity(token); 223 } 224 return true; 225 } 226 return false; 227 } 228 229 // Return true if we do not need to revoke. 230 if (newPackage == null || 231 (newPackage.equals(mPackage) && !newPackage.equals(VpnConfig.LEGACY_VPN))) { 232 return true; 233 } 234 235 // Check if the caller is authorized. 236 enforceControlPermission(); 237 238 // Reset the interface. 239 if (mInterface != null) { 240 agentDisconnect(); 241 jniReset(mInterface); 242 mInterface = null; 243 mVpnUsers = null; 244 } 245 246 // Revoke the connection or stop LegacyVpnRunner. 247 if (mConnection != null) { 248 try { 249 mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION, 250 Parcel.obtain(), null, IBinder.FLAG_ONEWAY); 251 } catch (Exception e) { 252 // ignore 253 } 254 mContext.unbindService(mConnection); 255 mConnection = null; 256 } else if (mLegacyVpnRunner != null) { 257 mLegacyVpnRunner.exit(); 258 mLegacyVpnRunner = null; 259 } 260 261 long token = Binder.clearCallingIdentity(); 262 try { 263 mNetd.denyProtect(mOwnerUID); 264 } catch (Exception e) { 265 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); 266 } finally { 267 Binder.restoreCallingIdentity(token); 268 } 269 270 Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); 271 mPackage = newPackage; 272 mOwnerUID = getAppUid(newPackage); 273 token = Binder.clearCallingIdentity(); 274 try { 275 mNetd.allowProtect(mOwnerUID); 276 } catch (Exception e) { 277 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); 278 } finally { 279 Binder.restoreCallingIdentity(token); 280 } 281 mConfig = null; 282 283 updateState(DetailedState.IDLE, "prepare"); 284 return true; 285 } 286 287 /** 288 * Set whether the current package has the ability to launch VPNs without user intervention. 289 */ 290 public void setPackageAuthorization(boolean authorized) { 291 // Check if the caller is authorized. 292 enforceControlPermission(); 293 294 if (mPackage == null || VpnConfig.LEGACY_VPN.equals(mPackage)) { 295 return; 296 } 297 298 long token = Binder.clearCallingIdentity(); 299 try { 300 AppOpsManager appOps = 301 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 302 appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, mOwnerUID, mPackage, 303 authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); 304 } catch (Exception e) { 305 Log.wtf(TAG, "Failed to set app ops for package " + mPackage, e); 306 } finally { 307 Binder.restoreCallingIdentity(token); 308 } 309 } 310 311 private boolean isVpnUserPreConsented(String packageName) { 312 AppOpsManager appOps = 313 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 314 315 // Verify that the caller matches the given package and has permission to activate VPNs. 316 return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(), 317 packageName) == AppOpsManager.MODE_ALLOWED; 318 } 319 320 private int getAppUid(String app) { 321 if (VpnConfig.LEGACY_VPN.equals(app)) { 322 return Process.myUid(); 323 } 324 PackageManager pm = mContext.getPackageManager(); 325 int result; 326 try { 327 result = pm.getPackageUid(app, mUserId); 328 } catch (NameNotFoundException e) { 329 result = -1; 330 } 331 return result; 332 } 333 334 public NetworkInfo getNetworkInfo() { 335 return mNetworkInfo; 336 } 337 338 private void agentConnect() { 339 LinkProperties lp = new LinkProperties(); 340 lp.setInterfaceName(mInterface); 341 342 boolean hasDefaultRoute = false; 343 for (RouteInfo route : mConfig.routes) { 344 lp.addRoute(route); 345 if (route.isDefaultRoute()) hasDefaultRoute = true; 346 } 347 if (hasDefaultRoute) { 348 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 349 } else { 350 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 351 } 352 353 if (mConfig.dnsServers != null) { 354 for (String dnsServer : mConfig.dnsServers) { 355 InetAddress address = InetAddress.parseNumericAddress(dnsServer); 356 lp.addDnsServer(address); 357 if (address instanceof Inet4Address) { 358 mAllowIPv4 = true; 359 } else { 360 mAllowIPv6 = true; 361 } 362 } 363 } 364 365 // Concatenate search domains into a string. 366 StringBuilder buffer = new StringBuilder(); 367 if (mConfig.searchDomains != null) { 368 for (String domain : mConfig.searchDomains) { 369 buffer.append(domain).append(' '); 370 } 371 } 372 lp.setDomains(buffer.toString().trim()); 373 374 mNetworkInfo.setIsAvailable(true); 375 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 376 377 NetworkMisc networkMisc = new NetworkMisc(); 378 networkMisc.allowBypass = mConfig.allowBypass; 379 380 long token = Binder.clearCallingIdentity(); 381 try { 382 mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE, 383 mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) { 384 @Override 385 public void unwanted() { 386 // We are user controlled, not driven by NetworkRequest. 387 } 388 }; 389 } finally { 390 Binder.restoreCallingIdentity(token); 391 } 392 393 if (!mAllowIPv4) { 394 mNetworkAgent.blockAddressFamily(AF_INET); 395 } 396 if (!mAllowIPv6) { 397 mNetworkAgent.blockAddressFamily(AF_INET6); 398 } 399 400 addVpnUserLocked(mUserId); 401 // If we are owner assign all Restricted Users to this VPN 402 if (mUserId == UserHandle.USER_OWNER) { 403 token = Binder.clearCallingIdentity(); 404 List<UserInfo> users; 405 try { 406 users = UserManager.get(mContext).getUsers(); 407 } finally { 408 Binder.restoreCallingIdentity(token); 409 } 410 for (UserInfo user : users) { 411 if (user.isRestricted()) { 412 addVpnUserLocked(user.id); 413 } 414 } 415 } 416 mNetworkAgent.addUidRanges(mVpnUsers.toArray(new UidRange[mVpnUsers.size()])); 417 } 418 419 private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) { 420 networkInfo.setIsAvailable(false); 421 networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 422 if (networkAgent != null) { 423 networkAgent.sendNetworkInfo(networkInfo); 424 } 425 } 426 427 private void agentDisconnect(NetworkAgent networkAgent) { 428 NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); 429 agentDisconnect(networkInfo, networkAgent); 430 } 431 432 private void agentDisconnect() { 433 if (mNetworkInfo.isConnected()) { 434 agentDisconnect(mNetworkInfo, mNetworkAgent); 435 mNetworkAgent = null; 436 } 437 } 438 439 /** 440 * Establish a VPN network and return the file descriptor of the VPN 441 * interface. This methods returns {@code null} if the application is 442 * revoked or not prepared. 443 * 444 * @param config The parameters to configure the network. 445 * @return The file descriptor of the VPN interface. 446 */ 447 public synchronized ParcelFileDescriptor establish(VpnConfig config) { 448 // Check if the caller is already prepared. 449 UserManager mgr = UserManager.get(mContext); 450 if (Binder.getCallingUid() != mOwnerUID) { 451 return null; 452 } 453 // Check if the service is properly declared. 454 Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 455 intent.setClassName(mPackage, config.user); 456 long token = Binder.clearCallingIdentity(); 457 try { 458 // Restricted users are not allowed to create VPNs, they are tied to Owner 459 UserInfo user = mgr.getUserInfo(mUserId); 460 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { 461 throw new SecurityException("Restricted users cannot establish VPNs"); 462 } 463 464 ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent, 465 null, 0, mUserId); 466 if (info == null) { 467 throw new SecurityException("Cannot find " + config.user); 468 } 469 if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) { 470 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE); 471 } 472 } catch (RemoteException e) { 473 throw new SecurityException("Cannot find " + config.user); 474 } finally { 475 Binder.restoreCallingIdentity(token); 476 } 477 478 // Save the old config in case we need to go back. 479 VpnConfig oldConfig = mConfig; 480 String oldInterface = mInterface; 481 Connection oldConnection = mConnection; 482 NetworkAgent oldNetworkAgent = mNetworkAgent; 483 mNetworkAgent = null; 484 List<UidRange> oldUsers = mVpnUsers; 485 boolean oldAllowIPv4 = mAllowIPv4; 486 boolean oldAllowIPv6 = mAllowIPv6; 487 488 // Configure the interface. Abort if any of these steps fails. 489 ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); 490 try { 491 updateState(DetailedState.CONNECTING, "establish"); 492 String interfaze = jniGetName(tun.getFd()); 493 494 // TEMP use the old jni calls until there is support for netd address setting 495 StringBuilder builder = new StringBuilder(); 496 for (LinkAddress address : config.addresses) { 497 builder.append(" " + address); 498 } 499 if (jniSetAddresses(interfaze, builder.toString()) < 1) { 500 throw new IllegalArgumentException("At least one address must be specified"); 501 } 502 Connection connection = new Connection(); 503 if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, 504 new UserHandle(mUserId))) { 505 throw new IllegalStateException("Cannot bind " + config.user); 506 } 507 508 mConnection = connection; 509 mInterface = interfaze; 510 511 // Fill more values. 512 config.user = mPackage; 513 config.interfaze = mInterface; 514 config.startTime = SystemClock.elapsedRealtime(); 515 mConfig = config; 516 517 // Set up forwarding and DNS rules. 518 mVpnUsers = new ArrayList<UidRange>(); 519 mAllowIPv4 = mConfig.allowIPv4; 520 mAllowIPv6 = mConfig.allowIPv6; 521 522 agentConnect(); 523 524 if (oldConnection != null) { 525 mContext.unbindService(oldConnection); 526 } 527 // Remove the old tun's user forwarding rules 528 // The new tun's user rules have already been added so they will take over 529 // as rules are deleted. This prevents data leakage as the rules are moved over. 530 agentDisconnect(oldNetworkAgent); 531 if (oldInterface != null && !oldInterface.equals(interfaze)) { 532 jniReset(oldInterface); 533 } 534 535 try { 536 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); 537 } catch (IOException e) { 538 throw new IllegalStateException( 539 "Cannot set tunnel's fd as blocking=" + config.blocking, e); 540 } 541 } catch (RuntimeException e) { 542 IoUtils.closeQuietly(tun); 543 agentDisconnect(); 544 // restore old state 545 mConfig = oldConfig; 546 mConnection = oldConnection; 547 mVpnUsers = oldUsers; 548 mNetworkAgent = oldNetworkAgent; 549 mInterface = oldInterface; 550 mAllowIPv4 = oldAllowIPv4; 551 mAllowIPv6 = oldAllowIPv6; 552 throw e; 553 } 554 Log.i(TAG, "Established by " + config.user + " on " + mInterface); 555 return tun; 556 } 557 558 private boolean isRunningLocked() { 559 return mVpnUsers != null; 560 } 561 562 // Note: This function adds to mVpnUsers but does not publish list to NetworkAgent. 563 private void addVpnUserLocked(int user) { 564 if (!isRunningLocked()) { 565 throw new IllegalStateException("VPN is not active"); 566 } 567 568 // add the user 569 mVpnUsers.add(UidRange.createForUser(user)); 570 } 571 572 private void removeVpnUserLocked(int user) { 573 if (!isRunningLocked()) { 574 throw new IllegalStateException("VPN is not active"); 575 } 576 UidRange uidRange = UidRange.createForUser(user); 577 if (mNetworkAgent != null) { 578 mNetworkAgent.removeUidRanges(new UidRange[] { uidRange }); 579 } 580 mVpnUsers.remove(uidRange); 581 } 582 583 private void onUserAdded(int userId) { 584 // If the user is restricted tie them to the owner's VPN 585 synchronized(Vpn.this) { 586 UserManager mgr = UserManager.get(mContext); 587 UserInfo user = mgr.getUserInfo(userId); 588 if (user.isRestricted()) { 589 try { 590 addVpnUserLocked(userId); 591 if (mNetworkAgent != null) { 592 UidRange uidRange = UidRange.createForUser(userId); 593 mNetworkAgent.addUidRanges(new UidRange[] { uidRange }); 594 } 595 } catch (Exception e) { 596 Log.wtf(TAG, "Failed to add restricted user to owner", e); 597 } 598 } 599 } 600 } 601 602 private void onUserRemoved(int userId) { 603 // clean up if restricted 604 synchronized(Vpn.this) { 605 UserManager mgr = UserManager.get(mContext); 606 UserInfo user = mgr.getUserInfo(userId); 607 if (user.isRestricted()) { 608 try { 609 removeVpnUserLocked(userId); 610 } catch (Exception e) { 611 Log.wtf(TAG, "Failed to remove restricted user to owner", e); 612 } 613 } 614 } 615 } 616 617 /** 618 * Return the configuration of the currently running VPN. 619 */ 620 public VpnConfig getVpnConfig() { 621 enforceControlPermission(); 622 return mConfig; 623 } 624 625 @Deprecated 626 public synchronized void interfaceStatusChanged(String iface, boolean up) { 627 try { 628 mObserver.interfaceStatusChanged(iface, up); 629 } catch (RemoteException e) { 630 // ignored; target is local 631 } 632 } 633 634 private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { 635 @Override 636 public void interfaceStatusChanged(String interfaze, boolean up) { 637 synchronized (Vpn.this) { 638 if (!up && mLegacyVpnRunner != null) { 639 mLegacyVpnRunner.check(interfaze); 640 } 641 } 642 } 643 644 @Override 645 public void interfaceRemoved(String interfaze) { 646 synchronized (Vpn.this) { 647 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { 648 mVpnUsers = null; 649 mInterface = null; 650 if (mConnection != null) { 651 mContext.unbindService(mConnection); 652 mConnection = null; 653 agentDisconnect(); 654 } else if (mLegacyVpnRunner != null) { 655 mLegacyVpnRunner.exit(); 656 mLegacyVpnRunner = null; 657 } 658 } 659 } 660 } 661 }; 662 663 private void enforceControlPermission() { 664 // System user is allowed to control VPN. 665 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 666 return; 667 } 668 int appId = UserHandle.getAppId(Binder.getCallingUid()); 669 final long token = Binder.clearCallingIdentity(); 670 try { 671 // System VPN dialogs are also allowed to control VPN. 672 PackageManager pm = mContext.getPackageManager(); 673 ApplicationInfo app = pm.getApplicationInfo(VpnConfig.DIALOGS_PACKAGE, 0); 674 if (((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == app.uid)) { 675 return; 676 } 677 // SystemUI dialogs are also allowed to control VPN. 678 ApplicationInfo sysUiApp = pm.getApplicationInfo("com.android.systemui", 0); 679 if (((sysUiApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == sysUiApp.uid)) { 680 return; 681 } 682 } catch (Exception e) { 683 // ignore 684 } finally { 685 Binder.restoreCallingIdentity(token); 686 } 687 688 throw new SecurityException("Unauthorized Caller"); 689 } 690 691 private class Connection implements ServiceConnection { 692 private IBinder mService; 693 694 @Override 695 public void onServiceConnected(ComponentName name, IBinder service) { 696 mService = service; 697 } 698 699 @Override 700 public void onServiceDisconnected(ComponentName name) { 701 mService = null; 702 } 703 } 704 705 public synchronized boolean addAddress(String address, int prefixLength) { 706 if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { 707 return false; 708 } 709 boolean success = jniAddAddress(mInterface, address, prefixLength); 710 if (success && (!mAllowIPv4 || !mAllowIPv6)) { 711 try { 712 InetAddress inetAddress = InetAddress.parseNumericAddress(address); 713 if ((inetAddress instanceof Inet4Address) && !mAllowIPv4) { 714 mAllowIPv4 = true; 715 mNetworkAgent.unblockAddressFamily(AF_INET); 716 } else if ((inetAddress instanceof Inet6Address) && !mAllowIPv6) { 717 mAllowIPv6 = true; 718 mNetworkAgent.unblockAddressFamily(AF_INET6); 719 } 720 } catch (IllegalArgumentException e) { 721 // ignore 722 } 723 } 724 // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService 725 // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set 726 // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect()) 727 // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()). 728 // TODO: Maybe fix this. 729 return success; 730 } 731 732 public synchronized boolean removeAddress(String address, int prefixLength) { 733 if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { 734 return false; 735 } 736 boolean success = jniDelAddress(mInterface, address, prefixLength); 737 // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService 738 // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set 739 // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect()) 740 // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()). 741 // TODO: Maybe fix this. 742 return success; 743 } 744 745 private native int jniCreate(int mtu); 746 private native String jniGetName(int tun); 747 private native int jniSetAddresses(String interfaze, String addresses); 748 private native void jniReset(String interfaze); 749 private native int jniCheck(String interfaze); 750 private native boolean jniAddAddress(String interfaze, String address, int prefixLen); 751 private native boolean jniDelAddress(String interfaze, String address, int prefixLen); 752 753 private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { 754 for (RouteInfo route : prop.getAllRoutes()) { 755 // Currently legacy VPN only works on IPv4. 756 if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 757 return route; 758 } 759 } 760 761 throw new IllegalStateException("Unable to find IPv4 default gateway"); 762 } 763 764 /** 765 * Start legacy VPN, controlling native daemons as needed. Creates a 766 * secondary thread to perform connection work, returning quickly. 767 */ 768 public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) { 769 enforceControlPermission(); 770 if (!keyStore.isUnlocked()) { 771 throw new IllegalStateException("KeyStore isn't unlocked"); 772 } 773 UserManager mgr = UserManager.get(mContext); 774 UserInfo user = mgr.getUserInfo(mUserId); 775 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { 776 throw new SecurityException("Restricted users cannot establish VPNs"); 777 } 778 779 final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); 780 final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); 781 final String iface = ipv4DefaultRoute.getInterface(); 782 783 // Load certificates. 784 String privateKey = ""; 785 String userCert = ""; 786 String caCert = ""; 787 String serverCert = ""; 788 if (!profile.ipsecUserCert.isEmpty()) { 789 privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; 790 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); 791 userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 792 } 793 if (!profile.ipsecCaCert.isEmpty()) { 794 byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); 795 caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 796 } 797 if (!profile.ipsecServerCert.isEmpty()) { 798 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); 799 serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 800 } 801 if (privateKey == null || userCert == null || caCert == null || serverCert == null) { 802 throw new IllegalStateException("Cannot load credentials"); 803 } 804 805 // Prepare arguments for racoon. 806 String[] racoon = null; 807 switch (profile.type) { 808 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 809 racoon = new String[] { 810 iface, profile.server, "udppsk", profile.ipsecIdentifier, 811 profile.ipsecSecret, "1701", 812 }; 813 break; 814 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 815 racoon = new String[] { 816 iface, profile.server, "udprsa", privateKey, userCert, 817 caCert, serverCert, "1701", 818 }; 819 break; 820 case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 821 racoon = new String[] { 822 iface, profile.server, "xauthpsk", profile.ipsecIdentifier, 823 profile.ipsecSecret, profile.username, profile.password, "", gateway, 824 }; 825 break; 826 case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 827 racoon = new String[] { 828 iface, profile.server, "xauthrsa", privateKey, userCert, 829 caCert, serverCert, profile.username, profile.password, "", gateway, 830 }; 831 break; 832 case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 833 racoon = new String[] { 834 iface, profile.server, "hybridrsa", 835 caCert, serverCert, profile.username, profile.password, "", gateway, 836 }; 837 break; 838 } 839 840 // Prepare arguments for mtpd. 841 String[] mtpd = null; 842 switch (profile.type) { 843 case VpnProfile.TYPE_PPTP: 844 mtpd = new String[] { 845 iface, "pptp", profile.server, "1723", 846 "name", profile.username, "password", profile.password, 847 "linkname", "vpn", "refuse-eap", "nodefaultroute", 848 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 849 (profile.mppe ? "+mppe" : "nomppe"), 850 }; 851 break; 852 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 853 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 854 mtpd = new String[] { 855 iface, "l2tp", profile.server, "1701", profile.l2tpSecret, 856 "name", profile.username, "password", profile.password, 857 "linkname", "vpn", "refuse-eap", "nodefaultroute", 858 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 859 }; 860 break; 861 } 862 863 VpnConfig config = new VpnConfig(); 864 config.legacy = true; 865 config.user = profile.key; 866 config.interfaze = iface; 867 config.session = profile.name; 868 869 config.addLegacyRoutes(profile.routes); 870 if (!profile.dnsServers.isEmpty()) { 871 config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 872 } 873 if (!profile.searchDomains.isEmpty()) { 874 config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 875 } 876 startLegacyVpn(config, racoon, mtpd); 877 } 878 879 private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { 880 stopLegacyVpn(); 881 882 // Prepare for the new request. This also checks the caller. 883 prepare(null, VpnConfig.LEGACY_VPN); 884 updateState(DetailedState.CONNECTING, "startLegacyVpn"); 885 886 // Start a new LegacyVpnRunner and we are done! 887 mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd); 888 mLegacyVpnRunner.start(); 889 } 890 891 public synchronized void stopLegacyVpn() { 892 if (mLegacyVpnRunner != null) { 893 mLegacyVpnRunner.exit(); 894 mLegacyVpnRunner = null; 895 896 synchronized (LegacyVpnRunner.TAG) { 897 // wait for old thread to completely finish before spinning up 898 // new instance, otherwise state updates can be out of order. 899 } 900 } 901 } 902 903 /** 904 * Return the information of the current ongoing legacy VPN. 905 */ 906 public synchronized LegacyVpnInfo getLegacyVpnInfo() { 907 // Check if the caller is authorized. 908 enforceControlPermission(); 909 if (mLegacyVpnRunner == null) return null; 910 911 final LegacyVpnInfo info = new LegacyVpnInfo(); 912 info.key = mConfig.user; 913 info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); 914 return info; 915 } 916 917 public VpnConfig getLegacyVpnConfig() { 918 if (mLegacyVpnRunner != null) { 919 return mConfig; 920 } else { 921 return null; 922 } 923 } 924 925 /** 926 * Bringing up a VPN connection takes time, and that is all this thread 927 * does. Here we have plenty of time. The only thing we need to take 928 * care of is responding to interruptions as soon as possible. Otherwise 929 * requests will be piled up. This can be done in a Handler as a state 930 * machine, but it is much easier to read in the current form. 931 */ 932 private class LegacyVpnRunner extends Thread { 933 private static final String TAG = "LegacyVpnRunner"; 934 935 private final String[] mDaemons; 936 private final String[][] mArguments; 937 private final LocalSocket[] mSockets; 938 private final String mOuterInterface; 939 private final AtomicInteger mOuterConnection = 940 new AtomicInteger(ConnectivityManager.TYPE_NONE); 941 942 private long mTimer = -1; 943 944 /** 945 * Watch for the outer connection (passing in the constructor) going away. 946 */ 947 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 948 @Override 949 public void onReceive(Context context, Intent intent) { 950 if (!mEnableTeardown) return; 951 952 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 953 if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 954 ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { 955 NetworkInfo info = (NetworkInfo)intent.getExtra( 956 ConnectivityManager.EXTRA_NETWORK_INFO); 957 if (info != null && !info.isConnectedOrConnecting()) { 958 try { 959 mObserver.interfaceStatusChanged(mOuterInterface, false); 960 } catch (RemoteException e) {} 961 } 962 } 963 } 964 } 965 }; 966 967 public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) { 968 super(TAG); 969 mConfig = config; 970 mDaemons = new String[] {"racoon", "mtpd"}; 971 // TODO: clear arguments from memory once launched 972 mArguments = new String[][] {racoon, mtpd}; 973 mSockets = new LocalSocket[mDaemons.length]; 974 975 // This is the interface which VPN is running on, 976 // mConfig.interfaze will change to point to OUR 977 // internal interface soon. TODO - add inner/outer to mconfig 978 // TODO - we have a race - if the outer iface goes away/disconnects before we hit this 979 // we will leave the VPN up. We should check that it's still there/connected after 980 // registering 981 mOuterInterface = mConfig.interfaze; 982 983 try { 984 mOuterConnection.set( 985 mConnService.findConnectionTypeForIface(mOuterInterface)); 986 } catch (Exception e) { 987 mOuterConnection.set(ConnectivityManager.TYPE_NONE); 988 } 989 990 IntentFilter filter = new IntentFilter(); 991 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 992 mContext.registerReceiver(mBroadcastReceiver, filter); 993 } 994 995 public void check(String interfaze) { 996 if (interfaze.equals(mOuterInterface)) { 997 Log.i(TAG, "Legacy VPN is going down with " + interfaze); 998 exit(); 999 } 1000 } 1001 1002 public void exit() { 1003 // We assume that everything is reset after stopping the daemons. 1004 interrupt(); 1005 for (LocalSocket socket : mSockets) { 1006 IoUtils.closeQuietly(socket); 1007 } 1008 agentDisconnect(); 1009 try { 1010 mContext.unregisterReceiver(mBroadcastReceiver); 1011 } catch (IllegalArgumentException e) {} 1012 } 1013 1014 @Override 1015 public void run() { 1016 // Wait for the previous thread since it has been interrupted. 1017 Log.v(TAG, "Waiting"); 1018 synchronized (TAG) { 1019 Log.v(TAG, "Executing"); 1020 execute(); 1021 monitorDaemons(); 1022 } 1023 } 1024 1025 private void checkpoint(boolean yield) throws InterruptedException { 1026 long now = SystemClock.elapsedRealtime(); 1027 if (mTimer == -1) { 1028 mTimer = now; 1029 Thread.sleep(1); 1030 } else if (now - mTimer <= 60000) { 1031 Thread.sleep(yield ? 200 : 1); 1032 } else { 1033 updateState(DetailedState.FAILED, "checkpoint"); 1034 throw new IllegalStateException("Time is up"); 1035 } 1036 } 1037 1038 private void execute() { 1039 // Catch all exceptions so we can clean up few things. 1040 boolean initFinished = false; 1041 try { 1042 // Initialize the timer. 1043 checkpoint(false); 1044 1045 // Wait for the daemons to stop. 1046 for (String daemon : mDaemons) { 1047 while (!SystemService.isStopped(daemon)) { 1048 checkpoint(true); 1049 } 1050 } 1051 1052 // Clear the previous state. 1053 File state = new File("/data/misc/vpn/state"); 1054 state.delete(); 1055 if (state.exists()) { 1056 throw new IllegalStateException("Cannot delete the state"); 1057 } 1058 new File("/data/misc/vpn/abort").delete(); 1059 initFinished = true; 1060 1061 // Check if we need to restart any of the daemons. 1062 boolean restart = false; 1063 for (String[] arguments : mArguments) { 1064 restart = restart || (arguments != null); 1065 } 1066 if (!restart) { 1067 agentDisconnect(); 1068 return; 1069 } 1070 updateState(DetailedState.CONNECTING, "execute"); 1071 1072 // Start the daemon with arguments. 1073 for (int i = 0; i < mDaemons.length; ++i) { 1074 String[] arguments = mArguments[i]; 1075 if (arguments == null) { 1076 continue; 1077 } 1078 1079 // Start the daemon. 1080 String daemon = mDaemons[i]; 1081 SystemService.start(daemon); 1082 1083 // Wait for the daemon to start. 1084 while (!SystemService.isRunning(daemon)) { 1085 checkpoint(true); 1086 } 1087 1088 // Create the control socket. 1089 mSockets[i] = new LocalSocket(); 1090 LocalSocketAddress address = new LocalSocketAddress( 1091 daemon, LocalSocketAddress.Namespace.RESERVED); 1092 1093 // Wait for the socket to connect. 1094 while (true) { 1095 try { 1096 mSockets[i].connect(address); 1097 break; 1098 } catch (Exception e) { 1099 // ignore 1100 } 1101 checkpoint(true); 1102 } 1103 mSockets[i].setSoTimeout(500); 1104 1105 // Send over the arguments. 1106 OutputStream out = mSockets[i].getOutputStream(); 1107 for (String argument : arguments) { 1108 byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); 1109 if (bytes.length >= 0xFFFF) { 1110 throw new IllegalArgumentException("Argument is too large"); 1111 } 1112 out.write(bytes.length >> 8); 1113 out.write(bytes.length); 1114 out.write(bytes); 1115 checkpoint(false); 1116 } 1117 out.write(0xFF); 1118 out.write(0xFF); 1119 out.flush(); 1120 1121 // Wait for End-of-File. 1122 InputStream in = mSockets[i].getInputStream(); 1123 while (true) { 1124 try { 1125 if (in.read() == -1) { 1126 break; 1127 } 1128 } catch (Exception e) { 1129 // ignore 1130 } 1131 checkpoint(true); 1132 } 1133 } 1134 1135 // Wait for the daemons to create the new state. 1136 while (!state.exists()) { 1137 // Check if a running daemon is dead. 1138 for (int i = 0; i < mDaemons.length; ++i) { 1139 String daemon = mDaemons[i]; 1140 if (mArguments[i] != null && !SystemService.isRunning(daemon)) { 1141 throw new IllegalStateException(daemon + " is dead"); 1142 } 1143 } 1144 checkpoint(true); 1145 } 1146 1147 // Now we are connected. Read and parse the new state. 1148 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); 1149 if (parameters.length != 6) { 1150 throw new IllegalStateException("Cannot parse the state"); 1151 } 1152 1153 // Set the interface and the addresses in the config. 1154 mConfig.interfaze = parameters[0].trim(); 1155 1156 mConfig.addLegacyAddresses(parameters[1]); 1157 // Set the routes if they are not set in the config. 1158 if (mConfig.routes == null || mConfig.routes.isEmpty()) { 1159 mConfig.addLegacyRoutes(parameters[2]); 1160 } 1161 1162 // Set the DNS servers if they are not set in the config. 1163 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { 1164 String dnsServers = parameters[3].trim(); 1165 if (!dnsServers.isEmpty()) { 1166 mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); 1167 } 1168 } 1169 1170 // Set the search domains if they are not set in the config. 1171 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { 1172 String searchDomains = parameters[4].trim(); 1173 if (!searchDomains.isEmpty()) { 1174 mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); 1175 } 1176 } 1177 1178 // Here is the last step and it must be done synchronously. 1179 synchronized (Vpn.this) { 1180 // Set the start time 1181 mConfig.startTime = SystemClock.elapsedRealtime(); 1182 1183 // Check if the thread is interrupted while we are waiting. 1184 checkpoint(false); 1185 1186 // Check if the interface is gone while we are waiting. 1187 if (jniCheck(mConfig.interfaze) == 0) { 1188 throw new IllegalStateException(mConfig.interfaze + " is gone"); 1189 } 1190 1191 // Now INetworkManagementEventObserver is watching our back. 1192 mInterface = mConfig.interfaze; 1193 mVpnUsers = new ArrayList<UidRange>(); 1194 mAllowIPv4 = mConfig.allowIPv4; 1195 mAllowIPv6 = mConfig.allowIPv6; 1196 1197 agentConnect(); 1198 1199 Log.i(TAG, "Connected!"); 1200 } 1201 } catch (Exception e) { 1202 Log.i(TAG, "Aborting", e); 1203 exit(); 1204 } finally { 1205 // Kill the daemons if they fail to stop. 1206 if (!initFinished) { 1207 for (String daemon : mDaemons) { 1208 SystemService.stop(daemon); 1209 } 1210 } 1211 1212 // Do not leave an unstable state. 1213 if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) { 1214 agentDisconnect(); 1215 } 1216 } 1217 } 1218 1219 /** 1220 * Monitor the daemons we started, moving to disconnected state if the 1221 * underlying services fail. 1222 */ 1223 private void monitorDaemons() { 1224 if (!mNetworkInfo.isConnected()) { 1225 return; 1226 } 1227 1228 try { 1229 while (true) { 1230 Thread.sleep(2000); 1231 for (int i = 0; i < mDaemons.length; i++) { 1232 if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) { 1233 return; 1234 } 1235 } 1236 } 1237 } catch (InterruptedException e) { 1238 Log.d(TAG, "interrupted during monitorDaemons(); stopping services"); 1239 } finally { 1240 for (String daemon : mDaemons) { 1241 SystemService.stop(daemon); 1242 } 1243 1244 agentDisconnect(); 1245 } 1246 } 1247 } 1248} 1249