From d841868f39ec245cc43928f3023421e397f1d41b Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 29 Mar 2021 17:19:47 +0800 Subject: [PATCH] Ensure SSID is not exposed to apps without correct permission The class NetworkCapabilities has an extra field for SSID that can be used by apps to obtain the router SSID (a surrogate for location) without holding permission. This is a circumvention of the permission system. Thus, add a test to ensure that visibility of SSID for apps are controlled by NETWORK_SETTING permission. Bug: 183911251 Test: atest CtsNetTestCasesLatestSdk:ConnectivityManagerTest Change-Id: I18d17093e2da37cde88b730c091c6a1deda08a8a --- .../net/cts/ConnectivityManagerTest.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java index bfab497316..096f656eaf 100644 --- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java +++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java @@ -1635,6 +1635,62 @@ public class ConnectivityManagerTest { } } + /** + * Verifies that apps are forbidden from getting ssid information from + * {@Code NetworkCapabilities} if they do not hold NETWORK_SETTINGS permission. + * See b/161370134. + */ + @AppModeFull(reason = "Cannot get WifiManager in instant app mode") + @Test + public void testSsidInNetworkCapabilities() throws Exception { + assumeTrue("testSsidInNetworkCapabilities cannot execute unless device supports WiFi", + mPackageManager.hasSystemFeature(FEATURE_WIFI)); + + final Network network = mCtsNetUtils.ensureWifiConnected(); + final String ssid = unquoteSSID(mWifiManager.getConnectionInfo().getSSID()); + assertNotNull("Ssid getting from WiifManager is null", ssid); + // This package should have no NETWORK_SETTINGS permission. Verify that no ssid is contained + // in the NetworkCapabilities. + verifySsidFromQueriedNetworkCapabilities(network, ssid, false /* hasSsid */); + verifySsidFromCallbackNetworkCapabilities(ssid, false /* hasSsid */); + // Adopt shell permission to allow to get ssid information. + runWithShellPermissionIdentity(() -> { + verifySsidFromQueriedNetworkCapabilities(network, ssid, true /* hasSsid */); + verifySsidFromCallbackNetworkCapabilities(ssid, true /* hasSsid */); + }); + } + + private void verifySsidFromQueriedNetworkCapabilities(@NonNull Network network, + @NonNull String ssid, boolean hasSsid) throws Exception { + // Verify if ssid is contained in NetworkCapabilities queried from ConnectivityManager. + final NetworkCapabilities nc = mCm.getNetworkCapabilities(network); + assertNotNull("NetworkCapabilities of the network is null", nc); + assertEquals(hasSsid, Pattern.compile(ssid).matcher(nc.toString()).find()); + } + + private void verifySsidFromCallbackNetworkCapabilities(@NonNull String ssid, boolean hasSsid) + throws Exception { + final CompletableFuture foundNc = new CompletableFuture(); + final NetworkCallback callback = new NetworkCallback() { + @Override + public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { + foundNc.complete(nc); + } + }; + try { + mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback); + // Registering a callback here guarantees onCapabilitiesChanged is called immediately + // because WiFi network should be connected. + final NetworkCapabilities nc = + foundNc.get(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); + // Verify if ssid is contained in the NetworkCapabilities received from callback. + assertNotNull("NetworkCapabilities of the network is null", nc); + assertEquals(hasSsid, Pattern.compile(ssid).matcher(nc.toString()).find()); + } finally { + mCm.unregisterNetworkCallback(callback); + } + } + /** * Verify background request can only be requested when acquiring * {@link android.Manifest.permission.NETWORK_SETTINGS}.