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