summaryrefslogtreecommitdiff
path: root/services/java/com/android/server/ConnectivityService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/ConnectivityService.java')
-rw-r--r--services/java/com/android/server/ConnectivityService.java131
1 files changed, 124 insertions, 7 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3c2ab163acbb..776a1a48e1bb 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
@@ -31,13 +32,13 @@ import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.bluetooth.BluetoothTetheringDataTracker;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -80,6 +81,7 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
+import android.security.Credentials;
import android.security.KeyStore;
import android.text.TextUtils;
import android.util.EventLog;
@@ -91,11 +93,11 @@ import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.util.Preconditions;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
+import com.android.server.net.LockdownVpnTracker;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -142,11 +144,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private Tethering mTethering;
private boolean mTetheringConfigValid = false;
- private final KeyStore mKeyStore;
+ private KeyStore mKeyStore;
private Vpn mVpn;
private VpnCallback mVpnCallback = new VpnCallback();
+ private boolean mLockdownEnabled;
+ private LockdownVpnTracker mLockdownTracker;
+
/** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
private Object mRulesLock = new Object();
/** Currently active network rules by UID. */
@@ -276,6 +281,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
private static final int EVENT_SET_POLICY_DATA_ENABLE = 13;
+ private static final int EVENT_VPN_STATE_CHANGED = 14;
+
/** Handler used for internal events. */
private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -786,6 +793,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
}
+ if (mLockdownTracker != null) {
+ info = mLockdownTracker.augmentNetworkInfo(info);
+ }
return info;
}
@@ -803,6 +813,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return getNetworkInfo(mActiveDefaultNetwork, uid);
}
+ public NetworkInfo getActiveNetworkInfoUnfiltered() {
+ enforceAccessPermission();
+ if (isNetworkTypeValid(mActiveDefaultNetwork)) {
+ final NetworkStateTracker tracker = mNetTrackers[mActiveDefaultNetwork];
+ if (tracker != null) {
+ return tracker.getNetworkInfo();
+ }
+ }
+ return null;
+ }
+
@Override
public NetworkInfo getActiveNetworkInfoForUid(int uid) {
enforceConnectivityInternalPermission();
@@ -1062,6 +1083,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// TODO - move this into individual networktrackers
int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
+ if (mLockdownEnabled) {
+ // Since carrier APNs usually aren't available from VPN
+ // endpoint, mark them as unavailable.
+ return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
+ }
+
if (mProtectedNetworks.contains(usedNetworkType)) {
enforceConnectivityInternalPermission();
}
@@ -1769,7 +1796,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
- private void sendConnectedBroadcast(NetworkInfo info) {
+ public void sendConnectedBroadcast(NetworkInfo info) {
sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
}
@@ -1784,6 +1811,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
+ if (mLockdownTracker != null) {
+ info = mLockdownTracker.augmentNetworkInfo(info);
+ }
+
Intent intent = new Intent(bcastType);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
@@ -1915,8 +1946,26 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
// load the global proxy at startup
mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
+
+ // Try bringing up tracker, but if KeyStore isn't ready yet, wait
+ // for user to unlock device.
+ if (!updateLockdownVpn()) {
+ final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
+ mContext.registerReceiver(mUserPresentReceiver, filter);
+ }
}
+ private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Try creating lockdown tracker, since user present usually means
+ // unlocked keystore.
+ if (updateLockdownVpn()) {
+ mContext.unregisterReceiver(this);
+ }
+ }
+ };
+
private void handleConnect(NetworkInfo info) {
final int type = info.getType();
@@ -2595,6 +2644,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} else if (state == NetworkInfo.State.CONNECTED) {
handleConnect(info);
}
+ if (mLockdownTracker != null) {
+ mLockdownTracker.onNetworkInfoChanged(info);
+ }
break;
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
info = (NetworkInfo) msg.obj;
@@ -2692,6 +2744,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
final int networkType = msg.arg1;
final boolean enabled = msg.arg2 == ENABLED;
handleSetPolicyDataEnable(networkType, enabled);
+ break;
+ }
+ case EVENT_VPN_STATE_CHANGED: {
+ if (mLockdownTracker != null) {
+ mLockdownTracker.onVpnStateChanged((NetworkInfo) msg.obj);
+ }
+ break;
}
}
}
@@ -3090,6 +3149,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
@Override
public boolean protectVpn(ParcelFileDescriptor socket) {
+ throwIfLockdownEnabled();
try {
int type = mActiveDefaultNetwork;
if (ConnectivityManager.isNetworkTypeValid(type)) {
@@ -3116,6 +3176,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
@Override
public boolean prepareVpn(String oldPackage, String newPackage) {
+ throwIfLockdownEnabled();
return mVpn.prepare(oldPackage, newPackage);
}
@@ -3128,6 +3189,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
@Override
public ParcelFileDescriptor establishVpn(VpnConfig config) {
+ throwIfLockdownEnabled();
return mVpn.establish(config);
}
@@ -3137,6 +3199,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
@Override
public void startLegacyVpn(VpnProfile profile) {
+ throwIfLockdownEnabled();
final LinkProperties egress = getActiveLinkProperties();
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
@@ -3152,6 +3215,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
@Override
public LegacyVpnInfo getLegacyVpnInfo() {
+ throwIfLockdownEnabled();
return mVpn.getLegacyVpnInfo();
}
@@ -3170,8 +3234,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
public void onStateChanged(NetworkInfo info) {
- // TODO: if connected, release delayed broadcast
- // TODO: if disconnected, consider kicking off reconnect
+ mHandler.obtainMessage(EVENT_VPN_STATE_CHANGED, info).sendToTarget();
}
public void override(List<String> dnsServers, List<String> searchDomains) {
@@ -3240,4 +3303,58 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
}
+
+ @Override
+ public boolean updateLockdownVpn() {
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
+ // Tear down existing lockdown if profile was removed
+ mLockdownEnabled = LockdownVpnTracker.isEnabled();
+ if (mLockdownEnabled) {
+ if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
+ Slog.w(TAG, "KeyStore locked; unable to create LockdownTracker");
+ return false;
+ }
+
+ final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
+ final VpnProfile profile = VpnProfile.decode(
+ profileName, mKeyStore.get(Credentials.VPN + profileName));
+ setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpn, profile));
+ } else {
+ setLockdownTracker(null);
+ }
+
+ return true;
+ }
+
+ /**
+ * Internally set new {@link LockdownVpnTracker}, shutting down any existing
+ * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
+ */
+ private void setLockdownTracker(LockdownVpnTracker tracker) {
+ // Shutdown any existing tracker
+ final LockdownVpnTracker existing = mLockdownTracker;
+ mLockdownTracker = null;
+ if (existing != null) {
+ existing.shutdown();
+ }
+
+ try {
+ if (tracker != null) {
+ mNetd.setFirewallEnabled(true);
+ mLockdownTracker = tracker;
+ mLockdownTracker.init();
+ } else {
+ mNetd.setFirewallEnabled(false);
+ }
+ } catch (RemoteException e) {
+ // ignored; NMS lives inside system_server
+ }
+ }
+
+ private void throwIfLockdownEnabled() {
+ if (mLockdownEnabled) {
+ throw new IllegalStateException("Unavailable in lockdown mode");
+ }
+ }
}