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