1 /*
2  * Copyright (C) 2016 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 package com.android.settings.vpn2;
17 
18 import android.content.Context;
19 import android.net.ConnectivityManager;
20 import android.net.IConnectivityManager;
21 import android.os.RemoteException;
22 import android.os.ServiceManager;
23 import android.provider.Settings;
24 import android.security.Credentials;
25 import android.security.KeyStore;
26 import android.util.Log;
27 
28 import com.android.internal.net.LegacyVpnInfo;
29 import com.android.internal.net.VpnConfig;
30 
31 /**
32  * Utility functions for vpn.
33  *
34  * Keystore methods should only be called in system user
35  */
36 public class VpnUtils {
37 
38     private static final String TAG = "VpnUtils";
39 
getLockdownVpn()40     public static String getLockdownVpn() {
41         final byte[] value = KeyStore.getInstance().get(
42             Credentials.LOCKDOWN_VPN, true /* suppressKeyNotFoundWarning */);
43         return value == null ? null : new String(value);
44     }
45 
clearLockdownVpn(Context context)46     public static void clearLockdownVpn(Context context) {
47         KeyStore.getInstance().delete(Credentials.LOCKDOWN_VPN);
48         // Always notify ConnectivityManager after keystore update
49         getConnectivityManager(context).updateLockdownVpn();
50     }
51 
setLockdownVpn(Context context, String lockdownKey)52     public static void setLockdownVpn(Context context, String lockdownKey) {
53         KeyStore.getInstance().put(Credentials.LOCKDOWN_VPN, lockdownKey.getBytes(),
54                 KeyStore.UID_SELF, /* flags */ 0);
55         // Always notify ConnectivityManager after keystore update
56         getConnectivityManager(context).updateLockdownVpn();
57     }
58 
isVpnLockdown(String key)59     public static boolean isVpnLockdown(String key) {
60         return key.equals(getLockdownVpn());
61     }
62 
isAnyLockdownActive(Context context)63     public static boolean isAnyLockdownActive(Context context) {
64         final int userId = context.getUserId();
65         if (getLockdownVpn() != null) {
66             return true;
67         }
68         return getConnectivityManager(context).getAlwaysOnVpnPackageForUser(userId) != null
69                 && Settings.Secure.getIntForUser(context.getContentResolver(),
70                         Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, /* default */ 0, userId) != 0;
71     }
72 
isVpnActive(Context context)73     public static boolean isVpnActive(Context context) throws RemoteException {
74         return getIConnectivityManager().getVpnConfig(context.getUserId()) != null;
75     }
76 
getConnectedPackage(IConnectivityManager service, final int userId)77     public static String getConnectedPackage(IConnectivityManager service, final int userId)
78             throws RemoteException {
79         final VpnConfig config = service.getVpnConfig(userId);
80         return config != null ? config.user : null;
81     }
82 
getConnectivityManager(Context context)83     private static ConnectivityManager getConnectivityManager(Context context) {
84         return context.getSystemService(ConnectivityManager.class);
85     }
86 
getIConnectivityManager()87     private static IConnectivityManager getIConnectivityManager() {
88         return IConnectivityManager.Stub.asInterface(
89                 ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
90     }
91 
isAlwaysOnVpnSet(ConnectivityManager cm, final int userId)92     public static boolean isAlwaysOnVpnSet(ConnectivityManager cm, final int userId) {
93         return cm.getAlwaysOnVpnPackageForUser(userId) != null;
94     }
95 
disconnectLegacyVpn(Context context)96     public static boolean disconnectLegacyVpn(Context context) {
97         try {
98             int userId = context.getUserId();
99             IConnectivityManager connectivityService = getIConnectivityManager();
100             LegacyVpnInfo currentLegacyVpn = connectivityService.getLegacyVpnInfo(userId);
101             if (currentLegacyVpn != null) {
102                 clearLockdownVpn(context);
103                 connectivityService.prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
104                 return true;
105             }
106         } catch (RemoteException e) {
107             Log.e(TAG, "Legacy VPN could not be disconnected", e);
108         }
109         return false;
110     }
111 }
112