diff options
Diffstat (limited to 'tests/net/java/com/android/server')
-rw-r--r-- | tests/net/java/com/android/server/ConnectivityServiceTest.java | 319 | ||||
-rw-r--r-- | tests/net/java/com/android/server/connectivity/VpnTest.java | 133 |
2 files changed, 331 insertions, 121 deletions
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index f489c9866e20..cc1bee5a5104 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -82,6 +82,10 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; +import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; +import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; +import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; +import static android.net.NetworkCapabilities.REDACT_NONE; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; import static android.net.NetworkCapabilities.TRANSPORT_VPN; @@ -237,7 +241,6 @@ import android.net.resolv.aidl.PrivateDnsValidationEventParcel; import android.net.shared.NetworkMonitorUtils; import android.net.shared.PrivateDnsConfig; import android.net.util.MultinetworkPolicyTracker; -import android.net.wifi.WifiInfo; import android.os.BadParcelableException; import android.os.Binder; import android.os.Build; @@ -268,6 +271,7 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; +import android.util.Range; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; @@ -1158,7 +1162,7 @@ public class ConnectivityServiceTest { } public void setUids(Set<UidRange> uids) { - mNetworkCapabilities.setUids(uids); + mNetworkCapabilities.setUids(UidRange.toIntRanges(uids)); if (mAgentRegistered) { mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true); } @@ -1448,6 +1452,8 @@ public class ConnectivityServiceTest { } private static final int PRIMARY_USER = 0; + private static final UidRange PRIMARY_UIDRANGE = + UidRange.createForUser(UserHandle.of(PRIMARY_USER)); private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100); private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101); private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043); @@ -6946,7 +6952,7 @@ public class ConnectivityServiceTest { final int uid = Process.myUid(); NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); assertNotNull("nc=" + nc, nc.getUids()); - assertEquals(nc.getUids(), uidRangesForUids(uid)); + assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid))); assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); // Set an underlying network and expect to see the VPN transports change. @@ -6971,10 +6977,13 @@ public class ConnectivityServiceTest { // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added // restricted user. + final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER)); + final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop); + final Range<Integer> singleUidRange = new Range<Integer>(uid, uid); callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 2 - && caps.getUids().contains(new UidRange(uid, uid)) - && caps.getUids().contains(createUidRange(RESTRICTED_USER)) + && caps.getUids().contains(singleUidRange) + && caps.getUids().contains(restrictUidRange) && caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_WIFI)); @@ -6983,8 +6992,8 @@ public class ConnectivityServiceTest { callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 2 - && caps.getUids().contains(new UidRange(uid, uid)) - && caps.getUids().contains(createUidRange(RESTRICTED_USER)) + && caps.getUids().contains(singleUidRange) + && caps.getUids().contains(restrictUidRange) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); @@ -6998,7 +7007,7 @@ public class ConnectivityServiceTest { // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved. callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 1 - && caps.getUids().contains(new UidRange(uid, uid)) + && caps.getUids().contains(singleUidRange) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); } @@ -7656,7 +7665,7 @@ public class ConnectivityServiceTest { assertNotNull(underlying); mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY); // The legacy lockdown VPN only supports userId 0. - final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.registerAgent(ranges); mMockVpn.setUnderlyingNetworks(new Network[]{underlying}); mMockVpn.connect(true); @@ -8618,7 +8627,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, VPN_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); @@ -8646,7 +8655,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); @@ -8662,7 +8671,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0")); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); @@ -8677,7 +8686,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.establish(lp, VPN_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); @@ -8729,7 +8738,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final UidRange vpnRange = createUidRange(PRIMARY_USER); + final UidRange vpnRange = PRIMARY_UIDRANGE; final Set<UidRange> vpnRanges = Collections.singleton(vpnRange); mMockVpn.establish(lp, VPN_UID, vpnRanges); assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); @@ -8834,29 +8843,34 @@ public class ConnectivityServiceTest { final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, callerUid, + netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid, mContext.getPackageName(), getAttributionTag()) .getOwnerUid(); } - private void verifyWifiInfoCopyNetCapsPermission( + private void verifyTransportInfoCopyNetCapsPermission( int callerUid, boolean includeLocationSensitiveInfo, boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { - final WifiInfo wifiInfo = mock(WifiInfo.class); - when(wifiInfo.hasLocationSensitiveFields()).thenReturn(true); - final NetworkCapabilities netCap = new NetworkCapabilities().setTransportInfo(wifiInfo); + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()).thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, callerUid, + netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid, mContext.getPackageName(), getAttributionTag()); - verify(wifiInfo).makeCopy(eq(shouldMakeCopyWithLocationSensitiveFieldsParcelable)); + if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) { + verify(transportInfo).makeCopy(REDACT_NONE); + } else { + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); + } } - private void verifyOwnerUidAndWifiInfoNetCapsPermission( + private void verifyOwnerUidAndTransportInfoNetCapsPermission( boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag, boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag, - boolean shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag, - boolean shouldInclLocationSensitiveWifiInfoWithIncludeFlag) { + boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag, + boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) { final int myUid = Process.myUid(); final int expectedOwnerUidWithoutIncludeFlag = @@ -8870,13 +8884,13 @@ public class ConnectivityServiceTest { assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission( myUid, myUid, true /* includeLocationSensitiveInfo */)); - verifyWifiInfoCopyNetCapsPermission(myUid, + verifyTransportInfoCopyNetCapsPermission(myUid, false, /* includeLocationSensitiveInfo */ - shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag); + shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag); - verifyWifiInfoCopyNetCapsPermission(myUid, + verifyTransportInfoCopyNetCapsPermission(myUid, true, /* includeLocationSensitiveInfo */ - shouldInclLocationSensitiveWifiInfoWithIncludeFlag); + shouldInclLocationSensitiveTransportInfoWithIncludeFlag); } @@ -8886,15 +8900,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we include owner uid even if the request asks to remove it since the // app has necessary permissions and targetSdk < S. true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8904,15 +8918,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we include owner uid even if the request asks to remove it since the // app has necessary permissions and targetSdk < S. true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8923,15 +8937,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we owner UID if the request asks us to remove it even if the app // has necessary permissions since targetSdk >= S. false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8941,15 +8955,15 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( // Ensure that we owner UID if the request asks us to remove it even if the app // has necessary permissions since targetSdk >= S. true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ // Ensure that we remove location info if the request asks to remove it even if the // app has necessary permissions. - true /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8959,11 +8973,11 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -8986,11 +9000,11 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ ); } @@ -9000,17 +9014,196 @@ public class ConnectivityServiceTest { // Test that not having fine location permission leads to sanitization. setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); - verifyOwnerUidAndWifiInfoNetCapsPermission( + verifyOwnerUidAndTransportInfoNetCapsPermission( false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveWifiInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveWifiInfoWithIncludeFlag */ + false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ + false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ + ); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // don't redact MAC_ADDRESS fields, only location sensitive fields. + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // redact both MAC_ADDRESS & location sensitive fields. + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION + | REDACT_FOR_LOCAL_MAC_ADDRESS); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // don't redact NETWORK_SETTINGS fields, only location sensitive fields. + verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); + } + + @Test + public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission() + throws Exception { + mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED); + + final TransportInfo transportInfo = mock(TransportInfo.class); + when(transportInfo.getApplicableRedactions()) + .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); + final NetworkCapabilities netCap = + new NetworkCapabilities().setTransportInfo(transportInfo); + + mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( + netCap, false /* includeLocationSensitiveInfoInTransportInfo */, + Process.myPid(), Process.myUid(), + mContext.getPackageName(), getAttributionTag()); + // redact both NETWORK_SETTINGS & location sensitive fields. + verify(transportInfo).makeCopy( + REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); + } + + /** + * Test TransportInfo to verify redaction mechanism. + */ + private static class TestTransportInfo implements TransportInfo { + public final boolean locationRedacted; + public final boolean localMacAddressRedacted; + public final boolean settingsRedacted; + + TestTransportInfo() { + locationRedacted = false; + localMacAddressRedacted = false; + settingsRedacted = false; + } + + TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted, + boolean settingsRedacted) { + this.locationRedacted = locationRedacted; + this.localMacAddressRedacted = + localMacAddressRedacted; + this.settingsRedacted = settingsRedacted; + } + + @Override + public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { + return new TestTransportInfo( + (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0, + (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, + (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 + ); + } + + @Override + public @NetworkCapabilities.RedactionType long getApplicableRedactions() { + return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS + | REDACT_FOR_NETWORK_SETTINGS; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TestTransportInfo)) return false; + TestTransportInfo that = (TestTransportInfo) other; + return that.locationRedacted == this.locationRedacted + && that.localMacAddressRedacted == this.localMacAddressRedacted + && that.settingsRedacted == this.settingsRedacted; + } + + @Override + public int hashCode() { + return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted); + } + } + + private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( + @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid, + @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid, + @NonNull TransportInfo expectedTransportInfo) throws Exception { + when(mPackageManager.getTargetSdkVersion(anyString())).thenReturn(Build.VERSION_CODES.S); + final NetworkCapabilities ncTemplate = + new NetworkCapabilities() + .addTransportType(TRANSPORT_WIFI) + .setOwnerUid(actualOwnerUid); + + final NetworkRequest wifiRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_WIFI).build(); + mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), + ncTemplate); + mWiFiNetworkAgent.connect(false); + + wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + + // Send network capabilities update with TransportInfo to trigger capabilities changed + // callback. + mWiFiNetworkAgent.setNetworkCapabilities( + ncTemplate.setTransportInfo(actualTransportInfo), true); + + wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent, + nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid()) + && Objects.equals(expectedTransportInfo, nc.getTransportInfo())); + + } + + @Test + public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception { + final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback(); + final int ownerUid = Process.myUid(); + final TransportInfo transportInfo = new TestTransportInfo(); + // Even though the test uid holds privileged permissions, mask location fields since + // the callback did not explicitly opt-in to get location data. + final TransportInfo sanitizedTransportInfo = new TestTransportInfo( + true, /* locationRedacted */ + true, /* localMacAddressRedacted */ + true /* settingsRedacted */ ); + // Should not expect location data since the callback does not set the flag for including + // location data. + verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( + wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo); } private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) throws Exception { - final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); mMockVpn.setVpnType(vpnType); mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid); @@ -9570,7 +9763,7 @@ public class ConnectivityServiceTest { lp.setInterfaceName("tun0"); lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - final UidRange vpnRange = createUidRange(PRIMARY_USER); + final UidRange vpnRange = PRIMARY_UIDRANGE; Set<UidRange> vpnRanges = Collections.singleton(vpnRange); mMockVpn.establish(lp, VPN_UID, vpnRanges); assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); @@ -9768,7 +9961,7 @@ public class ConnectivityServiceTest { .thenReturn(hasFeature); } - private UidRange getNriFirstUidRange( + private Range<Integer> getNriFirstUidRange( @NonNull final ConnectivityService.NetworkRequestInfo nri) { return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next(); } @@ -9951,11 +10144,11 @@ public class ConnectivityServiceTest { pref)); // Sort by uid to access nris by index - nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).start)); - assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).start); - assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).stop); - assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).start); - assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).stop); + nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower())); + assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower()); + assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper()); + assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower()); + assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper()); } @Test @@ -9985,17 +10178,17 @@ public class ConnectivityServiceTest { // UIDs for all users and all managed packages should be present. // Two users each with two packages. final int expectedUidSize = 2; - final List<UidRange> uids = + final List<Range<Integer>> uids = new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids()); assertEquals(expectedUidSize, uids.size()); // Sort by uid to access nris by index - uids.sort(Comparator.comparingInt(uid -> uid.start)); + uids.sort(Comparator.comparingInt(uid -> uid.getLower())); final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); - assertEquals(TEST_PACKAGE_UID, uids.get(0).start); - assertEquals(TEST_PACKAGE_UID, uids.get(0).stop); - assertEquals(secondUserTestPackageUid, uids.get(1).start); - assertEquals(secondUserTestPackageUid, uids.get(1).stop); + assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getLower()); + assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getUpper()); + assertEquals(secondUserTestPackageUid, (int) uids.get(1).getLower()); + assertEquals(secondUserTestPackageUid, (int) uids.get(1).getUpper()); } @Test diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 11fcea60d98d..6ad4900989f5 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -23,6 +23,7 @@ import static android.content.pm.UserInfo.FLAG_RESTRICTED; import static android.net.ConnectivityManager.NetworkCallback; import static android.net.INetd.IF_STATE_DOWN; import static android.net.INetd.IF_STATE_UP; +import static android.os.UserHandle.PER_USER_RANGE; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -74,7 +75,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo.DetailedState; import android.net.RouteInfo; -import android.net.UidRange; import android.net.UidRangeParcel; import android.net.VpnManager; import android.net.VpnService; @@ -181,8 +181,7 @@ public class VpnTest { mPackages.put(PKGS[i], PKG_UIDS[i]); } } - private static final UidRange PRI_USER_RANGE = - UidRange.createForUser(UserHandle.of(primaryUser.id)); + private static final Range<Integer> PRI_USER_RANGE = uidRangeForUser(primaryUser.id); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; @Mock private UserManager mUserManager; @@ -260,6 +259,21 @@ public class VpnTest { .thenReturn(tunnelResp); } + private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) { + final Set<Range<Integer>> range = new ArraySet<>(); + for (Range<Integer> r : ranges) range.add(r); + + return range; + } + + private static Range<Integer> uidRangeForUser(int userId) { + return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); + } + + private Range<Integer> uidRange(int start, int stop) { + return new Range<Integer>(start, stop); + } + @Test public void testRestrictedProfilesAreAddedToVpn() { setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); @@ -268,12 +282,10 @@ public class VpnTest { // Assume the user can have restricted profiles. doReturn(true).when(mUserManager).canHaveRestrictedProfile(); - final Set<UidRange> ranges = + final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id)) - })), ranges); + assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges); } @Test @@ -281,10 +293,10 @@ public class VpnTest { setMockedUsers(primaryUser, managedProfileA); final Vpn vpn = createVpn(primaryUser.id); - final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, + final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges); + assertEquals(rangeSet(PRI_USER_RANGE), ranges); } @Test @@ -292,35 +304,38 @@ public class VpnTest { setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); final Vpn vpn = createVpn(primaryUser.id); - final Set<UidRange> ranges = new ArraySet<>(); + final Set<Range<Integer>> ranges = new ArraySet<>(); vpn.addUserToRanges(ranges, primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges); + assertEquals(rangeSet(PRI_USER_RANGE), ranges); } @Test public void testUidAllowAndDenylist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = PRI_USER_RANGE; + final Range<Integer> user = PRI_USER_RANGE; + final int userStart = user.getLower(); + final int userStop = user.getUpper(); final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; // Allowed list - final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - Arrays.asList(packages), null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0], user.start + PKG_UIDS[0]), - new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]) - })), allow); + final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, + Arrays.asList(packages), null /* disallowedApplications */); + assertEquals(rangeSet( + uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]), + uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])), + allow); // Denied list - final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - null, Arrays.asList(packages)); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[0] - 1), - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) - })), disallow); + final Set<Range<Integer>> disallow = + vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, + null /* allowedApplications */, Arrays.asList(packages)); + assertEquals(rangeSet( + uidRange(userStart, userStart + PKG_UIDS[0] - 1), + uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), + /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ + uidRange(userStart + PKG_UIDS[2] + 1, userStop)), + disallow); } @Test @@ -350,84 +365,86 @@ public class VpnTest { @Test public void testLockdownChangingPackage() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = PRI_USER_RANGE; - + final Range<Integer> user = PRI_USER_RANGE; + final int userStart = user.getLower(); + final int userStop = user.getUpper(); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), - new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) + new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) })); } @Test public void testLockdownAllowlist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = PRI_USER_RANGE; - + final Range<Integer> user = PRI_USER_RANGE; + final int userStart = user.getLower(); + final int userStop = user.getUpper(); // Set always-on with lockdown and allow app PKGS[2] from lockdown. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[2]))); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) + verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) })); // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), - new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) })); // Change the VPN app. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) + new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1), - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) + new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1), + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1) })); // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), - new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop), + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop), })); // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[1]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); // Try allowing a package with a comma, should be rejected. @@ -439,12 +456,12 @@ public class VpnTest { assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1), - new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1), + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) })); } @@ -452,7 +469,7 @@ public class VpnTest { public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] { - new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)}; + new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())}; // Given legacy lockdown is already enabled, vpn.setLockdown(true); verify(mConnectivityManager, times(1)).setRequireVpnForUids(true, @@ -484,7 +501,7 @@ public class VpnTest { public void testLockdownRuleReversibility() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRangeParcel[] entireUser = { - new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop) + new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper()) }; final UidRangeParcel[] exceptPkg0 = { new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), |