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