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