169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey/* 269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Copyright (C) 2012 The Android Open Source Project 369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * 469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * you may not use this file except in compliance with the License. 669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * You may obtain a copy of the License at 769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * 869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * 1069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 1169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * See the License for the specific language governing permissions and 1469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * limitations under the License. 1569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey */ 1669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeypackage com.android.server.net; 1869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL; 2069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 2169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.app.Notification; 2269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.app.NotificationManager; 2369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.app.PendingIntent; 2469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.BroadcastReceiver; 2569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.Context; 2669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.Intent; 2769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.IntentFilter; 280cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colittiimport android.net.ConnectivityManager; 2969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.LinkProperties; 304ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubakerimport android.net.LinkAddress; 3169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.NetworkInfo; 3269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.NetworkInfo.DetailedState; 3369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.NetworkInfo.State; 3469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.os.INetworkManagementService; 3569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.os.RemoteException; 3669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.security.Credentials; 3769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.security.KeyStore; 38ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colittiimport android.system.Os; 3969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.text.TextUtils; 4069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.util.Slog; 4169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 4269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.R; 4369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.net.VpnConfig; 4469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.net.VpnProfile; 4569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.util.Preconditions; 4669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.server.ConnectivityService; 4791c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkeyimport com.android.server.EventLogTags; 4869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.server.connectivity.Vpn; 4969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 504ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubakerimport java.util.List; 514ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker 5269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey/** 5369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be 5469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * connected and kicks off VPN connection, managing any required {@code netd} 5569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * firewall rules. 5669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey */ 5769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeypublic class LockdownVpnTracker { 5869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private static final String TAG = "LockdownVpnTracker"; 5969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 6069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey /** Number of VPN attempts before waiting for user intervention. */ 6169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private static final int MAX_ERROR_COUNT = 4; 6269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 6369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private static final String ACTION_LOCKDOWN_RESET = "com.android.server.action.LOCKDOWN_RESET"; 644fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey 65580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS"; 664fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey private static final String EXTRA_PICK_LOCKDOWN = "android.net.vpn.PICK_LOCKDOWN"; 6769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 68ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti private static final int ROOT_UID = 0; 69ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti 7069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final Context mContext; 7169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final INetworkManagementService mNetService; 7269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final ConnectivityService mConnService; 7369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final Vpn mVpn; 7469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final VpnProfile mProfile; 7569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 7669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final Object mStateLock = new Object(); 7769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 784fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey private final PendingIntent mConfigIntent; 794fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey private final PendingIntent mResetIntent; 8069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 8169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private String mAcceptedEgressIface; 8269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private String mAcceptedIface; 834ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker private List<LinkAddress> mAcceptedSourceAddr; 8469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 8569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private int mErrorCount; 8669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 8769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public static boolean isEnabled() { 8869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey return KeyStore.getInstance().contains(Credentials.LOCKDOWN_VPN); 8969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 9069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 9169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public LockdownVpnTracker(Context context, INetworkManagementService netService, 9269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey ConnectivityService connService, Vpn vpn, VpnProfile profile) { 9369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mContext = Preconditions.checkNotNull(context); 9469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService = Preconditions.checkNotNull(netService); 9569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mConnService = Preconditions.checkNotNull(connService); 9669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mVpn = Preconditions.checkNotNull(vpn); 9769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mProfile = Preconditions.checkNotNull(profile); 9869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 994fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey final Intent configIntent = new Intent(ACTION_VPN_SETTINGS); 1004fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey configIntent.putExtra(EXTRA_PICK_LOCKDOWN, true); 1014fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0); 1024fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey 103580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey final Intent resetIntent = new Intent(ACTION_LOCKDOWN_RESET); 104580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey resetIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 105580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey mResetIntent = PendingIntent.getBroadcast(mContext, 0, resetIntent, 0); 10669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 10769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 10869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private BroadcastReceiver mResetReceiver = new BroadcastReceiver() { 10969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey @Override 11069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void onReceive(Context context, Intent intent) { 11169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey reset(); 11269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 11369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey }; 11469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 11569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey /** 11669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Watch for state changes to both active egress network, kicking off a VPN 11769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * connection when ready, or setting firewall rules once VPN is connected. 11869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey */ 11969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private void handleStateChangedLocked() { 12069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 12169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final NetworkInfo egressInfo = mConnService.getActiveNetworkInfoUnfiltered(); 12269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final LinkProperties egressProp = mConnService.getActiveLinkProperties(); 12369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 12469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final NetworkInfo vpnInfo = mVpn.getNetworkInfo(); 12569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final VpnConfig vpnConfig = mVpn.getLegacyVpnConfig(); 12669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 12769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey // Restart VPN when egress network disconnected or changed 12869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final boolean egressDisconnected = egressInfo == null 12969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey || State.DISCONNECTED.equals(egressInfo.getState()); 13069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final boolean egressChanged = egressProp == null 13169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey || !TextUtils.equals(mAcceptedEgressIface, egressProp.getInterfaceName()); 1320cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti 1330cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti final String egressTypeName = (egressInfo == null) ? 1340cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti null : ConnectivityManager.getNetworkTypeName(egressInfo.getType()); 1350cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti final String egressIface = (egressProp == null) ? 1360cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti null : egressProp.getInterfaceName(); 1370cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti Slog.d(TAG, "handleStateChanged: egress=" + egressTypeName + 1380cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti " " + mAcceptedEgressIface + "->" + egressIface); 1390cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti 14069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (egressDisconnected || egressChanged) { 141580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey clearSourceRulesLocked(); 14269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedEgressIface = null; 143b21298a686b04d55ff97223dd317497845713f4bJeff Davidson mVpn.stopLegacyVpnPrivileged(); 14469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 14557666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey if (egressDisconnected) { 14657666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey hideNotification(); 14757666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey return; 14857666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey } 14969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 15091c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey final int egressType = egressInfo.getType(); 15191c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey if (vpnInfo.getDetailedState() == DetailedState.FAILED) { 15291c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey EventLogTags.writeLockdownVpnError(egressType); 15391c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey } 15491c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey 15569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (mErrorCount > MAX_ERROR_COUNT) { 15669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); 15769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 15869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } else if (egressInfo.isConnected() && !vpnInfo.isConnectedOrConnecting()) { 15969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (mProfile.isValidLockdownProfile()) { 16069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey Slog.d(TAG, "Active network connected; starting VPN"); 16191c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey EventLogTags.writeLockdownVpnConnecting(egressType); 16269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected); 16369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 16469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedEgressIface = egressProp.getInterfaceName(); 165421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey try { 166b21298a686b04d55ff97223dd317497845713f4bJeff Davidson // Use the privileged method because Lockdown VPN is initiated by the system, so 167b21298a686b04d55ff97223dd317497845713f4bJeff Davidson // no additional permission checks are necessary. 168b21298a686b04d55ff97223dd317497845713f4bJeff Davidson mVpn.startLegacyVpnPrivileged(mProfile, KeyStore.getInstance(), egressProp); 169421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey } catch (IllegalStateException e) { 170421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey mAcceptedEgressIface = null; 171421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey Slog.e(TAG, "Failed to start VPN", e); 172421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); 173421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey } 17469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } else { 17569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey Slog.e(TAG, "Invalid VPN profile; requires IP-based server and DNS"); 17669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); 17769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 17869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 17969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } else if (vpnInfo.isConnected() && vpnConfig != null) { 18069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final String iface = vpnConfig.interfaze; 1814ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker final List<LinkAddress> sourceAddrs = vpnConfig.addresses; 18269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 18369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (TextUtils.equals(iface, mAcceptedIface) 1844ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker && sourceAddrs.equals(mAcceptedSourceAddr)) { 18569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey return; 18669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 18769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1884ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker Slog.d(TAG, "VPN connected using iface=" + iface + 1894ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker ", sourceAddr=" + sourceAddrs.toString()); 19091c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey EventLogTags.writeLockdownVpnConnected(egressType); 19169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected); 19269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 19369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey try { 194580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey clearSourceRulesLocked(); 19569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 19669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService.setFirewallInterfaceRule(iface, true); 1974ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker for (LinkAddress addr : sourceAddrs) { 19802c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti setFirewallEgressSourceRule(addr, true); 1994ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker } 20069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 201ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti mNetService.setFirewallUidRule(ROOT_UID, true); 202ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti mNetService.setFirewallUidRule(Os.getuid(), true); 203ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti 20469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mErrorCount = 0; 20569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedIface = iface; 2064ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker mAcceptedSourceAddr = sourceAddrs; 20769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } catch (RemoteException e) { 20869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey throw new RuntimeException("Problem setting firewall rules", e); 20969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 21069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 21169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mConnService.sendConnectedBroadcast(augmentNetworkInfo(egressInfo)); 21269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 21369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 21469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 21569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void init() { 216580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey synchronized (mStateLock) { 217580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey initLocked(); 218580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 219580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 220580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey 221580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey private void initLocked() { 222580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey Slog.d(TAG, "initLocked()"); 22369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 22457666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey mVpn.setEnableTeardown(false); 22569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 22669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET); 22769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, null); 22869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 22969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey try { 23069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey // TODO: support non-standard port numbers 23169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService.setFirewallEgressDestRule(mProfile.server, 500, true); 23269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService.setFirewallEgressDestRule(mProfile.server, 4500, true); 23342c0c9f35a8efa71703f810ce2bff6d86bb5b30eJeff Sharkey mNetService.setFirewallEgressDestRule(mProfile.server, 1701, true); 23469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } catch (RemoteException e) { 23569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey throw new RuntimeException("Problem setting firewall rules", e); 23669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 23769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 23869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 23969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 24069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 24169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 24269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 24369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void shutdown() { 244580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey synchronized (mStateLock) { 245580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey shutdownLocked(); 246580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 247580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 248580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey 249580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey private void shutdownLocked() { 250580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey Slog.d(TAG, "shutdownLocked()"); 25169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 25269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedEgressIface = null; 25369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mErrorCount = 0; 25469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 255b21298a686b04d55ff97223dd317497845713f4bJeff Davidson mVpn.stopLegacyVpnPrivileged(); 25669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey try { 25769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService.setFirewallEgressDestRule(mProfile.server, 500, false); 25869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService.setFirewallEgressDestRule(mProfile.server, 4500, false); 25942c0c9f35a8efa71703f810ce2bff6d86bb5b30eJeff Sharkey mNetService.setFirewallEgressDestRule(mProfile.server, 1701, false); 26069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } catch (RemoteException e) { 26169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey throw new RuntimeException("Problem setting firewall rules", e); 26269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 263580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey clearSourceRulesLocked(); 26469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey hideNotification(); 26569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 26669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mContext.unregisterReceiver(mResetReceiver); 26757666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey mVpn.setEnableTeardown(true); 26869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 26969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 27069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void reset() { 2710cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti Slog.d(TAG, "reset()"); 27269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 273580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey // cycle tracker, reset error count, and trigger retry 274580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey shutdownLocked(); 275580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey initLocked(); 27669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 27769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 27869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 27969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 280580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey private void clearSourceRulesLocked() { 28169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey try { 28269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (mAcceptedIface != null) { 28369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService.setFirewallInterfaceRule(mAcceptedIface, false); 28469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedIface = null; 28569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 28669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (mAcceptedSourceAddr != null) { 2874ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker for (LinkAddress addr : mAcceptedSourceAddr) { 28802c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti setFirewallEgressSourceRule(addr, false); 2894ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker } 290ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti 291ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti mNetService.setFirewallUidRule(ROOT_UID, false); 292ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti mNetService.setFirewallUidRule(Os.getuid(), false); 293ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti 29469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedSourceAddr = null; 29569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 29669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } catch (RemoteException e) { 29769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey throw new RuntimeException("Problem setting firewall rules", e); 29869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 29969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 30069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 30102c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti private void setFirewallEgressSourceRule( 30202c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti LinkAddress address, boolean allow) throws RemoteException { 30302c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti // Our source address based firewall rules must only cover our own source address, not the 30402c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti // whole subnet 30502c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti final String addrString = address.getAddress().getHostAddress(); 30602c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti mNetService.setFirewallEgressSourceRule(addrString, allow); 30702c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti } 30802c7abac856c3e94f4a2714d673cefb65c55efb7Lorenzo Colitti 3090cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti public void onNetworkInfoChanged() { 31069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 31169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 31269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 31369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 31469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 31569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void onVpnStateChanged(NetworkInfo info) { 31669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (info.getDetailedState() == DetailedState.FAILED) { 31769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mErrorCount++; 31869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 31969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 32069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 32169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 32269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 32369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 32469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public NetworkInfo augmentNetworkInfo(NetworkInfo info) { 3250b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey if (info.isConnected()) { 3260b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey final NetworkInfo vpnInfo = mVpn.getNetworkInfo(); 3270b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey info = new NetworkInfo(info); 3280b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey info.setDetailedState(vpnInfo.getDetailedState(), vpnInfo.getReason(), null); 3290b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey } 33069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey return info; 33169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 33269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 33369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private void showNotification(int titleRes, int iconRes) { 334255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek final Notification.Builder builder = new Notification.Builder(mContext) 335255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setWhen(0) 336255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setSmallIcon(iconRes) 337255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setContentTitle(mContext.getString(titleRes)) 338255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setContentText(mContext.getString(R.string.vpn_lockdown_config)) 339255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setContentIntent(mConfigIntent) 340255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setPriority(Notification.PRIORITY_LOW) 341255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setOngoing(true) 342255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset), 343255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek mResetIntent) 344255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setColor(mContext.getResources().getColor( 345255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek com.android.internal.R.color.system_notification_accent_color)); 3464fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey 34769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey NotificationManager.from(mContext).notify(TAG, 0, builder.build()); 34869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 34969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 35069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private void hideNotification() { 35169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey NotificationManager.from(mContext).cancel(TAG, 0); 35269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 35369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey} 354