OSDN Git Service

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