Loading core/java/android/net/NetworkSpecifier.java +26 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ package android.net; /** * Describes specific properties of a network for use in a {@link NetworkRequest}. * Describes specific properties of a requested network for use in a {@link NetworkRequest}. * * Applications cannot instantiate this class by themselves, but can obtain instances of * subclasses of this class via other APIs. Loading Loading @@ -49,4 +49,29 @@ public abstract class NetworkSpecifier { public void assertValidFromUid(int requestorUid) { // empty } /** * Optional method which can be overridden by concrete implementations of NetworkSpecifier to * perform any redaction of information from the NetworkSpecifier, e.g. if it contains * sensitive information. The default implementation simply returns the object itself - i.e. * no information is redacted. A concrete implementation may return a modified (copy) of the * NetworkSpecifier, or even return a null to fully remove all information. * <p> * This method is relevant to NetworkSpecifier objects used by agents - those are shared with * apps by default. Some agents may store sensitive matching information in the specifier, * e.g. a Wi-Fi SSID (which should not be shared since it may leak location). Those classes * can redact to a null. Other agents use the Network Specifier to share public information * with apps - those should not be redacted. * <p> * The default implementation redacts no information. * * @return A NetworkSpecifier object to be passed along to the requesting app. * * @hide */ public NetworkSpecifier redact() { // TODO (b/122160111): convert default to null once all platform NetworkSpecifiers // implement this method. return this; } } services/core/java/com/android/server/ConnectivityService.java +5 −1 Original line number Diff line number Diff line Loading @@ -1433,6 +1433,9 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.setUids(null); newNc.setSSID(null); } if (newNc.getNetworkSpecifier() != null) { newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); } return newNc; } Loading Loading @@ -5145,7 +5148,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions( networkAgent.networkCapabilities, nri.mPid, nri.mUid)); putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); break; } Loading tests/net/java/com/android/server/ConnectivityServiceTest.java +98 −11 Original line number Diff line number Diff line Loading @@ -113,7 +113,6 @@ import android.net.NetworkSpecifier; import android.net.NetworkState; import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.StringNetworkSpecifier; import android.net.UidRange; import android.net.VpnService; import android.net.captiveportal.CaptivePortalProbeResult; Loading @@ -135,6 +134,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; Loading Loading @@ -2495,16 +2495,76 @@ public class ConnectivityServiceTest { return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); } /** * Verify request matching behavior with network specifiers. * * Note: this test is somewhat problematic since it involves removing capabilities from * agents - i.e. agents rejecting requests which they previously accepted. This is flagged * as a WTF bug in * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but * does work. */ @Test public void testNetworkSpecifier() { // A NetworkSpecifier subclass that matches all networks but must not be visible to apps. class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable { @Override public boolean satisfiedBy(NetworkSpecifier other) { return true; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) {} @Override public NetworkSpecifier redact() { return null; } } // A network specifier that matches either another LocalNetworkSpecifier with the same // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is. class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable { private String mString; LocalStringNetworkSpecifier(String string) { mString = string; } @Override public boolean satisfiedBy(NetworkSpecifier other) { if (other instanceof LocalStringNetworkSpecifier) { return TextUtils.equals(mString, ((LocalStringNetworkSpecifier) other).mString); } if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true; return false; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) {} } NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( (NetworkSpecifier) null).build(); NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier( new LocalStringNetworkSpecifier("foo")).build(); NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( new StringNetworkSpecifier("bar")).build(); new LocalStringNetworkSpecifier("bar")).build(); TestNetworkCallback cEmpty1 = new TestNetworkCallback(); TestNetworkCallback cEmpty2 = new TestNetworkCallback(); Loading @@ -2513,7 +2573,7 @@ public class ConnectivityServiceTest { TestNetworkCallback cFoo = new TestNetworkCallback(); TestNetworkCallback cBar = new TestNetworkCallback(); TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { cEmpty1, cEmpty2, cEmpty3 }; cEmpty1, cEmpty2, cEmpty3, cEmpty4 }; mCm.registerNetworkCallback(rEmpty1, cEmpty1); mCm.registerNetworkCallback(rEmpty2, cEmpty2); Loading @@ -2522,6 +2582,9 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(rFoo, cFoo); mCm.registerNetworkCallback(rBar, cBar); LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo"); LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar"); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); Loading @@ -2530,30 +2593,54 @@ public class ConnectivityServiceTest { cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertNoCallbacks(cFoo, cBar); mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), mWiFiNetworkAgent); } cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), mWiFiNetworkAgent); assertEquals(nsFoo, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cFoo.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); mWiFiNetworkAgent.setNetworkSpecifier(nsBar); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), mWiFiNetworkAgent); } cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), mWiFiNetworkAgent); assertEquals(nsBar, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cBar.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c : emptyCallbacks) { c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, mWiFiNetworkAgent); } cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, mWiFiNetworkAgent); cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, mWiFiNetworkAgent); assertNull( mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cFoo.assertNoCallback(); cBar.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(null); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); } assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); } @Test Loading Loading
core/java/android/net/NetworkSpecifier.java +26 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ package android.net; /** * Describes specific properties of a network for use in a {@link NetworkRequest}. * Describes specific properties of a requested network for use in a {@link NetworkRequest}. * * Applications cannot instantiate this class by themselves, but can obtain instances of * subclasses of this class via other APIs. Loading Loading @@ -49,4 +49,29 @@ public abstract class NetworkSpecifier { public void assertValidFromUid(int requestorUid) { // empty } /** * Optional method which can be overridden by concrete implementations of NetworkSpecifier to * perform any redaction of information from the NetworkSpecifier, e.g. if it contains * sensitive information. The default implementation simply returns the object itself - i.e. * no information is redacted. A concrete implementation may return a modified (copy) of the * NetworkSpecifier, or even return a null to fully remove all information. * <p> * This method is relevant to NetworkSpecifier objects used by agents - those are shared with * apps by default. Some agents may store sensitive matching information in the specifier, * e.g. a Wi-Fi SSID (which should not be shared since it may leak location). Those classes * can redact to a null. Other agents use the Network Specifier to share public information * with apps - those should not be redacted. * <p> * The default implementation redacts no information. * * @return A NetworkSpecifier object to be passed along to the requesting app. * * @hide */ public NetworkSpecifier redact() { // TODO (b/122160111): convert default to null once all platform NetworkSpecifiers // implement this method. return this; } }
services/core/java/com/android/server/ConnectivityService.java +5 −1 Original line number Diff line number Diff line Loading @@ -1433,6 +1433,9 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.setUids(null); newNc.setSSID(null); } if (newNc.getNetworkSpecifier() != null) { newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); } return newNc; } Loading Loading @@ -5145,7 +5148,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions( networkAgent.networkCapabilities, nri.mPid, nri.mUid)); putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); break; } Loading
tests/net/java/com/android/server/ConnectivityServiceTest.java +98 −11 Original line number Diff line number Diff line Loading @@ -113,7 +113,6 @@ import android.net.NetworkSpecifier; import android.net.NetworkState; import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.StringNetworkSpecifier; import android.net.UidRange; import android.net.VpnService; import android.net.captiveportal.CaptivePortalProbeResult; Loading @@ -135,6 +134,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; Loading Loading @@ -2495,16 +2495,76 @@ public class ConnectivityServiceTest { return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); } /** * Verify request matching behavior with network specifiers. * * Note: this test is somewhat problematic since it involves removing capabilities from * agents - i.e. agents rejecting requests which they previously accepted. This is flagged * as a WTF bug in * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but * does work. */ @Test public void testNetworkSpecifier() { // A NetworkSpecifier subclass that matches all networks but must not be visible to apps. class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable { @Override public boolean satisfiedBy(NetworkSpecifier other) { return true; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) {} @Override public NetworkSpecifier redact() { return null; } } // A network specifier that matches either another LocalNetworkSpecifier with the same // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is. class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable { private String mString; LocalStringNetworkSpecifier(String string) { mString = string; } @Override public boolean satisfiedBy(NetworkSpecifier other) { if (other instanceof LocalStringNetworkSpecifier) { return TextUtils.equals(mString, ((LocalStringNetworkSpecifier) other).mString); } if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true; return false; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) {} } NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( (NetworkSpecifier) null).build(); NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier( new LocalStringNetworkSpecifier("foo")).build(); NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( new StringNetworkSpecifier("bar")).build(); new LocalStringNetworkSpecifier("bar")).build(); TestNetworkCallback cEmpty1 = new TestNetworkCallback(); TestNetworkCallback cEmpty2 = new TestNetworkCallback(); Loading @@ -2513,7 +2573,7 @@ public class ConnectivityServiceTest { TestNetworkCallback cFoo = new TestNetworkCallback(); TestNetworkCallback cBar = new TestNetworkCallback(); TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { cEmpty1, cEmpty2, cEmpty3 }; cEmpty1, cEmpty2, cEmpty3, cEmpty4 }; mCm.registerNetworkCallback(rEmpty1, cEmpty1); mCm.registerNetworkCallback(rEmpty2, cEmpty2); Loading @@ -2522,6 +2582,9 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(rFoo, cFoo); mCm.registerNetworkCallback(rBar, cBar); LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo"); LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar"); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); Loading @@ -2530,30 +2593,54 @@ public class ConnectivityServiceTest { cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertNoCallbacks(cFoo, cBar); mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), mWiFiNetworkAgent); } cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), mWiFiNetworkAgent); assertEquals(nsFoo, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cFoo.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); mWiFiNetworkAgent.setNetworkSpecifier(nsBar); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), mWiFiNetworkAgent); } cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), mWiFiNetworkAgent); assertEquals(nsBar, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cBar.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c : emptyCallbacks) { c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, mWiFiNetworkAgent); } cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, mWiFiNetworkAgent); cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, mWiFiNetworkAgent); assertNull( mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cFoo.assertNoCallback(); cBar.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(null); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); } assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); } @Test Loading