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