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