Home | History | Annotate | Download | only in connectivity
      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 import static android.net.ConnectivityManager.NETID_UNSET;
     21 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
     22 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
     23 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
     24 import static android.net.RouteInfo.RTN_THROW;
     25 import static android.net.RouteInfo.RTN_UNREACHABLE;
     26 
     27 import android.Manifest;
     28 import android.annotation.NonNull;
     29 import android.annotation.Nullable;
     30 import android.annotation.UserIdInt;
     31 import android.app.AppGlobals;
     32 import android.app.AppOpsManager;
     33 import android.app.Notification;
     34 import android.app.NotificationManager;
     35 import android.app.PendingIntent;
     36 import android.content.BroadcastReceiver;
     37 import android.content.ComponentName;
     38 import android.content.Context;
     39 import android.content.Intent;
     40 import android.content.IntentFilter;
     41 import android.content.ServiceConnection;
     42 import android.content.pm.ApplicationInfo;
     43 import android.content.pm.PackageManager;
     44 import android.content.pm.PackageManager.NameNotFoundException;
     45 import android.content.pm.ResolveInfo;
     46 import android.content.pm.UserInfo;
     47 import android.net.ConnectivityManager;
     48 import android.net.INetworkManagementEventObserver;
     49 import android.net.IpPrefix;
     50 import android.net.LinkAddress;
     51 import android.net.LinkProperties;
     52 import android.net.LocalSocket;
     53 import android.net.LocalSocketAddress;
     54 import android.net.Network;
     55 import android.net.NetworkAgent;
     56 import android.net.NetworkCapabilities;
     57 import android.net.NetworkInfo;
     58 import android.net.NetworkInfo.DetailedState;
     59 import android.net.NetworkMisc;
     60 import android.net.NetworkUtils;
     61 import android.net.RouteInfo;
     62 import android.net.UidRange;
     63 import android.net.Uri;
     64 import android.net.VpnService;
     65 import android.os.Binder;
     66 import android.os.Build.VERSION_CODES;
     67 import android.os.Bundle;
     68 import android.os.FileUtils;
     69 import android.os.IBinder;
     70 import android.os.INetworkManagementService;
     71 import android.os.Looper;
     72 import android.os.Parcel;
     73 import android.os.ParcelFileDescriptor;
     74 import android.os.PatternMatcher;
     75 import android.os.Process;
     76 import android.os.RemoteException;
     77 import android.os.SystemClock;
     78 import android.os.SystemService;
     79 import android.os.UserHandle;
     80 import android.os.UserManager;
     81 import android.provider.Settings;
     82 import android.security.Credentials;
     83 import android.security.KeyStore;
     84 import android.text.TextUtils;
     85 import android.util.ArraySet;
     86 import android.util.Log;
     87 
     88 import com.android.internal.R;
     89 import com.android.internal.annotations.GuardedBy;
     90 import com.android.internal.annotations.VisibleForTesting;
     91 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
     92 import com.android.internal.net.LegacyVpnInfo;
     93 import com.android.internal.net.VpnConfig;
     94 import com.android.internal.net.VpnInfo;
     95 import com.android.internal.net.VpnProfile;
     96 import com.android.internal.notification.SystemNotificationChannels;
     97 import com.android.internal.util.ArrayUtils;
     98 import com.android.server.ConnectivityService;
     99 import com.android.server.DeviceIdleController;
    100 import com.android.server.LocalServices;
    101 import com.android.server.net.BaseNetworkObserver;
    102 
    103 import libcore.io.IoUtils;
    104 
    105 import java.io.File;
    106 import java.io.IOException;
    107 import java.io.InputStream;
    108 import java.io.OutputStream;
    109 import java.math.BigInteger;
    110 import java.net.Inet4Address;
    111 import java.net.Inet6Address;
    112 import java.net.InetAddress;
    113 import java.nio.charset.StandardCharsets;
    114 import java.util.ArrayList;
    115 import java.util.Arrays;
    116 import java.util.Collection;
    117 import java.util.Collections;
    118 import java.util.Comparator;
    119 import java.util.List;
    120 import java.util.Objects;
    121 import java.util.Set;
    122 import java.util.SortedSet;
    123 import java.util.TreeSet;
    124 import java.util.concurrent.atomic.AtomicInteger;
    125 
    126 /**
    127  * @hide
    128  */
    129 public class Vpn {
    130     private static final String NETWORKTYPE = "VPN";
    131     private static final String TAG = "Vpn";
    132     private static final boolean LOGD = true;
    133 
    134     // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on
    135     // the device idle whitelist during service launch and VPN bootstrap.
    136     private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000;
    137 
    138     // Settings for how much of the address space should be routed so that Vpn considers
    139     // "most" of the address space is routed. This is used to determine whether this Vpn
    140     // should be marked with the INTERNET capability.
    141     private static final long MOST_IPV4_ADDRESSES_COUNT;
    142     private static final BigInteger MOST_IPV6_ADDRESSES_COUNT;
    143     static {
    144         // 85% of the address space must be routed for Vpn to consider this VPN to provide
    145         // INTERNET access.
    146         final int howManyPercentIsMost = 85;
    147 
    148         final long twoPower32 = 1L << 32;
    149         MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100;
    150         final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128);
    151         MOST_IPV6_ADDRESSES_COUNT = twoPower128
    152                 .multiply(BigInteger.valueOf(howManyPercentIsMost))
    153                 .divide(BigInteger.valueOf(100));
    154     }
    155     // How many routes to evaluate before bailing and declaring this Vpn should provide
    156     // the INTERNET capability. This is necessary because computing the adress space is
    157     // O(n) and this is running in the system service, so a limit is needed to alleviate
    158     // the risk of attack.
    159     // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm
    160     // is actually O(n)+O(n).
    161     private static final int MAX_ROUTES_TO_EVALUATE = 150;
    162 
    163     // TODO: create separate trackers for each unique VPN to support
    164     // automated reconnection
    165 
    166     private Context mContext;
    167     private NetworkInfo mNetworkInfo;
    168     private String mPackage;
    169     private int mOwnerUID;
    170     private String mInterface;
    171     private Connection mConnection;
    172     private LegacyVpnRunner mLegacyVpnRunner;
    173     private PendingIntent mStatusIntent;
    174     private volatile boolean mEnableTeardown = true;
    175     private final INetworkManagementService mNetd;
    176     @VisibleForTesting
    177     protected VpnConfig mConfig;
    178     @VisibleForTesting
    179     protected NetworkAgent mNetworkAgent;
    180     private final Looper mLooper;
    181     @VisibleForTesting
    182     protected final NetworkCapabilities mNetworkCapabilities;
    183     private final SystemServices mSystemServices;
    184 
    185     /**
    186      * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
    187      * only applies to {@link VpnService} connections.
    188      */
    189     private boolean mAlwaysOn = false;
    190 
    191     /**
    192      * Whether to disable traffic outside of this VPN even when the VPN is not connected. System
    193      * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is
    194      * not set.
    195      */
    196     private boolean mLockdown = false;
    197 
    198     /**
    199      * List of UIDs for which networking should be blocked until VPN is ready, during brief periods
    200      * when VPN is not running. For example, during system startup or after a crash.
    201      * @see mLockdown
    202      */
    203     @GuardedBy("this")
    204     private Set<UidRange> mBlockedUsers = new ArraySet<>();
    205 
    206     // Handle of the user initiating VPN.
    207     private final int mUserHandle;
    208 
    209     // Listen to package removal and change events (update/uninstall) for this user
    210     private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
    211         @Override
    212         public void onReceive(Context context, Intent intent) {
    213             final Uri data = intent.getData();
    214             final String packageName = data == null ? null : data.getSchemeSpecificPart();
    215             if (packageName == null) {
    216                 return;
    217             }
    218 
    219             synchronized (Vpn.this) {
    220                 // Avoid race where always-on package has been unset
    221                 if (!packageName.equals(getAlwaysOnPackage())) {
    222                     return;
    223                 }
    224 
    225                 final String action = intent.getAction();
    226                 Log.i(TAG, "Received broadcast " + action + " for always-on VPN package "
    227                         + packageName + " in user " + mUserHandle);
    228 
    229                 switch(action) {
    230                     case Intent.ACTION_PACKAGE_REPLACED:
    231                         // Start vpn after app upgrade
    232                         startAlwaysOnVpn();
    233                         break;
    234                     case Intent.ACTION_PACKAGE_REMOVED:
    235                         final boolean isPackageRemoved = !intent.getBooleanExtra(
    236                                 Intent.EXTRA_REPLACING, false);
    237                         if (isPackageRemoved) {
    238                             setAlwaysOnPackage(null, false);
    239                         }
    240                         break;
    241                 }
    242             }
    243         }
    244     };
    245 
    246     private boolean mIsPackageIntentReceiverRegistered = false;
    247 
    248     public Vpn(Looper looper, Context context, INetworkManagementService netService,
    249             @UserIdInt int userHandle) {
    250         this(looper, context, netService, userHandle, new SystemServices(context));
    251     }
    252 
    253     @VisibleForTesting
    254     protected Vpn(Looper looper, Context context, INetworkManagementService netService,
    255             int userHandle, SystemServices systemServices) {
    256         mContext = context;
    257         mNetd = netService;
    258         mUserHandle = userHandle;
    259         mLooper = looper;
    260         mSystemServices = systemServices;
    261 
    262         mPackage = VpnConfig.LEGACY_VPN;
    263         mOwnerUID = getAppUid(mPackage, mUserHandle);
    264 
    265         try {
    266             netService.registerObserver(mObserver);
    267         } catch (RemoteException e) {
    268             Log.wtf(TAG, "Problem registering observer", e);
    269         }
    270 
    271         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
    272                 "" /* subtypeName */);
    273         mNetworkCapabilities = new NetworkCapabilities();
    274         mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
    275         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
    276         updateCapabilities();
    277 
    278         loadAlwaysOnPackage();
    279     }
    280 
    281     /**
    282      * Set whether this object is responsible for watching for {@link NetworkInfo}
    283      * teardown. When {@code false}, teardown is handled externally by someone
    284      * else.
    285      */
    286     public void setEnableTeardown(boolean enableTeardown) {
    287         mEnableTeardown = enableTeardown;
    288     }
    289 
    290     /**
    291      * Update current state, dispaching event to listeners.
    292      */
    293     @VisibleForTesting
    294     protected void updateState(DetailedState detailedState, String reason) {
    295         if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
    296         mNetworkInfo.setDetailedState(detailedState, reason, null);
    297         if (mNetworkAgent != null) {
    298             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    299         }
    300         updateAlwaysOnNotification(detailedState);
    301     }
    302 
    303     public void updateCapabilities() {
    304         final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null;
    305         updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks,
    306                 mNetworkCapabilities);
    307 
    308         if (mNetworkAgent != null) {
    309             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
    310         }
    311     }
    312 
    313     @VisibleForTesting
    314     public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks,
    315             NetworkCapabilities caps) {
    316         int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
    317         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
    318         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
    319         boolean metered = false;
    320         boolean roaming = false;
    321         boolean congested = false;
    322 
    323         boolean hadUnderlyingNetworks = false;
    324         if (null != underlyingNetworks) {
    325             for (Network underlying : underlyingNetworks) {
    326                 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
    327                 if (underlyingCaps == null) continue;
    328                 hadUnderlyingNetworks = true;
    329                 for (int underlyingType : underlyingCaps.getTransportTypes()) {
    330                     transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
    331                 }
    332 
    333                 // When we have multiple networks, we have to assume the
    334                 // worst-case link speed and restrictions.
    335                 downKbps = NetworkCapabilities.minBandwidth(downKbps,
    336                         underlyingCaps.getLinkDownstreamBandwidthKbps());
    337                 upKbps = NetworkCapabilities.minBandwidth(upKbps,
    338                         underlyingCaps.getLinkUpstreamBandwidthKbps());
    339                 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
    340                 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
    341                 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
    342             }
    343         }
    344         if (!hadUnderlyingNetworks) {
    345             // No idea what the underlying networks are; assume sane defaults
    346             metered = true;
    347             roaming = false;
    348             congested = false;
    349         }
    350 
    351         caps.setTransportTypes(transportTypes);
    352         caps.setLinkDownstreamBandwidthKbps(downKbps);
    353         caps.setLinkUpstreamBandwidthKbps(upKbps);
    354         caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
    355         caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
    356         caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
    357     }
    358 
    359     /**
    360      * Chooses whether to force all connections to go though VPN.
    361      *
    362      * Used to enable/disable legacy VPN lockdown.
    363      *
    364      * This uses the same ip rule mechanism as {@link #setAlwaysOnPackage(String, boolean)};
    365      * previous settings from calling that function will be replaced and saved with the
    366      * always-on state.
    367      *
    368      * @param lockdown whether to prevent all traffic outside of a VPN.
    369      */
    370     public synchronized void setLockdown(boolean lockdown) {
    371         enforceControlPermissionOrInternalCaller();
    372 
    373         setVpnForcedLocked(lockdown);
    374         mLockdown = lockdown;
    375 
    376         // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by
    377         // LockdownVpnTracker.isEnabled() which keeps track of its own state.
    378         if (mAlwaysOn) {
    379             saveAlwaysOnPackage();
    380         }
    381     }
    382 
    383     /**
    384      * Checks if a VPN app supports always-on mode.
    385      *
    386      * In order to support the always-on feature, an app has to
    387      * <ul>
    388      *     <li>target {@link VERSION_CODES#N API 24} or above, and
    389      *     <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
    390      *         meta-data field.
    391      * </ul>
    392      *
    393      * @param packageName the canonical package name of the VPN app
    394      * @return {@code true} if and only if the VPN app exists and supports always-on mode
    395      */
    396     public boolean isAlwaysOnPackageSupported(String packageName) {
    397         enforceSettingsPermission();
    398 
    399         if (packageName == null) {
    400             return false;
    401         }
    402 
    403         PackageManager pm = mContext.getPackageManager();
    404         ApplicationInfo appInfo = null;
    405         try {
    406             appInfo = pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle);
    407         } catch (NameNotFoundException unused) {
    408             Log.w(TAG, "Can't find \"" + packageName + "\" when checking always-on support");
    409         }
    410         if (appInfo == null || appInfo.targetSdkVersion < VERSION_CODES.N) {
    411             return false;
    412         }
    413 
    414         final Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
    415         intent.setPackage(packageName);
    416         List<ResolveInfo> services =
    417                 pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, mUserHandle);
    418         if (services == null || services.size() == 0) {
    419             return false;
    420         }
    421 
    422         for (ResolveInfo rInfo : services) {
    423             final Bundle metaData = rInfo.serviceInfo.metaData;
    424             if (metaData != null &&
    425                     !metaData.getBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, true)) {
    426                 return false;
    427             }
    428         }
    429 
    430         return true;
    431     }
    432 
    433     /**
    434      * Configures an always-on VPN connection through a specific application.
    435      * This connection is automatically granted and persisted after a reboot.
    436      *
    437      * <p>The designated package should exist and declare a {@link VpnService} in its
    438      *    manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
    439      *    otherwise the call will fail.
    440      *
    441      * <p>Note that this method does not check if the VPN app supports always-on mode. The check is
    442      *    delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this
    443      *    method in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}.
    444      *
    445      * @param packageName the package to designate as always-on VPN supplier.
    446      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
    447      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
    448      */
    449     public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) {
    450         enforceControlPermissionOrInternalCaller();
    451 
    452         if (setAlwaysOnPackageInternal(packageName, lockdown)) {
    453             saveAlwaysOnPackage();
    454             return true;
    455         }
    456         return false;
    457     }
    458 
    459     /**
    460      * Configures an always-on VPN connection through a specific application, the same as
    461      * {@link #setAlwaysOnPackage}.
    462      *
    463      * Does not perform permission checks. Does not persist any of the changes to storage.
    464      *
    465      * @param packageName the package to designate as always-on VPN supplier.
    466      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
    467      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
    468      */
    469     @GuardedBy("this")
    470     private boolean setAlwaysOnPackageInternal(String packageName, boolean lockdown) {
    471         if (VpnConfig.LEGACY_VPN.equals(packageName)) {
    472             Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
    473             return false;
    474         }
    475 
    476         if (packageName != null) {
    477             // Pre-authorize new always-on VPN package.
    478             if (!setPackageAuthorization(packageName, true)) {
    479                 return false;
    480             }
    481             mAlwaysOn = true;
    482         } else {
    483             packageName = VpnConfig.LEGACY_VPN;
    484             mAlwaysOn = false;
    485         }
    486 
    487         mLockdown = (mAlwaysOn && lockdown);
    488         if (isCurrentPreparedPackage(packageName)) {
    489             updateAlwaysOnNotification(mNetworkInfo.getDetailedState());
    490         } else {
    491             // Prepare this app. The notification will update as a side-effect of updateState().
    492             prepareInternal(packageName);
    493         }
    494         maybeRegisterPackageChangeReceiverLocked(packageName);
    495         setVpnForcedLocked(mLockdown);
    496         return true;
    497     }
    498 
    499     private static boolean isNullOrLegacyVpn(String packageName) {
    500         return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName);
    501     }
    502 
    503     private void unregisterPackageChangeReceiverLocked() {
    504         if (mIsPackageIntentReceiverRegistered) {
    505             mContext.unregisterReceiver(mPackageIntentReceiver);
    506             mIsPackageIntentReceiverRegistered = false;
    507         }
    508     }
    509 
    510     private void maybeRegisterPackageChangeReceiverLocked(String packageName) {
    511         // Unregister IntentFilter listening for previous always-on package change
    512         unregisterPackageChangeReceiverLocked();
    513 
    514         if (!isNullOrLegacyVpn(packageName)) {
    515             mIsPackageIntentReceiverRegistered = true;
    516 
    517             IntentFilter intentFilter = new IntentFilter();
    518             // Protected intent can only be sent by system. No permission required in register.
    519             intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
    520             intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    521             intentFilter.addDataScheme("package");
    522             intentFilter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL);
    523             mContext.registerReceiverAsUser(
    524                     mPackageIntentReceiver, UserHandle.of(mUserHandle), intentFilter, null, null);
    525         }
    526     }
    527 
    528     /**
    529      * @return the package name of the VPN controller responsible for always-on VPN,
    530      *         or {@code null} if none is set or always-on VPN is controlled through
    531      *         lockdown instead.
    532      * @hide
    533      */
    534     public synchronized String getAlwaysOnPackage() {
    535         enforceControlPermissionOrInternalCaller();
    536         return (mAlwaysOn ? mPackage : null);
    537     }
    538 
    539     /**
    540      * Save the always-on package and lockdown config into Settings.Secure
    541      */
    542     @GuardedBy("this")
    543     private void saveAlwaysOnPackage() {
    544         final long token = Binder.clearCallingIdentity();
    545         try {
    546             mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP,
    547                     getAlwaysOnPackage(), mUserHandle);
    548             mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
    549                     (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle);
    550         } finally {
    551             Binder.restoreCallingIdentity(token);
    552         }
    553     }
    554 
    555     /**
    556      * Load the always-on package and lockdown config from Settings.Secure
    557      */
    558     @GuardedBy("this")
    559     private void loadAlwaysOnPackage() {
    560         final long token = Binder.clearCallingIdentity();
    561         try {
    562             final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser(
    563                     Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle);
    564             final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser(
    565                     Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0;
    566             setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown);
    567         } finally {
    568             Binder.restoreCallingIdentity(token);
    569         }
    570     }
    571 
    572     /**
    573      * @return {@code true} if the service was started, the service was already connected, or there
    574      *         was no always-on VPN to start. {@code false} otherwise.
    575      */
    576     public boolean startAlwaysOnVpn() {
    577         final String alwaysOnPackage;
    578         synchronized (this) {
    579             alwaysOnPackage = getAlwaysOnPackage();
    580             // Skip if there is no service to start.
    581             if (alwaysOnPackage == null) {
    582                 return true;
    583             }
    584             // Remove always-on VPN if it's not supported.
    585             if (!isAlwaysOnPackageSupported(alwaysOnPackage)) {
    586                 setAlwaysOnPackage(null, false);
    587                 return false;
    588             }
    589             // Skip if the service is already established. This isn't bulletproof: it's not bound
    590             // until after establish(), so if it's mid-setup onStartCommand will be sent twice,
    591             // which may restart the connection.
    592             if (getNetworkInfo().isConnected()) {
    593                 return true;
    594             }
    595         }
    596 
    597         // Tell the OS that background services in this app need to be allowed for
    598         // a short time, so we can bootstrap the VPN service.
    599         final long oldId = Binder.clearCallingIdentity();
    600         try {
    601             DeviceIdleController.LocalService idleController =
    602                     LocalServices.getService(DeviceIdleController.LocalService.class);
    603             idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
    604                     VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn");
    605 
    606             // Start the VPN service declared in the app's manifest.
    607             Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE);
    608             serviceIntent.setPackage(alwaysOnPackage);
    609             try {
    610                 return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null;
    611             } catch (RuntimeException e) {
    612                 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e);
    613                 return false;
    614             }
    615         } finally {
    616             Binder.restoreCallingIdentity(oldId);
    617         }
    618     }
    619 
    620     /**
    621      * Prepare for a VPN application. This method is designed to solve
    622      * race conditions. It first compares the current prepared package
    623      * with {@code oldPackage}. If they are the same, the prepared
    624      * package is revoked and replaced with {@code newPackage}. If
    625      * {@code oldPackage} is {@code null}, the comparison is omitted.
    626      * If {@code newPackage} is the same package or {@code null}, the
    627      * revocation is omitted. This method returns {@code true} if the
    628      * operation is succeeded.
    629      *
    630      * Legacy VPN is handled specially since it is not a real package.
    631      * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
    632      * it can be revoked by itself.
    633      *
    634      * Note: when we added VPN pre-consent in
    635      * https://android.googlesource.com/platform/frameworks/base/+/0554260
    636      * the names oldPackage and newPackage became misleading, because when
    637      * an app is pre-consented, we actually prepare oldPackage, not newPackage.
    638      *
    639      * Their meanings actually are:
    640      *
    641      * - oldPackage non-null, newPackage null: App calling VpnService#prepare().
    642      * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn().
    643      * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect
    644      *   and revoke any current app VPN and re-prepare legacy vpn.
    645      *
    646      * TODO: Rename the variables - or split this method into two - and end this confusion.
    647      * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN)
    648      * to prepare(oldPackage=null, newPackage=LEGACY_VPN)
    649      *
    650      * @param oldPackage The package name of the old VPN application
    651      * @param newPackage The package name of the new VPN application
    652      *
    653      * @return true if the operation succeeded.
    654      */
    655     public synchronized boolean prepare(String oldPackage, String newPackage) {
    656         if (oldPackage != null) {
    657             // Stop an existing always-on VPN from being dethroned by other apps.
    658             if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) {
    659                 return false;
    660             }
    661 
    662             // Package is not the same or old package was reinstalled.
    663             if (!isCurrentPreparedPackage(oldPackage)) {
    664                 // The package doesn't match. We return false (to obtain user consent) unless the
    665                 // user has already consented to that VPN package.
    666                 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
    667                     prepareInternal(oldPackage);
    668                     return true;
    669                 }
    670                 return false;
    671             } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN)
    672                     && !isVpnUserPreConsented(oldPackage)) {
    673                 // Currently prepared VPN is revoked, so unprepare it and return false.
    674                 prepareInternal(VpnConfig.LEGACY_VPN);
    675                 return false;
    676             }
    677         }
    678 
    679         // Return true if we do not need to revoke.
    680         if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) &&
    681                 isCurrentPreparedPackage(newPackage))) {
    682             return true;
    683         }
    684 
    685         // Check that the caller is authorized.
    686         enforceControlPermission();
    687 
    688         // Stop an existing always-on VPN from being dethroned by other apps.
    689         if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) {
    690             return false;
    691         }
    692 
    693         prepareInternal(newPackage);
    694         return true;
    695     }
    696 
    697     private boolean isCurrentPreparedPackage(String packageName) {
    698         // We can't just check that packageName matches mPackage, because if the app was uninstalled
    699         // and reinstalled it will no longer be prepared. Instead check the UID.
    700         return getAppUid(packageName, mUserHandle) == mOwnerUID;
    701     }
    702 
    703     /** Prepare the VPN for the given package. Does not perform permission checks. */
    704     private void prepareInternal(String newPackage) {
    705         long token = Binder.clearCallingIdentity();
    706         try {
    707             // Reset the interface.
    708             if (mInterface != null) {
    709                 mStatusIntent = null;
    710                 agentDisconnect();
    711                 jniReset(mInterface);
    712                 mInterface = null;
    713                 mNetworkCapabilities.setUids(null);
    714             }
    715 
    716             // Revoke the connection or stop LegacyVpnRunner.
    717             if (mConnection != null) {
    718                 try {
    719                     mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION,
    720                             Parcel.obtain(), null, IBinder.FLAG_ONEWAY);
    721                 } catch (Exception e) {
    722                     // ignore
    723                 }
    724                 mContext.unbindService(mConnection);
    725                 mConnection = null;
    726             } else if (mLegacyVpnRunner != null) {
    727                 mLegacyVpnRunner.exit();
    728                 mLegacyVpnRunner = null;
    729             }
    730 
    731             try {
    732                 mNetd.denyProtect(mOwnerUID);
    733             } catch (Exception e) {
    734                 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
    735             }
    736 
    737             Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
    738             mPackage = newPackage;
    739             mOwnerUID = getAppUid(newPackage, mUserHandle);
    740             try {
    741                 mNetd.allowProtect(mOwnerUID);
    742             } catch (Exception e) {
    743                 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
    744             }
    745             mConfig = null;
    746 
    747             updateState(DetailedState.IDLE, "prepare");
    748             setVpnForcedLocked(mLockdown);
    749         } finally {
    750             Binder.restoreCallingIdentity(token);
    751         }
    752     }
    753 
    754     /**
    755      * Set whether a package has the ability to launch VPNs without user intervention.
    756      */
    757     public boolean setPackageAuthorization(String packageName, boolean authorized) {
    758         // Check if the caller is authorized.
    759         enforceControlPermissionOrInternalCaller();
    760 
    761         int uid = getAppUid(packageName, mUserHandle);
    762         if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) {
    763             // Authorization for nonexistent packages (or fake ones) can't be updated.
    764             return false;
    765         }
    766 
    767         long token = Binder.clearCallingIdentity();
    768         try {
    769             AppOpsManager appOps =
    770                     (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    771             appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, uid, packageName,
    772                     authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
    773             return true;
    774         } catch (Exception e) {
    775             Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e);
    776         } finally {
    777             Binder.restoreCallingIdentity(token);
    778         }
    779         return false;
    780     }
    781 
    782     private boolean isVpnUserPreConsented(String packageName) {
    783         AppOpsManager appOps =
    784                 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    785 
    786         // Verify that the caller matches the given package and has permission to activate VPNs.
    787         return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(),
    788                 packageName) == AppOpsManager.MODE_ALLOWED;
    789     }
    790 
    791     private int getAppUid(String app, int userHandle) {
    792         if (VpnConfig.LEGACY_VPN.equals(app)) {
    793             return Process.myUid();
    794         }
    795         PackageManager pm = mContext.getPackageManager();
    796         int result;
    797         try {
    798             result = pm.getPackageUidAsUser(app, userHandle);
    799         } catch (NameNotFoundException e) {
    800             result = -1;
    801         }
    802         return result;
    803     }
    804 
    805     public NetworkInfo getNetworkInfo() {
    806         return mNetworkInfo;
    807     }
    808 
    809     public int getNetId() {
    810         return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET;
    811     }
    812 
    813     private LinkProperties makeLinkProperties() {
    814         boolean allowIPv4 = mConfig.allowIPv4;
    815         boolean allowIPv6 = mConfig.allowIPv6;
    816 
    817         LinkProperties lp = new LinkProperties();
    818 
    819         lp.setInterfaceName(mInterface);
    820 
    821         if (mConfig.addresses != null) {
    822             for (LinkAddress address : mConfig.addresses) {
    823                 lp.addLinkAddress(address);
    824                 allowIPv4 |= address.getAddress() instanceof Inet4Address;
    825                 allowIPv6 |= address.getAddress() instanceof Inet6Address;
    826             }
    827         }
    828 
    829         if (mConfig.routes != null) {
    830             for (RouteInfo route : mConfig.routes) {
    831                 lp.addRoute(route);
    832                 InetAddress address = route.getDestination().getAddress();
    833                 allowIPv4 |= address instanceof Inet4Address;
    834                 allowIPv6 |= address instanceof Inet6Address;
    835             }
    836         }
    837 
    838         if (mConfig.dnsServers != null) {
    839             for (String dnsServer : mConfig.dnsServers) {
    840                 InetAddress address = InetAddress.parseNumericAddress(dnsServer);
    841                 lp.addDnsServer(address);
    842                 allowIPv4 |= address instanceof Inet4Address;
    843                 allowIPv6 |= address instanceof Inet6Address;
    844             }
    845         }
    846 
    847         if (!allowIPv4) {
    848             lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
    849         }
    850         if (!allowIPv6) {
    851             lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
    852         }
    853 
    854         // Concatenate search domains into a string.
    855         StringBuilder buffer = new StringBuilder();
    856         if (mConfig.searchDomains != null) {
    857             for (String domain : mConfig.searchDomains) {
    858                 buffer.append(domain).append(' ');
    859             }
    860         }
    861         lp.setDomains(buffer.toString().trim());
    862 
    863         // TODO: Stop setting the MTU in jniCreate and set it here.
    864 
    865         return lp;
    866     }
    867 
    868     /**
    869      * Analyzes the passed LinkedProperties to figure out whether it routes to most of the IP space.
    870      *
    871      * This returns true if the passed LinkedProperties contains routes to either most of the IPv4
    872      * space or to most of the IPv6 address space, where "most" is defined by the value of the
    873      * MOST_IPV{4,6}_ADDRESSES_COUNT constants : if more than this number of addresses are matched
    874      * by any of the routes, then it's decided that most of the space is routed.
    875      * @hide
    876      */
    877     @VisibleForTesting
    878     static boolean providesRoutesToMostDestinations(LinkProperties lp) {
    879         final List<RouteInfo> routes = lp.getAllRoutes();
    880         if (routes.size() > MAX_ROUTES_TO_EVALUATE) return true;
    881         final Comparator<IpPrefix> prefixLengthComparator = IpPrefix.lengthComparator();
    882         TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator);
    883         TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator);
    884         for (final RouteInfo route : routes) {
    885             IpPrefix destination = route.getDestination();
    886             if (destination.isIPv4()) {
    887                 ipv4Prefixes.add(destination);
    888             } else {
    889                 ipv6Prefixes.add(destination);
    890             }
    891         }
    892         if (NetworkUtils.routedIPv4AddressCount(ipv4Prefixes) > MOST_IPV4_ADDRESSES_COUNT) {
    893             return true;
    894         }
    895         return NetworkUtils.routedIPv6AddressCount(ipv6Prefixes)
    896                 .compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
    897     }
    898 
    899     /**
    900      * Attempt to perform a seamless handover of VPNs by only updating LinkProperties without
    901      * registering a new NetworkAgent. This is not always possible if the new VPN configuration
    902      * has certain changes, in which case this method would just return {@code false}.
    903      */
    904     private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) {
    905         // NetworkMisc cannot be updated without registering a new NetworkAgent.
    906         if (oldConfig.allowBypass != mConfig.allowBypass) {
    907             Log.i(TAG, "Handover not possible due to changes to allowBypass");
    908             return false;
    909         }
    910 
    911         // TODO: we currently do not support seamless handover if the allowed or disallowed
    912         // applications have changed. Consider diffing UID ranges and only applying the delta.
    913         if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) ||
    914                 !Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) {
    915             Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps");
    916             return false;
    917         }
    918 
    919         LinkProperties lp = makeLinkProperties();
    920         final boolean hadInternetCapability = mNetworkCapabilities.hasCapability(
    921                 NetworkCapabilities.NET_CAPABILITY_INTERNET);
    922         final boolean willHaveInternetCapability = providesRoutesToMostDestinations(lp);
    923         if (hadInternetCapability != willHaveInternetCapability) {
    924             // A seamless handover would have led to a change to INTERNET capability, which
    925             // is supposed to be immutable for a given network. In this case bail out and do not
    926             // perform handover.
    927             Log.i(TAG, "Handover not possible due to changes to INTERNET capability");
    928             return false;
    929         }
    930 
    931         agent.sendLinkProperties(lp);
    932         return true;
    933     }
    934 
    935     private void agentConnect() {
    936         LinkProperties lp = makeLinkProperties();
    937 
    938         if (providesRoutesToMostDestinations(lp)) {
    939             mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    940         } else {
    941             mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    942         }
    943 
    944         mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
    945 
    946         NetworkMisc networkMisc = new NetworkMisc();
    947         networkMisc.allowBypass = mConfig.allowBypass && !mLockdown;
    948 
    949         mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid());
    950         mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle,
    951                 mConfig.allowedApplications, mConfig.disallowedApplications));
    952         long token = Binder.clearCallingIdentity();
    953         try {
    954             mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
    955                     mNetworkInfo, mNetworkCapabilities, lp,
    956                     ConnectivityConstants.VPN_DEFAULT_SCORE, networkMisc) {
    957                             @Override
    958                             public void unwanted() {
    959                                 // We are user controlled, not driven by NetworkRequest.
    960                             }
    961                         };
    962         } finally {
    963             Binder.restoreCallingIdentity(token);
    964         }
    965         mNetworkInfo.setIsAvailable(true);
    966         updateState(DetailedState.CONNECTED, "agentConnect");
    967     }
    968 
    969     private boolean canHaveRestrictedProfile(int userId) {
    970         long token = Binder.clearCallingIdentity();
    971         try {
    972             return UserManager.get(mContext).canHaveRestrictedProfile(userId);
    973         } finally {
    974             Binder.restoreCallingIdentity(token);
    975         }
    976     }
    977 
    978     private void agentDisconnect(NetworkAgent networkAgent) {
    979         if (networkAgent != null) {
    980             NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
    981             networkInfo.setIsAvailable(false);
    982             networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
    983             networkAgent.sendNetworkInfo(networkInfo);
    984         }
    985     }
    986 
    987     private void agentDisconnect() {
    988         if (mNetworkInfo.isConnected()) {
    989             mNetworkInfo.setIsAvailable(false);
    990             updateState(DetailedState.DISCONNECTED, "agentDisconnect");
    991             mNetworkAgent = null;
    992         }
    993     }
    994 
    995     /**
    996      * Establish a VPN network and return the file descriptor of the VPN
    997      * interface. This methods returns {@code null} if the application is
    998      * revoked or not prepared.
    999      *
   1000      * @param config The parameters to configure the network.
   1001      * @return The file descriptor of the VPN interface.
   1002      */
   1003     public synchronized ParcelFileDescriptor establish(VpnConfig config) {
   1004         // Check if the caller is already prepared.
   1005         UserManager mgr = UserManager.get(mContext);
   1006         if (Binder.getCallingUid() != mOwnerUID) {
   1007             return null;
   1008         }
   1009         // Check to ensure consent hasn't been revoked since we were prepared.
   1010         if (!isVpnUserPreConsented(mPackage)) {
   1011             return null;
   1012         }
   1013         // Check if the service is properly declared.
   1014         Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
   1015         intent.setClassName(mPackage, config.user);
   1016         long token = Binder.clearCallingIdentity();
   1017         try {
   1018             // Restricted users are not allowed to create VPNs, they are tied to Owner
   1019             UserInfo user = mgr.getUserInfo(mUserHandle);
   1020             if (user.isRestricted()) {
   1021                 throw new SecurityException("Restricted users cannot establish VPNs");
   1022             }
   1023 
   1024             ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
   1025                     null, 0, mUserHandle);
   1026             if (info == null) {
   1027                 throw new SecurityException("Cannot find " + config.user);
   1028             }
   1029             if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
   1030                 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
   1031             }
   1032         } catch (RemoteException e) {
   1033             throw new SecurityException("Cannot find " + config.user);
   1034         } finally {
   1035             Binder.restoreCallingIdentity(token);
   1036         }
   1037 
   1038         // Save the old config in case we need to go back.
   1039         VpnConfig oldConfig = mConfig;
   1040         String oldInterface = mInterface;
   1041         Connection oldConnection = mConnection;
   1042         NetworkAgent oldNetworkAgent = mNetworkAgent;
   1043         Set<UidRange> oldUsers = mNetworkCapabilities.getUids();
   1044 
   1045         // Configure the interface. Abort if any of these steps fails.
   1046         ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
   1047         try {
   1048             String interfaze = jniGetName(tun.getFd());
   1049 
   1050             // TEMP use the old jni calls until there is support for netd address setting
   1051             StringBuilder builder = new StringBuilder();
   1052             for (LinkAddress address : config.addresses) {
   1053                 builder.append(" " + address);
   1054             }
   1055             if (jniSetAddresses(interfaze, builder.toString()) < 1) {
   1056                 throw new IllegalArgumentException("At least one address must be specified");
   1057             }
   1058             Connection connection = new Connection();
   1059             if (!mContext.bindServiceAsUser(intent, connection,
   1060                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
   1061                     new UserHandle(mUserHandle))) {
   1062                 throw new IllegalStateException("Cannot bind " + config.user);
   1063             }
   1064 
   1065             mConnection = connection;
   1066             mInterface = interfaze;
   1067 
   1068             // Fill more values.
   1069             config.user = mPackage;
   1070             config.interfaze = mInterface;
   1071             config.startTime = SystemClock.elapsedRealtime();
   1072             mConfig = config;
   1073 
   1074             // Set up forwarding and DNS rules.
   1075             // First attempt to do a seamless handover that only changes the interface name and
   1076             // parameters. If that fails, disconnect.
   1077             if (oldConfig != null
   1078                     && updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) {
   1079                 // Keep mNetworkAgent unchanged
   1080             } else {
   1081                 mNetworkAgent = null;
   1082                 updateState(DetailedState.CONNECTING, "establish");
   1083                 // Set up forwarding and DNS rules.
   1084                 agentConnect();
   1085                 // Remove the old tun's user forwarding rules
   1086                 // The new tun's user rules have already been added above so they will take over
   1087                 // as rules are deleted. This prevents data leakage as the rules are moved over.
   1088                 agentDisconnect(oldNetworkAgent);
   1089             }
   1090 
   1091             if (oldConnection != null) {
   1092                 mContext.unbindService(oldConnection);
   1093             }
   1094 
   1095             if (oldInterface != null && !oldInterface.equals(interfaze)) {
   1096                 jniReset(oldInterface);
   1097             }
   1098 
   1099             try {
   1100                 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
   1101             } catch (IOException e) {
   1102                 throw new IllegalStateException(
   1103                         "Cannot set tunnel's fd as blocking=" + config.blocking, e);
   1104             }
   1105         } catch (RuntimeException e) {
   1106             IoUtils.closeQuietly(tun);
   1107             agentDisconnect();
   1108             // restore old state
   1109             mConfig = oldConfig;
   1110             mConnection = oldConnection;
   1111             mNetworkCapabilities.setUids(oldUsers);
   1112             mNetworkAgent = oldNetworkAgent;
   1113             mInterface = oldInterface;
   1114             throw e;
   1115         }
   1116         Log.i(TAG, "Established by " + config.user + " on " + mInterface);
   1117         return tun;
   1118     }
   1119 
   1120     private boolean isRunningLocked() {
   1121         return mNetworkAgent != null && mInterface != null;
   1122     }
   1123 
   1124     // Returns true if the VPN has been established and the calling UID is its owner. Used to check
   1125     // that a call to mutate VPN state is admissible.
   1126     @VisibleForTesting
   1127     protected boolean isCallerEstablishedOwnerLocked() {
   1128         return isRunningLocked() && Binder.getCallingUid() == mOwnerUID;
   1129     }
   1130 
   1131     // Note: Return type guarantees results are deduped and sorted, which callers require.
   1132     private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) {
   1133         SortedSet<Integer> uids = new TreeSet<Integer>();
   1134         for (String app : packageNames) {
   1135             int uid = getAppUid(app, userHandle);
   1136             if (uid != -1) uids.add(uid);
   1137         }
   1138         return uids;
   1139     }
   1140 
   1141     /**
   1142      * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs
   1143      * associated with one user, and any restricted profiles attached to that user.
   1144      *
   1145      * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
   1146      * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
   1147      * in each user and profile will be included.
   1148      *
   1149      * @param userHandle The userId to create UID ranges for along with any of its restricted
   1150      *                   profiles.
   1151      * @param allowedApplications (optional) whitelist of applications to include.
   1152      * @param disallowedApplications (optional) blacklist of applications to exclude.
   1153      */
   1154     @VisibleForTesting
   1155     Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle,
   1156             @Nullable List<String> allowedApplications,
   1157             @Nullable List<String> disallowedApplications) {
   1158         final Set<UidRange> ranges = new ArraySet<>();
   1159 
   1160         // Assign the top-level user to the set of ranges
   1161         addUserToRanges(ranges, userHandle, allowedApplications, disallowedApplications);
   1162 
   1163         // If the user can have restricted profiles, assign all its restricted profiles too
   1164         if (canHaveRestrictedProfile(userHandle)) {
   1165             final long token = Binder.clearCallingIdentity();
   1166             List<UserInfo> users;
   1167             try {
   1168                 users = UserManager.get(mContext).getUsers(true);
   1169             } finally {
   1170                 Binder.restoreCallingIdentity(token);
   1171             }
   1172             for (UserInfo user : users) {
   1173                 if (user.isRestricted() && (user.restrictedProfileParentId == userHandle)) {
   1174                     addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications);
   1175                 }
   1176             }
   1177         }
   1178         return ranges;
   1179     }
   1180 
   1181     /**
   1182      * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs
   1183      * associated with one user.
   1184      *
   1185      * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
   1186      * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
   1187      * in the user will be included.
   1188      *
   1189      * @param ranges {@link Set} of {@link UidRange}s to which to add.
   1190      * @param userHandle The userId to add to {@param ranges}.
   1191      * @param allowedApplications (optional) whitelist of applications to include.
   1192      * @param disallowedApplications (optional) blacklist of applications to exclude.
   1193      */
   1194     @VisibleForTesting
   1195     void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle,
   1196             @Nullable List<String> allowedApplications,
   1197             @Nullable List<String> disallowedApplications) {
   1198         if (allowedApplications != null) {
   1199             // Add ranges covering all UIDs for allowedApplications.
   1200             int start = -1, stop = -1;
   1201             for (int uid : getAppsUids(allowedApplications, userHandle)) {
   1202                 if (start == -1) {
   1203                     start = uid;
   1204                 } else if (uid != stop + 1) {
   1205                     ranges.add(new UidRange(start, stop));
   1206                     start = uid;
   1207                 }
   1208                 stop = uid;
   1209             }
   1210             if (start != -1) ranges.add(new UidRange(start, stop));
   1211         } else if (disallowedApplications != null) {
   1212             // Add all ranges for user skipping UIDs for disallowedApplications.
   1213             final UidRange userRange = UidRange.createForUser(userHandle);
   1214             int start = userRange.start;
   1215             for (int uid : getAppsUids(disallowedApplications, userHandle)) {
   1216                 if (uid == start) {
   1217                     start++;
   1218                 } else {
   1219                     ranges.add(new UidRange(start, uid - 1));
   1220                     start = uid + 1;
   1221                 }
   1222             }
   1223             if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop));
   1224         } else {
   1225             // Add all UIDs for the user.
   1226             ranges.add(UidRange.createForUser(userHandle));
   1227         }
   1228     }
   1229 
   1230     // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that
   1231     // apply to userHandle.
   1232     static private List<UidRange> uidRangesForUser(int userHandle, Set<UidRange> existingRanges) {
   1233         // UidRange#createForUser returns the entire range of UIDs available to a macro-user.
   1234         // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE}
   1235         final UidRange userRange = UidRange.createForUser(userHandle);
   1236         final List<UidRange> ranges = new ArrayList<UidRange>();
   1237         for (UidRange range : existingRanges) {
   1238             if (userRange.containsRange(range)) {
   1239                 ranges.add(range);
   1240             }
   1241         }
   1242         return ranges;
   1243     }
   1244 
   1245     public void onUserAdded(int userHandle) {
   1246         // If the user is restricted tie them to the parent user's VPN
   1247         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
   1248         if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
   1249             synchronized(Vpn.this) {
   1250                 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids();
   1251                 if (existingRanges != null) {
   1252                     try {
   1253                         addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications,
   1254                                 mConfig.disallowedApplications);
   1255                         mNetworkCapabilities.setUids(existingRanges);
   1256                         updateCapabilities();
   1257                     } catch (Exception e) {
   1258                         Log.wtf(TAG, "Failed to add restricted user to owner", e);
   1259                     }
   1260                 }
   1261                 setVpnForcedLocked(mLockdown);
   1262             }
   1263         }
   1264     }
   1265 
   1266     public void onUserRemoved(int userHandle) {
   1267         // clean up if restricted
   1268         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
   1269         if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
   1270             synchronized(Vpn.this) {
   1271                 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids();
   1272                 if (existingRanges != null) {
   1273                     try {
   1274                         final List<UidRange> removedRanges =
   1275                             uidRangesForUser(userHandle, existingRanges);
   1276                         existingRanges.removeAll(removedRanges);
   1277                         mNetworkCapabilities.setUids(existingRanges);
   1278                         updateCapabilities();
   1279                     } catch (Exception e) {
   1280                         Log.wtf(TAG, "Failed to remove restricted user to owner", e);
   1281                     }
   1282                 }
   1283                 setVpnForcedLocked(mLockdown);
   1284             }
   1285         }
   1286     }
   1287 
   1288     /**
   1289      * Called when the user associated with this VPN has just been stopped.
   1290      */
   1291     public synchronized void onUserStopped() {
   1292         // Switch off networking lockdown (if it was enabled)
   1293         setLockdown(false);
   1294         mAlwaysOn = false;
   1295 
   1296         unregisterPackageChangeReceiverLocked();
   1297         // Quit any active connections
   1298         agentDisconnect();
   1299     }
   1300 
   1301     /**
   1302      * Restrict network access from all UIDs affected by this {@link Vpn}, apart from the VPN
   1303      * service app itself, to only sockets that have had {@code protect()} called on them. All
   1304      * non-VPN traffic is blocked via a {@code PROHIBIT} response from the kernel.
   1305      *
   1306      * The exception for the VPN UID isn't technically necessary -- setup should use protected
   1307      * sockets -- but in practice it saves apps that don't protect their sockets from breaking.
   1308      *
   1309      * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to
   1310      * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}.
   1311      *
   1312      * @param enforce {@code true} to require that all traffic under the jurisdiction of this
   1313      *                {@link Vpn} goes through a VPN connection or is blocked until one is
   1314      *                available, {@code false} to lift the requirement.
   1315      *
   1316      * @see #mBlockedUsers
   1317      */
   1318     @GuardedBy("this")
   1319     private void setVpnForcedLocked(boolean enforce) {
   1320         final List<String> exemptedPackages =
   1321                 isNullOrLegacyVpn(mPackage) ? null : Collections.singletonList(mPackage);
   1322         final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers);
   1323 
   1324         Set<UidRange> addedRanges = Collections.emptySet();
   1325         if (enforce) {
   1326             addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle,
   1327                     /* allowedApplications */ null,
   1328                     /* disallowedApplications */ exemptedPackages);
   1329 
   1330             removedRanges.removeAll(addedRanges);
   1331             addedRanges.removeAll(mBlockedUsers);
   1332         }
   1333 
   1334         setAllowOnlyVpnForUids(false, removedRanges);
   1335         setAllowOnlyVpnForUids(true, addedRanges);
   1336     }
   1337 
   1338     /**
   1339      * Either add or remove a list of {@link UidRange}s to the list of UIDs that are only allowed
   1340      * to make connections through sockets that have had {@code protect()} called on them.
   1341      *
   1342      * @param enforce {@code true} to add to the blacklist, {@code false} to remove.
   1343      * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is
   1344      *               {@code true}) or to remove.
   1345      * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise,
   1346      *         including added ranges that already existed or removed ones that didn't.
   1347      */
   1348     @GuardedBy("this")
   1349     private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) {
   1350         if (ranges.size() == 0) {
   1351             return true;
   1352         }
   1353         final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]);
   1354         try {
   1355             mNetd.setAllowOnlyVpnForUids(enforce, rangesArray);
   1356         } catch (RemoteException | RuntimeException e) {
   1357             Log.e(TAG, "Updating blocked=" + enforce
   1358                     + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e);
   1359             return false;
   1360         }
   1361         if (enforce) {
   1362             mBlockedUsers.addAll(ranges);
   1363         } else {
   1364             mBlockedUsers.removeAll(ranges);
   1365         }
   1366         return true;
   1367     }
   1368 
   1369     /**
   1370      * Return the configuration of the currently running VPN.
   1371      */
   1372     public VpnConfig getVpnConfig() {
   1373         enforceControlPermission();
   1374         return mConfig;
   1375     }
   1376 
   1377     @Deprecated
   1378     public synchronized void interfaceStatusChanged(String iface, boolean up) {
   1379         try {
   1380             mObserver.interfaceStatusChanged(iface, up);
   1381         } catch (RemoteException e) {
   1382             // ignored; target is local
   1383         }
   1384     }
   1385 
   1386     private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() {
   1387         @Override
   1388         public void interfaceStatusChanged(String interfaze, boolean up) {
   1389             synchronized (Vpn.this) {
   1390                 if (!up && mLegacyVpnRunner != null) {
   1391                     mLegacyVpnRunner.check(interfaze);
   1392                 }
   1393             }
   1394         }
   1395 
   1396         @Override
   1397         public void interfaceRemoved(String interfaze) {
   1398             synchronized (Vpn.this) {
   1399                 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
   1400                     mStatusIntent = null;
   1401                     mNetworkCapabilities.setUids(null);
   1402                     mConfig = null;
   1403                     mInterface = null;
   1404                     if (mConnection != null) {
   1405                         mContext.unbindService(mConnection);
   1406                         mConnection = null;
   1407                         agentDisconnect();
   1408                     } else if (mLegacyVpnRunner != null) {
   1409                         mLegacyVpnRunner.exit();
   1410                         mLegacyVpnRunner = null;
   1411                     }
   1412                 }
   1413             }
   1414         }
   1415     };
   1416 
   1417     private void enforceControlPermission() {
   1418         mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller");
   1419     }
   1420 
   1421     private void enforceControlPermissionOrInternalCaller() {
   1422         // Require the caller to be either an application with CONTROL_VPN permission or a process
   1423         // in the system server.
   1424         mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN,
   1425                 "Unauthorized Caller");
   1426     }
   1427 
   1428     private void enforceSettingsPermission() {
   1429         mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_SETTINGS,
   1430                 "Unauthorized Caller");
   1431     }
   1432 
   1433     private class Connection implements ServiceConnection {
   1434         private IBinder mService;
   1435 
   1436         @Override
   1437         public void onServiceConnected(ComponentName name, IBinder service) {
   1438             mService = service;
   1439         }
   1440 
   1441         @Override
   1442         public void onServiceDisconnected(ComponentName name) {
   1443             mService = null;
   1444         }
   1445     }
   1446 
   1447     private void prepareStatusIntent() {
   1448         final long token = Binder.clearCallingIdentity();
   1449         try {
   1450             mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
   1451         } finally {
   1452             Binder.restoreCallingIdentity(token);
   1453         }
   1454     }
   1455 
   1456     public synchronized boolean addAddress(String address, int prefixLength) {
   1457         if (!isCallerEstablishedOwnerLocked()) {
   1458             return false;
   1459         }
   1460         boolean success = jniAddAddress(mInterface, address, prefixLength);
   1461         mNetworkAgent.sendLinkProperties(makeLinkProperties());
   1462         return success;
   1463     }
   1464 
   1465     public synchronized boolean removeAddress(String address, int prefixLength) {
   1466         if (!isCallerEstablishedOwnerLocked()) {
   1467             return false;
   1468         }
   1469         boolean success = jniDelAddress(mInterface, address, prefixLength);
   1470         mNetworkAgent.sendLinkProperties(makeLinkProperties());
   1471         return success;
   1472     }
   1473 
   1474     public synchronized boolean setUnderlyingNetworks(Network[] networks) {
   1475         if (!isCallerEstablishedOwnerLocked()) {
   1476             return false;
   1477         }
   1478         if (networks == null) {
   1479             mConfig.underlyingNetworks = null;
   1480         } else {
   1481             mConfig.underlyingNetworks = new Network[networks.length];
   1482             for (int i = 0; i < networks.length; ++i) {
   1483                 if (networks[i] == null) {
   1484                     mConfig.underlyingNetworks[i] = null;
   1485                 } else {
   1486                     mConfig.underlyingNetworks[i] = new Network(networks[i].netId);
   1487                 }
   1488             }
   1489         }
   1490         updateCapabilities();
   1491         return true;
   1492     }
   1493 
   1494     public synchronized Network[] getUnderlyingNetworks() {
   1495         if (!isRunningLocked()) {
   1496             return null;
   1497         }
   1498         return mConfig.underlyingNetworks;
   1499     }
   1500 
   1501     /**
   1502      * This method should only be called by ConnectivityService because it doesn't
   1503      * have enough data to fill VpnInfo.primaryUnderlyingIface field.
   1504      */
   1505     public synchronized VpnInfo getVpnInfo() {
   1506         if (!isRunningLocked()) {
   1507             return null;
   1508         }
   1509 
   1510         VpnInfo info = new VpnInfo();
   1511         info.ownerUid = mOwnerUID;
   1512         info.vpnIface = mInterface;
   1513         return info;
   1514     }
   1515 
   1516     public synchronized boolean appliesToUid(int uid) {
   1517         if (!isRunningLocked()) {
   1518             return false;
   1519         }
   1520         return mNetworkCapabilities.appliesToUid(uid);
   1521     }
   1522 
   1523     /**
   1524      * @return {@code true} if {@param uid} is blocked by an always-on VPN.
   1525      *         A UID is blocked if it's included in one of the mBlockedUsers ranges and the VPN is
   1526      *         not connected, or if the VPN is connected but does not apply to the UID.
   1527      *
   1528      * @see #mBlockedUsers
   1529      */
   1530     public synchronized boolean isBlockingUid(int uid) {
   1531         if (!mLockdown) {
   1532             return false;
   1533         }
   1534 
   1535         if (mNetworkInfo.isConnected()) {
   1536             return !appliesToUid(uid);
   1537         } else {
   1538             for (UidRange uidRange : mBlockedUsers) {
   1539                 if (uidRange.contains(uid)) {
   1540                     return true;
   1541                 }
   1542             }
   1543             return false;
   1544         }
   1545     }
   1546 
   1547     private void updateAlwaysOnNotification(DetailedState networkState) {
   1548         final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
   1549 
   1550         final UserHandle user = UserHandle.of(mUserHandle);
   1551         final long token = Binder.clearCallingIdentity();
   1552         try {
   1553             final NotificationManager notificationManager = NotificationManager.from(mContext);
   1554             if (!visible) {
   1555                 notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user);
   1556                 return;
   1557             }
   1558             final Intent intent = new Intent();
   1559             intent.setComponent(ComponentName.unflattenFromString(mContext.getString(
   1560                     R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)));
   1561             intent.putExtra("lockdown", mLockdown);
   1562             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1563             final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser(
   1564                     intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user);
   1565             final Notification.Builder builder =
   1566                     new Notification.Builder(mContext, SystemNotificationChannels.VPN)
   1567                             .setSmallIcon(R.drawable.vpn_connected)
   1568                             .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected))
   1569                             .setContentText(mContext.getString(R.string.vpn_lockdown_config))
   1570                             .setContentIntent(configIntent)
   1571                             .setCategory(Notification.CATEGORY_SYSTEM)
   1572                             .setVisibility(Notification.VISIBILITY_PUBLIC)
   1573                             .setOngoing(true)
   1574                             .setColor(mContext.getColor(R.color.system_notification_accent_color));
   1575             notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED,
   1576                     builder.build(), user);
   1577         } finally {
   1578             Binder.restoreCallingIdentity(token);
   1579         }
   1580     }
   1581 
   1582     /**
   1583      * Facade for system service calls that change, or depend on, state outside of
   1584      * {@link ConnectivityService} and have hard-to-mock interfaces.
   1585      *
   1586      * @see com.android.server.connectivity.VpnTest
   1587      */
   1588     @VisibleForTesting
   1589     public static class SystemServices {
   1590         private final Context mContext;
   1591 
   1592         public SystemServices(@NonNull Context context) {
   1593             mContext = context;
   1594         }
   1595 
   1596         /**
   1597          * @see PendingIntent#getActivityAsUser()
   1598          */
   1599         public PendingIntent pendingIntentGetActivityAsUser(
   1600                 Intent intent, int flags, UserHandle user) {
   1601             return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags,
   1602                     null /*options*/, user);
   1603         }
   1604 
   1605         /**
   1606          * @see Settings.Secure#putStringForUser
   1607          */
   1608         public void settingsSecurePutStringForUser(String key, String value, int userId) {
   1609             Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId);
   1610         }
   1611 
   1612         /**
   1613          * @see Settings.Secure#putIntForUser
   1614          */
   1615         public void settingsSecurePutIntForUser(String key, int value, int userId) {
   1616             Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId);
   1617         }
   1618 
   1619         /**
   1620          * @see Settings.Secure#getStringForUser
   1621          */
   1622         public String settingsSecureGetStringForUser(String key, int userId) {
   1623             return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId);
   1624         }
   1625 
   1626         /**
   1627          * @see Settings.Secure#getIntForUser
   1628          */
   1629         public int settingsSecureGetIntForUser(String key, int def, int userId) {
   1630             return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId);
   1631         }
   1632     }
   1633 
   1634     private native int jniCreate(int mtu);
   1635     private native String jniGetName(int tun);
   1636     private native int jniSetAddresses(String interfaze, String addresses);
   1637     private native void jniReset(String interfaze);
   1638     private native int jniCheck(String interfaze);
   1639     private native boolean jniAddAddress(String interfaze, String address, int prefixLen);
   1640     private native boolean jniDelAddress(String interfaze, String address, int prefixLen);
   1641 
   1642     private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
   1643         for (RouteInfo route : prop.getAllRoutes()) {
   1644             // Currently legacy VPN only works on IPv4.
   1645             if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
   1646                 return route;
   1647             }
   1648         }
   1649 
   1650         throw new IllegalStateException("Unable to find IPv4 default gateway");
   1651     }
   1652 
   1653     /**
   1654      * Start legacy VPN, controlling native daemons as needed. Creates a
   1655      * secondary thread to perform connection work, returning quickly.
   1656      *
   1657      * Should only be called to respond to Binder requests as this enforces caller permission. Use
   1658      * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the
   1659      * permission check only when the caller is trusted (or the call is initiated by the system).
   1660      */
   1661     public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
   1662         enforceControlPermission();
   1663         long token = Binder.clearCallingIdentity();
   1664         try {
   1665             startLegacyVpnPrivileged(profile, keyStore, egress);
   1666         } finally {
   1667             Binder.restoreCallingIdentity(token);
   1668         }
   1669     }
   1670 
   1671     /**
   1672      * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check
   1673      * permissions under the assumption that the caller is the system.
   1674      *
   1675      * Callers are responsible for checking permissions if needed.
   1676      */
   1677     public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore,
   1678             LinkProperties egress) {
   1679         UserManager mgr = UserManager.get(mContext);
   1680         UserInfo user = mgr.getUserInfo(mUserHandle);
   1681         if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
   1682                     new UserHandle(mUserHandle))) {
   1683             throw new SecurityException("Restricted users cannot establish VPNs");
   1684         }
   1685 
   1686         final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
   1687         final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
   1688         final String iface = ipv4DefaultRoute.getInterface();
   1689 
   1690         // Load certificates.
   1691         String privateKey = "";
   1692         String userCert = "";
   1693         String caCert = "";
   1694         String serverCert = "";
   1695         if (!profile.ipsecUserCert.isEmpty()) {
   1696             privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
   1697             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
   1698             userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
   1699         }
   1700         if (!profile.ipsecCaCert.isEmpty()) {
   1701             byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
   1702             caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
   1703         }
   1704         if (!profile.ipsecServerCert.isEmpty()) {
   1705             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
   1706             serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
   1707         }
   1708         if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
   1709             throw new IllegalStateException("Cannot load credentials");
   1710         }
   1711 
   1712         // Prepare arguments for racoon.
   1713         String[] racoon = null;
   1714         switch (profile.type) {
   1715             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
   1716                 racoon = new String[] {
   1717                     iface, profile.server, "udppsk", profile.ipsecIdentifier,
   1718                     profile.ipsecSecret, "1701",
   1719                 };
   1720                 break;
   1721             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
   1722                 racoon = new String[] {
   1723                     iface, profile.server, "udprsa", privateKey, userCert,
   1724                     caCert, serverCert, "1701",
   1725                 };
   1726                 break;
   1727             case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
   1728                 racoon = new String[] {
   1729                     iface, profile.server, "xauthpsk", profile.ipsecIdentifier,
   1730                     profile.ipsecSecret, profile.username, profile.password, "", gateway,
   1731                 };
   1732                 break;
   1733             case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
   1734                 racoon = new String[] {
   1735                     iface, profile.server, "xauthrsa", privateKey, userCert,
   1736                     caCert, serverCert, profile.username, profile.password, "", gateway,
   1737                 };
   1738                 break;
   1739             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
   1740                 racoon = new String[] {
   1741                     iface, profile.server, "hybridrsa",
   1742                     caCert, serverCert, profile.username, profile.password, "", gateway,
   1743                 };
   1744                 break;
   1745         }
   1746 
   1747         // Prepare arguments for mtpd.
   1748         String[] mtpd = null;
   1749         switch (profile.type) {
   1750             case VpnProfile.TYPE_PPTP:
   1751                 mtpd = new String[] {
   1752                     iface, "pptp", profile.server, "1723",
   1753                     "name", profile.username, "password", profile.password,
   1754                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
   1755                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
   1756                     (profile.mppe ? "+mppe" : "nomppe"),
   1757                 };
   1758                 break;
   1759             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
   1760             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
   1761                 mtpd = new String[] {
   1762                     iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
   1763                     "name", profile.username, "password", profile.password,
   1764                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
   1765                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
   1766                 };
   1767                 break;
   1768         }
   1769 
   1770         VpnConfig config = new VpnConfig();
   1771         config.legacy = true;
   1772         config.user = profile.key;
   1773         config.interfaze = iface;
   1774         config.session = profile.name;
   1775 
   1776         config.addLegacyRoutes(profile.routes);
   1777         if (!profile.dnsServers.isEmpty()) {
   1778             config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
   1779         }
   1780         if (!profile.searchDomains.isEmpty()) {
   1781             config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
   1782         }
   1783         startLegacyVpn(config, racoon, mtpd);
   1784     }
   1785 
   1786     private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
   1787         stopLegacyVpnPrivileged();
   1788 
   1789         // Prepare for the new request.
   1790         prepareInternal(VpnConfig.LEGACY_VPN);
   1791         updateState(DetailedState.CONNECTING, "startLegacyVpn");
   1792 
   1793         // Start a new LegacyVpnRunner and we are done!
   1794         mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
   1795         mLegacyVpnRunner.start();
   1796     }
   1797 
   1798     /** Stop legacy VPN. Permissions must be checked by callers. */
   1799     public synchronized void stopLegacyVpnPrivileged() {
   1800         if (mLegacyVpnRunner != null) {
   1801             mLegacyVpnRunner.exit();
   1802             mLegacyVpnRunner = null;
   1803 
   1804             synchronized (LegacyVpnRunner.TAG) {
   1805                 // wait for old thread to completely finish before spinning up
   1806                 // new instance, otherwise state updates can be out of order.
   1807             }
   1808         }
   1809     }
   1810 
   1811     /**
   1812      * Return the information of the current ongoing legacy VPN.
   1813      */
   1814     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
   1815         // Check if the caller is authorized.
   1816         enforceControlPermission();
   1817         return getLegacyVpnInfoPrivileged();
   1818     }
   1819 
   1820     /**
   1821      * Return the information of the current ongoing legacy VPN.
   1822      * Callers are responsible for checking permissions if needed.
   1823      */
   1824     public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
   1825         if (mLegacyVpnRunner == null) return null;
   1826 
   1827         final LegacyVpnInfo info = new LegacyVpnInfo();
   1828         info.key = mConfig.user;
   1829         info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
   1830         if (mNetworkInfo.isConnected()) {
   1831             info.intent = mStatusIntent;
   1832         }
   1833         return info;
   1834     }
   1835 
   1836     public VpnConfig getLegacyVpnConfig() {
   1837         if (mLegacyVpnRunner != null) {
   1838             return mConfig;
   1839         } else {
   1840             return null;
   1841         }
   1842     }
   1843 
   1844     /**
   1845      * Bringing up a VPN connection takes time, and that is all this thread
   1846      * does. Here we have plenty of time. The only thing we need to take
   1847      * care of is responding to interruptions as soon as possible. Otherwise
   1848      * requests will pile up. This could be done in a Handler as a state
   1849      * machine, but it is much easier to read in the current form.
   1850      */
   1851     private class LegacyVpnRunner extends Thread {
   1852         private static final String TAG = "LegacyVpnRunner";
   1853 
   1854         private final String[] mDaemons;
   1855         private final String[][] mArguments;
   1856         private final LocalSocket[] mSockets;
   1857         private final String mOuterInterface;
   1858         private final AtomicInteger mOuterConnection =
   1859                 new AtomicInteger(ConnectivityManager.TYPE_NONE);
   1860 
   1861         private long mBringupStartTime = -1;
   1862 
   1863         /**
   1864          * Watch for the outer connection (passing in the constructor) going away.
   1865          */
   1866         private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
   1867             @Override
   1868             public void onReceive(Context context, Intent intent) {
   1869                 if (!mEnableTeardown) return;
   1870 
   1871                 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
   1872                     if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
   1873                             ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) {
   1874                         NetworkInfo info = (NetworkInfo)intent.getExtra(
   1875                                 ConnectivityManager.EXTRA_NETWORK_INFO);
   1876                         if (info != null && !info.isConnectedOrConnecting()) {
   1877                             try {
   1878                                 mObserver.interfaceStatusChanged(mOuterInterface, false);
   1879                             } catch (RemoteException e) {}
   1880                         }
   1881                     }
   1882                 }
   1883             }
   1884         };
   1885 
   1886         public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
   1887             super(TAG);
   1888             mConfig = config;
   1889             mDaemons = new String[] {"racoon", "mtpd"};
   1890             // TODO: clear arguments from memory once launched
   1891             mArguments = new String[][] {racoon, mtpd};
   1892             mSockets = new LocalSocket[mDaemons.length];
   1893 
   1894             // This is the interface which VPN is running on,
   1895             // mConfig.interfaze will change to point to OUR
   1896             // internal interface soon. TODO - add inner/outer to mconfig
   1897             // TODO - we have a race - if the outer iface goes away/disconnects before we hit this
   1898             // we will leave the VPN up.  We should check that it's still there/connected after
   1899             // registering
   1900             mOuterInterface = mConfig.interfaze;
   1901 
   1902             if (!TextUtils.isEmpty(mOuterInterface)) {
   1903                 final ConnectivityManager cm = ConnectivityManager.from(mContext);
   1904                 for (Network network : cm.getAllNetworks()) {
   1905                     final LinkProperties lp = cm.getLinkProperties(network);
   1906                     if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) {
   1907                         final NetworkInfo networkInfo = cm.getNetworkInfo(network);
   1908                         if (networkInfo != null) mOuterConnection.set(networkInfo.getType());
   1909                     }
   1910                 }
   1911             }
   1912 
   1913             IntentFilter filter = new IntentFilter();
   1914             filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
   1915             mContext.registerReceiver(mBroadcastReceiver, filter);
   1916         }
   1917 
   1918         public void check(String interfaze) {
   1919             if (interfaze.equals(mOuterInterface)) {
   1920                 Log.i(TAG, "Legacy VPN is going down with " + interfaze);
   1921                 exit();
   1922             }
   1923         }
   1924 
   1925         public void exit() {
   1926             // We assume that everything is reset after stopping the daemons.
   1927             interrupt();
   1928             agentDisconnect();
   1929             try {
   1930                 mContext.unregisterReceiver(mBroadcastReceiver);
   1931             } catch (IllegalArgumentException e) {}
   1932         }
   1933 
   1934         @Override
   1935         public void run() {
   1936             // Wait for the previous thread since it has been interrupted.
   1937             Log.v(TAG, "Waiting");
   1938             synchronized (TAG) {
   1939                 Log.v(TAG, "Executing");
   1940                 try {
   1941                     bringup();
   1942                     waitForDaemonsToStop();
   1943                     interrupted(); // Clear interrupt flag if execute called exit.
   1944                 } catch (InterruptedException e) {
   1945                 } finally {
   1946                     for (LocalSocket socket : mSockets) {
   1947                         IoUtils.closeQuietly(socket);
   1948                     }
   1949                     // This sleep is necessary for racoon to successfully complete sending delete
   1950                     // message to server.
   1951                     try {
   1952                         Thread.sleep(50);
   1953                     } catch (InterruptedException e) {
   1954                     }
   1955                     for (String daemon : mDaemons) {
   1956                         SystemService.stop(daemon);
   1957                     }
   1958                 }
   1959                 agentDisconnect();
   1960             }
   1961         }
   1962 
   1963         private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException {
   1964             long now = SystemClock.elapsedRealtime();
   1965             if (now - mBringupStartTime <= 60000) {
   1966                 Thread.sleep(sleepLonger ? 200 : 1);
   1967             } else {
   1968                 updateState(DetailedState.FAILED, "checkpoint");
   1969                 throw new IllegalStateException("VPN bringup took too long");
   1970             }
   1971         }
   1972 
   1973         private void bringup() {
   1974             // Catch all exceptions so we can clean up a few things.
   1975             boolean initFinished = false;
   1976             try {
   1977                 // Initialize the timer.
   1978                 mBringupStartTime = SystemClock.elapsedRealtime();
   1979 
   1980                 // Wait for the daemons to stop.
   1981                 for (String daemon : mDaemons) {
   1982                     while (!SystemService.isStopped(daemon)) {
   1983                         checkInterruptAndDelay(true);
   1984                     }
   1985                 }
   1986 
   1987                 // Clear the previous state.
   1988                 File state = new File("/data/misc/vpn/state");
   1989                 state.delete();
   1990                 if (state.exists()) {
   1991                     throw new IllegalStateException("Cannot delete the state");
   1992                 }
   1993                 new File("/data/misc/vpn/abort").delete();
   1994                 initFinished = true;
   1995 
   1996                 // Check if we need to restart any of the daemons.
   1997                 boolean restart = false;
   1998                 for (String[] arguments : mArguments) {
   1999                     restart = restart || (arguments != null);
   2000                 }
   2001                 if (!restart) {
   2002                     agentDisconnect();
   2003                     return;
   2004                 }
   2005                 updateState(DetailedState.CONNECTING, "execute");
   2006 
   2007                 // Start the daemon with arguments.
   2008                 for (int i = 0; i < mDaemons.length; ++i) {
   2009                     String[] arguments = mArguments[i];
   2010                     if (arguments == null) {
   2011                         continue;
   2012                     }
   2013 
   2014                     // Start the daemon.
   2015                     String daemon = mDaemons[i];
   2016                     SystemService.start(daemon);
   2017 
   2018                     // Wait for the daemon to start.
   2019                     while (!SystemService.isRunning(daemon)) {
   2020                         checkInterruptAndDelay(true);
   2021                     }
   2022 
   2023                     // Create the control socket.
   2024                     mSockets[i] = new LocalSocket();
   2025                     LocalSocketAddress address = new LocalSocketAddress(
   2026                             daemon, LocalSocketAddress.Namespace.RESERVED);
   2027 
   2028                     // Wait for the socket to connect.
   2029                     while (true) {
   2030                         try {
   2031                             mSockets[i].connect(address);
   2032                             break;
   2033                         } catch (Exception e) {
   2034                             // ignore
   2035                         }
   2036                         checkInterruptAndDelay(true);
   2037                     }
   2038                     mSockets[i].setSoTimeout(500);
   2039 
   2040                     // Send over the arguments.
   2041                     OutputStream out = mSockets[i].getOutputStream();
   2042                     for (String argument : arguments) {
   2043                         byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
   2044                         if (bytes.length >= 0xFFFF) {
   2045                             throw new IllegalArgumentException("Argument is too large");
   2046                         }
   2047                         out.write(bytes.length >> 8);
   2048                         out.write(bytes.length);
   2049                         out.write(bytes);
   2050                         checkInterruptAndDelay(false);
   2051                     }
   2052                     out.write(0xFF);
   2053                     out.write(0xFF);
   2054                     out.flush();
   2055 
   2056                     // Wait for End-of-File.
   2057                     InputStream in = mSockets[i].getInputStream();
   2058                     while (true) {
   2059                         try {
   2060                             if (in.read() == -1) {
   2061                                 break;
   2062                             }
   2063                         } catch (Exception e) {
   2064                             // ignore
   2065                         }
   2066                         checkInterruptAndDelay(true);
   2067                     }
   2068                 }
   2069 
   2070                 // Wait for the daemons to create the new state.
   2071                 while (!state.exists()) {
   2072                     // Check if a running daemon is dead.
   2073                     for (int i = 0; i < mDaemons.length; ++i) {
   2074                         String daemon = mDaemons[i];
   2075                         if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
   2076                             throw new IllegalStateException(daemon + " is dead");
   2077                         }
   2078                     }
   2079                     checkInterruptAndDelay(true);
   2080                 }
   2081 
   2082                 // Now we are connected. Read and parse the new state.
   2083                 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
   2084                 if (parameters.length != 7) {
   2085                     throw new IllegalStateException("Cannot parse the state");
   2086                 }
   2087 
   2088                 // Set the interface and the addresses in the config.
   2089                 mConfig.interfaze = parameters[0].trim();
   2090 
   2091                 mConfig.addLegacyAddresses(parameters[1]);
   2092                 // Set the routes if they are not set in the config.
   2093                 if (mConfig.routes == null || mConfig.routes.isEmpty()) {
   2094                     mConfig.addLegacyRoutes(parameters[2]);
   2095                 }
   2096 
   2097                 // Set the DNS servers if they are not set in the config.
   2098                 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
   2099                     String dnsServers = parameters[3].trim();
   2100                     if (!dnsServers.isEmpty()) {
   2101                         mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
   2102                     }
   2103                 }
   2104 
   2105                 // Set the search domains if they are not set in the config.
   2106                 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) {
   2107                     String searchDomains = parameters[4].trim();
   2108                     if (!searchDomains.isEmpty()) {
   2109                         mConfig.searchDomains = Arrays.asList(searchDomains.split(" "));
   2110                     }
   2111                 }
   2112 
   2113                 // Add a throw route for the VPN server endpoint, if one was specified.
   2114                 String endpoint = parameters[5];
   2115                 if (!endpoint.isEmpty()) {
   2116                     try {
   2117                         InetAddress addr = InetAddress.parseNumericAddress(endpoint);
   2118                         if (addr instanceof Inet4Address) {
   2119                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
   2120                         } else if (addr instanceof Inet6Address) {
   2121                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
   2122                         } else {
   2123                             Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
   2124                         }
   2125                     } catch (IllegalArgumentException e) {
   2126                         Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
   2127                     }
   2128                 }
   2129 
   2130                 // Here is the last step and it must be done synchronously.
   2131                 synchronized (Vpn.this) {
   2132                     // Set the start time
   2133                     mConfig.startTime = SystemClock.elapsedRealtime();
   2134 
   2135                     // Check if the thread was interrupted while we were waiting on the lock.
   2136                     checkInterruptAndDelay(false);
   2137 
   2138                     // Check if the interface is gone while we are waiting.
   2139                     if (jniCheck(mConfig.interfaze) == 0) {
   2140                         throw new IllegalStateException(mConfig.interfaze + " is gone");
   2141                     }
   2142 
   2143                     // Now INetworkManagementEventObserver is watching our back.
   2144                     mInterface = mConfig.interfaze;
   2145                     prepareStatusIntent();
   2146 
   2147                     agentConnect();
   2148 
   2149                     Log.i(TAG, "Connected!");
   2150                 }
   2151             } catch (Exception e) {
   2152                 Log.i(TAG, "Aborting", e);
   2153                 updateState(DetailedState.FAILED, e.getMessage());
   2154                 exit();
   2155             }
   2156         }
   2157 
   2158         /**
   2159          * Check all daemons every two seconds. Return when one of them is stopped.
   2160          * The caller will move to the disconnected state when this function returns,
   2161          * which can happen if a daemon failed or if the VPN was torn down.
   2162          */
   2163         private void waitForDaemonsToStop() throws InterruptedException {
   2164             if (!mNetworkInfo.isConnected()) {
   2165                 return;
   2166             }
   2167             while (true) {
   2168                 Thread.sleep(2000);
   2169                 for (int i = 0; i < mDaemons.length; i++) {
   2170                     if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
   2171                         return;
   2172                     }
   2173                 }
   2174             }
   2175         }
   2176     }
   2177 }
   2178