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