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