Loading core/java/android/net/IConnectivityManager.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -106,13 +106,13 @@ interface IConnectivityManager ProxyInfo getDefaultProxy(); boolean prepareVpn(String oldPackage, String newPackage); boolean prepareVpn(String oldPackage, String newPackage, int userId); void setVpnPackageAuthorization(boolean authorized); void setVpnPackageAuthorization(String packageName, int userId, boolean authorized); ParcelFileDescriptor establishVpn(in VpnConfig config); VpnConfig getVpnConfig(); VpnConfig getVpnConfig(int userId); void startLegacyVpn(in VpnProfile profile); Loading core/java/android/net/VpnService.java +5 −4 Original line number Diff line number Diff line Loading @@ -156,7 +156,7 @@ public class VpnService extends Service { */ public static Intent prepare(Context context) { try { if (getService().prepareVpn(context.getPackageName(), null)) { if (getService().prepareVpn(context.getPackageName(), null, UserHandle.myUserId())) { return null; } } catch (RemoteException e) { Loading @@ -182,10 +182,11 @@ public class VpnService extends Service { String packageName = context.getPackageName(); try { // Only prepare if we're not already prepared. if (!cm.prepareVpn(packageName, null)) { cm.prepareVpn(null, packageName); int userId = UserHandle.myUserId(); if (!cm.prepareVpn(packageName, null, userId)) { cm.prepareVpn(null, packageName, userId); } cm.setVpnPackageAuthorization(true); cm.setVpnPackageAuthorization(packageName, userId, true); } catch (RemoteException e) { // ignore } Loading packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +4 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.net.IConnectivityManager; import android.os.ServiceManager; import android.os.UserHandle; import android.text.Html; import android.text.Html.ImageGetter; import android.util.Log; Loading Loading @@ -50,7 +51,7 @@ public class ConfirmDialog extends AlertActivity mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); if (mService.prepareVpn(mPackage, null)) { if (mService.prepareVpn(mPackage, null, UserHandle.myUserId())) { setResult(RESULT_OK); finish(); return; Loading Loading @@ -94,10 +95,10 @@ public class ConfirmDialog extends AlertActivity @Override public void onClick(DialogInterface dialog, int which) { try { if (mService.prepareVpn(null, mPackage)) { if (mService.prepareVpn(null, mPackage, UserHandle.myUserId())) { // Authorize this app to initiate VPN connections in the future without user // intervention. mService.setVpnPackageAuthorization(true); mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true); setResult(RESULT_OK); } } catch (Exception e) { Loading packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java +5 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.os.Handler; import android.os.Message; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.util.Log; import android.view.View; import android.widget.TextView; Loading Loading @@ -63,7 +64,7 @@ public class ManageDialog extends AlertActivity implements mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); mConfig = mService.getVpnConfig(); mConfig = mService.getVpnConfig(UserHandle.myUserId()); // mConfig can be null if we are a restricted user, in that case don't show this dialog if (mConfig == null) { Loading Loading @@ -120,10 +121,11 @@ public class ManageDialog extends AlertActivity implements if (which == DialogInterface.BUTTON_POSITIVE) { mConfig.configureIntent.send(); } else if (which == DialogInterface.BUTTON_NEUTRAL) { final int myUserId = UserHandle.myUserId(); if (mConfig.legacy) { mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, myUserId); } else { mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN); mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN, myUserId); } } } catch (Exception e) { Loading services/core/java/com/android/server/ConnectivityService.java +58 −21 Original line number Diff line number Diff line Loading @@ -1410,6 +1410,22 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; /** * Require that the caller is either in the same user or has appropriate permission to interact * across users. * * @param userId Target user for whatever operation the current IPC is supposed to perform. */ private void enforceCrossUserPermission(int userId) { if (userId == UserHandle.getCallingUserId()) { // Not a cross-user call. return; } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "ConnectivityService"); } private void enforceInternetPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERNET, Loading Loading @@ -2945,29 +2961,48 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * Prepare for a VPN application. * Permissions are checked in Vpn class. * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. * * @param oldPackage Package name of the application which currently controls VPN, which will * be replaced. If there is no such application, this should should either be * {@code null} or {@link VpnConfig.LEGACY_VPN}. * @param newPackage Package name of the application which should gain control of VPN, or * {@code null} to disable. * @param userId User for whom to prepare the new VPN. * * @hide */ @Override public boolean prepareVpn(String oldPackage, String newPackage) { public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, int userId) { enforceCrossUserPermission(userId); throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized(mVpns) { return mVpns.get(user).prepare(oldPackage, newPackage); return mVpns.get(userId).prepare(oldPackage, newPackage); } } /** * Set whether the current VPN package has the ability to launch VPNs without * user intervention. This method is used by system-privileged apps. * Permissions are checked in Vpn class. * Set whether the VPN package has the ability to launch VPNs without user intervention. * This method is used by system-privileged apps. * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. * * @param packageName The package for which authorization state should change. * @param userId User for whom {@code packageName} is installed. * @param authorized {@code true} if this app should be able to start a VPN connection without * explicit user approval, {@code false} if not. * * @hide */ @Override public void setVpnPackageAuthorization(boolean authorized) { int user = UserHandle.getUserId(Binder.getCallingUid()); public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) { enforceCrossUserPermission(userId); synchronized(mVpns) { mVpns.get(user).setPackageAuthorization(authorized); mVpns.get(userId).setPackageAuthorization(packageName, authorized); } } Loading Loading @@ -3069,16 +3104,16 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** * Returns the information of the ongoing VPN. This method is used by VpnDialogs and * not available in ConnectivityManager. * Returns the information of the ongoing VPN for {@code userId}. This method is used by * VpnDialogs and not available in ConnectivityManager. * Permissions are checked in Vpn class. * @hide */ @Override public VpnConfig getVpnConfig() { int user = UserHandle.getUserId(Binder.getCallingUid()); public VpnConfig getVpnConfig(int userId) { enforceCrossUserPermission(userId); synchronized(mVpns) { return mVpns.get(user).getVpnConfig(); return mVpns.get(userId).getVpnConfig(); } } Loading Loading @@ -4560,6 +4595,8 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void factoryReset() { enforceConnectivityInternalPermission(); final int userId = UserHandle.getCallingUserId(); // Turn airplane mode off setAirplaneMode(false); Loading @@ -4569,16 +4606,16 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Turn VPN off VpnConfig vpnConfig = getVpnConfig(); VpnConfig vpnConfig = getVpnConfig(userId); if (vpnConfig != null) { if (vpnConfig.legacy) { prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); } else { // Prevent this app from initiating VPN connections in the future without // user intervention. setVpnPackageAuthorization(false); // Prevent this app (packagename = vpnConfig.user) from initiating VPN connections // in the future without user intervention. setVpnPackageAuthorization(vpnConfig.user, userId, false); prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN); prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN, userId); } } } Loading Loading
core/java/android/net/IConnectivityManager.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -106,13 +106,13 @@ interface IConnectivityManager ProxyInfo getDefaultProxy(); boolean prepareVpn(String oldPackage, String newPackage); boolean prepareVpn(String oldPackage, String newPackage, int userId); void setVpnPackageAuthorization(boolean authorized); void setVpnPackageAuthorization(String packageName, int userId, boolean authorized); ParcelFileDescriptor establishVpn(in VpnConfig config); VpnConfig getVpnConfig(); VpnConfig getVpnConfig(int userId); void startLegacyVpn(in VpnProfile profile); Loading
core/java/android/net/VpnService.java +5 −4 Original line number Diff line number Diff line Loading @@ -156,7 +156,7 @@ public class VpnService extends Service { */ public static Intent prepare(Context context) { try { if (getService().prepareVpn(context.getPackageName(), null)) { if (getService().prepareVpn(context.getPackageName(), null, UserHandle.myUserId())) { return null; } } catch (RemoteException e) { Loading @@ -182,10 +182,11 @@ public class VpnService extends Service { String packageName = context.getPackageName(); try { // Only prepare if we're not already prepared. if (!cm.prepareVpn(packageName, null)) { cm.prepareVpn(null, packageName); int userId = UserHandle.myUserId(); if (!cm.prepareVpn(packageName, null, userId)) { cm.prepareVpn(null, packageName, userId); } cm.setVpnPackageAuthorization(true); cm.setVpnPackageAuthorization(packageName, userId, true); } catch (RemoteException e) { // ignore } Loading
packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +4 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.net.IConnectivityManager; import android.os.ServiceManager; import android.os.UserHandle; import android.text.Html; import android.text.Html.ImageGetter; import android.util.Log; Loading Loading @@ -50,7 +51,7 @@ public class ConfirmDialog extends AlertActivity mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); if (mService.prepareVpn(mPackage, null)) { if (mService.prepareVpn(mPackage, null, UserHandle.myUserId())) { setResult(RESULT_OK); finish(); return; Loading Loading @@ -94,10 +95,10 @@ public class ConfirmDialog extends AlertActivity @Override public void onClick(DialogInterface dialog, int which) { try { if (mService.prepareVpn(null, mPackage)) { if (mService.prepareVpn(null, mPackage, UserHandle.myUserId())) { // Authorize this app to initiate VPN connections in the future without user // intervention. mService.setVpnPackageAuthorization(true); mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true); setResult(RESULT_OK); } } catch (Exception e) { Loading
packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java +5 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.os.Handler; import android.os.Message; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.util.Log; import android.view.View; import android.widget.TextView; Loading Loading @@ -63,7 +64,7 @@ public class ManageDialog extends AlertActivity implements mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); mConfig = mService.getVpnConfig(); mConfig = mService.getVpnConfig(UserHandle.myUserId()); // mConfig can be null if we are a restricted user, in that case don't show this dialog if (mConfig == null) { Loading Loading @@ -120,10 +121,11 @@ public class ManageDialog extends AlertActivity implements if (which == DialogInterface.BUTTON_POSITIVE) { mConfig.configureIntent.send(); } else if (which == DialogInterface.BUTTON_NEUTRAL) { final int myUserId = UserHandle.myUserId(); if (mConfig.legacy) { mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, myUserId); } else { mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN); mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN, myUserId); } } } catch (Exception e) { Loading
services/core/java/com/android/server/ConnectivityService.java +58 −21 Original line number Diff line number Diff line Loading @@ -1410,6 +1410,22 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; /** * Require that the caller is either in the same user or has appropriate permission to interact * across users. * * @param userId Target user for whatever operation the current IPC is supposed to perform. */ private void enforceCrossUserPermission(int userId) { if (userId == UserHandle.getCallingUserId()) { // Not a cross-user call. return; } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "ConnectivityService"); } private void enforceInternetPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERNET, Loading Loading @@ -2945,29 +2961,48 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * Prepare for a VPN application. * Permissions are checked in Vpn class. * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. * * @param oldPackage Package name of the application which currently controls VPN, which will * be replaced. If there is no such application, this should should either be * {@code null} or {@link VpnConfig.LEGACY_VPN}. * @param newPackage Package name of the application which should gain control of VPN, or * {@code null} to disable. * @param userId User for whom to prepare the new VPN. * * @hide */ @Override public boolean prepareVpn(String oldPackage, String newPackage) { public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, int userId) { enforceCrossUserPermission(userId); throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized(mVpns) { return mVpns.get(user).prepare(oldPackage, newPackage); return mVpns.get(userId).prepare(oldPackage, newPackage); } } /** * Set whether the current VPN package has the ability to launch VPNs without * user intervention. This method is used by system-privileged apps. * Permissions are checked in Vpn class. * Set whether the VPN package has the ability to launch VPNs without user intervention. * This method is used by system-privileged apps. * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. * * @param packageName The package for which authorization state should change. * @param userId User for whom {@code packageName} is installed. * @param authorized {@code true} if this app should be able to start a VPN connection without * explicit user approval, {@code false} if not. * * @hide */ @Override public void setVpnPackageAuthorization(boolean authorized) { int user = UserHandle.getUserId(Binder.getCallingUid()); public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) { enforceCrossUserPermission(userId); synchronized(mVpns) { mVpns.get(user).setPackageAuthorization(authorized); mVpns.get(userId).setPackageAuthorization(packageName, authorized); } } Loading Loading @@ -3069,16 +3104,16 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** * Returns the information of the ongoing VPN. This method is used by VpnDialogs and * not available in ConnectivityManager. * Returns the information of the ongoing VPN for {@code userId}. This method is used by * VpnDialogs and not available in ConnectivityManager. * Permissions are checked in Vpn class. * @hide */ @Override public VpnConfig getVpnConfig() { int user = UserHandle.getUserId(Binder.getCallingUid()); public VpnConfig getVpnConfig(int userId) { enforceCrossUserPermission(userId); synchronized(mVpns) { return mVpns.get(user).getVpnConfig(); return mVpns.get(userId).getVpnConfig(); } } Loading Loading @@ -4560,6 +4595,8 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void factoryReset() { enforceConnectivityInternalPermission(); final int userId = UserHandle.getCallingUserId(); // Turn airplane mode off setAirplaneMode(false); Loading @@ -4569,16 +4606,16 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Turn VPN off VpnConfig vpnConfig = getVpnConfig(); VpnConfig vpnConfig = getVpnConfig(userId); if (vpnConfig != null) { if (vpnConfig.legacy) { prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); } else { // Prevent this app from initiating VPN connections in the future without // user intervention. setVpnPackageAuthorization(false); // Prevent this app (packagename = vpnConfig.user) from initiating VPN connections // in the future without user intervention. setVpnPackageAuthorization(vpnConfig.user, userId, false); prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN); prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN, userId); } } } Loading