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