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