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