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