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