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