use of com.android.internal.net.VpnConfig in project android_frameworks_base by ParanoidAndroid.
the class LockdownVpnTracker method handleStateChangedLocked.
/**
* Watch for state changes to both active egress network, kicking off a VPN
* connection when ready, or setting firewall rules once VPN is connected.
*/
private void handleStateChangedLocked() {
Slog.d(TAG, "handleStateChanged()");
final NetworkInfo egressInfo = mConnService.getActiveNetworkInfoUnfiltered();
final LinkProperties egressProp = mConnService.getActiveLinkProperties();
final NetworkInfo vpnInfo = mVpn.getNetworkInfo();
final VpnConfig vpnConfig = mVpn.getLegacyVpnConfig();
// Restart VPN when egress network disconnected or changed
final boolean egressDisconnected = egressInfo == null || State.DISCONNECTED.equals(egressInfo.getState());
final boolean egressChanged = egressProp == null || !TextUtils.equals(mAcceptedEgressIface, egressProp.getInterfaceName());
if (egressDisconnected || egressChanged) {
clearSourceRulesLocked();
mAcceptedEgressIface = null;
mVpn.stopLegacyVpn();
}
if (egressDisconnected) {
hideNotification();
return;
}
final int egressType = egressInfo.getType();
if (vpnInfo.getDetailedState() == DetailedState.FAILED) {
EventLogTags.writeLockdownVpnError(egressType);
}
if (mErrorCount > MAX_ERROR_COUNT) {
showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected);
} else if (egressInfo.isConnected() && !vpnInfo.isConnectedOrConnecting()) {
if (mProfile.isValidLockdownProfile()) {
Slog.d(TAG, "Active network connected; starting VPN");
EventLogTags.writeLockdownVpnConnecting(egressType);
showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected);
mAcceptedEgressIface = egressProp.getInterfaceName();
mVpn.startLegacyVpn(mProfile, KeyStore.getInstance(), egressProp);
} else {
Slog.e(TAG, "Invalid VPN profile; requires IP-based server and DNS");
showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected);
}
} else if (vpnInfo.isConnected() && vpnConfig != null) {
final String iface = vpnConfig.interfaze;
final String sourceAddr = vpnConfig.addresses;
if (TextUtils.equals(iface, mAcceptedIface) && TextUtils.equals(sourceAddr, mAcceptedSourceAddr)) {
return;
}
Slog.d(TAG, "VPN connected using iface=" + iface + ", sourceAddr=" + sourceAddr);
EventLogTags.writeLockdownVpnConnected(egressType);
showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected);
try {
clearSourceRulesLocked();
mNetService.setFirewallInterfaceRule(iface, true);
mNetService.setFirewallEgressSourceRule(sourceAddr, true);
mErrorCount = 0;
mAcceptedIface = iface;
mAcceptedSourceAddr = sourceAddr;
} catch (RemoteException e) {
throw new RuntimeException("Problem setting firewall rules", e);
}
mConnService.sendConnectedBroadcast(augmentNetworkInfo(egressInfo));
}
}
use of com.android.internal.net.VpnConfig in project platform_frameworks_base by android.
the class ConnectivityService method factoryReset.
@Override
public void factoryReset() {
enforceConnectivityInternalPermission();
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
return;
}
final int userId = UserHandle.getCallingUserId();
// Turn airplane mode off
setAirplaneMode(false);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
// Untether
for (String tether : getTetheredIfaces()) {
untether(tether);
}
}
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
// Remove always-on package
synchronized (mVpns) {
final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
if (alwaysOnPackage != null) {
setAlwaysOnVpnPackage(userId, null, false);
setVpnPackageAuthorization(alwaysOnPackage, userId, false);
}
}
// Turn Always-on VPN off
if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
final long ident = Binder.clearCallingIdentity();
try {
mKeyStore.delete(Credentials.LOCKDOWN_VPN);
mLockdownEnabled = false;
setLockdownTracker(null);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
// Turn VPN off
VpnConfig vpnConfig = getVpnConfig(userId);
if (vpnConfig != null) {
if (vpnConfig.legacy) {
prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
} else {
// Prevent this app (packagename = vpnConfig.user) from initiating VPN connections
// in the future without user intervention.
setVpnPackageAuthorization(vpnConfig.user, userId, false);
prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
}
}
}
Settings.Global.putString(mContext.getContentResolver(), Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
}
use of com.android.internal.net.VpnConfig in project platform_frameworks_base by android.
the class SecurityControllerImpl method updateState.
private void updateState() {
// Find all users with an active VPN
SparseArray<VpnConfig> vpns = new SparseArray<>();
try {
for (UserInfo user : mUserManager.getUsers()) {
VpnConfig cfg = mConnectivityManagerService.getVpnConfig(user.id);
if (cfg == null) {
continue;
} else if (cfg.legacy) {
// Legacy VPNs should do nothing if the network is disconnected. Third-party
// VPN warnings need to continue as traffic can still go to the app.
LegacyVpnInfo legacyVpn = mConnectivityManagerService.getLegacyVpnInfo(user.id);
if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) {
continue;
}
}
vpns.put(user.id, cfg);
}
} catch (RemoteException rme) {
// Roll back to previous state
Log.e(TAG, "Unable to list active VPNs", rme);
return;
}
mCurrentVpns = vpns;
}
use of com.android.internal.net.VpnConfig in project platform_frameworks_base by android.
the class SecurityControllerImpl method isVpnBranded.
@Override
public boolean isVpnBranded() {
VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
if (cfg == null) {
return false;
}
String packageName = getPackageNameForVpnConfig(cfg);
if (packageName == null) {
return false;
}
return isVpnPackageBranded(packageName);
}
use of com.android.internal.net.VpnConfig in project platform_frameworks_base by android.
the class Vpn method establish.
/**
* Establish a VPN network and return the file descriptor of the VPN
* interface. This methods returns {@code null} if the application is
* revoked or not prepared.
*
* @param config The parameters to configure the network.
* @return The file descriptor of the VPN interface.
*/
public synchronized ParcelFileDescriptor establish(VpnConfig config) {
// Check if the caller is already prepared.
UserManager mgr = UserManager.get(mContext);
if (Binder.getCallingUid() != mOwnerUID) {
return null;
}
// Check to ensure consent hasn't been revoked since we were prepared.
if (!isVpnUserPreConsented(mPackage)) {
return null;
}
// Check if the service is properly declared.
Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
intent.setClassName(mPackage, config.user);
long token = Binder.clearCallingIdentity();
try {
// Restricted users are not allowed to create VPNs, they are tied to Owner
UserInfo user = mgr.getUserInfo(mUserHandle);
if (user.isRestricted()) {
throw new SecurityException("Restricted users cannot establish VPNs");
}
ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent, null, 0, mUserHandle);
if (info == null) {
throw new SecurityException("Cannot find " + config.user);
}
if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
}
} catch (RemoteException e) {
throw new SecurityException("Cannot find " + config.user);
} finally {
Binder.restoreCallingIdentity(token);
}
// Save the old config in case we need to go back.
VpnConfig oldConfig = mConfig;
String oldInterface = mInterface;
Connection oldConnection = mConnection;
NetworkAgent oldNetworkAgent = mNetworkAgent;
mNetworkAgent = null;
Set<UidRange> oldUsers = mVpnUsers;
// Configure the interface. Abort if any of these steps fails.
ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
try {
updateState(DetailedState.CONNECTING, "establish");
String interfaze = jniGetName(tun.getFd());
// TEMP use the old jni calls until there is support for netd address setting
StringBuilder builder = new StringBuilder();
for (LinkAddress address : config.addresses) {
builder.append(" " + address);
}
if (jniSetAddresses(interfaze, builder.toString()) < 1) {
throw new IllegalArgumentException("At least one address must be specified");
}
Connection connection = new Connection();
if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUserHandle))) {
throw new IllegalStateException("Cannot bind " + config.user);
}
mConnection = connection;
mInterface = interfaze;
// Fill more values.
config.user = mPackage;
config.interfaze = mInterface;
config.startTime = SystemClock.elapsedRealtime();
mConfig = config;
// Set up forwarding and DNS rules.
agentConnect();
if (oldConnection != null) {
mContext.unbindService(oldConnection);
}
// Remove the old tun's user forwarding rules
// The new tun's user rules have already been added so they will take over
// as rules are deleted. This prevents data leakage as the rules are moved over.
agentDisconnect(oldNetworkAgent);
if (oldInterface != null && !oldInterface.equals(interfaze)) {
jniReset(oldInterface);
}
try {
IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
} catch (IOException e) {
throw new IllegalStateException("Cannot set tunnel's fd as blocking=" + config.blocking, e);
}
} catch (RuntimeException e) {
IoUtils.closeQuietly(tun);
agentDisconnect();
// restore old state
mConfig = oldConfig;
mConnection = oldConnection;
mVpnUsers = oldUsers;
mNetworkAgent = oldNetworkAgent;
mInterface = oldInterface;
throw e;
}
Log.i(TAG, "Established by " + config.user + " on " + mInterface);
return tun;
}
Aggregations