PageRenderTime 118ms CodeModel.GetById 51ms app.highlight 56ms RepoModel.GetById 2ms app.codeStats 0ms

/services/java/com/android/server/connectivity/Vpn.java

https://github.com/aizuzi/platform_frameworks_base
Java | 1240 lines | 930 code | 130 blank | 180 comment | 187 complexity | 3eda5165e1d673fe77ff13d7f3148988 MD5 | raw file
   1/*
   2 * Copyright (C) 2011 The Android Open Source Project
   3 *
   4 * Licensed under the Apache License, Version 2.0 (the "License");
   5 * you may not use this file except in compliance with the License.
   6 * You may obtain a copy of the License at
   7 *
   8 *      http://www.apache.org/licenses/LICENSE-2.0
   9 *
  10 * Unless required by applicable law or agreed to in writing, software
  11 * distributed under the License is distributed on an "AS IS" BASIS,
  12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 * See the License for the specific language governing permissions and
  14 * limitations under the License.
  15 */
  16
  17package com.android.server.connectivity;
  18
  19import static android.Manifest.permission.BIND_VPN_SERVICE;
  20
  21import android.app.AppGlobals;
  22import android.app.Notification;
  23import android.app.NotificationManager;
  24import android.app.PendingIntent;
  25import android.content.BroadcastReceiver;
  26import android.content.ComponentName;
  27import android.content.Context;
  28import android.content.Intent;
  29import android.content.IntentFilter;
  30import android.content.ServiceConnection;
  31import android.content.pm.ApplicationInfo;
  32import android.content.pm.IPackageManager;
  33import android.content.pm.PackageManager;
  34import android.content.pm.ResolveInfo;
  35import android.content.pm.UserInfo;
  36import android.graphics.Bitmap;
  37import android.graphics.Canvas;
  38import android.graphics.drawable.Drawable;
  39import android.net.BaseNetworkStateTracker;
  40import android.net.ConnectivityManager;
  41import android.net.IConnectivityManager;
  42import android.net.INetworkManagementEventObserver;
  43import android.net.LinkAddress;
  44import android.net.LinkProperties;
  45import android.net.LocalSocket;
  46import android.net.LocalSocketAddress;
  47import android.net.NetworkInfo;
  48import android.net.NetworkUtils;
  49import android.net.RouteInfo;
  50import android.net.NetworkInfo.DetailedState;
  51import android.os.Binder;
  52import android.os.FileUtils;
  53import android.os.IBinder;
  54import android.os.INetworkManagementService;
  55import android.os.Parcel;
  56import android.os.ParcelFileDescriptor;
  57import android.os.Process;
  58import android.os.RemoteException;
  59import android.os.SystemClock;
  60import android.os.SystemService;
  61import android.os.UserHandle;
  62import android.os.UserManager;
  63import android.security.Credentials;
  64import android.security.KeyStore;
  65import android.util.Log;
  66import android.util.SparseBooleanArray;
  67import android.widget.Toast;
  68
  69import com.android.internal.annotations.GuardedBy;
  70import com.android.internal.R;
  71import com.android.internal.net.LegacyVpnInfo;
  72import com.android.internal.net.VpnConfig;
  73import com.android.internal.net.VpnProfile;
  74import com.android.internal.util.Preconditions;
  75import com.android.server.ConnectivityService.VpnCallback;
  76import com.android.server.net.BaseNetworkObserver;
  77
  78import java.io.File;
  79import java.io.InputStream;
  80import java.io.OutputStream;
  81import java.net.InetAddress;
  82import java.net.Inet4Address;
  83import java.net.InetAddress;
  84import java.nio.charset.StandardCharsets;
  85import java.util.Arrays;
  86import java.util.List;
  87import java.util.concurrent.atomic.AtomicInteger;
  88
  89import libcore.io.IoUtils;
  90
  91/**
  92 * @hide
  93 */
  94public 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 VPN dialogs are also allowed to control VPN.
 637            PackageManager pm = mContext.getPackageManager();
 638            ApplicationInfo app = pm.getApplicationInfo(VpnConfig.DIALOGS_PACKAGE, 0);
 639            if (((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (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}