Vpn.java revision 11008a78b8e30910cedd8b8431980c7738183292
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.os.UserHandle.PER_USER_RANGE;
21import static android.net.RouteInfo.RTN_THROW;
22import static android.net.RouteInfo.RTN_UNREACHABLE;
23import static android.system.OsConstants.AF_INET;
24import static android.system.OsConstants.AF_INET6;
25
26import android.Manifest;
27import android.app.AppGlobals;
28import android.app.AppOpsManager;
29import android.app.PendingIntent;
30import android.content.BroadcastReceiver;
31import android.content.ComponentName;
32import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
35import android.content.ServiceConnection;
36import android.content.pm.ApplicationInfo;
37import android.content.pm.PackageManager;
38import android.content.pm.PackageManager.NameNotFoundException;
39import android.content.pm.ResolveInfo;
40import android.content.pm.UserInfo;
41import android.net.ConnectivityManager;
42import android.net.IConnectivityManager;
43import android.net.INetworkManagementEventObserver;
44import android.net.IpPrefix;
45import android.net.LinkAddress;
46import android.net.LinkProperties;
47import android.net.LocalSocket;
48import android.net.LocalSocketAddress;
49import android.net.NetworkAgent;
50import android.net.NetworkCapabilities;
51import android.net.NetworkInfo;
52import android.net.NetworkInfo.DetailedState;
53import android.net.NetworkMisc;
54import android.net.RouteInfo;
55import android.net.UidRange;
56import android.os.Binder;
57import android.os.FileUtils;
58import android.os.IBinder;
59import android.os.INetworkManagementService;
60import android.os.Looper;
61import android.os.Parcel;
62import android.os.ParcelFileDescriptor;
63import android.os.Process;
64import android.os.RemoteException;
65import android.os.SystemClock;
66import android.os.SystemService;
67import android.os.UserHandle;
68import android.os.UserManager;
69import android.security.Credentials;
70import android.security.KeyStore;
71import android.util.Log;
72
73import com.android.internal.annotations.GuardedBy;
74import com.android.internal.net.LegacyVpnInfo;
75import com.android.internal.net.VpnConfig;
76import com.android.internal.net.VpnProfile;
77import com.android.server.net.BaseNetworkObserver;
78
79import libcore.io.IoUtils;
80
81import java.io.File;
82import java.io.IOException;
83import java.io.InputStream;
84import java.io.OutputStream;
85import java.net.Inet4Address;
86import java.net.Inet6Address;
87import java.net.InetAddress;
88import java.nio.charset.StandardCharsets;
89import java.util.ArrayList;
90import java.util.Arrays;
91import java.util.List;
92import java.util.SortedSet;
93import java.util.TreeSet;
94import java.util.concurrent.atomic.AtomicInteger;
95
96/**
97 * @hide
98 */
99public class Vpn {
100    private static final String NETWORKTYPE = "VPN";
101    private static final String TAG = "Vpn";
102    private static final boolean LOGD = true;
103
104    // TODO: create separate trackers for each unique VPN to support
105    // automated reconnection
106
107    private Context mContext;
108    private NetworkInfo mNetworkInfo;
109    private String mPackage;
110    private int mOwnerUID;
111    private String mInterface;
112    private Connection mConnection;
113    private LegacyVpnRunner mLegacyVpnRunner;
114    private PendingIntent mStatusIntent;
115    private volatile boolean mEnableTeardown = true;
116    private final IConnectivityManager mConnService;
117    private final INetworkManagementService mNetd;
118    private VpnConfig mConfig;
119    private NetworkAgent mNetworkAgent;
120    private final Looper mLooper;
121    private final NetworkCapabilities mNetworkCapabilities;
122
123    /* list of users using this VPN. */
124    @GuardedBy("this")
125    private List<UidRange> mVpnUsers = null;
126    private BroadcastReceiver mUserIntentReceiver = null;
127
128    // Handle of user initiating VPN.
129    private final int mUserHandle;
130
131    public Vpn(Looper looper, Context context, INetworkManagementService netService,
132            IConnectivityManager connService, int userHandle) {
133        mContext = context;
134        mNetd = netService;
135        mConnService = connService;
136        mUserHandle = userHandle;
137        mLooper = looper;
138
139        mPackage = VpnConfig.LEGACY_VPN;
140        mOwnerUID = getAppUid(mPackage, mUserHandle);
141
142        try {
143            netService.registerObserver(mObserver);
144        } catch (RemoteException e) {
145            Log.wtf(TAG, "Problem registering observer", e);
146        }
147        if (userHandle == UserHandle.USER_OWNER) {
148            // Owner's VPN also needs to handle restricted users
149            mUserIntentReceiver = new BroadcastReceiver() {
150                @Override
151                public void onReceive(Context context, Intent intent) {
152                    final String action = intent.getAction();
153                    final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
154                            UserHandle.USER_NULL);
155                    if (userHandle == UserHandle.USER_NULL) return;
156
157                    if (Intent.ACTION_USER_ADDED.equals(action)) {
158                        onUserAdded(userHandle);
159                    } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
160                        onUserRemoved(userHandle);
161                    }
162                }
163            };
164
165            IntentFilter intentFilter = new IntentFilter();
166            intentFilter.addAction(Intent.ACTION_USER_ADDED);
167            intentFilter.addAction(Intent.ACTION_USER_REMOVED);
168            mContext.registerReceiverAsUser(
169                    mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
170        }
171
172        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, "");
173        // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332
174        mNetworkCapabilities = new NetworkCapabilities();
175        mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
176        mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
177    }
178
179    /**
180     * Set if this object is responsible for watching for {@link NetworkInfo}
181     * teardown. When {@code false}, teardown is handled externally by someone
182     * else.
183     */
184    public void setEnableTeardown(boolean enableTeardown) {
185        mEnableTeardown = enableTeardown;
186    }
187
188    /**
189     * Update current state, dispaching event to listeners.
190     */
191    private void updateState(DetailedState detailedState, String reason) {
192        if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
193        mNetworkInfo.setDetailedState(detailedState, reason, null);
194        if (mNetworkAgent != null) {
195            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
196        }
197    }
198
199    /**
200     * Prepare for a VPN application. This method is designed to solve
201     * race conditions. It first compares the current prepared package
202     * with {@code oldPackage}. If they are the same, the prepared
203     * package is revoked and replaced with {@code newPackage}. If
204     * {@code oldPackage} is {@code null}, the comparison is omitted.
205     * If {@code newPackage} is the same package or {@code null}, the
206     * revocation is omitted. This method returns {@code true} if the
207     * operation is succeeded.
208     *
209     * Legacy VPN is handled specially since it is not a real package.
210     * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
211     * it can be revoked by itself.
212     *
213     * @param oldPackage The package name of the old VPN application.
214     * @param newPackage The package name of the new VPN application.
215     * @return true if the operation is succeeded.
216     */
217    public synchronized boolean prepare(String oldPackage, String newPackage) {
218        if (oldPackage != null && getAppUid(oldPackage, mUserHandle) != mOwnerUID) {
219            // The package doesn't match. We return false (to obtain user consent) unless the user
220            // has already consented to that VPN package.
221            if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
222                prepareInternal(oldPackage);
223                return true;
224            }
225            return false;
226        }
227
228        // Return true if we do not need to revoke.
229        if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) &&
230                getAppUid(newPackage, mUserHandle) == mOwnerUID)) {
231            return true;
232        }
233
234        // Check if the caller is authorized.
235        enforceControlPermission();
236
237        prepareInternal(newPackage);
238        return true;
239    }
240
241    /** Prepare the VPN for the given package. Does not perform permission checks. */
242    private void prepareInternal(String newPackage) {
243        long token = Binder.clearCallingIdentity();
244        try {
245            // Reset the interface.
246            if (mInterface != null) {
247                mStatusIntent = null;
248                agentDisconnect();
249                jniReset(mInterface);
250                mInterface = null;
251                mVpnUsers = null;
252            }
253
254            // Revoke the connection or stop LegacyVpnRunner.
255            if (mConnection != null) {
256                try {
257                    mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION,
258                            Parcel.obtain(), null, IBinder.FLAG_ONEWAY);
259                } catch (Exception e) {
260                    // ignore
261                }
262                mContext.unbindService(mConnection);
263                mConnection = null;
264            } else if (mLegacyVpnRunner != null) {
265                mLegacyVpnRunner.exit();
266                mLegacyVpnRunner = null;
267            }
268
269            try {
270                mNetd.denyProtect(mOwnerUID);
271            } catch (Exception e) {
272                Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
273            }
274
275            Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
276            mPackage = newPackage;
277            mOwnerUID = getAppUid(newPackage, mUserHandle);
278            try {
279                mNetd.allowProtect(mOwnerUID);
280            } catch (Exception e) {
281                Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
282            }
283            mConfig = null;
284
285            updateState(DetailedState.IDLE, "prepare");
286        } finally {
287            Binder.restoreCallingIdentity(token);
288        }
289    }
290
291    /**
292     * Set whether the current package has the ability to launch VPNs without user intervention.
293     */
294    public void setPackageAuthorization(boolean authorized) {
295        // Check if the caller is authorized.
296        enforceControlPermission();
297
298        if (mPackage == null || VpnConfig.LEGACY_VPN.equals(mPackage)) {
299            return;
300        }
301
302        long token = Binder.clearCallingIdentity();
303        try {
304            AppOpsManager appOps =
305                    (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
306            appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, mOwnerUID, mPackage,
307                    authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
308        } catch (Exception e) {
309            Log.wtf(TAG, "Failed to set app ops for package " + mPackage, e);
310        } finally {
311            Binder.restoreCallingIdentity(token);
312        }
313    }
314
315    private boolean isVpnUserPreConsented(String packageName) {
316        AppOpsManager appOps =
317                (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
318
319        // Verify that the caller matches the given package and has permission to activate VPNs.
320        return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(),
321                packageName) == AppOpsManager.MODE_ALLOWED;
322    }
323
324    private int getAppUid(String app, int userHandle) {
325        if (VpnConfig.LEGACY_VPN.equals(app)) {
326            return Process.myUid();
327        }
328        PackageManager pm = mContext.getPackageManager();
329        int result;
330        try {
331            result = pm.getPackageUid(app, userHandle);
332        } catch (NameNotFoundException e) {
333            result = -1;
334        }
335        return result;
336    }
337
338    public NetworkInfo getNetworkInfo() {
339        return mNetworkInfo;
340    }
341
342    private LinkProperties makeLinkProperties() {
343        boolean allowIPv4 = mConfig.allowIPv4;
344        boolean allowIPv6 = mConfig.allowIPv6;
345
346        LinkProperties lp = new LinkProperties();
347
348        lp.setInterfaceName(mInterface);
349
350        if (mConfig.addresses != null) {
351            for (LinkAddress address : mConfig.addresses) {
352                lp.addLinkAddress(address);
353                allowIPv4 |= address.getAddress() instanceof Inet4Address;
354                allowIPv6 |= address.getAddress() instanceof Inet6Address;
355            }
356        }
357
358        if (mConfig.routes != null) {
359            for (RouteInfo route : mConfig.routes) {
360                lp.addRoute(route);
361                InetAddress address = route.getDestination().getAddress();
362                allowIPv4 |= address instanceof Inet4Address;
363                allowIPv6 |= address instanceof Inet6Address;
364            }
365        }
366
367        if (mConfig.dnsServers != null) {
368            for (String dnsServer : mConfig.dnsServers) {
369                InetAddress address = InetAddress.parseNumericAddress(dnsServer);
370                lp.addDnsServer(address);
371                allowIPv4 |= address instanceof Inet4Address;
372                allowIPv6 |= address instanceof Inet6Address;
373            }
374        }
375
376        if (!allowIPv4) {
377            lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
378        }
379        if (!allowIPv6) {
380            lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
381        }
382
383        // Concatenate search domains into a string.
384        StringBuilder buffer = new StringBuilder();
385        if (mConfig.searchDomains != null) {
386            for (String domain : mConfig.searchDomains) {
387                buffer.append(domain).append(' ');
388            }
389        }
390        lp.setDomains(buffer.toString().trim());
391
392        // TODO: Stop setting the MTU in jniCreate and set it here.
393
394        return lp;
395    }
396
397    private void agentConnect() {
398        LinkProperties lp = makeLinkProperties();
399
400        if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) {
401            mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
402        } else {
403            mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
404        }
405
406        mNetworkInfo.setIsAvailable(true);
407        mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
408
409        NetworkMisc networkMisc = new NetworkMisc();
410        networkMisc.allowBypass = mConfig.allowBypass;
411
412        long token = Binder.clearCallingIdentity();
413        try {
414            mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE,
415                    mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) {
416                            @Override
417                            public void unwanted() {
418                                // We are user controlled, not driven by NetworkRequest.
419                            }
420                        };
421        } finally {
422            Binder.restoreCallingIdentity(token);
423        }
424
425        addVpnUserLocked(mUserHandle);
426        // If we are owner assign all Restricted Users to this VPN
427        if (mUserHandle == UserHandle.USER_OWNER) {
428            token = Binder.clearCallingIdentity();
429            List<UserInfo> users;
430            try {
431                users = UserManager.get(mContext).getUsers();
432            } finally {
433                Binder.restoreCallingIdentity(token);
434            }
435            for (UserInfo user : users) {
436                if (user.isRestricted()) {
437                    addVpnUserLocked(user.id);
438                }
439            }
440        }
441        mNetworkAgent.addUidRanges(mVpnUsers.toArray(new UidRange[mVpnUsers.size()]));
442    }
443
444    private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) {
445        networkInfo.setIsAvailable(false);
446        networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
447        if (networkAgent != null) {
448            networkAgent.sendNetworkInfo(networkInfo);
449        }
450    }
451
452    private void agentDisconnect(NetworkAgent networkAgent) {
453        NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
454        agentDisconnect(networkInfo, networkAgent);
455    }
456
457    private void agentDisconnect() {
458        if (mNetworkInfo.isConnected()) {
459            agentDisconnect(mNetworkInfo, mNetworkAgent);
460            mNetworkAgent = null;
461        }
462    }
463
464    /**
465     * Establish a VPN network and return the file descriptor of the VPN
466     * interface. This methods returns {@code null} if the application is
467     * revoked or not prepared.
468     *
469     * @param config The parameters to configure the network.
470     * @return The file descriptor of the VPN interface.
471     */
472    public synchronized ParcelFileDescriptor establish(VpnConfig config) {
473        // Check if the caller is already prepared.
474        UserManager mgr = UserManager.get(mContext);
475        if (Binder.getCallingUid() != mOwnerUID) {
476            return null;
477        }
478        // Check if the service is properly declared.
479        Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
480        intent.setClassName(mPackage, config.user);
481        long token = Binder.clearCallingIdentity();
482        try {
483            // Restricted users are not allowed to create VPNs, they are tied to Owner
484            UserInfo user = mgr.getUserInfo(mUserHandle);
485            if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
486                throw new SecurityException("Restricted users cannot establish VPNs");
487            }
488
489            ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
490                                                                        null, 0, mUserHandle);
491            if (info == null) {
492                throw new SecurityException("Cannot find " + config.user);
493            }
494            if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
495                throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
496            }
497        } catch (RemoteException e) {
498                throw new SecurityException("Cannot find " + config.user);
499        } finally {
500            Binder.restoreCallingIdentity(token);
501        }
502
503        // Save the old config in case we need to go back.
504        VpnConfig oldConfig = mConfig;
505        String oldInterface = mInterface;
506        Connection oldConnection = mConnection;
507        NetworkAgent oldNetworkAgent = mNetworkAgent;
508        mNetworkAgent = null;
509        List<UidRange> oldUsers = mVpnUsers;
510
511        // Configure the interface. Abort if any of these steps fails.
512        ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
513        try {
514            updateState(DetailedState.CONNECTING, "establish");
515            String interfaze = jniGetName(tun.getFd());
516
517            // TEMP use the old jni calls until there is support for netd address setting
518            StringBuilder builder = new StringBuilder();
519            for (LinkAddress address : config.addresses) {
520                builder.append(" " + address);
521            }
522            if (jniSetAddresses(interfaze, builder.toString()) < 1) {
523                throw new IllegalArgumentException("At least one address must be specified");
524            }
525            Connection connection = new Connection();
526            if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
527                        new UserHandle(mUserHandle))) {
528                throw new IllegalStateException("Cannot bind " + config.user);
529            }
530
531            mConnection = connection;
532            mInterface = interfaze;
533
534            // Fill more values.
535            config.user = mPackage;
536            config.interfaze = mInterface;
537            config.startTime = SystemClock.elapsedRealtime();
538            mConfig = config;
539
540            // Set up forwarding and DNS rules.
541            mVpnUsers = new ArrayList<UidRange>();
542
543            agentConnect();
544
545            if (oldConnection != null) {
546                mContext.unbindService(oldConnection);
547            }
548            // Remove the old tun's user forwarding rules
549            // The new tun's user rules have already been added so they will take over
550            // as rules are deleted. This prevents data leakage as the rules are moved over.
551            agentDisconnect(oldNetworkAgent);
552            if (oldInterface != null && !oldInterface.equals(interfaze)) {
553                jniReset(oldInterface);
554            }
555
556            try {
557                IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
558            } catch (IOException e) {
559                throw new IllegalStateException(
560                        "Cannot set tunnel's fd as blocking=" + config.blocking, e);
561            }
562        } catch (RuntimeException e) {
563            IoUtils.closeQuietly(tun);
564            agentDisconnect();
565            // restore old state
566            mConfig = oldConfig;
567            mConnection = oldConnection;
568            mVpnUsers = oldUsers;
569            mNetworkAgent = oldNetworkAgent;
570            mInterface = oldInterface;
571            throw e;
572        }
573        Log.i(TAG, "Established by " + config.user + " on " + mInterface);
574        return tun;
575    }
576
577    private boolean isRunningLocked() {
578        return mVpnUsers != null;
579    }
580
581    // Note: Return type guarantees results are deduped and sorted, which callers require.
582    private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) {
583        SortedSet<Integer> uids = new TreeSet<Integer>();
584        for (String app : packageNames) {
585            int uid = getAppUid(app, userHandle);
586            if (uid != -1) uids.add(uid);
587        }
588        return uids;
589    }
590
591    // Note: This function adds to mVpnUsers but does not publish list to NetworkAgent.
592    private void addVpnUserLocked(int userHandle) {
593        if (!isRunningLocked()) {
594            throw new IllegalStateException("VPN is not active");
595        }
596
597        if (mConfig.allowedApplications != null) {
598            // Add ranges covering all UIDs for allowedApplications.
599            int start = -1, stop = -1;
600            for (int uid : getAppsUids(mConfig.allowedApplications, userHandle)) {
601                if (start == -1) {
602                    start = uid;
603                } else if (uid != stop + 1) {
604                    mVpnUsers.add(new UidRange(start, stop));
605                    start = uid;
606                }
607                stop = uid;
608            }
609            if (start != -1) mVpnUsers.add(new UidRange(start, stop));
610        } else if (mConfig.disallowedApplications != null) {
611            // Add all ranges for user skipping UIDs for disallowedApplications.
612            final UidRange userRange = UidRange.createForUser(userHandle);
613            int start = userRange.start;
614            for (int uid : getAppsUids(mConfig.disallowedApplications, userHandle)) {
615                if (uid == start) {
616                    start++;
617                } else {
618                    mVpnUsers.add(new UidRange(start, uid - 1));
619                    start = uid + 1;
620                }
621            }
622            if (start <= userRange.stop) mVpnUsers.add(new UidRange(start, userRange.stop));
623        } else {
624            // Add all UIDs for the user.
625            mVpnUsers.add(UidRange.createForUser(userHandle));
626        }
627
628        prepareStatusIntent();
629    }
630
631    // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that
632    // apply to userHandle.
633    private List<UidRange> uidRangesForUser(int userHandle) {
634        final UidRange userRange = UidRange.createForUser(userHandle);
635        final List<UidRange> ranges = new ArrayList<UidRange>();
636        for (UidRange range : mVpnUsers) {
637            if (range.start >= userRange.start && range.stop <= userRange.stop) {
638                ranges.add(range);
639            }
640        }
641        return ranges;
642    }
643
644    private void removeVpnUserLocked(int userHandle) {
645        if (!isRunningLocked()) {
646            throw new IllegalStateException("VPN is not active");
647        }
648        final List<UidRange> ranges = uidRangesForUser(userHandle);
649        if (mNetworkAgent != null) {
650            mNetworkAgent.removeUidRanges(ranges.toArray(new UidRange[ranges.size()]));
651        }
652        mVpnUsers.removeAll(ranges);
653        mStatusIntent = null;
654    }
655
656    private void onUserAdded(int userHandle) {
657        // If the user is restricted tie them to the owner's VPN
658        synchronized(Vpn.this) {
659            UserManager mgr = UserManager.get(mContext);
660            UserInfo user = mgr.getUserInfo(userHandle);
661            if (user.isRestricted()) {
662                try {
663                    addVpnUserLocked(userHandle);
664                    if (mNetworkAgent != null) {
665                        final List<UidRange> ranges = uidRangesForUser(userHandle);
666                        mNetworkAgent.addUidRanges(ranges.toArray(new UidRange[ranges.size()]));
667                    }
668                } catch (Exception e) {
669                    Log.wtf(TAG, "Failed to add restricted user to owner", e);
670                }
671            }
672        }
673    }
674
675    private void onUserRemoved(int userHandle) {
676        // clean up if restricted
677        synchronized(Vpn.this) {
678            UserManager mgr = UserManager.get(mContext);
679            UserInfo user = mgr.getUserInfo(userHandle);
680            if (user.isRestricted()) {
681                try {
682                    removeVpnUserLocked(userHandle);
683                } catch (Exception e) {
684                    Log.wtf(TAG, "Failed to remove restricted user to owner", e);
685                }
686            }
687        }
688    }
689
690    /**
691     * Return the configuration of the currently running VPN.
692     */
693    public VpnConfig getVpnConfig() {
694        enforceControlPermission();
695        return mConfig;
696    }
697
698    @Deprecated
699    public synchronized void interfaceStatusChanged(String iface, boolean up) {
700        try {
701            mObserver.interfaceStatusChanged(iface, up);
702        } catch (RemoteException e) {
703            // ignored; target is local
704        }
705    }
706
707    private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() {
708        @Override
709        public void interfaceStatusChanged(String interfaze, boolean up) {
710            synchronized (Vpn.this) {
711                if (!up && mLegacyVpnRunner != null) {
712                    mLegacyVpnRunner.check(interfaze);
713                }
714            }
715        }
716
717        @Override
718        public void interfaceRemoved(String interfaze) {
719            synchronized (Vpn.this) {
720                if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
721                    mStatusIntent = null;
722                    mVpnUsers = null;
723                    mInterface = null;
724                    if (mConnection != null) {
725                        mContext.unbindService(mConnection);
726                        mConnection = null;
727                        agentDisconnect();
728                    } else if (mLegacyVpnRunner != null) {
729                        mLegacyVpnRunner.exit();
730                        mLegacyVpnRunner = null;
731                    }
732                }
733            }
734        }
735    };
736
737    private void enforceControlPermission() {
738        mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller");
739    }
740
741    private class Connection implements ServiceConnection {
742        private IBinder mService;
743
744        @Override
745        public void onServiceConnected(ComponentName name, IBinder service) {
746            mService = service;
747        }
748
749        @Override
750        public void onServiceDisconnected(ComponentName name) {
751            mService = null;
752        }
753    }
754
755    private void prepareStatusIntent() {
756        final long token = Binder.clearCallingIdentity();
757        try {
758            mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
759        } finally {
760            Binder.restoreCallingIdentity(token);
761        }
762    }
763
764    public synchronized boolean addAddress(String address, int prefixLength) {
765        if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) {
766            return false;
767        }
768        boolean success = jniAddAddress(mInterface, address, prefixLength);
769        if (mNetworkAgent != null) {
770            mNetworkAgent.sendLinkProperties(makeLinkProperties());
771        }
772        return success;
773    }
774
775    public synchronized boolean removeAddress(String address, int prefixLength) {
776        if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) {
777            return false;
778        }
779        boolean success = jniDelAddress(mInterface, address, prefixLength);
780        if (mNetworkAgent != null) {
781            mNetworkAgent.sendLinkProperties(makeLinkProperties());
782        }
783        return success;
784    }
785
786    private native int jniCreate(int mtu);
787    private native String jniGetName(int tun);
788    private native int jniSetAddresses(String interfaze, String addresses);
789    private native void jniReset(String interfaze);
790    private native int jniCheck(String interfaze);
791    private native boolean jniAddAddress(String interfaze, String address, int prefixLen);
792    private native boolean jniDelAddress(String interfaze, String address, int prefixLen);
793
794    private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
795        for (RouteInfo route : prop.getAllRoutes()) {
796            // Currently legacy VPN only works on IPv4.
797            if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
798                return route;
799            }
800        }
801
802        throw new IllegalStateException("Unable to find IPv4 default gateway");
803    }
804
805    /**
806     * Start legacy VPN, controlling native daemons as needed. Creates a
807     * secondary thread to perform connection work, returning quickly.
808     */
809    public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
810        enforceControlPermission();
811        if (!keyStore.isUnlocked()) {
812            throw new IllegalStateException("KeyStore isn't unlocked");
813        }
814        UserManager mgr = UserManager.get(mContext);
815        UserInfo user = mgr.getUserInfo(mUserHandle);
816        if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
817            throw new SecurityException("Restricted users cannot establish VPNs");
818        }
819
820        final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
821        final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
822        final String iface = ipv4DefaultRoute.getInterface();
823
824        // Load certificates.
825        String privateKey = "";
826        String userCert = "";
827        String caCert = "";
828        String serverCert = "";
829        if (!profile.ipsecUserCert.isEmpty()) {
830            privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
831            byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
832            userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
833        }
834        if (!profile.ipsecCaCert.isEmpty()) {
835            byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
836            caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
837        }
838        if (!profile.ipsecServerCert.isEmpty()) {
839            byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
840            serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
841        }
842        if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
843            throw new IllegalStateException("Cannot load credentials");
844        }
845
846        // Prepare arguments for racoon.
847        String[] racoon = null;
848        switch (profile.type) {
849            case VpnProfile.TYPE_L2TP_IPSEC_PSK:
850                racoon = new String[] {
851                    iface, profile.server, "udppsk", profile.ipsecIdentifier,
852                    profile.ipsecSecret, "1701",
853                };
854                break;
855            case VpnProfile.TYPE_L2TP_IPSEC_RSA:
856                racoon = new String[] {
857                    iface, profile.server, "udprsa", privateKey, userCert,
858                    caCert, serverCert, "1701",
859                };
860                break;
861            case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
862                racoon = new String[] {
863                    iface, profile.server, "xauthpsk", profile.ipsecIdentifier,
864                    profile.ipsecSecret, profile.username, profile.password, "", gateway,
865                };
866                break;
867            case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
868                racoon = new String[] {
869                    iface, profile.server, "xauthrsa", privateKey, userCert,
870                    caCert, serverCert, profile.username, profile.password, "", gateway,
871                };
872                break;
873            case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
874                racoon = new String[] {
875                    iface, profile.server, "hybridrsa",
876                    caCert, serverCert, profile.username, profile.password, "", gateway,
877                };
878                break;
879        }
880
881        // Prepare arguments for mtpd.
882        String[] mtpd = null;
883        switch (profile.type) {
884            case VpnProfile.TYPE_PPTP:
885                mtpd = new String[] {
886                    iface, "pptp", profile.server, "1723",
887                    "name", profile.username, "password", profile.password,
888                    "linkname", "vpn", "refuse-eap", "nodefaultroute",
889                    "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
890                    (profile.mppe ? "+mppe" : "nomppe"),
891                };
892                break;
893            case VpnProfile.TYPE_L2TP_IPSEC_PSK:
894            case VpnProfile.TYPE_L2TP_IPSEC_RSA:
895                mtpd = new String[] {
896                    iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
897                    "name", profile.username, "password", profile.password,
898                    "linkname", "vpn", "refuse-eap", "nodefaultroute",
899                    "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
900                };
901                break;
902        }
903
904        VpnConfig config = new VpnConfig();
905        config.legacy = true;
906        config.user = profile.key;
907        config.interfaze = iface;
908        config.session = profile.name;
909
910        config.addLegacyRoutes(profile.routes);
911        if (!profile.dnsServers.isEmpty()) {
912            config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
913        }
914        if (!profile.searchDomains.isEmpty()) {
915            config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
916        }
917        startLegacyVpn(config, racoon, mtpd);
918    }
919
920    private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
921        stopLegacyVpn();
922
923        // Prepare for the new request. This also checks the caller.
924        prepare(null, VpnConfig.LEGACY_VPN);
925        updateState(DetailedState.CONNECTING, "startLegacyVpn");
926
927        // Start a new LegacyVpnRunner and we are done!
928        mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
929        mLegacyVpnRunner.start();
930    }
931
932    public synchronized void stopLegacyVpn() {
933        if (mLegacyVpnRunner != null) {
934            mLegacyVpnRunner.exit();
935            mLegacyVpnRunner = null;
936
937            synchronized (LegacyVpnRunner.TAG) {
938                // wait for old thread to completely finish before spinning up
939                // new instance, otherwise state updates can be out of order.
940            }
941        }
942    }
943
944    /**
945     * Return the information of the current ongoing legacy VPN.
946     */
947    public synchronized LegacyVpnInfo getLegacyVpnInfo() {
948        // Check if the caller is authorized.
949        enforceControlPermission();
950        if (mLegacyVpnRunner == null) return null;
951
952        final LegacyVpnInfo info = new LegacyVpnInfo();
953        info.key = mConfig.user;
954        info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
955        if (mNetworkInfo.isConnected()) {
956            info.intent = mStatusIntent;
957        }
958        return info;
959    }
960
961    public VpnConfig getLegacyVpnConfig() {
962        if (mLegacyVpnRunner != null) {
963            return mConfig;
964        } else {
965            return null;
966        }
967    }
968
969    /**
970     * Bringing up a VPN connection takes time, and that is all this thread
971     * does. Here we have plenty of time. The only thing we need to take
972     * care of is responding to interruptions as soon as possible. Otherwise
973     * requests will be piled up. This can be done in a Handler as a state
974     * machine, but it is much easier to read in the current form.
975     */
976    private class LegacyVpnRunner extends Thread {
977        private static final String TAG = "LegacyVpnRunner";
978
979        private final String[] mDaemons;
980        private final String[][] mArguments;
981        private final LocalSocket[] mSockets;
982        private final String mOuterInterface;
983        private final AtomicInteger mOuterConnection =
984                new AtomicInteger(ConnectivityManager.TYPE_NONE);
985
986        private long mTimer = -1;
987
988        /**
989         * Watch for the outer connection (passing in the constructor) going away.
990         */
991        private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
992            @Override
993            public void onReceive(Context context, Intent intent) {
994                if (!mEnableTeardown) return;
995
996                if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
997                    if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
998                            ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) {
999                        NetworkInfo info = (NetworkInfo)intent.getExtra(
1000                                ConnectivityManager.EXTRA_NETWORK_INFO);
1001                        if (info != null && !info.isConnectedOrConnecting()) {
1002                            try {
1003                                mObserver.interfaceStatusChanged(mOuterInterface, false);
1004                            } catch (RemoteException e) {}
1005                        }
1006                    }
1007                }
1008            }
1009        };
1010
1011        public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
1012            super(TAG);
1013            mConfig = config;
1014            mDaemons = new String[] {"racoon", "mtpd"};
1015            // TODO: clear arguments from memory once launched
1016            mArguments = new String[][] {racoon, mtpd};
1017            mSockets = new LocalSocket[mDaemons.length];
1018
1019            // This is the interface which VPN is running on,
1020            // mConfig.interfaze will change to point to OUR
1021            // internal interface soon. TODO - add inner/outer to mconfig
1022            // TODO - we have a race - if the outer iface goes away/disconnects before we hit this
1023            // we will leave the VPN up.  We should check that it's still there/connected after
1024            // registering
1025            mOuterInterface = mConfig.interfaze;
1026
1027            try {
1028                mOuterConnection.set(
1029                        mConnService.findConnectionTypeForIface(mOuterInterface));
1030            } catch (Exception e) {
1031                mOuterConnection.set(ConnectivityManager.TYPE_NONE);
1032            }
1033
1034            IntentFilter filter = new IntentFilter();
1035            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
1036            mContext.registerReceiver(mBroadcastReceiver, filter);
1037        }
1038
1039        public void check(String interfaze) {
1040            if (interfaze.equals(mOuterInterface)) {
1041                Log.i(TAG, "Legacy VPN is going down with " + interfaze);
1042                exit();
1043            }
1044        }
1045
1046        public void exit() {
1047            // We assume that everything is reset after stopping the daemons.
1048            interrupt();
1049            for (LocalSocket socket : mSockets) {
1050                IoUtils.closeQuietly(socket);
1051            }
1052            agentDisconnect();
1053            try {
1054                mContext.unregisterReceiver(mBroadcastReceiver);
1055            } catch (IllegalArgumentException e) {}
1056        }
1057
1058        @Override
1059        public void run() {
1060            // Wait for the previous thread since it has been interrupted.
1061            Log.v(TAG, "Waiting");
1062            synchronized (TAG) {
1063                Log.v(TAG, "Executing");
1064                execute();
1065                monitorDaemons();
1066            }
1067        }
1068
1069        private void checkpoint(boolean yield) throws InterruptedException {
1070            long now = SystemClock.elapsedRealtime();
1071            if (mTimer == -1) {
1072                mTimer = now;
1073                Thread.sleep(1);
1074            } else if (now - mTimer <= 60000) {
1075                Thread.sleep(yield ? 200 : 1);
1076            } else {
1077                updateState(DetailedState.FAILED, "checkpoint");
1078                throw new IllegalStateException("Time is up");
1079            }
1080        }
1081
1082        private void execute() {
1083            // Catch all exceptions so we can clean up few things.
1084            boolean initFinished = false;
1085            try {
1086                // Initialize the timer.
1087                checkpoint(false);
1088
1089                // Wait for the daemons to stop.
1090                for (String daemon : mDaemons) {
1091                    while (!SystemService.isStopped(daemon)) {
1092                        checkpoint(true);
1093                    }
1094                }
1095
1096                // Clear the previous state.
1097                File state = new File("/data/misc/vpn/state");
1098                state.delete();
1099                if (state.exists()) {
1100                    throw new IllegalStateException("Cannot delete the state");
1101                }
1102                new File("/data/misc/vpn/abort").delete();
1103                initFinished = true;
1104
1105                // Check if we need to restart any of the daemons.
1106                boolean restart = false;
1107                for (String[] arguments : mArguments) {
1108                    restart = restart || (arguments != null);
1109                }
1110                if (!restart) {
1111                    agentDisconnect();
1112                    return;
1113                }
1114                updateState(DetailedState.CONNECTING, "execute");
1115
1116                // Start the daemon with arguments.
1117                for (int i = 0; i < mDaemons.length; ++i) {
1118                    String[] arguments = mArguments[i];
1119                    if (arguments == null) {
1120                        continue;
1121                    }
1122
1123                    // Start the daemon.
1124                    String daemon = mDaemons[i];
1125                    SystemService.start(daemon);
1126
1127                    // Wait for the daemon to start.
1128                    while (!SystemService.isRunning(daemon)) {
1129                        checkpoint(true);
1130                    }
1131
1132                    // Create the control socket.
1133                    mSockets[i] = new LocalSocket();
1134                    LocalSocketAddress address = new LocalSocketAddress(
1135                            daemon, LocalSocketAddress.Namespace.RESERVED);
1136
1137                    // Wait for the socket to connect.
1138                    while (true) {
1139                        try {
1140                            mSockets[i].connect(address);
1141                            break;
1142                        } catch (Exception e) {
1143                            // ignore
1144                        }
1145                        checkpoint(true);
1146                    }
1147                    mSockets[i].setSoTimeout(500);
1148
1149                    // Send over the arguments.
1150                    OutputStream out = mSockets[i].getOutputStream();
1151                    for (String argument : arguments) {
1152                        byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
1153                        if (bytes.length >= 0xFFFF) {
1154                            throw new IllegalArgumentException("Argument is too large");
1155                        }
1156                        out.write(bytes.length >> 8);
1157                        out.write(bytes.length);
1158                        out.write(bytes);
1159                        checkpoint(false);
1160                    }
1161                    out.write(0xFF);
1162                    out.write(0xFF);
1163                    out.flush();
1164
1165                    // Wait for End-of-File.
1166                    InputStream in = mSockets[i].getInputStream();
1167                    while (true) {
1168                        try {
1169                            if (in.read() == -1) {
1170                                break;
1171                            }
1172                        } catch (Exception e) {
1173                            // ignore
1174                        }
1175                        checkpoint(true);
1176                    }
1177                }
1178
1179                // Wait for the daemons to create the new state.
1180                while (!state.exists()) {
1181                    // Check if a running daemon is dead.
1182                    for (int i = 0; i < mDaemons.length; ++i) {
1183                        String daemon = mDaemons[i];
1184                        if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
1185                            throw new IllegalStateException(daemon + " is dead");
1186                        }
1187                    }
1188                    checkpoint(true);
1189                }
1190
1191                // Now we are connected. Read and parse the new state.
1192                String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
1193                if (parameters.length != 7) {
1194                    throw new IllegalStateException("Cannot parse the state");
1195                }
1196
1197                // Set the interface and the addresses in the config.
1198                mConfig.interfaze = parameters[0].trim();
1199
1200                mConfig.addLegacyAddresses(parameters[1]);
1201                // Set the routes if they are not set in the config.
1202                if (mConfig.routes == null || mConfig.routes.isEmpty()) {
1203                    mConfig.addLegacyRoutes(parameters[2]);
1204                }
1205
1206                // Set the DNS servers if they are not set in the config.
1207                if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
1208                    String dnsServers = parameters[3].trim();
1209                    if (!dnsServers.isEmpty()) {
1210                        mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
1211                    }
1212                }
1213
1214                // Set the search domains if they are not set in the config.
1215                if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) {
1216                    String searchDomains = parameters[4].trim();
1217                    if (!searchDomains.isEmpty()) {
1218                        mConfig.searchDomains = Arrays.asList(searchDomains.split(" "));
1219                    }
1220                }
1221
1222                // Add a throw route for the VPN server endpoint, if one was specified.
1223                String endpoint = parameters[5];
1224                if (!endpoint.isEmpty()) {
1225                    try {
1226                        InetAddress addr = InetAddress.parseNumericAddress(endpoint);
1227                        if (addr instanceof Inet4Address) {
1228                            mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
1229                        } else if (addr instanceof Inet6Address) {
1230                            mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
1231                        } else {
1232                            Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
1233                        }
1234                    } catch (IllegalArgumentException e) {
1235                        Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
1236                    }
1237                }
1238
1239                // Here is the last step and it must be done synchronously.
1240                synchronized (Vpn.this) {
1241                    // Set the start time
1242                    mConfig.startTime = SystemClock.elapsedRealtime();
1243
1244                    // Check if the thread is interrupted while we are waiting.
1245                    checkpoint(false);
1246
1247                    // Check if the interface is gone while we are waiting.
1248                    if (jniCheck(mConfig.interfaze) == 0) {
1249                        throw new IllegalStateException(mConfig.interfaze + " is gone");
1250                    }
1251
1252                    // Now INetworkManagementEventObserver is watching our back.
1253                    mInterface = mConfig.interfaze;
1254                    mVpnUsers = new ArrayList<UidRange>();
1255
1256                    agentConnect();
1257
1258                    Log.i(TAG, "Connected!");
1259                }
1260            } catch (Exception e) {
1261                Log.i(TAG, "Aborting", e);
1262                updateState(DetailedState.FAILED, e.getMessage());
1263                exit();
1264            } finally {
1265                // Kill the daemons if they fail to stop.
1266                if (!initFinished) {
1267                    for (String daemon : mDaemons) {
1268                        SystemService.stop(daemon);
1269                    }
1270                }
1271
1272                // Do not leave an unstable state.
1273                if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) {
1274                    agentDisconnect();
1275                }
1276            }
1277        }
1278
1279        /**
1280         * Monitor the daemons we started, moving to disconnected state if the
1281         * underlying services fail.
1282         */
1283        private void monitorDaemons() {
1284            if (!mNetworkInfo.isConnected()) {
1285                return;
1286            }
1287
1288            try {
1289                while (true) {
1290                    Thread.sleep(2000);
1291                    for (int i = 0; i < mDaemons.length; i++) {
1292                        if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
1293                            return;
1294                        }
1295                    }
1296                }
1297            } catch (InterruptedException e) {
1298                Log.d(TAG, "interrupted during monitorDaemons(); stopping services");
1299            } finally {
1300                for (String daemon : mDaemons) {
1301                    SystemService.stop(daemon);
1302                }
1303
1304                agentDisconnect();
1305            }
1306        }
1307    }
1308}
1309