Skip to content

Commit 69ddab4

Browse files
committed
Always-on VPN.
Adds support for always-on VPN profiles, also called "lockdown." When enabled, LockdownVpnTracker manages the netd firewall to prevent unencrypted traffic from leaving the device. It creates narrow rules to only allow traffic to the selected VPN server. When an egress network becomes available, LockdownVpnTracker will try bringing up the VPN connection, and will reconnect if disconnected. ConnectivityService augments any NetworkInfo based on the lockdown VPN status to help apps wait until the VPN is connected. This feature requires that VPN profiles use an IP address for both VPN server and DNS. It also blocks non-default APN access when enabled. Waits for USER_PRESENT after boot to check KeyStore status. Bug: 5756357 Change-Id: If615f206b1634000d78a8350a17e88bfcac8e0d0
1 parent 080ca09 commit 69ddab4

File tree

11 files changed

+477
-10
lines changed

11 files changed

+477
-10
lines changed

core/java/android/app/NotificationManager.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
package android.app;
1818

1919
import android.content.Context;
20-
import android.os.Binder;
21-
import android.os.RemoteException;
2220
import android.os.Handler;
2321
import android.os.IBinder;
22+
import android.os.RemoteException;
2423
import android.os.ServiceManager;
2524
import android.util.Log;
2625

@@ -88,6 +87,11 @@ static public INotificationManager getService()
8887
mContext = context;
8988
}
9089

90+
/** {@hide} */
91+
public static NotificationManager from(Context context) {
92+
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
93+
}
94+
9195
/**
9296
* Post a notification to be shown in the status bar. If a notification with
9397
* the same id has already been posted by your application and has not yet been canceled, it

core/java/android/net/ConnectivityManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,4 +912,13 @@ public boolean isActiveNetworkMetered() {
912912
return false;
913913
}
914914
}
915+
916+
/** {@hide} */
917+
public boolean updateLockdownVpn() {
918+
try {
919+
return mService.updateLockdownVpn();
920+
} catch (RemoteException e) {
921+
return false;
922+
}
923+
}
915924
}

core/java/android/net/IConnectivityManager.aidl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,6 @@ interface IConnectivityManager
122122
void startLegacyVpn(in VpnProfile profile);
123123

124124
LegacyVpnInfo getLegacyVpnInfo();
125+
126+
boolean updateLockdownVpn();
125127
}

core/java/com/android/internal/net/VpnProfile.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818

1919
import android.os.Parcel;
2020
import android.os.Parcelable;
21+
import android.text.TextUtils;
22+
import android.util.Log;
2123

24+
import java.net.InetAddress;
2225
import java.nio.charset.Charsets;
2326

2427
/**
@@ -31,6 +34,8 @@
3134
* @hide
3235
*/
3336
public class VpnProfile implements Cloneable, Parcelable {
37+
private static final String TAG = "VpnProfile";
38+
3439
// Match these constants with R.array.vpn_types.
3540
public static final int TYPE_PPTP = 0;
3641
public static final int TYPE_L2TP_IPSEC_PSK = 1;
@@ -124,6 +129,32 @@ public byte[] encode() {
124129
return builder.toString().getBytes(Charsets.UTF_8);
125130
}
126131

132+
/**
133+
* Test if profile is valid for lockdown, which requires IPv4 address for
134+
* both server and DNS. Server hostnames would require using DNS before
135+
* connection.
136+
*/
137+
public boolean isValidLockdownProfile() {
138+
try {
139+
InetAddress.parseNumericAddress(server);
140+
141+
for (String dnsServer : dnsServers.split(" +")) {
142+
InetAddress.parseNumericAddress(this.dnsServers);
143+
}
144+
if (TextUtils.isEmpty(dnsServers)) {
145+
Log.w(TAG, "DNS required");
146+
return false;
147+
}
148+
149+
// Everything checked out above
150+
return true;
151+
152+
} catch (IllegalArgumentException e) {
153+
Log.w(TAG, "Invalid address", e);
154+
return false;
155+
}
156+
}
157+
127158
@Override
128159
public void writeToParcel(Parcel out, int flags) {
129160
out.writeString(key);

core/res/res/values/public.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,7 @@
14421442
<java-symbol type="drawable" name="stat_sys_tether_usb" />
14431443
<java-symbol type="drawable" name="stat_sys_throttled" />
14441444
<java-symbol type="drawable" name="vpn_connected" />
1445+
<java-symbol type="drawable" name="vpn_disconnected" />
14451446
<java-symbol type="id" name="ask_checkbox" />
14461447
<java-symbol type="id" name="compat_checkbox" />
14471448
<java-symbol type="id" name="original_app_icon" />
@@ -1557,6 +1558,10 @@
15571558
<java-symbol type="string" name="vpn_text_long" />
15581559
<java-symbol type="string" name="vpn_title" />
15591560
<java-symbol type="string" name="vpn_title_long" />
1561+
<java-symbol type="string" name="vpn_lockdown_connecting" />
1562+
<java-symbol type="string" name="vpn_lockdown_connected" />
1563+
<java-symbol type="string" name="vpn_lockdown_error" />
1564+
<java-symbol type="string" name="vpn_lockdown_reset" />
15601565
<java-symbol type="string" name="wallpaper_binding_label" />
15611566
<java-symbol type="style" name="Theme.Dialog.AppError" />
15621567
<java-symbol type="style" name="Theme.Toast" />

core/res/res/values/strings.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,6 +3272,15 @@
32723272
<!-- The text of the notification when VPN is active with a session name. -->
32733273
<string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Touch to manage the network.</string>
32743274

3275+
<!-- Notification title when connecting to lockdown VPN. -->
3276+
<string name="vpn_lockdown_connecting">Always-on VPN connecting\u2026</string>
3277+
<!-- Notification title when connected to lockdown VPN. -->
3278+
<string name="vpn_lockdown_connected">Always-on VPN connected</string>
3279+
<!-- Notification title when error connecting to lockdown VPN. -->
3280+
<string name="vpn_lockdown_error">Always-on VPN error</string>
3281+
<!-- Notification body that indicates user can touch to cycle lockdown VPN connection. -->
3282+
<string name="vpn_lockdown_reset">Touch to reset connection</string>
3283+
32753284
<!-- Localized strings for WebView -->
32763285
<!-- Label for button in a WebView that will open a chooser to choose a file to upload -->
32773286
<string name="upload_file">Choose file</string>

keystore/java/android/security/Credentials.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public class Credentials {
6161
/** Key prefix for WIFI. */
6262
public static final String WIFI = "WIFI_";
6363

64+
/** Key containing suffix of lockdown VPN profile. */
65+
public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
66+
6467
/** Data type for public keys. */
6568
public static final String EXTRA_PUBLIC_KEY = "KEY";
6669

0 commit comments

Comments
 (0)