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.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
25 import static android.net.RouteInfo.RTN_THROW;
26 import static android.net.RouteInfo.RTN_UNREACHABLE;
27 
28 import static com.android.internal.util.Preconditions.checkNotNull;
29 
30 import android.Manifest;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.annotation.UserIdInt;
34 import android.app.AppGlobals;
35 import android.app.AppOpsManager;
36 import android.app.Notification;
37 import android.app.NotificationManager;
38 import android.app.PendingIntent;
39 import android.content.BroadcastReceiver;
40 import android.content.ComponentName;
41 import android.content.Context;
42 import android.content.Intent;
43 import android.content.IntentFilter;
44 import android.content.ServiceConnection;
45 import android.content.pm.ApplicationInfo;
46 import android.content.pm.PackageManager;
47 import android.content.pm.PackageManager.NameNotFoundException;
48 import android.content.pm.ResolveInfo;
49 import android.content.pm.UserInfo;
50 import android.net.ConnectivityManager;
51 import android.net.INetworkManagementEventObserver;
52 import android.net.Ikev2VpnProfile;
53 import android.net.IpPrefix;
54 import android.net.IpSecManager;
55 import android.net.IpSecManager.IpSecTunnelInterface;
56 import android.net.IpSecTransform;
57 import android.net.LinkAddress;
58 import android.net.LinkProperties;
59 import android.net.LocalSocket;
60 import android.net.LocalSocketAddress;
61 import android.net.Network;
62 import android.net.NetworkAgent;
63 import android.net.NetworkAgentConfig;
64 import android.net.NetworkCapabilities;
65 import android.net.NetworkInfo;
66 import android.net.NetworkInfo.DetailedState;
67 import android.net.NetworkProvider;
68 import android.net.NetworkRequest;
69 import android.net.RouteInfo;
70 import android.net.UidRange;
71 import android.net.VpnManager;
72 import android.net.VpnService;
73 import android.net.ipsec.ike.ChildSessionCallback;
74 import android.net.ipsec.ike.ChildSessionConfiguration;
75 import android.net.ipsec.ike.ChildSessionParams;
76 import android.net.ipsec.ike.IkeSession;
77 import android.net.ipsec.ike.IkeSessionCallback;
78 import android.net.ipsec.ike.IkeSessionParams;
79 import android.os.Binder;
80 import android.os.Build.VERSION_CODES;
81 import android.os.Bundle;
82 import android.os.FileUtils;
83 import android.os.IBinder;
84 import android.os.INetworkManagementService;
85 import android.os.Looper;
86 import android.os.Parcel;
87 import android.os.ParcelFileDescriptor;
88 import android.os.Process;
89 import android.os.RemoteException;
90 import android.os.SystemClock;
91 import android.os.SystemService;
92 import android.os.UserHandle;
93 import android.os.UserManager;
94 import android.provider.Settings;
95 import android.security.Credentials;
96 import android.security.KeyStore;
97 import android.text.TextUtils;
98 import android.util.ArraySet;
99 import android.util.Log;
100 
101 import com.android.internal.R;
102 import com.android.internal.annotations.GuardedBy;
103 import com.android.internal.annotations.VisibleForTesting;
104 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
105 import com.android.internal.net.LegacyVpnInfo;
106 import com.android.internal.net.VpnConfig;
107 import com.android.internal.net.VpnInfo;
108 import com.android.internal.net.VpnProfile;
109 import com.android.internal.notification.SystemNotificationChannels;
110 import com.android.internal.util.ArrayUtils;
111 import com.android.server.ConnectivityService;
112 import com.android.server.DeviceIdleController;
113 import com.android.server.LocalServices;
114 import com.android.server.net.BaseNetworkObserver;
115 
116 import libcore.io.IoUtils;
117 
118 import java.io.File;
119 import java.io.IOException;
120 import java.io.InputStream;
121 import java.io.OutputStream;
122 import java.math.BigInteger;
123 import java.net.Inet4Address;
124 import java.net.Inet6Address;
125 import java.net.InetAddress;
126 import java.nio.charset.StandardCharsets;
127 import java.security.GeneralSecurityException;
128 import java.util.ArrayList;
129 import java.util.Arrays;
130 import java.util.Collection;
131 import java.util.Collections;
132 import java.util.List;
133 import java.util.Objects;
134 import java.util.Set;
135 import java.util.SortedSet;
136 import java.util.TreeSet;
137 import java.util.concurrent.Executor;
138 import java.util.concurrent.ExecutorService;
139 import java.util.concurrent.Executors;
140 import java.util.concurrent.atomic.AtomicInteger;
141 
142 /**
143  * @hide
144  */
145 public class Vpn {
146     private static final String NETWORKTYPE = "VPN";
147     private static final String TAG = "Vpn";
148     private static final boolean LOGD = true;
149 
150     // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on
151     // the device idle whitelist during service launch and VPN bootstrap.
152     private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000;
153 
154     // Settings for how much of the address space should be routed so that Vpn considers
155     // "most" of the address space is routed. This is used to determine whether this Vpn
156     // should be marked with the INTERNET capability.
157     private static final long MOST_IPV4_ADDRESSES_COUNT;
158     private static final BigInteger MOST_IPV6_ADDRESSES_COUNT;
159     static {
160         // 85% of the address space must be routed for Vpn to consider this VPN to provide
161         // INTERNET access.
162         final int howManyPercentIsMost = 85;
163 
164         final long twoPower32 = 1L << 32;
165         MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100;
166         final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128);
167         MOST_IPV6_ADDRESSES_COUNT = twoPower128
168                 .multiply(BigInteger.valueOf(howManyPercentIsMost))
169                 .divide(BigInteger.valueOf(100));
170     }
171     // How many routes to evaluate before bailing and declaring this Vpn should provide
172     // the INTERNET capability. This is necessary because computing the address space is
173     // O(n²) and this is running in the system service, so a limit is needed to alleviate
174     // the risk of attack.
175     // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm
176     // is actually O(n²)+O(n²).
177     private static final int MAX_ROUTES_TO_EVALUATE = 150;
178 
179     /**
180      * Largest profile size allowable for Platform VPNs.
181      *
182      * <p>The largest platform VPN profiles use IKEv2 RSA Certificate Authentication and have two
183      * X509Certificates, and one RSAPrivateKey. This should lead to a max size of 2x 12kB for the
184      * certificates, plus a reasonable upper bound on the private key of 32kB. The rest of the
185      * profile is expected to be negligible in size.
186      */
187     @VisibleForTesting static final int MAX_VPN_PROFILE_SIZE_BYTES = 1 << 17; // 128kB
188 
189     // TODO: create separate trackers for each unique VPN to support
190     // automated reconnection
191 
192     private final Context mContext;
193     private final NetworkInfo mNetworkInfo;
194     @VisibleForTesting protected String mPackage;
195     private int mOwnerUID;
196     private boolean mIsPackageTargetingAtLeastQ;
197     private String mInterface;
198     private Connection mConnection;
199 
200     /** Tracks the runners for all VPN types managed by the platform (eg. LegacyVpn, PlatformVpn) */
201     @VisibleForTesting protected VpnRunner mVpnRunner;
202 
203     private PendingIntent mStatusIntent;
204     private volatile boolean mEnableTeardown = true;
205     private final INetworkManagementService mNetd;
206     @VisibleForTesting
207     protected VpnConfig mConfig;
208     @VisibleForTesting
209     protected NetworkAgent mNetworkAgent;
210     private final Looper mLooper;
211     @VisibleForTesting
212     protected final NetworkCapabilities mNetworkCapabilities;
213     private final SystemServices mSystemServices;
214     private final Ikev2SessionCreator mIkev2SessionCreator;
215 
216     /**
217      * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
218      * only applies to {@link VpnService} connections.
219      */
220     @VisibleForTesting protected boolean mAlwaysOn = false;
221 
222     /**
223      * Whether to disable traffic outside of this VPN even when the VPN is not connected. System
224      * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is
225      * not set. Applies to all types of VPNs.
226      */
227     @VisibleForTesting protected boolean mLockdown = false;
228 
229     /**
230      * Set of packages in addition to the VPN app itself that can access the network directly when
231      * VPN is not connected even if {@code mLockdown} is set.
232      */
233     private @NonNull List<String> mLockdownWhitelist = Collections.emptyList();
234 
235      /**
236      * A memory of what UIDs this class told netd to block for the lockdown feature.
237      *
238      * Netd maintains ranges of UIDs for which network should be restricted to using only the VPN
239      * for the lockdown feature. This class manages these UIDs and sends this information to netd.
240      * To avoid sending the same commands multiple times (which would be wasteful) and to be able
241      * to revoke lists (when the rules should change), it's simplest to keep this cache of what
242      * netd knows, so it can be diffed and sent most efficiently.
243      *
244      * The contents of this list must only be changed when updating the UIDs lists with netd,
245      * since it needs to keep in sync with the picture netd has of them.
246      *
247      * @see mLockdown
248      */
249     @GuardedBy("this")
250     private final Set<UidRange> mBlockedUidsAsToldToNetd = new ArraySet<>();
251 
252     // Handle of the user initiating VPN.
253     private final int mUserHandle;
254 
Vpn(Looper looper, Context context, INetworkManagementService netService, @UserIdInt int userHandle, @NonNull KeyStore keyStore)255     public Vpn(Looper looper, Context context, INetworkManagementService netService,
256             @UserIdInt int userHandle, @NonNull KeyStore keyStore) {
257         this(looper, context, netService, userHandle, keyStore,
258                 new SystemServices(context), new Ikev2SessionCreator());
259     }
260 
261     @VisibleForTesting
Vpn(Looper looper, Context context, INetworkManagementService netService, int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator)262     protected Vpn(Looper looper, Context context, INetworkManagementService netService,
263             int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices,
264             Ikev2SessionCreator ikev2SessionCreator) {
265         mContext = context;
266         mNetd = netService;
267         mUserHandle = userHandle;
268         mLooper = looper;
269         mSystemServices = systemServices;
270         mIkev2SessionCreator = ikev2SessionCreator;
271 
272         mPackage = VpnConfig.LEGACY_VPN;
273         mOwnerUID = getAppUid(mPackage, mUserHandle);
274         mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage);
275 
276         try {
277             netService.registerObserver(mObserver);
278         } catch (RemoteException e) {
279             Log.wtf(TAG, "Problem registering observer", e);
280         }
281 
282         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
283                 "" /* subtypeName */);
284         mNetworkCapabilities = new NetworkCapabilities();
285         mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
286         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
287         updateCapabilities(null /* defaultNetwork */);
288 
289         loadAlwaysOnPackage(keyStore);
290     }
291 
292     /**
293      * Set whether this object is responsible for watching for {@link NetworkInfo}
294      * teardown. When {@code false}, teardown is handled externally by someone
295      * else.
296      */
setEnableTeardown(boolean enableTeardown)297     public void setEnableTeardown(boolean enableTeardown) {
298         mEnableTeardown = enableTeardown;
299     }
300 
301     /**
302      * Update current state, dispatching event to listeners.
303      */
304     @VisibleForTesting
updateState(DetailedState detailedState, String reason)305     protected void updateState(DetailedState detailedState, String reason) {
306         if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
307         mNetworkInfo.setDetailedState(detailedState, reason, null);
308         if (mNetworkAgent != null) {
309             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
310         }
311         updateAlwaysOnNotification(detailedState);
312     }
313 
314     /**
315      * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a
316      * defensive copy.
317      *
318      * <p>Does not propagate updated capabilities to apps.
319      *
320      * @param defaultNetwork underlying network for VPNs following platform's default
321      */
updateCapabilities(@ullable Network defaultNetwork)322     public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) {
323         if (mConfig == null) {
324             // VPN is not running.
325             return null;
326         }
327 
328         Network[] underlyingNetworks = mConfig.underlyingNetworks;
329         if (underlyingNetworks == null && defaultNetwork != null) {
330             // null underlying networks means to track the default.
331             underlyingNetworks = new Network[] { defaultNetwork };
332         }
333         // Only apps targeting Q and above can explicitly declare themselves as metered.
334         final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered;
335 
336         applyUnderlyingCapabilities(
337                 mContext.getSystemService(ConnectivityManager.class),
338                 underlyingNetworks,
339                 mNetworkCapabilities,
340                 isAlwaysMetered);
341 
342         return new NetworkCapabilities(mNetworkCapabilities);
343     }
344 
345     @VisibleForTesting
applyUnderlyingCapabilities( ConnectivityManager cm, Network[] underlyingNetworks, NetworkCapabilities caps, boolean isAlwaysMetered)346     public static void applyUnderlyingCapabilities(
347             ConnectivityManager cm,
348             Network[] underlyingNetworks,
349             NetworkCapabilities caps,
350             boolean isAlwaysMetered) {
351         int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
352         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
353         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
354         boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered
355         boolean roaming = false; // roaming if any underlying is roaming
356         boolean congested = false; // congested if any underlying is congested
357         boolean suspended = true; // suspended if all underlying are suspended
358 
359         boolean hadUnderlyingNetworks = false;
360         if (null != underlyingNetworks) {
361             for (Network underlying : underlyingNetworks) {
362                 // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
363                 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
364                 if (underlyingCaps == null) continue;
365                 hadUnderlyingNetworks = true;
366                 for (int underlyingType : underlyingCaps.getTransportTypes()) {
367                     transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
368                 }
369 
370                 // Merge capabilities of this underlying network. For bandwidth, assume the
371                 // worst case.
372                 downKbps = NetworkCapabilities.minBandwidth(downKbps,
373                         underlyingCaps.getLinkDownstreamBandwidthKbps());
374                 upKbps = NetworkCapabilities.minBandwidth(upKbps,
375                         underlyingCaps.getLinkUpstreamBandwidthKbps());
376                 // If this underlying network is metered, the VPN is metered (it may cost money
377                 // to send packets on this network).
378                 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
379                 // If this underlying network is roaming, the VPN is roaming (the billing structure
380                 // is different than the usual, local one).
381                 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
382                 // If this underlying network is congested, the VPN is congested (the current
383                 // condition of the network affects the performance of this network).
384                 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
385                 // If this network is not suspended, the VPN is not suspended (the VPN
386                 // is able to transfer some data).
387                 suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
388             }
389         }
390         if (!hadUnderlyingNetworks) {
391             // No idea what the underlying networks are; assume sane defaults
392             metered = true;
393             roaming = false;
394             congested = false;
395             suspended = false;
396         }
397 
398         caps.setTransportTypes(transportTypes);
399         caps.setLinkDownstreamBandwidthKbps(downKbps);
400         caps.setLinkUpstreamBandwidthKbps(upKbps);
401         caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
402         caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
403         caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
404         caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
405     }
406 
407     /**
408      * Chooses whether to force all connections to go though VPN.
409      *
410      * Used to enable/disable legacy VPN lockdown.
411      *
412      * This uses the same ip rule mechanism as
413      * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling
414      * that function will be replaced and saved with the always-on state.
415      *
416      * @param lockdown whether to prevent all traffic outside of a VPN.
417      */
setLockdown(boolean lockdown)418     public synchronized void setLockdown(boolean lockdown) {
419         enforceControlPermissionOrInternalCaller();
420 
421         setVpnForcedLocked(lockdown);
422         mLockdown = lockdown;
423 
424         // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by
425         // LockdownVpnTracker.isEnabled() which keeps track of its own state.
426         if (mAlwaysOn) {
427             saveAlwaysOnPackage();
428         }
429     }
430 
431     /**
432      * Check whether to prevent all traffic outside of a VPN even when the VPN is not connected.
433      *
434      * @return {@code true} if VPN lockdown is enabled.
435      */
getLockdown()436     public synchronized boolean getLockdown() {
437         return mLockdown;
438     }
439 
440     /**
441      * Returns whether VPN is configured as always-on.
442      */
getAlwaysOn()443     public synchronized boolean getAlwaysOn() {
444         return mAlwaysOn;
445     }
446 
447     /**
448      * Checks if a VPN app supports always-on mode.
449      *
450      * <p>In order to support the always-on feature, an app has to either have an installed
451      * PlatformVpnProfile, or:
452      *
453      * <ul>
454      *   <li>target {@link VERSION_CODES#N API 24} or above, and
455      *   <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
456      *       meta-data field.
457      * </ul>
458      *
459      * @param packageName the canonical package name of the VPN app
460      * @param keyStore the keystore instance to use for checking if the app has a Platform VPN
461      *     profile installed.
462      * @return {@code true} if and only if the VPN app exists and supports always-on mode
463      */
isAlwaysOnPackageSupported(String packageName, @NonNull KeyStore keyStore)464     public boolean isAlwaysOnPackageSupported(String packageName, @NonNull KeyStore keyStore) {
465         enforceSettingsPermission();
466 
467         if (packageName == null) {
468             return false;
469         }
470 
471         final long oldId = Binder.clearCallingIdentity();
472         try {
473             if (getVpnProfilePrivileged(packageName, keyStore) != null) {
474                 return true;
475             }
476         } finally {
477             Binder.restoreCallingIdentity(oldId);
478         }
479 
480         PackageManager pm = mContext.getPackageManager();
481         ApplicationInfo appInfo = null;
482         try {
483             appInfo = pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle);
484         } catch (NameNotFoundException unused) {
485             Log.w(TAG, "Can't find \"" + packageName + "\" when checking always-on support");
486         }
487         if (appInfo == null || appInfo.targetSdkVersion < VERSION_CODES.N) {
488             return false;
489         }
490 
491         final Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
492         intent.setPackage(packageName);
493         List<ResolveInfo> services =
494                 pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, mUserHandle);
495         if (services == null || services.size() == 0) {
496             return false;
497         }
498 
499         for (ResolveInfo rInfo : services) {
500             final Bundle metaData = rInfo.serviceInfo.metaData;
501             if (metaData != null &&
502                     !metaData.getBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, true)) {
503                 return false;
504             }
505         }
506 
507         return true;
508     }
509 
510     /**
511      * Configures an always-on VPN connection through a specific application. This connection is
512      * automatically granted and persisted after a reboot.
513      *
514      * <p>The designated package should either have a PlatformVpnProfile installed, or declare a
515      * {@link VpnService} in its manifest guarded by {@link
516      * android.Manifest.permission.BIND_VPN_SERVICE}, otherwise the call will fail.
517      *
518      * <p>Note that this method does not check if the VPN app supports always-on mode. The check is
519      * delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this method
520      * in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}.
521      *
522      * @param packageName the package to designate as always-on VPN supplier.
523      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
524      * @param lockdownWhitelist packages to be whitelisted from lockdown.
525      * @param keyStore the Keystore instance to use for checking of PlatformVpnProfile(s)
526      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
527      */
setAlwaysOnPackage( @ullable String packageName, boolean lockdown, @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore)528     public synchronized boolean setAlwaysOnPackage(
529             @Nullable String packageName,
530             boolean lockdown,
531             @Nullable List<String> lockdownWhitelist,
532             @NonNull KeyStore keyStore) {
533         enforceControlPermissionOrInternalCaller();
534 
535         if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist, keyStore)) {
536             saveAlwaysOnPackage();
537             return true;
538         }
539         return false;
540     }
541 
542     /**
543      * Configures an always-on VPN connection through a specific application, the same as {@link
544      * #setAlwaysOnPackage}.
545      *
546      * <p>Does not perform permission checks. Does not persist any of the changes to storage.
547      *
548      * @param packageName the package to designate as always-on VPN supplier.
549      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
550      * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if
551      *     {@code lockdown} is {@code true}. Packages must not contain commas.
552      * @param keyStore the system keystore instance to check for profiles
553      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
554      */
555     @GuardedBy("this")
setAlwaysOnPackageInternal( @ullable String packageName, boolean lockdown, @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore)556     private boolean setAlwaysOnPackageInternal(
557             @Nullable String packageName, boolean lockdown,
558             @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore) {
559         if (VpnConfig.LEGACY_VPN.equals(packageName)) {
560             Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
561             return false;
562         }
563 
564         if (lockdownWhitelist != null) {
565             for (String pkg : lockdownWhitelist) {
566                 if (pkg.contains(",")) {
567                     Log.w(TAG, "Not setting always-on vpn, invalid whitelisted package: " + pkg);
568                     return false;
569                 }
570             }
571         }
572 
573         if (packageName != null) {
574             final VpnProfile profile;
575             final long oldId = Binder.clearCallingIdentity();
576             try {
577                 profile = getVpnProfilePrivileged(packageName, keyStore);
578             } finally {
579                 Binder.restoreCallingIdentity(oldId);
580             }
581 
582             // Pre-authorize new always-on VPN package.
583             final int grantType =
584                     (profile == null) ? VpnManager.TYPE_VPN_SERVICE : VpnManager.TYPE_VPN_PLATFORM;
585             if (!setPackageAuthorization(packageName, grantType)) {
586                 return false;
587             }
588             mAlwaysOn = true;
589         } else {
590             packageName = VpnConfig.LEGACY_VPN;
591             mAlwaysOn = false;
592         }
593 
594         mLockdown = (mAlwaysOn && lockdown);
595         mLockdownWhitelist = (mLockdown && lockdownWhitelist != null)
596                 ? Collections.unmodifiableList(new ArrayList<>(lockdownWhitelist))
597                 : Collections.emptyList();
598 
599         if (isCurrentPreparedPackage(packageName)) {
600             updateAlwaysOnNotification(mNetworkInfo.getDetailedState());
601             setVpnForcedLocked(mLockdown);
602         } else {
603             // Prepare this app. The notification will update as a side-effect of updateState().
604             // It also calls setVpnForcedLocked().
605             prepareInternal(packageName);
606         }
607         return true;
608     }
609 
isNullOrLegacyVpn(String packageName)610     private static boolean isNullOrLegacyVpn(String packageName) {
611         return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName);
612     }
613 
614     /**
615      * @return the package name of the VPN controller responsible for always-on VPN,
616      *         or {@code null} if none is set or always-on VPN is controlled through
617      *         lockdown instead.
618      */
getAlwaysOnPackage()619     public synchronized String getAlwaysOnPackage() {
620         enforceControlPermissionOrInternalCaller();
621         return (mAlwaysOn ? mPackage : null);
622     }
623 
624     /**
625      * @return an immutable list of packages whitelisted from always-on VPN lockdown.
626      */
getLockdownWhitelist()627     public synchronized List<String> getLockdownWhitelist() {
628         return mLockdown ? mLockdownWhitelist : null;
629     }
630 
631     /**
632      * Save the always-on package and lockdown config into Settings.Secure
633      */
634     @GuardedBy("this")
saveAlwaysOnPackage()635     private void saveAlwaysOnPackage() {
636         final long token = Binder.clearCallingIdentity();
637         try {
638             mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP,
639                     getAlwaysOnPackage(), mUserHandle);
640             mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
641                     (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle);
642             mSystemServices.settingsSecurePutStringForUser(
643                     Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST,
644                     String.join(",", mLockdownWhitelist), mUserHandle);
645         } finally {
646             Binder.restoreCallingIdentity(token);
647         }
648     }
649 
650     /** Load the always-on package and lockdown config from Settings. */
651     @GuardedBy("this")
loadAlwaysOnPackage(@onNull KeyStore keyStore)652     private void loadAlwaysOnPackage(@NonNull KeyStore keyStore) {
653         final long token = Binder.clearCallingIdentity();
654         try {
655             final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser(
656                     Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle);
657             final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser(
658                     Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0;
659             final String whitelistString = mSystemServices.settingsSecureGetStringForUser(
660                     Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle);
661             final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString)
662                     ? Collections.emptyList() : Arrays.asList(whitelistString.split(","));
663             setAlwaysOnPackageInternal(
664                     alwaysOnPackage, alwaysOnLockdown, whitelistedPackages, keyStore);
665         } finally {
666             Binder.restoreCallingIdentity(token);
667         }
668     }
669 
670     /**
671      * Starts the currently selected always-on VPN
672      *
673      * @param keyStore the keyStore instance for looking up PlatformVpnProfile(s)
674      * @return {@code true} if the service was started, the service was already connected, or there
675      *     was no always-on VPN to start. {@code false} otherwise.
676      */
startAlwaysOnVpn(@onNull KeyStore keyStore)677     public boolean startAlwaysOnVpn(@NonNull KeyStore keyStore) {
678         final String alwaysOnPackage;
679         synchronized (this) {
680             alwaysOnPackage = getAlwaysOnPackage();
681             // Skip if there is no service to start.
682             if (alwaysOnPackage == null) {
683                 return true;
684             }
685             // Remove always-on VPN if it's not supported.
686             if (!isAlwaysOnPackageSupported(alwaysOnPackage, keyStore)) {
687                 setAlwaysOnPackage(null, false, null, keyStore);
688                 return false;
689             }
690             // Skip if the service is already established. This isn't bulletproof: it's not bound
691             // until after establish(), so if it's mid-setup onStartCommand will be sent twice,
692             // which may restart the connection.
693             if (getNetworkInfo().isConnected()) {
694                 return true;
695             }
696         }
697 
698         final long oldId = Binder.clearCallingIdentity();
699         try {
700             // Prefer VPN profiles, if any exist.
701             VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage, keyStore);
702             if (profile != null) {
703                 startVpnProfilePrivileged(profile, alwaysOnPackage,
704                         null /* keyStore for private key retrieval - unneeded */);
705 
706                 // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was
707                 // correctly parsed, and the VPN has started running in a different thread. The only
708                 // other possibility is that the above call threw an exception, which will be
709                 // caught below, and returns false (clearing the always-on VPN). Once started, the
710                 // Platform VPN cannot permanently fail, and is resilient to temporary failures. It
711                 // will continue retrying until shut down by the user, or always-on is toggled off.
712                 return true;
713             }
714 
715             // Tell the OS that background services in this app need to be allowed for
716             // a short time, so we can bootstrap the VPN service.
717             DeviceIdleController.LocalService idleController =
718                     LocalServices.getService(DeviceIdleController.LocalService.class);
719             idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
720                     VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn");
721 
722             // Start the VPN service declared in the app's manifest.
723             Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE);
724             serviceIntent.setPackage(alwaysOnPackage);
725             try {
726                 return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null;
727             } catch (RuntimeException e) {
728                 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e);
729                 return false;
730             }
731         } catch (Exception e) {
732             Log.e(TAG, "Error starting always-on VPN", e);
733             return false;
734         } finally {
735             Binder.restoreCallingIdentity(oldId);
736         }
737     }
738 
739     /**
740      * Prepare for a VPN application. This method is designed to solve
741      * race conditions. It first compares the current prepared package
742      * with {@code oldPackage}. If they are the same, the prepared
743      * package is revoked and replaced with {@code newPackage}. If
744      * {@code oldPackage} is {@code null}, the comparison is omitted.
745      * If {@code newPackage} is the same package or {@code null}, the
746      * revocation is omitted. This method returns {@code true} if the
747      * operation is succeeded.
748      *
749      * Legacy VPN is handled specially since it is not a real package.
750      * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
751      * it can be revoked by itself.
752      *
753      * The permission checks to verify that the VPN has already been granted
754      * user consent are dependent on the type of the VPN being prepared. See
755      * {@link AppOpsManager#OP_ACTIVATE_VPN} and {@link
756      * AppOpsManager#OP_ACTIVATE_PLATFORM_VPN} for more information.
757      *
758      * Note: when we added VPN pre-consent in
759      * https://android.googlesource.com/platform/frameworks/base/+/0554260
760      * the names oldPackage and newPackage became misleading, because when
761      * an app is pre-consented, we actually prepare oldPackage, not newPackage.
762      *
763      * Their meanings actually are:
764      *
765      * - oldPackage non-null, newPackage null: App calling VpnService#prepare().
766      * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn().
767      * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect
768      *   and revoke any current app VPN and re-prepare legacy vpn.
769      *
770      * TODO: Rename the variables - or split this method into two - and end this confusion.
771      * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN)
772      * to prepare(oldPackage=null, newPackage=LEGACY_VPN)
773      *
774      * @param oldPackage The package name of the old VPN application
775      * @param newPackage The package name of the new VPN application
776      * @param vpnType The type of VPN being prepared. One of {@link VpnManager.VpnType} Preparing a
777      *     platform VPN profile requires only the lesser ACTIVATE_PLATFORM_VPN appop.
778      * @return true if the operation succeeded.
779      */
prepare( String oldPackage, String newPackage, @VpnManager.VpnType int vpnType)780     public synchronized boolean prepare(
781             String oldPackage, String newPackage, @VpnManager.VpnType int vpnType) {
782         if (oldPackage != null) {
783             // Stop an existing always-on VPN from being dethroned by other apps.
784             if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) {
785                 return false;
786             }
787 
788             // Package is not the same or old package was reinstalled.
789             if (!isCurrentPreparedPackage(oldPackage)) {
790                 // The package doesn't match. We return false (to obtain user consent) unless the
791                 // user has already consented to that VPN package.
792                 if (!oldPackage.equals(VpnConfig.LEGACY_VPN)
793                         && isVpnPreConsented(mContext, oldPackage, vpnType)) {
794                     prepareInternal(oldPackage);
795                     return true;
796                 }
797                 return false;
798             } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN)
799                     && !isVpnPreConsented(mContext, oldPackage, vpnType)) {
800                 // Currently prepared VPN is revoked, so unprepare it and return false.
801                 prepareInternal(VpnConfig.LEGACY_VPN);
802                 return false;
803             }
804         }
805 
806         // Return true if we do not need to revoke.
807         if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) &&
808                 isCurrentPreparedPackage(newPackage))) {
809             return true;
810         }
811 
812         // Check that the caller is authorized.
813         enforceControlPermission();
814 
815         // Stop an existing always-on VPN from being dethroned by other apps.
816         if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) {
817             return false;
818         }
819 
820         prepareInternal(newPackage);
821         return true;
822     }
823 
isCurrentPreparedPackage(String packageName)824     private boolean isCurrentPreparedPackage(String packageName) {
825         // We can't just check that packageName matches mPackage, because if the app was uninstalled
826         // and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the
827         // calling package may not be the same as the prepared package. Check both UID and package.
828         return getAppUid(packageName, mUserHandle) == mOwnerUID && mPackage.equals(packageName);
829     }
830 
831     /** Prepare the VPN for the given package. Does not perform permission checks. */
832     @GuardedBy("this")
prepareInternal(String newPackage)833     private void prepareInternal(String newPackage) {
834         long token = Binder.clearCallingIdentity();
835         try {
836             // Reset the interface.
837             if (mInterface != null) {
838                 mStatusIntent = null;
839                 agentDisconnect();
840                 jniReset(mInterface);
841                 mInterface = null;
842                 mNetworkCapabilities.setUids(null);
843             }
844 
845             // Revoke the connection or stop the VpnRunner.
846             if (mConnection != null) {
847                 try {
848                     mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION,
849                             Parcel.obtain(), null, IBinder.FLAG_ONEWAY);
850                 } catch (Exception e) {
851                     // ignore
852                 }
853                 mContext.unbindService(mConnection);
854                 cleanupVpnStateLocked();
855             } else if (mVpnRunner != null) {
856                 // cleanupVpnStateLocked() is called from mVpnRunner.exit()
857                 mVpnRunner.exit();
858             }
859 
860             try {
861                 mNetd.denyProtect(mOwnerUID);
862             } catch (Exception e) {
863                 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
864             }
865 
866             Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
867             mPackage = newPackage;
868             mOwnerUID = getAppUid(newPackage, mUserHandle);
869             mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
870             try {
871                 mNetd.allowProtect(mOwnerUID);
872             } catch (Exception e) {
873                 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
874             }
875             mConfig = null;
876 
877             updateState(DetailedState.IDLE, "prepare");
878             setVpnForcedLocked(mLockdown);
879         } finally {
880             Binder.restoreCallingIdentity(token);
881         }
882     }
883 
884     /** Set whether a package has the ability to launch VPNs without user intervention. */
setPackageAuthorization(String packageName, @VpnManager.VpnType int vpnType)885     public boolean setPackageAuthorization(String packageName, @VpnManager.VpnType int vpnType) {
886         // Check if the caller is authorized.
887         enforceControlPermissionOrInternalCaller();
888 
889         final int uid = getAppUid(packageName, mUserHandle);
890         if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) {
891             // Authorization for nonexistent packages (or fake ones) can't be updated.
892             return false;
893         }
894 
895         final long token = Binder.clearCallingIdentity();
896         try {
897             final int[] toChange;
898 
899             // Clear all AppOps if the app is being unauthorized.
900             switch (vpnType) {
901                 case VpnManager.TYPE_VPN_NONE:
902                     toChange = new int[] {
903                             AppOpsManager.OP_ACTIVATE_VPN, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN
904                     };
905                     break;
906                 case VpnManager.TYPE_VPN_PLATFORM:
907                     toChange = new int[] {AppOpsManager.OP_ACTIVATE_PLATFORM_VPN};
908                     break;
909                 case VpnManager.TYPE_VPN_SERVICE:
910                     toChange = new int[] {AppOpsManager.OP_ACTIVATE_VPN};
911                     break;
912                 default:
913                     Log.wtf(TAG, "Unrecognized VPN type while granting authorization");
914                     return false;
915             }
916 
917             final AppOpsManager appOpMgr =
918                     (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
919             for (final int appOp : toChange) {
920                 appOpMgr.setMode(
921                         appOp,
922                         uid,
923                         packageName,
924                         vpnType == VpnManager.TYPE_VPN_NONE
925                                 ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED);
926             }
927             return true;
928         } catch (Exception e) {
929             Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e);
930         } finally {
931             Binder.restoreCallingIdentity(token);
932         }
933         return false;
934     }
935 
isVpnPreConsented(Context context, String packageName, int vpnType)936     private static boolean isVpnPreConsented(Context context, String packageName, int vpnType) {
937         switch (vpnType) {
938             case VpnManager.TYPE_VPN_SERVICE:
939                 return isVpnServicePreConsented(context, packageName);
940             case VpnManager.TYPE_VPN_PLATFORM:
941                 return isVpnProfilePreConsented(context, packageName);
942             default:
943                 return false;
944         }
945     }
946 
doesPackageHaveAppop(Context context, String packageName, int appop)947     private static boolean doesPackageHaveAppop(Context context, String packageName, int appop) {
948         final AppOpsManager appOps =
949                 (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
950 
951         // Verify that the caller matches the given package and has the required permission.
952         return appOps.noteOpNoThrow(appop, Binder.getCallingUid(), packageName)
953                 == AppOpsManager.MODE_ALLOWED;
954     }
955 
isVpnServicePreConsented(Context context, String packageName)956     private static boolean isVpnServicePreConsented(Context context, String packageName) {
957         return doesPackageHaveAppop(context, packageName, AppOpsManager.OP_ACTIVATE_VPN);
958     }
959 
isVpnProfilePreConsented(Context context, String packageName)960     private static boolean isVpnProfilePreConsented(Context context, String packageName) {
961         return doesPackageHaveAppop(context, packageName, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN)
962                 || isVpnServicePreConsented(context, packageName);
963     }
964 
getAppUid(final String app, final int userHandle)965     private int getAppUid(final String app, final int userHandle) {
966         if (VpnConfig.LEGACY_VPN.equals(app)) {
967             return Process.myUid();
968         }
969         PackageManager pm = mContext.getPackageManager();
970         return Binder.withCleanCallingIdentity(() -> {
971             try {
972                 return pm.getPackageUidAsUser(app, userHandle);
973             } catch (NameNotFoundException e) {
974                 return -1;
975             }
976         });
977     }
978 
979     private boolean doesPackageTargetAtLeastQ(String packageName) {
980         if (VpnConfig.LEGACY_VPN.equals(packageName)) {
981             return true;
982         }
983         PackageManager pm = mContext.getPackageManager();
984         try {
985             ApplicationInfo appInfo =
986                     pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle);
987             return appInfo.targetSdkVersion >= VERSION_CODES.Q;
988         } catch (NameNotFoundException unused) {
989             Log.w(TAG, "Can't find \"" + packageName + "\"");
990             return false;
991         }
992     }
993 
994     public NetworkInfo getNetworkInfo() {
995         return mNetworkInfo;
996     }
997 
998     public int getNetId() {
999         final NetworkAgent agent = mNetworkAgent;
1000         if (null == agent) return NETID_UNSET;
1001         final Network network = agent.getNetwork();
1002         if (null == network) return NETID_UNSET;
1003         return network.netId;
1004     }
1005 
1006     private LinkProperties makeLinkProperties() {
1007         boolean allowIPv4 = mConfig.allowIPv4;
1008         boolean allowIPv6 = mConfig.allowIPv6;
1009 
1010         LinkProperties lp = new LinkProperties();
1011 
1012         lp.setInterfaceName(mInterface);
1013 
1014         if (mConfig.addresses != null) {
1015             for (LinkAddress address : mConfig.addresses) {
1016                 lp.addLinkAddress(address);
1017                 allowIPv4 |= address.getAddress() instanceof Inet4Address;
1018                 allowIPv6 |= address.getAddress() instanceof Inet6Address;
1019             }
1020         }
1021 
1022         if (mConfig.routes != null) {
1023             for (RouteInfo route : mConfig.routes) {
1024                 lp.addRoute(route);
1025                 InetAddress address = route.getDestination().getAddress();
1026                 allowIPv4 |= address instanceof Inet4Address;
1027                 allowIPv6 |= address instanceof Inet6Address;
1028             }
1029         }
1030 
1031         if (mConfig.dnsServers != null) {
1032             for (String dnsServer : mConfig.dnsServers) {
1033                 InetAddress address = InetAddress.parseNumericAddress(dnsServer);
1034                 lp.addDnsServer(address);
1035                 allowIPv4 |= address instanceof Inet4Address;
1036                 allowIPv6 |= address instanceof Inet6Address;
1037             }
1038         }
1039 
1040         lp.setHttpProxy(mConfig.proxyInfo);
1041 
1042         if (!allowIPv4) {
1043             lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
1044         }
1045         if (!allowIPv6) {
1046             lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
1047         }
1048 
1049         // Concatenate search domains into a string.
1050         StringBuilder buffer = new StringBuilder();
1051         if (mConfig.searchDomains != null) {
1052             for (String domain : mConfig.searchDomains) {
1053                 buffer.append(domain).append(' ');
1054             }
1055         }
1056         lp.setDomains(buffer.toString().trim());
1057 
1058         if (mConfig.mtu > 0) {
1059             lp.setMtu(mConfig.mtu);
1060         }
1061 
1062         // TODO: Stop setting the MTU in jniCreate
1063 
1064         return lp;
1065     }
1066 
1067     /**
1068      * Attempt to perform a seamless handover of VPNs by only updating LinkProperties without
1069      * registering a new NetworkAgent. This is not always possible if the new VPN configuration
1070      * has certain changes, in which case this method would just return {@code false}.
1071      */
1072     private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) {
1073         // NetworkAgentConfig cannot be updated without registering a new NetworkAgent.
1074         if (oldConfig.allowBypass != mConfig.allowBypass) {
1075             Log.i(TAG, "Handover not possible due to changes to allowBypass");
1076             return false;
1077         }
1078 
1079         // TODO: we currently do not support seamless handover if the allowed or disallowed
1080         // applications have changed. Consider diffing UID ranges and only applying the delta.
1081         if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) ||
1082                 !Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) {
1083             Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps");
1084             return false;
1085         }
1086 
1087         agent.sendLinkProperties(makeLinkProperties());
1088         return true;
1089     }
1090 
1091     private void agentConnect() {
1092         LinkProperties lp = makeLinkProperties();
1093 
1094         // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel
1095         // that falls back to the default network, which by definition provides INTERNET (unless
1096         // there is no default network, in which case none of this matters in any sense).
1097         // Also, always setting the INTERNET bit guarantees that when a VPN applies to an app,
1098         // the VPN will always be reported as the network by getDefaultNetwork and callbacks
1099         // registered with registerDefaultNetworkCallback. This in turn protects the invariant
1100         // that an app calling ConnectivityManager#bindProcessToNetwork(getDefaultNetwork())
1101         // behaves the same as when it uses the default network.
1102         mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
1103 
1104         mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
1105 
1106         NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
1107         networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
1108 
1109         mNetworkCapabilities.setOwnerUid(mOwnerUID);
1110         mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID});
1111         mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle,
1112                 mConfig.allowedApplications, mConfig.disallowedApplications));
1113         long token = Binder.clearCallingIdentity();
1114         try {
1115             mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
1116                     mNetworkInfo, mNetworkCapabilities, lp,
1117                     ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig,
1118                     NetworkProvider.ID_VPN) {
1119                             @Override
1120                             public void unwanted() {
1121                                 // We are user controlled, not driven by NetworkRequest.
1122                             }
1123                         };
1124         } finally {
1125             Binder.restoreCallingIdentity(token);
1126         }
1127         mNetworkInfo.setIsAvailable(true);
1128         updateState(DetailedState.CONNECTED, "agentConnect");
1129     }
1130 
1131     private boolean canHaveRestrictedProfile(int userId) {
1132         long token = Binder.clearCallingIdentity();
1133         try {
1134             return UserManager.get(mContext).canHaveRestrictedProfile(userId);
1135         } finally {
1136             Binder.restoreCallingIdentity(token);
1137         }
1138     }
1139 
1140     private void agentDisconnect(NetworkAgent networkAgent) {
1141         if (networkAgent != null) {
1142             NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
1143             networkInfo.setIsAvailable(false);
1144             networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
1145             networkAgent.sendNetworkInfo(networkInfo);
1146         }
1147     }
1148 
1149     private void agentDisconnect() {
1150         if (mNetworkInfo.isConnected()) {
1151             mNetworkInfo.setIsAvailable(false);
1152             updateState(DetailedState.DISCONNECTED, "agentDisconnect");
1153             mNetworkAgent = null;
1154         }
1155     }
1156 
1157     /**
1158      * Establish a VPN network and return the file descriptor of the VPN interface. This methods
1159      * returns {@code null} if the application is revoked or not prepared.
1160      *
1161      * <p>This method supports ONLY VpnService-based VPNs. For Platform VPNs, see {@link
1162      * provisionVpnProfile} and {@link startVpnProfile}
1163      *
1164      * @param config The parameters to configure the network.
1165      * @return The file descriptor of the VPN interface.
1166      */
1167     public synchronized ParcelFileDescriptor establish(VpnConfig config) {
1168         // Check if the caller is already prepared.
1169         if (Binder.getCallingUid() != mOwnerUID) {
1170             return null;
1171         }
1172         // Check to ensure consent hasn't been revoked since we were prepared.
1173         if (!isVpnServicePreConsented(mContext, mPackage)) {
1174             return null;
1175         }
1176         // Check if the service is properly declared.
1177         Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
1178         intent.setClassName(mPackage, config.user);
1179         long token = Binder.clearCallingIdentity();
1180         try {
1181             // Restricted users are not allowed to create VPNs, they are tied to Owner
1182             enforceNotRestrictedUser();
1183 
1184             ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
1185                     null, 0, mUserHandle);
1186             if (info == null) {
1187                 throw new SecurityException("Cannot find " + config.user);
1188             }
1189             if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
1190                 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
1191             }
1192         } catch (RemoteException e) {
1193             throw new SecurityException("Cannot find " + config.user);
1194         } finally {
1195             Binder.restoreCallingIdentity(token);
1196         }
1197 
1198         // Save the old config in case we need to go back.
1199         VpnConfig oldConfig = mConfig;
1200         String oldInterface = mInterface;
1201         Connection oldConnection = mConnection;
1202         NetworkAgent oldNetworkAgent = mNetworkAgent;
1203         Set<UidRange> oldUsers = mNetworkCapabilities.getUids();
1204 
1205         // Configure the interface. Abort if any of these steps fails.
1206         ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
1207         try {
1208             String interfaze = jniGetName(tun.getFd());
1209 
1210             // TEMP use the old jni calls until there is support for netd address setting
1211             StringBuilder builder = new StringBuilder();
1212             for (LinkAddress address : config.addresses) {
1213                 builder.append(" ");
1214                 builder.append(address);
1215             }
1216             if (jniSetAddresses(interfaze, builder.toString()) < 1) {
1217                 throw new IllegalArgumentException("At least one address must be specified");
1218             }
1219             Connection connection = new Connection();
1220             if (!mContext.bindServiceAsUser(intent, connection,
1221                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
1222                     new UserHandle(mUserHandle))) {
1223                 throw new IllegalStateException("Cannot bind " + config.user);
1224             }
1225 
1226             mConnection = connection;
1227             mInterface = interfaze;
1228 
1229             // Fill more values.
1230             config.user = mPackage;
1231             config.interfaze = mInterface;
1232             config.startTime = SystemClock.elapsedRealtime();
1233             mConfig = config;
1234 
1235             // Set up forwarding and DNS rules.
1236             // First attempt to do a seamless handover that only changes the interface name and
1237             // parameters. If that fails, disconnect.
1238             if (oldConfig != null
1239                     && updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) {
1240                 // Keep mNetworkAgent unchanged
1241             } else {
1242                 mNetworkAgent = null;
1243                 updateState(DetailedState.CONNECTING, "establish");
1244                 // Set up forwarding and DNS rules.
1245                 agentConnect();
1246                 // Remove the old tun's user forwarding rules
1247                 // The new tun's user rules have already been added above so they will take over
1248                 // as rules are deleted. This prevents data leakage as the rules are moved over.
1249                 agentDisconnect(oldNetworkAgent);
1250             }
1251 
1252             if (oldConnection != null) {
1253                 mContext.unbindService(oldConnection);
1254             }
1255 
1256             if (oldInterface != null && !oldInterface.equals(interfaze)) {
1257                 jniReset(oldInterface);
1258             }
1259 
1260             try {
1261                 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
1262             } catch (IOException e) {
1263                 throw new IllegalStateException(
1264                         "Cannot set tunnel's fd as blocking=" + config.blocking, e);
1265             }
1266         } catch (RuntimeException e) {
1267             IoUtils.closeQuietly(tun);
1268             // If this is not seamless handover, disconnect partially-established network when error
1269             // occurs.
1270             if (oldNetworkAgent != mNetworkAgent) {
1271                 agentDisconnect();
1272             }
1273             // restore old state
1274             mConfig = oldConfig;
1275             mConnection = oldConnection;
1276             mNetworkCapabilities.setUids(oldUsers);
1277             mNetworkAgent = oldNetworkAgent;
1278             mInterface = oldInterface;
1279             throw e;
1280         }
1281         Log.i(TAG, "Established by " + config.user + " on " + mInterface);
1282         return tun;
1283     }
1284 
1285     private boolean isRunningLocked() {
1286         return mNetworkAgent != null && mInterface != null;
1287     }
1288 
1289     // Returns true if the VPN has been established and the calling UID is its owner. Used to check
1290     // that a call to mutate VPN state is admissible.
1291     @VisibleForTesting
1292     protected boolean isCallerEstablishedOwnerLocked() {
1293         return isRunningLocked() && Binder.getCallingUid() == mOwnerUID;
1294     }
1295 
1296     // Note: Return type guarantees results are deduped and sorted, which callers require.
1297     private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) {
1298         SortedSet<Integer> uids = new TreeSet<>();
1299         for (String app : packageNames) {
1300             int uid = getAppUid(app, userHandle);
1301             if (uid != -1) uids.add(uid);
1302         }
1303         return uids;
1304     }
1305 
1306     /**
1307      * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs
1308      * associated with one user, and any restricted profiles attached to that user.
1309      *
1310      * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
1311      * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
1312      * in each user and profile will be included.
1313      *
1314      * @param userHandle The userId to create UID ranges for along with any of its restricted
1315      *                   profiles.
1316      * @param allowedApplications (optional) whitelist of applications to include.
1317      * @param disallowedApplications (optional) blacklist of applications to exclude.
1318      */
1319     @VisibleForTesting
1320     Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle,
1321             @Nullable List<String> allowedApplications,
1322             @Nullable List<String> disallowedApplications) {
1323         final Set<UidRange> ranges = new ArraySet<>();
1324 
1325         // Assign the top-level user to the set of ranges
1326         addUserToRanges(ranges, userHandle, allowedApplications, disallowedApplications);
1327 
1328         // If the user can have restricted profiles, assign all its restricted profiles too
1329         if (canHaveRestrictedProfile(userHandle)) {
1330             final long token = Binder.clearCallingIdentity();
1331             List<UserInfo> users;
1332             try {
1333                 users = UserManager.get(mContext).getUsers(true);
1334             } finally {
1335                 Binder.restoreCallingIdentity(token);
1336             }
1337             for (UserInfo user : users) {
1338                 if (user.isRestricted() && (user.restrictedProfileParentId == userHandle)) {
1339                     addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications);
1340                 }
1341             }
1342         }
1343         return ranges;
1344     }
1345 
1346     /**
1347      * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs
1348      * associated with one user.
1349      *
1350      * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
1351      * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
1352      * in the user will be included.
1353      *
1354      * @param ranges {@link Set} of {@link UidRange}s to which to add.
1355      * @param userHandle The userId to add to {@param ranges}.
1356      * @param allowedApplications (optional) whitelist of applications to include.
1357      * @param disallowedApplications (optional) blacklist of applications to exclude.
1358      */
1359     @VisibleForTesting
1360     void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle,
1361             @Nullable List<String> allowedApplications,
1362             @Nullable List<String> disallowedApplications) {
1363         if (allowedApplications != null) {
1364             // Add ranges covering all UIDs for allowedApplications.
1365             int start = -1, stop = -1;
1366             for (int uid : getAppsUids(allowedApplications, userHandle)) {
1367                 if (start == -1) {
1368                     start = uid;
1369                 } else if (uid != stop + 1) {
1370                     ranges.add(new UidRange(start, stop));
1371                     start = uid;
1372                 }
1373                 stop = uid;
1374             }
1375             if (start != -1) ranges.add(new UidRange(start, stop));
1376         } else if (disallowedApplications != null) {
1377             // Add all ranges for user skipping UIDs for disallowedApplications.
1378             final UidRange userRange = UidRange.createForUser(userHandle);
1379             int start = userRange.start;
1380             for (int uid : getAppsUids(disallowedApplications, userHandle)) {
1381                 if (uid == start) {
1382                     start++;
1383                 } else {
1384                     ranges.add(new UidRange(start, uid - 1));
1385                     start = uid + 1;
1386                 }
1387             }
1388             if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop));
1389         } else {
1390             // Add all UIDs for the user.
1391             ranges.add(UidRange.createForUser(userHandle));
1392         }
1393     }
1394 
1395     // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that
1396     // apply to userHandle.
1397     static private List<UidRange> uidRangesForUser(int userHandle, Set<UidRange> existingRanges) {
1398         // UidRange#createForUser returns the entire range of UIDs available to a macro-user.
1399         // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE}
1400         final UidRange userRange = UidRange.createForUser(userHandle);
1401         final List<UidRange> ranges = new ArrayList<>();
1402         for (UidRange range : existingRanges) {
1403             if (userRange.containsRange(range)) {
1404                 ranges.add(range);
1405             }
1406         }
1407         return ranges;
1408     }
1409 
1410     /**
1411      * Updates UID ranges for this VPN and also updates its internal capabilities.
1412      *
1413      * <p>Should be called on primary ConnectivityService thread.
1414      */
1415     public void onUserAdded(int userHandle) {
1416         // If the user is restricted tie them to the parent user's VPN
1417         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
1418         if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
1419             synchronized(Vpn.this) {
1420                 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids();
1421                 if (existingRanges != null) {
1422                     try {
1423                         addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications,
1424                                 mConfig.disallowedApplications);
1425                         // ConnectivityService will call {@link #updateCapabilities} and apply
1426                         // those for VPN network.
1427                         mNetworkCapabilities.setUids(existingRanges);
1428                     } catch (Exception e) {
1429                         Log.wtf(TAG, "Failed to add restricted user to owner", e);
1430                     }
1431                 }
1432                 setVpnForcedLocked(mLockdown);
1433             }
1434         }
1435     }
1436 
1437     /**
1438      * Updates UID ranges for this VPN and also updates its capabilities.
1439      *
1440      * <p>Should be called on primary ConnectivityService thread.
1441      */
1442     public void onUserRemoved(int userHandle) {
1443         // clean up if restricted
1444         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
1445         if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
1446             synchronized(Vpn.this) {
1447                 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids();
1448                 if (existingRanges != null) {
1449                     try {
1450                         final List<UidRange> removedRanges =
1451                             uidRangesForUser(userHandle, existingRanges);
1452                         existingRanges.removeAll(removedRanges);
1453                         // ConnectivityService will call {@link #updateCapabilities} and
1454                         // apply those for VPN network.
1455                         mNetworkCapabilities.setUids(existingRanges);
1456                     } catch (Exception e) {
1457                         Log.wtf(TAG, "Failed to remove restricted user to owner", e);
1458                     }
1459                 }
1460                 setVpnForcedLocked(mLockdown);
1461             }
1462         }
1463     }
1464 
1465     /**
1466      * Called when the user associated with this VPN has just been stopped.
1467      */
1468     public synchronized void onUserStopped() {
1469         // Switch off networking lockdown (if it was enabled)
1470         setLockdown(false);
1471         mAlwaysOn = false;
1472 
1473         // Quit any active connections
1474         agentDisconnect();
1475     }
1476 
1477     /**
1478      * Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN
1479      * service app itself and whitelisted packages, to only sockets that have had {@code protect()}
1480      * called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the
1481      * kernel.
1482      *
1483      * The exception for the VPN UID isn't technically necessary -- setup should use protected
1484      * sockets -- but in practice it saves apps that don't protect their sockets from breaking.
1485      *
1486      * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to
1487      * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}.
1488      *
1489      * @param enforce {@code true} to require that all traffic under the jurisdiction of this
1490      *                {@link Vpn} goes through a VPN connection or is blocked until one is
1491      *                available, {@code false} to lift the requirement.
1492      *
1493      * @see #mBlockedUidsAsToldToNetd
1494      */
1495     @GuardedBy("this")
1496     private void setVpnForcedLocked(boolean enforce) {
1497         final List<String> exemptedPackages;
1498         if (isNullOrLegacyVpn(mPackage)) {
1499             exemptedPackages = null;
1500         } else {
1501             exemptedPackages = new ArrayList<>(mLockdownWhitelist);
1502             exemptedPackages.add(mPackage);
1503         }
1504         final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd);
1505 
1506         final Set<UidRange> rangesToTellNetdToAdd;
1507         if (enforce) {
1508             final Set<UidRange> rangesThatShouldBeBlocked =
1509                     createUserAndRestrictedProfilesRanges(mUserHandle,
1510                             /* allowedApplications */ null,
1511                             /* disallowedApplications */ exemptedPackages);
1512 
1513             // The UID range of the first user (0-99999) would block the IPSec traffic, which comes
1514             // directly from the kernel and is marked as uid=0. So we adjust the range to allow
1515             // it through (b/69873852).
1516             for (UidRange range : rangesThatShouldBeBlocked) {
1517                 if (range.start == 0) {
1518                     rangesThatShouldBeBlocked.remove(range);
1519                     if (range.stop != 0) {
1520                         rangesThatShouldBeBlocked.add(new UidRange(1, range.stop));
1521                     }
1522                 }
1523             }
1524 
1525             rangesToTellNetdToRemove.removeAll(rangesThatShouldBeBlocked);
1526             rangesToTellNetdToAdd = rangesThatShouldBeBlocked;
1527             // The ranges to tell netd to add are the ones that should be blocked minus the
1528             // ones it already knows to block. Note that this will change the contents of
1529             // rangesThatShouldBeBlocked, but the list of ranges that should be blocked is
1530             // not used after this so it's fine to destroy it.
1531             rangesToTellNetdToAdd.removeAll(mBlockedUidsAsToldToNetd);
1532         } else {
1533             rangesToTellNetdToAdd = Collections.emptySet();
1534         }
1535 
1536         // If mBlockedUidsAsToldToNetd used to be empty, this will always be a no-op.
1537         setAllowOnlyVpnForUids(false, rangesToTellNetdToRemove);
1538         // If nothing should be blocked now, this will now be a no-op.
1539         setAllowOnlyVpnForUids(true, rangesToTellNetdToAdd);
1540     }
1541 
1542     /**
1543      * Tell netd to add or remove a list of {@link UidRange}s to the list of UIDs that are only
1544      * allowed to make connections through sockets that have had {@code protect()} called on them.
1545      *
1546      * @param enforce {@code true} to add to the blacklist, {@code false} to remove.
1547      * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is
1548      *               {@code true}) or to remove.
1549      * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise,
1550      *         including added ranges that already existed or removed ones that didn't.
1551      */
1552     @GuardedBy("this")
1553     private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) {
1554         if (ranges.size() == 0) {
1555             return true;
1556         }
1557         final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]);
1558         try {
1559             mNetd.setAllowOnlyVpnForUids(enforce, rangesArray);
1560         } catch (RemoteException | RuntimeException e) {
1561             Log.e(TAG, "Updating blocked=" + enforce
1562                     + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e);
1563             return false;
1564         }
1565         if (enforce) {
1566             mBlockedUidsAsToldToNetd.addAll(ranges);
1567         } else {
1568             mBlockedUidsAsToldToNetd.removeAll(ranges);
1569         }
1570         return true;
1571     }
1572 
1573     /**
1574      * Return the configuration of the currently running VPN.
1575      */
1576     public VpnConfig getVpnConfig() {
1577         enforceControlPermission();
1578         return mConfig;
1579     }
1580 
1581     @Deprecated
1582     public synchronized void interfaceStatusChanged(String iface, boolean up) {
1583         try {
1584             mObserver.interfaceStatusChanged(iface, up);
1585         } catch (RemoteException e) {
1586             // ignored; target is local
1587         }
1588     }
1589 
1590     private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() {
1591         @Override
1592         public void interfaceStatusChanged(String interfaze, boolean up) {
1593             synchronized (Vpn.this) {
1594                 if (!up && mVpnRunner != null && mVpnRunner instanceof LegacyVpnRunner) {
1595                     ((LegacyVpnRunner) mVpnRunner).exitIfOuterInterfaceIs(interfaze);
1596                 }
1597             }
1598         }
1599 
1600         @Override
1601         public void interfaceRemoved(String interfaze) {
1602             synchronized (Vpn.this) {
1603                 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
1604                     if (mConnection != null) {
1605                         mContext.unbindService(mConnection);
1606                         cleanupVpnStateLocked();
1607                     } else if (mVpnRunner != null) {
1608                         // cleanupVpnStateLocked() is called from mVpnRunner.exit()
1609                         mVpnRunner.exit();
1610                     }
1611                 }
1612             }
1613         }
1614     };
1615 
1616     private void cleanupVpnStateLocked() {
1617         mStatusIntent = null;
1618         mNetworkCapabilities.setUids(null);
1619         mConfig = null;
1620         mInterface = null;
1621 
1622         // Unconditionally clear both VpnService and VpnRunner fields.
1623         mVpnRunner = null;
1624         mConnection = null;
1625         agentDisconnect();
1626     }
1627 
1628     private void enforceControlPermission() {
1629         mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller");
1630     }
1631 
1632     private void enforceControlPermissionOrInternalCaller() {
1633         // Require the caller to be either an application with CONTROL_VPN permission or a process
1634         // in the system server.
1635         mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN,
1636                 "Unauthorized Caller");
1637     }
1638 
1639     private void enforceSettingsPermission() {
1640         mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_SETTINGS,
1641                 "Unauthorized Caller");
1642     }
1643 
1644     private class Connection implements ServiceConnection {
1645         private IBinder mService;
1646 
1647         @Override
1648         public void onServiceConnected(ComponentName name, IBinder service) {
1649             mService = service;
1650         }
1651 
1652         @Override
1653         public void onServiceDisconnected(ComponentName name) {
1654             mService = null;
1655         }
1656     }
1657 
1658     private void prepareStatusIntent() {
1659         final long token = Binder.clearCallingIdentity();
1660         try {
1661             mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
1662         } finally {
1663             Binder.restoreCallingIdentity(token);
1664         }
1665     }
1666 
1667     public synchronized boolean addAddress(String address, int prefixLength) {
1668         if (!isCallerEstablishedOwnerLocked()) {
1669             return false;
1670         }
1671         boolean success = jniAddAddress(mInterface, address, prefixLength);
1672         mNetworkAgent.sendLinkProperties(makeLinkProperties());
1673         return success;
1674     }
1675 
1676     public synchronized boolean removeAddress(String address, int prefixLength) {
1677         if (!isCallerEstablishedOwnerLocked()) {
1678             return false;
1679         }
1680         boolean success = jniDelAddress(mInterface, address, prefixLength);
1681         mNetworkAgent.sendLinkProperties(makeLinkProperties());
1682         return success;
1683     }
1684 
1685     /**
1686      * Updates underlying network set.
1687      *
1688      * <p>Note: Does not updates capabilities. Call {@link #updateCapabilities} from
1689      * ConnectivityService thread to get updated capabilities.
1690      */
1691     public synchronized boolean setUnderlyingNetworks(Network[] networks) {
1692         if (!isCallerEstablishedOwnerLocked()) {
1693             return false;
1694         }
1695         if (networks == null) {
1696             mConfig.underlyingNetworks = null;
1697         } else {
1698             mConfig.underlyingNetworks = new Network[networks.length];
1699             for (int i = 0; i < networks.length; ++i) {
1700                 if (networks[i] == null) {
1701                     mConfig.underlyingNetworks[i] = null;
1702                 } else {
1703                     mConfig.underlyingNetworks[i] = new Network(networks[i].netId);
1704                 }
1705             }
1706         }
1707         return true;
1708     }
1709 
1710     public synchronized Network[] getUnderlyingNetworks() {
1711         if (!isRunningLocked()) {
1712             return null;
1713         }
1714         return mConfig.underlyingNetworks;
1715     }
1716 
1717     /**
1718      * This method should only be called by ConnectivityService because it doesn't
1719      * have enough data to fill VpnInfo.primaryUnderlyingIface field.
1720      */
1721     public synchronized VpnInfo getVpnInfo() {
1722         if (!isRunningLocked()) {
1723             return null;
1724         }
1725 
1726         VpnInfo info = new VpnInfo();
1727         info.ownerUid = mOwnerUID;
1728         info.vpnIface = mInterface;
1729         return info;
1730     }
1731 
1732     public synchronized boolean appliesToUid(int uid) {
1733         if (!isRunningLocked()) {
1734             return false;
1735         }
1736         return mNetworkCapabilities.appliesToUid(uid);
1737     }
1738 
1739     /**
1740      * Gets the currently running App-based VPN type
1741      *
1742      * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running an
1743      *     app-based VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always
1744      *     Settings-based, the Platform VPNs can be initiated by both apps and Settings.
1745      */
1746     public synchronized int getActiveAppVpnType() {
1747         if (VpnConfig.LEGACY_VPN.equals(mPackage)) {
1748             return VpnManager.TYPE_VPN_NONE;
1749         }
1750 
1751         if (mVpnRunner != null && mVpnRunner instanceof IkeV2VpnRunner) {
1752             return VpnManager.TYPE_VPN_PLATFORM;
1753         } else {
1754             return VpnManager.TYPE_VPN_SERVICE;
1755         }
1756     }
1757 
1758     /**
1759      * @param uid The target uid.
1760      *
1761      * @return {@code true} if {@code uid} is included in one of the mBlockedUidsAsToldToNetd
1762      * ranges and the VPN is not connected, or if the VPN is connected but does not apply to
1763      * the {@code uid}.
1764      *
1765      * @apiNote This method don't check VPN lockdown status.
1766      * @see #mBlockedUidsAsToldToNetd
1767      */
1768     public synchronized boolean isBlockingUid(int uid) {
1769         if (mNetworkInfo.isConnected()) {
1770             return !appliesToUid(uid);
1771         } else {
1772             return UidRange.containsUid(mBlockedUidsAsToldToNetd, uid);
1773         }
1774     }
1775 
1776     private void updateAlwaysOnNotification(DetailedState networkState) {
1777         final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
1778 
1779         final UserHandle user = UserHandle.of(mUserHandle);
1780         final long token = Binder.clearCallingIdentity();
1781         try {
1782             final NotificationManager notificationManager = NotificationManager.from(mContext);
1783             if (!visible) {
1784                 notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user);
1785                 return;
1786             }
1787             final Intent intent = new Intent();
1788             intent.setComponent(ComponentName.unflattenFromString(mContext.getString(
1789                     R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)));
1790             intent.putExtra("lockdown", mLockdown);
1791             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1792             final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser(
1793                     intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user);
1794             final Notification.Builder builder =
1795                     new Notification.Builder(mContext, SystemNotificationChannels.VPN)
1796                             .setSmallIcon(R.drawable.vpn_connected)
1797                             .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected))
1798                             .setContentText(mContext.getString(R.string.vpn_lockdown_config))
1799                             .setContentIntent(configIntent)
1800                             .setCategory(Notification.CATEGORY_SYSTEM)
1801                             .setVisibility(Notification.VISIBILITY_PUBLIC)
1802                             .setOngoing(true)
1803                             .setColor(mContext.getColor(R.color.system_notification_accent_color));
1804             notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED,
1805                     builder.build(), user);
1806         } finally {
1807             Binder.restoreCallingIdentity(token);
1808         }
1809     }
1810 
1811     /**
1812      * Facade for system service calls that change, or depend on, state outside of
1813      * {@link ConnectivityService} and have hard-to-mock interfaces.
1814      *
1815      * @see com.android.server.connectivity.VpnTest
1816      */
1817     @VisibleForTesting
1818     public static class SystemServices {
1819         private final Context mContext;
1820 
1821         public SystemServices(@NonNull Context context) {
1822             mContext = context;
1823         }
1824 
1825         /**
1826          * @see PendingIntent#getActivityAsUser()
1827          */
1828         public PendingIntent pendingIntentGetActivityAsUser(
1829                 Intent intent, int flags, UserHandle user) {
1830             return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags,
1831                     null /*options*/, user);
1832         }
1833 
1834         /**
1835          * @see Settings.Secure#putStringForUser
1836          */
1837         public void settingsSecurePutStringForUser(String key, String value, int userId) {
1838             Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId);
1839         }
1840 
1841         /**
1842          * @see Settings.Secure#putIntForUser
1843          */
1844         public void settingsSecurePutIntForUser(String key, int value, int userId) {
1845             Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId);
1846         }
1847 
1848         /**
1849          * @see Settings.Secure#getStringForUser
1850          */
1851         public String settingsSecureGetStringForUser(String key, int userId) {
1852             return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId);
1853         }
1854 
1855         /**
1856          * @see Settings.Secure#getIntForUser
1857          */
1858         public int settingsSecureGetIntForUser(String key, int def, int userId) {
1859             return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId);
1860         }
1861 
1862         public boolean isCallerSystem() {
1863             return Binder.getCallingUid() == Process.SYSTEM_UID;
1864         }
1865     }
1866 
1867     private native int jniCreate(int mtu);
1868     private native String jniGetName(int tun);
1869     private native int jniSetAddresses(String interfaze, String addresses);
1870     private native void jniReset(String interfaze);
1871     private native int jniCheck(String interfaze);
1872     private native boolean jniAddAddress(String interfaze, String address, int prefixLen);
1873     private native boolean jniDelAddress(String interfaze, String address, int prefixLen);
1874 
1875     private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
1876         for (RouteInfo route : prop.getAllRoutes()) {
1877             // Currently legacy VPN only works on IPv4.
1878             if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
1879                 return route;
1880             }
1881         }
1882 
1883         throw new IllegalStateException("Unable to find IPv4 default gateway");
1884     }
1885 
1886     private void enforceNotRestrictedUser() {
1887         Binder.withCleanCallingIdentity(() -> {
1888             final UserManager mgr = UserManager.get(mContext);
1889             final UserInfo user = mgr.getUserInfo(mUserHandle);
1890 
1891             if (user.isRestricted()) {
1892                 throw new SecurityException("Restricted users cannot configure VPNs");
1893             }
1894         });
1895     }
1896 
1897     /**
1898      * Start legacy VPN, controlling native daemons as needed. Creates a
1899      * secondary thread to perform connection work, returning quickly.
1900      *
1901      * Should only be called to respond to Binder requests as this enforces caller permission. Use
1902      * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the
1903      * permission check only when the caller is trusted (or the call is initiated by the system).
1904      */
1905     public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
1906         enforceControlPermission();
1907         long token = Binder.clearCallingIdentity();
1908         try {
1909             startLegacyVpnPrivileged(profile, keyStore, egress);
1910         } finally {
1911             Binder.restoreCallingIdentity(token);
1912         }
1913     }
1914 
1915     /**
1916      * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check
1917      * permissions under the assumption that the caller is the system.
1918      *
1919      * Callers are responsible for checking permissions if needed.
1920      */
1921     public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore,
1922             LinkProperties egress) {
1923         UserManager mgr = UserManager.get(mContext);
1924         UserInfo user = mgr.getUserInfo(mUserHandle);
1925         if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
1926                     new UserHandle(mUserHandle))) {
1927             throw new SecurityException("Restricted users cannot establish VPNs");
1928         }
1929 
1930         final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
1931         final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
1932         final String iface = ipv4DefaultRoute.getInterface();
1933 
1934         // Load certificates.
1935         String privateKey = "";
1936         String userCert = "";
1937         String caCert = "";
1938         String serverCert = "";
1939         if (!profile.ipsecUserCert.isEmpty()) {
1940             privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
1941             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
1942             userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
1943         }
1944         if (!profile.ipsecCaCert.isEmpty()) {
1945             byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
1946             caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
1947         }
1948         if (!profile.ipsecServerCert.isEmpty()) {
1949             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
1950             serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
1951         }
1952         if (userCert == null || caCert == null || serverCert == null) {
1953             throw new IllegalStateException("Cannot load credentials");
1954         }
1955 
1956         // Prepare arguments for racoon.
1957         String[] racoon = null;
1958         switch (profile.type) {
1959             case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
1960                 // Secret key is still just the alias (not the actual private key). The private key
1961                 // is retrieved from the KeyStore during conversion of the VpnProfile to an
1962                 // Ikev2VpnProfile.
1963                 profile.ipsecSecret = Ikev2VpnProfile.PREFIX_KEYSTORE_ALIAS + privateKey;
1964                 profile.ipsecUserCert = userCert;
1965                 // Fallthrough
1966             case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
1967                 profile.ipsecCaCert = caCert;
1968 
1969                 // Start VPN profile
1970                 profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS);
1971                 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore);
1972                 return;
1973             case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
1974                 // Ikev2VpnProfiles expect a base64-encoded preshared key.
1975                 profile.ipsecSecret =
1976                         Ikev2VpnProfile.encodeForIpsecSecret(profile.ipsecSecret.getBytes());
1977 
1978                 // Start VPN profile
1979                 profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS);
1980                 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore);
1981                 return;
1982             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
1983                 racoon = new String[] {
1984                     iface, profile.server, "udppsk", profile.ipsecIdentifier,
1985                     profile.ipsecSecret, "1701",
1986                 };
1987                 break;
1988             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
1989                 racoon = new String[] {
1990                     iface, profile.server, "udprsa", privateKey, userCert,
1991                     caCert, serverCert, "1701",
1992                 };
1993                 break;
1994             case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
1995                 racoon = new String[] {
1996                     iface, profile.server, "xauthpsk", profile.ipsecIdentifier,
1997                     profile.ipsecSecret, profile.username, profile.password, "", gateway,
1998                 };
1999                 break;
2000             case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
2001                 racoon = new String[] {
2002                     iface, profile.server, "xauthrsa", privateKey, userCert,
2003                     caCert, serverCert, profile.username, profile.password, "", gateway,
2004                 };
2005                 break;
2006             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
2007                 racoon = new String[] {
2008                     iface, profile.server, "hybridrsa",
2009                     caCert, serverCert, profile.username, profile.password, "", gateway,
2010                 };
2011                 break;
2012         }
2013 
2014         // Prepare arguments for mtpd.
2015         String[] mtpd = null;
2016         switch (profile.type) {
2017             case VpnProfile.TYPE_PPTP:
2018                 mtpd = new String[] {
2019                     iface, "pptp", profile.server, "1723",
2020                     "name", profile.username, "password", profile.password,
2021                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
2022                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
2023                     (profile.mppe ? "+mppe" : "nomppe"),
2024                 };
2025                 break;
2026             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
2027             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
2028                 mtpd = new String[] {
2029                     iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
2030                     "name", profile.username, "password", profile.password,
2031                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
2032                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
2033                 };
2034                 break;
2035         }
2036 
2037         VpnConfig config = new VpnConfig();
2038         config.legacy = true;
2039         config.user = profile.key;
2040         config.interfaze = iface;
2041         config.session = profile.name;
2042         config.isMetered = false;
2043         config.proxyInfo = profile.proxy;
2044 
2045         config.addLegacyRoutes(profile.routes);
2046         if (!profile.dnsServers.isEmpty()) {
2047             config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
2048         }
2049         if (!profile.searchDomains.isEmpty()) {
2050             config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
2051         }
2052         startLegacyVpn(config, racoon, mtpd, profile);
2053     }
2054 
2055     private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd,
2056             VpnProfile profile) {
2057         stopVpnRunnerPrivileged();
2058 
2059         // Prepare for the new request.
2060         prepareInternal(VpnConfig.LEGACY_VPN);
2061         updateState(DetailedState.CONNECTING, "startLegacyVpn");
2062 
2063         // Start a new LegacyVpnRunner and we are done!
2064         mVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile);
2065         mVpnRunner.start();
2066     }
2067 
2068     /**
2069      * Checks if this the currently running VPN (if any) was started by the Settings app
2070      *
2071      * <p>This includes both Legacy VPNs and Platform VPNs.
2072      */
2073     private boolean isSettingsVpnLocked() {
2074         return mVpnRunner != null && VpnConfig.LEGACY_VPN.equals(mPackage);
2075     }
2076 
2077     /** Stop VPN runner. Permissions must be checked by callers. */
2078     public synchronized void stopVpnRunnerPrivileged() {
2079         if (!isSettingsVpnLocked()) {
2080             return;
2081         }
2082 
2083         final boolean isLegacyVpn = mVpnRunner instanceof LegacyVpnRunner;
2084 
2085         mVpnRunner.exit();
2086         mVpnRunner = null;
2087 
2088         // LegacyVpn uses daemons that must be shut down before new ones are brought up.
2089         // The same limitation does not apply to Platform VPNs.
2090         if (isLegacyVpn) {
2091             synchronized (LegacyVpnRunner.TAG) {
2092                 // wait for old thread to completely finish before spinning up
2093                 // new instance, otherwise state updates can be out of order.
2094             }
2095         }
2096     }
2097 
2098     /**
2099      * Return the information of the current ongoing legacy VPN.
2100      */
2101     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
2102         // Check if the caller is authorized.
2103         enforceControlPermission();
2104         return getLegacyVpnInfoPrivileged();
2105     }
2106 
2107     /**
2108      * Return the information of the current ongoing legacy VPN.
2109      * Callers are responsible for checking permissions if needed.
2110      */
2111     private synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
2112         if (!isSettingsVpnLocked()) return null;
2113 
2114         final LegacyVpnInfo info = new LegacyVpnInfo();
2115         info.key = mConfig.user;
2116         info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
2117         if (mNetworkInfo.isConnected()) {
2118             info.intent = mStatusIntent;
2119         }
2120         return info;
2121     }
2122 
2123     public synchronized VpnConfig getLegacyVpnConfig() {
2124         if (isSettingsVpnLocked()) {
2125             return mConfig;
2126         } else {
2127             return null;
2128         }
2129     }
2130 
2131     /** This class represents the common interface for all VPN runners. */
2132     private abstract class VpnRunner extends Thread {
2133 
2134         protected VpnRunner(String name) {
2135             super(name);
2136         }
2137 
2138         public abstract void run();
2139 
2140         /**
2141          * Disconnects the NetworkAgent and cleans up all state related to the VpnRunner.
2142          *
2143          * <p>All outer Vpn instance state is cleaned up in cleanupVpnStateLocked()
2144          */
2145         protected abstract void exitVpnRunner();
2146 
2147         /**
2148          * Triggers the cleanup of the VpnRunner, and additionally cleans up Vpn instance-wide state
2149          *
2150          * <p>This method ensures that simple calls to exit() will always clean up global state
2151          * properly.
2152          */
2153         protected final void exit() {
2154             synchronized (Vpn.this) {
2155                 exitVpnRunner();
2156                 cleanupVpnStateLocked();
2157             }
2158         }
2159     }
2160 
2161     interface IkeV2VpnRunnerCallback {
2162         void onDefaultNetworkChanged(@NonNull Network network);
2163 
2164         void onChildOpened(
2165                 @NonNull Network network, @NonNull ChildSessionConfiguration childConfig);
2166 
2167         void onChildTransformCreated(
2168                 @NonNull Network network, @NonNull IpSecTransform transform, int direction);
2169 
2170         void onSessionLost(@NonNull Network network);
2171     }
2172 
2173     /**
2174      * Internal class managing IKEv2/IPsec VPN connectivity
2175      *
2176      * <p>The IKEv2 VPN will listen to, and run based on the lifecycle of Android's default Network.
2177      * As a new default is selected, old IKE sessions will be torn down, and a new one will be
2178      * started.
2179      *
2180      * <p>This class uses locking minimally - the Vpn instance lock is only ever held when fields of
2181      * the outer class are modified. As such, care must be taken to ensure that no calls are added
2182      * that might modify the outer class' state without acquiring a lock.
2183      *
2184      * <p>The overall structure of the Ikev2VpnRunner is as follows:
2185      *
2186      * <ol>
2187      *   <li>Upon startup, a NetworkRequest is registered with ConnectivityManager. This is called
2188      *       any time a new default network is selected
2189      *   <li>When a new default is connected, an IKE session is started on that Network. If there
2190      *       were any existing IKE sessions on other Networks, they are torn down before starting
2191      *       the new IKE session
2192      *   <li>Upon establishment, the onChildTransformCreated() callback is called twice, one for
2193      *       each direction, and finally onChildOpened() is called
2194      *   <li>Upon the onChildOpened() call, the VPN is fully set up.
2195      *   <li>Subsequent Network changes result in new onDefaultNetworkChanged() callbacks. See (2).
2196      * </ol>
2197      */
2198     class IkeV2VpnRunner extends VpnRunner implements IkeV2VpnRunnerCallback {
2199         @NonNull private static final String TAG = "IkeV2VpnRunner";
2200 
2201         @NonNull private final IpSecManager mIpSecManager;
2202         @NonNull private final Ikev2VpnProfile mProfile;
2203         @NonNull private final ConnectivityManager.NetworkCallback mNetworkCallback;
2204 
2205         /**
2206          * Executor upon which ALL callbacks must be run.
2207          *
2208          * <p>This executor MUST be a single threaded executor, in order to ensure the consistency
2209          * of the mutable Ikev2VpnRunner fields. The Ikev2VpnRunner is built mostly lock-free by
2210          * virtue of everything being serialized on this executor.
2211          */
2212         @NonNull private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
2213 
2214         /** Signal to ensure shutdown is honored even if a new Network is connected. */
2215         private boolean mIsRunning = true;
2216 
2217         @Nullable private IpSecTunnelInterface mTunnelIface;
2218         @Nullable private IkeSession mSession;
2219         @Nullable private Network mActiveNetwork;
2220 
2221         IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
2222             super(TAG);
2223             mProfile = profile;
2224             mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
2225             mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this);
2226         }
2227 
2228         @Override
2229         public void run() {
2230             // Unless the profile is restricted to test networks, explicitly use only the network
2231             // that ConnectivityService thinks is the "best." In other words, only ever use the
2232             // currently selected default network. This does mean that in both onLost() and
2233             // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs.
2234             //
2235             // When restricted to test networks, select any network with TRANSPORT_TEST. Since the
2236             // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS,
2237             // this is considered safe.
2238             final ConnectivityManager cm = ConnectivityManager.from(mContext);
2239             final NetworkRequest req;
2240 
2241             if (mProfile.isRestrictedToTestNetworks()) {
2242                 req = new NetworkRequest.Builder()
2243                         .clearCapabilities()
2244                         .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
2245                         .build();
2246             } else {
2247                 req = cm.getDefaultRequest();
2248             }
2249 
2250             cm.requestNetwork(req, mNetworkCallback);
2251         }
2252 
2253         private boolean isActiveNetwork(@Nullable Network network) {
2254             return Objects.equals(mActiveNetwork, network) && mIsRunning;
2255         }
2256 
2257         /**
2258          * Called when an IKE Child session has been opened, signalling completion of the startup.
2259          *
2260          * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor
2261          * thread in order to ensure consistency of the Ikev2VpnRunner fields.
2262          */
2263         public void onChildOpened(
2264                 @NonNull Network network, @NonNull ChildSessionConfiguration childConfig) {
2265             if (!isActiveNetwork(network)) {
2266                 Log.d(TAG, "onOpened called for obsolete network " + network);
2267 
2268                 // Do nothing; this signals that either: (1) a new/better Network was found,
2269                 // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
2270                 // IKE session was already shut down (exited, or an error was encountered somewhere
2271                 // else). In both cases, all resources and sessions are torn down via
2272                 // resetIkeState().
2273                 return;
2274             }
2275 
2276             try {
2277                 final String interfaceName = mTunnelIface.getInterfaceName();
2278                 final int maxMtu = mProfile.getMaxMtu();
2279                 final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses();
2280                 final List<String> dnsAddrStrings = new ArrayList<>();
2281 
2282                 final Collection<RouteInfo> newRoutes = VpnIkev2Utils.getRoutesFromTrafficSelectors(
2283                         childConfig.getOutboundTrafficSelectors());
2284                 for (final LinkAddress address : internalAddresses) {
2285                     mTunnelIface.addAddress(address.getAddress(), address.getPrefixLength());
2286                 }
2287                 for (InetAddress addr : childConfig.getInternalDnsServers()) {
2288                     dnsAddrStrings.add(addr.getHostAddress());
2289                 }
2290 
2291                 final NetworkAgent networkAgent;
2292                 final LinkProperties lp;
2293 
2294                 synchronized (Vpn.this) {
2295                     mInterface = interfaceName;
2296                     mConfig.mtu = maxMtu;
2297                     mConfig.interfaze = mInterface;
2298 
2299                     mConfig.addresses.clear();
2300                     mConfig.addresses.addAll(internalAddresses);
2301 
2302                     mConfig.routes.clear();
2303                     mConfig.routes.addAll(newRoutes);
2304 
2305                     if (mConfig.dnsServers == null) mConfig.dnsServers = new ArrayList<>();
2306                     mConfig.dnsServers.clear();
2307                     mConfig.dnsServers.addAll(dnsAddrStrings);
2308 
2309                     networkAgent = mNetworkAgent;
2310 
2311                     // The below must be done atomically with the mConfig update, otherwise
2312                     // isRunningLocked() will be racy.
2313                     if (networkAgent == null) {
2314                         if (isSettingsVpnLocked()) {
2315                             prepareStatusIntent();
2316                         }
2317                         agentConnect();
2318                         return; // Link properties are already sent.
2319                     }
2320 
2321                     lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked
2322                 }
2323 
2324                 networkAgent.sendLinkProperties(lp);
2325             } catch (Exception e) {
2326                 Log.d(TAG, "Error in ChildOpened for network " + network, e);
2327                 onSessionLost(network);
2328             }
2329         }
2330 
2331         /**
2332          * Called when an IPsec transform has been created, and should be applied.
2333          *
2334          * <p>This method is called multiple times over the lifetime of an IkeSession (or default
2335          * network), and is MUST always be called on the mExecutor thread in order to ensure
2336          * consistency of the Ikev2VpnRunner fields.
2337          */
2338         public void onChildTransformCreated(
2339                 @NonNull Network network, @NonNull IpSecTransform transform, int direction) {
2340             if (!isActiveNetwork(network)) {
2341                 Log.d(TAG, "ChildTransformCreated for obsolete network " + network);
2342 
2343                 // Do nothing; this signals that either: (1) a new/better Network was found,
2344                 // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
2345                 // IKE session was already shut down (exited, or an error was encountered somewhere
2346                 // else). In both cases, all resources and sessions are torn down via
2347                 // resetIkeState().
2348                 return;
2349             }
2350 
2351             try {
2352                 // Transforms do not need to be persisted; the IkeSession will keep
2353                 // them alive for us
2354                 mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform);
2355             } catch (IOException e) {
2356                 Log.d(TAG, "Transform application failed for network " + network, e);
2357                 onSessionLost(network);
2358             }
2359         }
2360 
2361         /**
2362          * Called when a new default network is connected.
2363          *
2364          * <p>The Ikev2VpnRunner will unconditionally switch to the new network, killing the old IKE
2365          * state in the process, and starting a new IkeSession instance.
2366          *
2367          * <p>This method is called multiple times over the lifetime of the Ikev2VpnRunner, and is
2368          * called on the ConnectivityService thread. Thus, the actual work MUST be proxied to the
2369          * mExecutor thread in order to ensure consistency of the Ikev2VpnRunner fields.
2370          */
2371         public void onDefaultNetworkChanged(@NonNull Network network) {
2372             Log.d(TAG, "Starting IKEv2/IPsec session on new network: " + network);
2373 
2374             // Proxy to the Ikev2VpnRunner (single-thread) executor to ensure consistency in lieu
2375             // of locking.
2376             mExecutor.execute(() -> {
2377                 try {
2378                     if (!mIsRunning) {
2379                         Log.d(TAG, "onDefaultNetworkChanged after exit");
2380                         return; // VPN has been shut down.
2381                     }
2382 
2383                     // Without MOBIKE, we have no way to seamlessly migrate. Close on old
2384                     // (non-default) network, and start the new one.
2385                     resetIkeState();
2386                     mActiveNetwork = network;
2387 
2388                     final IkeSessionParams ikeSessionParams =
2389                             VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, network);
2390                     final ChildSessionParams childSessionParams =
2391                             VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms());
2392 
2393                     // TODO: Remove the need for adding two unused addresses with
2394                     // IPsec tunnels.
2395                     final InetAddress address = InetAddress.getLocalHost();
2396                     mTunnelIface =
2397                             mIpSecManager.createIpSecTunnelInterface(
2398                                     address /* unused */,
2399                                     address /* unused */,
2400                                     network);
2401                     mNetd.setInterfaceUp(mTunnelIface.getInterfaceName());
2402 
2403                     mSession = mIkev2SessionCreator.createIkeSession(
2404                             mContext,
2405                             ikeSessionParams,
2406                             childSessionParams,
2407                             mExecutor,
2408                             new VpnIkev2Utils.IkeSessionCallbackImpl(
2409                                     TAG, IkeV2VpnRunner.this, network),
2410                             new VpnIkev2Utils.ChildSessionCallbackImpl(
2411                                     TAG, IkeV2VpnRunner.this, network));
2412                     Log.d(TAG, "Ike Session started for network " + network);
2413                 } catch (Exception e) {
2414                     Log.i(TAG, "Setup failed for network " + network + ". Aborting", e);
2415                     onSessionLost(network);
2416                 }
2417             });
2418         }
2419 
2420         /**
2421          * Handles loss of a session
2422          *
2423          * <p>The loss of a session might be due to an onLost() call, the IKE session getting torn
2424          * down for any reason, or an error in updating state (transform application, VPN setup)
2425          *
2426          * <p>This method MUST always be called on the mExecutor thread in order to ensure
2427          * consistency of the Ikev2VpnRunner fields.
2428          */
2429         public void onSessionLost(@NonNull Network network) {
2430             if (!isActiveNetwork(network)) {
2431                 Log.d(TAG, "onSessionLost() called for obsolete network " + network);
2432 
2433                 // Do nothing; this signals that either: (1) a new/better Network was found,
2434                 // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
2435                 // IKE session was already shut down (exited, or an error was encountered somewhere
2436                 // else). In both cases, all resources and sessions are torn down via
2437                 // onSessionLost() and resetIkeState().
2438                 return;
2439             }
2440 
2441             mActiveNetwork = null;
2442 
2443             // Close all obsolete state, but keep VPN alive incase a usable network comes up.
2444             // (Mirrors VpnService behavior)
2445             Log.d(TAG, "Resetting state for network: " + network);
2446 
2447             synchronized (Vpn.this) {
2448                 // Since this method handles non-fatal errors only, set mInterface to null to
2449                 // prevent the NetworkManagementEventObserver from killing this VPN based on the
2450                 // interface going down (which we expect).
2451                 mInterface = null;
2452                 mConfig.interfaze = null;
2453 
2454                 // Set as unroutable to prevent traffic leaking while the interface is down.
2455                 if (mConfig != null && mConfig.routes != null) {
2456                     final List<RouteInfo> oldRoutes = new ArrayList<>(mConfig.routes);
2457 
2458                     mConfig.routes.clear();
2459                     for (final RouteInfo route : oldRoutes) {
2460                         mConfig.routes.add(new RouteInfo(route.getDestination(), RTN_UNREACHABLE));
2461                     }
2462                     if (mNetworkAgent != null) {
2463                         mNetworkAgent.sendLinkProperties(makeLinkProperties());
2464                     }
2465                 }
2466             }
2467 
2468             resetIkeState();
2469         }
2470 
2471         /**
2472          * Cleans up all IKE state
2473          *
2474          * <p>This method MUST always be called on the mExecutor thread in order to ensure
2475          * consistency of the Ikev2VpnRunner fields.
2476          */
2477         private void resetIkeState() {
2478             if (mTunnelIface != null) {
2479                 // No need to call setInterfaceDown(); the IpSecInterface is being fully torn down.
2480                 mTunnelIface.close();
2481                 mTunnelIface = null;
2482             }
2483             if (mSession != null) {
2484                 mSession.kill(); // Kill here to make sure all resources are released immediately
2485                 mSession = null;
2486             }
2487         }
2488 
2489         /**
2490          * Cleans up all Ikev2VpnRunner internal state
2491          *
2492          * <p>This method MUST always be called on the mExecutor thread in order to ensure
2493          * consistency of the Ikev2VpnRunner fields.
2494          */
2495         private void shutdownVpnRunner() {
2496             mActiveNetwork = null;
2497             mIsRunning = false;
2498 
2499             resetIkeState();
2500 
2501             final ConnectivityManager cm = ConnectivityManager.from(mContext);
2502             cm.unregisterNetworkCallback(mNetworkCallback);
2503 
2504             mExecutor.shutdown();
2505         }
2506 
2507         @Override
2508         public void exitVpnRunner() {
2509             mExecutor.execute(() -> {
2510                 shutdownVpnRunner();
2511             });
2512         }
2513     }
2514 
2515     /**
2516      * Bringing up a VPN connection takes time, and that is all this thread
2517      * does. Here we have plenty of time. The only thing we need to take
2518      * care of is responding to interruptions as soon as possible. Otherwise
2519      * requests will pile up. This could be done in a Handler as a state
2520      * machine, but it is much easier to read in the current form.
2521      */
2522     private class LegacyVpnRunner extends VpnRunner {
2523         private static final String TAG = "LegacyVpnRunner";
2524 
2525         private final String[] mDaemons;
2526         private final String[][] mArguments;
2527         private final LocalSocket[] mSockets;
2528         private final String mOuterInterface;
2529         private final AtomicInteger mOuterConnection =
2530                 new AtomicInteger(ConnectivityManager.TYPE_NONE);
2531         private final VpnProfile mProfile;
2532 
2533         private long mBringupStartTime = -1;
2534 
2535         /**
2536          * Watch for the outer connection (passing in the constructor) going away.
2537          */
2538         private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
2539             @Override
2540             public void onReceive(Context context, Intent intent) {
2541                 if (!mEnableTeardown) return;
2542 
2543                 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
2544                     if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
2545                             ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) {
2546                         NetworkInfo info = (NetworkInfo)intent.getExtra(
2547                                 ConnectivityManager.EXTRA_NETWORK_INFO);
2548                         if (info != null && !info.isConnectedOrConnecting()) {
2549                             try {
2550                                 mObserver.interfaceStatusChanged(mOuterInterface, false);
2551                             } catch (RemoteException e) {}
2552                         }
2553                     }
2554                 }
2555             }
2556         };
2557 
2558         LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) {
2559             super(TAG);
2560             mConfig = config;
2561             mDaemons = new String[] {"racoon", "mtpd"};
2562             // TODO: clear arguments from memory once launched
2563             mArguments = new String[][] {racoon, mtpd};
2564             mSockets = new LocalSocket[mDaemons.length];
2565 
2566             // This is the interface which VPN is running on,
2567             // mConfig.interfaze will change to point to OUR
2568             // internal interface soon. TODO - add inner/outer to mconfig
2569             // TODO - we have a race - if the outer iface goes away/disconnects before we hit this
2570             // we will leave the VPN up.  We should check that it's still there/connected after
2571             // registering
2572             mOuterInterface = mConfig.interfaze;
2573 
2574             mProfile = profile;
2575 
2576             if (!TextUtils.isEmpty(mOuterInterface)) {
2577                 final ConnectivityManager cm = ConnectivityManager.from(mContext);
2578                 for (Network network : cm.getAllNetworks()) {
2579                     final LinkProperties lp = cm.getLinkProperties(network);
2580                     if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) {
2581                         final NetworkInfo networkInfo = cm.getNetworkInfo(network);
2582                         if (networkInfo != null) mOuterConnection.set(networkInfo.getType());
2583                     }
2584                 }
2585             }
2586 
2587             IntentFilter filter = new IntentFilter();
2588             filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
2589             mContext.registerReceiver(mBroadcastReceiver, filter);
2590         }
2591 
2592         /**
2593          * Checks if the parameter matches the underlying interface
2594          *
2595          * <p>If the underlying interface is torn down, the LegacyVpnRunner also should be. It has
2596          * no ability to migrate between interfaces (or Networks).
2597          */
2598         public void exitIfOuterInterfaceIs(String interfaze) {
2599             if (interfaze.equals(mOuterInterface)) {
2600                 Log.i(TAG, "Legacy VPN is going down with " + interfaze);
2601                 exitVpnRunner();
2602             }
2603         }
2604 
2605         /** Tears down this LegacyVpn connection */
2606         @Override
2607         public void exitVpnRunner() {
2608             // We assume that everything is reset after stopping the daemons.
2609             interrupt();
2610 
2611             // Always disconnect. This may be called again in cleanupVpnStateLocked() if
2612             // exitVpnRunner() was called from exit(), but it will be a no-op.
2613             agentDisconnect();
2614             try {
2615                 mContext.unregisterReceiver(mBroadcastReceiver);
2616             } catch (IllegalArgumentException e) {}
2617         }
2618 
2619         @Override
2620         public void run() {
2621             // Wait for the previous thread since it has been interrupted.
2622             Log.v(TAG, "Waiting");
2623             synchronized (TAG) {
2624                 Log.v(TAG, "Executing");
2625                 try {
2626                     bringup();
2627                     waitForDaemonsToStop();
2628                     interrupted(); // Clear interrupt flag if execute called exit.
2629                 } catch (InterruptedException e) {
2630                 } finally {
2631                     for (LocalSocket socket : mSockets) {
2632                         IoUtils.closeQuietly(socket);
2633                     }
2634                     // This sleep is necessary for racoon to successfully complete sending delete
2635                     // message to server.
2636                     try {
2637                         Thread.sleep(50);
2638                     } catch (InterruptedException e) {
2639                     }
2640                     for (String daemon : mDaemons) {
2641                         SystemService.stop(daemon);
2642                     }
2643                 }
2644                 agentDisconnect();
2645             }
2646         }
2647 
2648         private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException {
2649             long now = SystemClock.elapsedRealtime();
2650             if (now - mBringupStartTime <= 60000) {
2651                 Thread.sleep(sleepLonger ? 200 : 1);
2652             } else {
2653                 updateState(DetailedState.FAILED, "checkpoint");
2654                 throw new IllegalStateException("VPN bringup took too long");
2655             }
2656         }
2657 
2658         private void bringup() {
2659             // Catch all exceptions so we can clean up a few things.
2660             try {
2661                 // Initialize the timer.
2662                 mBringupStartTime = SystemClock.elapsedRealtime();
2663 
2664                 // Wait for the daemons to stop.
2665                 for (String daemon : mDaemons) {
2666                     while (!SystemService.isStopped(daemon)) {
2667                         checkInterruptAndDelay(true);
2668                     }
2669                 }
2670 
2671                 // Clear the previous state.
2672                 File state = new File("/data/misc/vpn/state");
2673                 state.delete();
2674                 if (state.exists()) {
2675                     throw new IllegalStateException("Cannot delete the state");
2676                 }
2677                 new File("/data/misc/vpn/abort").delete();
2678 
2679                 // Check if we need to restart any of the daemons.
2680                 boolean restart = false;
2681                 for (String[] arguments : mArguments) {
2682                     restart = restart || (arguments != null);
2683                 }
2684                 if (!restart) {
2685                     agentDisconnect();
2686                     return;
2687                 }
2688                 updateState(DetailedState.CONNECTING, "execute");
2689 
2690                 // Start the daemon with arguments.
2691                 for (int i = 0; i < mDaemons.length; ++i) {
2692                     String[] arguments = mArguments[i];
2693                     if (arguments == null) {
2694                         continue;
2695                     }
2696 
2697                     // Start the daemon.
2698                     String daemon = mDaemons[i];
2699                     SystemService.start(daemon);
2700 
2701                     // Wait for the daemon to start.
2702                     while (!SystemService.isRunning(daemon)) {
2703                         checkInterruptAndDelay(true);
2704                     }
2705 
2706                     // Create the control socket.
2707                     mSockets[i] = new LocalSocket();
2708                     LocalSocketAddress address = new LocalSocketAddress(
2709                             daemon, LocalSocketAddress.Namespace.RESERVED);
2710 
2711                     // Wait for the socket to connect.
2712                     while (true) {
2713                         try {
2714                             mSockets[i].connect(address);
2715                             break;
2716                         } catch (Exception e) {
2717                             // ignore
2718                         }
2719                         checkInterruptAndDelay(true);
2720                     }
2721                     mSockets[i].setSoTimeout(500);
2722 
2723                     // Send over the arguments.
2724                     OutputStream out = mSockets[i].getOutputStream();
2725                     for (String argument : arguments) {
2726                         byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
2727                         if (bytes.length >= 0xFFFF) {
2728                             throw new IllegalArgumentException("Argument is too large");
2729                         }
2730                         out.write(bytes.length >> 8);
2731                         out.write(bytes.length);
2732                         out.write(bytes);
2733                         checkInterruptAndDelay(false);
2734                     }
2735                     out.write(0xFF);
2736                     out.write(0xFF);
2737 
2738                     // Wait for End-of-File.
2739                     InputStream in = mSockets[i].getInputStream();
2740                     while (true) {
2741                         try {
2742                             if (in.read() == -1) {
2743                                 break;
2744                             }
2745                         } catch (Exception e) {
2746                             // ignore
2747                         }
2748                         checkInterruptAndDelay(true);
2749                     }
2750                 }
2751 
2752                 // Wait for the daemons to create the new state.
2753                 while (!state.exists()) {
2754                     // Check if a running daemon is dead.
2755                     for (int i = 0; i < mDaemons.length; ++i) {
2756                         String daemon = mDaemons[i];
2757                         if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
2758                             throw new IllegalStateException(daemon + " is dead");
2759                         }
2760                     }
2761                     checkInterruptAndDelay(true);
2762                 }
2763 
2764                 // Now we are connected. Read and parse the new state.
2765                 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
2766                 if (parameters.length != 7) {
2767                     throw new IllegalStateException("Cannot parse the state");
2768                 }
2769 
2770                 // Set the interface and the addresses in the config.
2771                 mConfig.interfaze = parameters[0].trim();
2772 
2773                 mConfig.addLegacyAddresses(parameters[1]);
2774                 // Set the routes if they are not set in the config.
2775                 if (mConfig.routes == null || mConfig.routes.isEmpty()) {
2776                     mConfig.addLegacyRoutes(parameters[2]);
2777                 }
2778 
2779                 // Set the DNS servers if they are not set in the config.
2780                 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
2781                     String dnsServers = parameters[3].trim();
2782                     if (!dnsServers.isEmpty()) {
2783                         mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
2784                     }
2785                 }
2786 
2787                 // Set the search domains if they are not set in the config.
2788                 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) {
2789                     String searchDomains = parameters[4].trim();
2790                     if (!searchDomains.isEmpty()) {
2791                         mConfig.searchDomains = Arrays.asList(searchDomains.split(" "));
2792                     }
2793                 }
2794 
2795                 // Add a throw route for the VPN server endpoint, if one was specified.
2796                 String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5];
2797                 if (!endpoint.isEmpty()) {
2798                     try {
2799                         InetAddress addr = InetAddress.parseNumericAddress(endpoint);
2800                         if (addr instanceof Inet4Address) {
2801                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
2802                         } else if (addr instanceof Inet6Address) {
2803                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
2804                         } else {
2805                             Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
2806                         }
2807                     } catch (IllegalArgumentException e) {
2808                         Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
2809                     }
2810                 }
2811 
2812                 // Here is the last step and it must be done synchronously.
2813                 synchronized (Vpn.this) {
2814                     // Set the start time
2815                     mConfig.startTime = SystemClock.elapsedRealtime();
2816 
2817                     // Check if the thread was interrupted while we were waiting on the lock.
2818                     checkInterruptAndDelay(false);
2819 
2820                     // Check if the interface is gone while we are waiting.
2821                     if (jniCheck(mConfig.interfaze) == 0) {
2822                         throw new IllegalStateException(mConfig.interfaze + " is gone");
2823                     }
2824 
2825                     // Now INetworkManagementEventObserver is watching our back.
2826                     mInterface = mConfig.interfaze;
2827                     prepareStatusIntent();
2828 
2829                     agentConnect();
2830 
2831                     Log.i(TAG, "Connected!");
2832                 }
2833             } catch (Exception e) {
2834                 Log.i(TAG, "Aborting", e);
2835                 updateState(DetailedState.FAILED, e.getMessage());
2836                 exitVpnRunner();
2837             }
2838         }
2839 
2840         /**
2841          * Check all daemons every two seconds. Return when one of them is stopped.
2842          * The caller will move to the disconnected state when this function returns,
2843          * which can happen if a daemon failed or if the VPN was torn down.
2844          */
2845         private void waitForDaemonsToStop() throws InterruptedException {
2846             if (!mNetworkInfo.isConnected()) {
2847                 return;
2848             }
2849             while (true) {
2850                 Thread.sleep(2000);
2851                 for (int i = 0; i < mDaemons.length; i++) {
2852                     if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
2853                         return;
2854                     }
2855                 }
2856             }
2857         }
2858     }
2859 
2860     private void verifyCallingUidAndPackage(String packageName) {
2861         if (getAppUid(packageName, mUserHandle) != Binder.getCallingUid()) {
2862             throw new SecurityException("Mismatched package and UID");
2863         }
2864     }
2865 
2866     @VisibleForTesting
2867     String getProfileNameForPackage(String packageName) {
2868         return Credentials.PLATFORM_VPN + mUserHandle + "_" + packageName;
2869     }
2870 
2871     @VisibleForTesting
2872     void validateRequiredFeatures(VpnProfile profile) {
2873         switch (profile.type) {
2874             case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
2875             case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
2876             case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
2877                 if (!mContext.getPackageManager().hasSystemFeature(
2878                         PackageManager.FEATURE_IPSEC_TUNNELS)) {
2879                     throw new UnsupportedOperationException(
2880                             "Ikev2VpnProfile(s) requires PackageManager.FEATURE_IPSEC_TUNNELS");
2881                 }
2882                 break;
2883             default:
2884                 return;
2885         }
2886     }
2887 
2888     /**
2889      * Stores an app-provisioned VPN profile and returns whether the app is already prepared.
2890      *
2891      * @param packageName the package name of the app provisioning this profile
2892      * @param profile the profile to be stored and provisioned
2893      * @param keyStore the System keystore instance to save VPN profiles
2894      * @returns whether or not the app has already been granted user consent
2895      */
2896     public synchronized boolean provisionVpnProfile(
2897             @NonNull String packageName, @NonNull VpnProfile profile, @NonNull KeyStore keyStore) {
2898         checkNotNull(packageName, "No package name provided");
2899         checkNotNull(profile, "No profile provided");
2900         checkNotNull(keyStore, "KeyStore missing");
2901 
2902         verifyCallingUidAndPackage(packageName);
2903         enforceNotRestrictedUser();
2904         validateRequiredFeatures(profile);
2905 
2906         if (profile.isRestrictedToTestNetworks) {
2907             mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS,
2908                     "Test-mode profiles require the MANAGE_TEST_NETWORKS permission");
2909         }
2910 
2911         final byte[] encodedProfile = profile.encode();
2912         if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) {
2913             throw new IllegalArgumentException("Profile too big");
2914         }
2915 
2916         // Permissions checked during startVpnProfile()
2917         Binder.withCleanCallingIdentity(
2918                 () -> {
2919                     keyStore.put(
2920                             getProfileNameForPackage(packageName),
2921                             encodedProfile,
2922                             Process.SYSTEM_UID,
2923                             0 /* flags */);
2924                 });
2925 
2926         // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop.
2927         // This mirrors the prepareAndAuthorize that is used by VpnService.
2928 
2929         // Return whether the app is already pre-consented
2930         return isVpnProfilePreConsented(mContext, packageName);
2931     }
2932 
2933     private boolean isCurrentIkev2VpnLocked(@NonNull String packageName) {
2934         return isCurrentPreparedPackage(packageName) && mVpnRunner instanceof IkeV2VpnRunner;
2935     }
2936 
2937     /**
2938      * Deletes an app-provisioned VPN profile.
2939      *
2940      * @param packageName the package name of the app provisioning this profile
2941      * @param keyStore the System keystore instance to save VPN profiles
2942      */
2943     public synchronized void deleteVpnProfile(
2944             @NonNull String packageName, @NonNull KeyStore keyStore) {
2945         checkNotNull(packageName, "No package name provided");
2946         checkNotNull(keyStore, "KeyStore missing");
2947 
2948         verifyCallingUidAndPackage(packageName);
2949         enforceNotRestrictedUser();
2950 
2951         Binder.withCleanCallingIdentity(
2952                 () -> {
2953                     // If this profile is providing the current VPN, turn it off, disabling
2954                     // always-on as well if enabled.
2955                     if (isCurrentIkev2VpnLocked(packageName)) {
2956                         if (mAlwaysOn) {
2957                             // Will transitively call prepareInternal(VpnConfig.LEGACY_VPN).
2958                             setAlwaysOnPackage(null, false, null, keyStore);
2959                         } else {
2960                             prepareInternal(VpnConfig.LEGACY_VPN);
2961                         }
2962                     }
2963 
2964                     keyStore.delete(getProfileNameForPackage(packageName), Process.SYSTEM_UID);
2965                 });
2966     }
2967 
2968     /**
2969      * Retrieves the VpnProfile.
2970      *
2971      * <p>Must be used only as SYSTEM_UID, otherwise the key/UID pair will not match anything in the
2972      * keystore.
2973      */
2974     @VisibleForTesting
2975     @Nullable
2976     VpnProfile getVpnProfilePrivileged(@NonNull String packageName, @NonNull KeyStore keyStore) {
2977         if (!mSystemServices.isCallerSystem()) {
2978             Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID ");
2979             return null;
2980         }
2981 
2982         final byte[] encoded = keyStore.get(getProfileNameForPackage(packageName));
2983         if (encoded == null) return null;
2984 
2985         return VpnProfile.decode("" /* Key unused */, encoded);
2986     }
2987 
2988     /**
2989      * Starts an already provisioned VPN Profile, keyed by package name.
2990      *
2991      * <p>This method is meant to be called by apps (via VpnManager and ConnectivityService).
2992      * Privileged (system) callers should use startVpnProfilePrivileged instead. Otherwise the UIDs
2993      * will not match during appop checks.
2994      *
2995      * @param packageName the package name of the app provisioning this profile
2996      * @param keyStore the System keystore instance to retrieve VPN profiles
2997      */
2998     public synchronized void startVpnProfile(
2999             @NonNull String packageName, @NonNull KeyStore keyStore) {
3000         checkNotNull(packageName, "No package name provided");
3001         checkNotNull(keyStore, "KeyStore missing");
3002 
3003         enforceNotRestrictedUser();
3004 
3005         // Prepare VPN for startup
3006         if (!prepare(packageName, null /* newPackage */, VpnManager.TYPE_VPN_PLATFORM)) {
3007             throw new SecurityException("User consent not granted for package " + packageName);
3008         }
3009 
3010         Binder.withCleanCallingIdentity(
3011                 () -> {
3012                     final VpnProfile profile = getVpnProfilePrivileged(packageName, keyStore);
3013                     if (profile == null) {
3014                         throw new IllegalArgumentException("No profile found for " + packageName);
3015                     }
3016 
3017                     startVpnProfilePrivileged(profile, packageName,
3018                             null /* keyStore for private key retrieval - unneeded */);
3019                 });
3020     }
3021 
3022     private synchronized void startVpnProfilePrivileged(
3023             @NonNull VpnProfile profile, @NonNull String packageName, @Nullable KeyStore keyStore) {
3024         // Make sure VPN is prepared. This method can be called by user apps via startVpnProfile(),
3025         // by the Setting app via startLegacyVpn(), or by ConnectivityService via
3026         // startAlwaysOnVpn(), so this is the common place to prepare the VPN. This also has the
3027         // nice property of ensuring there are no other VpnRunner instances running.
3028         prepareInternal(packageName);
3029         updateState(DetailedState.CONNECTING, "startPlatformVpn");
3030 
3031         try {
3032             // Build basic config
3033             mConfig = new VpnConfig();
3034             if (VpnConfig.LEGACY_VPN.equals(packageName)) {
3035                 mConfig.legacy = true;
3036                 mConfig.session = profile.name;
3037                 mConfig.user = profile.key;
3038 
3039                 // TODO: Add support for configuring meteredness via Settings. Until then, use a
3040                 // safe default.
3041                 mConfig.isMetered = true;
3042             } else {
3043                 mConfig.user = packageName;
3044                 mConfig.isMetered = profile.isMetered;
3045             }
3046             mConfig.startTime = SystemClock.elapsedRealtime();
3047             mConfig.proxyInfo = profile.proxy;
3048 
3049             switch (profile.type) {
3050                 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
3051                 case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
3052                 case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
3053                     mVpnRunner =
3054                             new IkeV2VpnRunner(Ikev2VpnProfile.fromVpnProfile(profile, keyStore));
3055                     mVpnRunner.start();
3056                     break;
3057                 default:
3058                     updateState(DetailedState.FAILED, "Invalid platform VPN type");
3059                     Log.d(TAG, "Unknown VPN profile type: " + profile.type);
3060                     break;
3061             }
3062         } catch (IOException | GeneralSecurityException e) {
3063             // Reset mConfig
3064             mConfig = null;
3065 
3066             updateState(DetailedState.FAILED, "VPN startup failed");
3067             throw new IllegalArgumentException("VPN startup failed", e);
3068         }
3069     }
3070 
3071     /**
3072      * Stops an already running VPN Profile for the given package.
3073      *
3074      * <p>This method is meant to be called by apps (via VpnManager and ConnectivityService).
3075      * Privileged (system) callers should (re-)prepare the LEGACY_VPN instead.
3076      *
3077      * @param packageName the package name of the app provisioning this profile
3078      */
3079     public synchronized void stopVpnProfile(@NonNull String packageName) {
3080         checkNotNull(packageName, "No package name provided");
3081 
3082         enforceNotRestrictedUser();
3083 
3084         // To stop the VPN profile, the caller must be the current prepared package and must be
3085         // running an Ikev2VpnProfile.
3086         if (isCurrentIkev2VpnLocked(packageName)) {
3087             prepareInternal(VpnConfig.LEGACY_VPN);
3088         }
3089     }
3090 
3091     /**
3092      * Proxy to allow testing
3093      *
3094      * @hide
3095      */
3096     @VisibleForTesting
3097     public static class Ikev2SessionCreator {
3098         /** Creates a IKE session */
3099         public IkeSession createIkeSession(
3100                 @NonNull Context context,
3101                 @NonNull IkeSessionParams ikeSessionParams,
3102                 @NonNull ChildSessionParams firstChildSessionParams,
3103                 @NonNull Executor userCbExecutor,
3104                 @NonNull IkeSessionCallback ikeSessionCallback,
3105                 @NonNull ChildSessionCallback firstChildSessionCallback) {
3106             return new IkeSession(
3107                     context,
3108                     ikeSessionParams,
3109                     firstChildSessionParams,
3110                     userCbExecutor,
3111                     ikeSessionCallback,
3112                     firstChildSessionCallback);
3113         }
3114     }
3115 }
3116