diff options
author | Jeremy Joslin <jjoslin@google.com> | 2017-09-18 10:35:01 -0700 |
---|---|---|
committer | Jeremy Joslin <jjoslin@google.com> | 2017-10-04 15:47:31 -0700 |
commit | 1982ffd9f5a9434623e1e6229df9d23c506e7491 (patch) | |
tree | f0f0a504b75c06dce2f32b0c20c676f0406f5dab /service | |
parent | f3654b5e48f9e4f6f599b11ff5cd5ae235908916 (diff) |
DO NOT MERGE Allow the USE_OPEN_WIFI_PACKAGE to access WifiInfo unfiltered.
Do not remove the SSID/BSSID from the WifiInfo in
getConnectionInfo() if the requester is:
* The Settings.Global.USE_OPEN_WIFI_PACKAGE
* The current user or has been granted INTERACT_ACROSS_USERS_FULL
This only applies when the device is connected to an open network.
In all other cases the SSID/BSSID will be removed unless the caller
has scan result access.
Bug: 65639900
Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Test: Local testing with app.
Change-Id: I71eddca75a84945775be476f9ccaf1bb5c668fec
Diffstat (limited to 'service')
-rw-r--r-- | service/java/com/android/server/wifi/WifiStateMachine.java | 4 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/util/WifiPermissionsUtil.java | 118 |
2 files changed, 120 insertions, 2 deletions
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index faad0e2d1..c47dba621 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -1770,7 +1770,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss uid) == PackageManager.PERMISSION_GRANTED) { result.setMacAddress(mWifiInfo.getMacAddress()); } - if (mWifiPermissionsUtil.canAccessScanResults( + final WifiConfiguration currentWifiConfiguration = getCurrentWifiConfiguration(); + if (mWifiPermissionsUtil.canAccessFullConnectionInfo( + currentWifiConfiguration, callingPackage, uid, Build.VERSION_CODES.O)) { diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java index 069e5a823..52c96183e 100644 --- a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java +++ b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java @@ -17,17 +17,23 @@ package com.android.server.wifi.util; import android.Manifest; +import android.annotation.Nullable; import android.app.AppOpsManager; +import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.net.ConnectivityManager; import android.net.NetworkScoreManager; +import android.net.NetworkScorerAppData; +import android.net.wifi.WifiConfiguration; import android.os.Binder; import android.os.RemoteException; import android.os.UserManager; import android.provider.Settings; +import android.text.TextUtils; +import com.android.server.wifi.FrameworkFacade; import com.android.server.wifi.WifiInjector; import com.android.server.wifi.WifiLog; import com.android.server.wifi.WifiSettingsStore; @@ -46,6 +52,7 @@ public class WifiPermissionsUtil { private final UserManager mUserManager; private final WifiSettingsStore mSettingsStore; private final NetworkScoreManager mNetworkScoreManager; + private final FrameworkFacade mFrameworkFacade; private WifiLog mLog; public WifiPermissionsUtil(WifiPermissionsWrapper wifiPermissionsWrapper, @@ -58,6 +65,7 @@ public class WifiPermissionsUtil { mSettingsStore = settingsStore; mLog = wifiInjector.makeLog(TAG); mNetworkScoreManager = networkScoreManager; + mFrameworkFacade = wifiInjector.getFrameworkFacade(); } /** @@ -168,10 +176,81 @@ public class WifiPermissionsUtil { } // If the User or profile is current, permission is granted // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission. - if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) { + if (!canAccessUserProfile(uid)) { + mLog.tC("Denied: Profile not permitted"); + return false; + } + return true; + } + + /** + * API to determine if the caller has permissions to get a {@link android.net.wifi.WifiInfo} + * instance containing the SSID and BSSID. + * + * + * @param currentConfig the currently connected WiFi config + * @param pkgName package name of the application requesting access + * @param uid The uid of the package + * @param minVersion Minimum app API Version number to enforce location permission + * @return boolean true if the SSID/BSSID can be sent to the user, false if they + * should be hidden/removed. + */ + public boolean canAccessFullConnectionInfo(@Nullable WifiConfiguration currentConfig, + String pkgName, int uid, int minVersion) throws SecurityException { + mAppOps.checkPackage(uid, pkgName); + + // The User or profile must be current or the uid must + // have INTERACT_ACROSS_USERS_FULL permission. + if (!canAccessUserProfile(uid)) { mLog.tC("Denied: Profile not permitted"); return false; } + + // If the caller has scan result access then they can also see the full connection info. + // Otherwise the caller must be the active use open wifi package and the current config + // must be for an open network. + return canAccessScanResults(pkgName, uid, minVersion) + || isUseOpenWifiPackageWithConnectionInfoAccess(currentConfig, pkgName); + + } + + /** + * Returns true if the given WiFi config is for an open network and the package is the active + * use open wifi app. + */ + private boolean isUseOpenWifiPackageWithConnectionInfoAccess( + @Nullable WifiConfiguration currentConfig, String pkgName) { + + // Access is only granted for open networks. + if (currentConfig == null) { + mLog.tC("Denied: WifiConfiguration is NULL."); + return false; + } + + // Access is only granted for open networks. + if (!currentConfig.isOpenNetwork()) { + mLog.tC("Denied: The current config is not for an open network."); + return false; + } + + // The USE_OPEN_WIFI_PACKAGE can access the full connection info details without + // scan result access. + if (!isUseOpenWifiPackage(pkgName)) { + mLog.tC("Denied: caller is not the current USE_OPEN_WIFI_PACKAGE"); + return false; + } + + return true; + } + + /** + * Returns true if the User or profile is current or the + * uid has the INTERACT_ACROSS_USERS_FULL permission. + */ + private boolean canAccessUserProfile(int uid) { + if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) { + return false; + } return true; } @@ -192,6 +271,43 @@ public class WifiPermissionsUtil { } /** + * Returns true if the given package is equal to the setting keyed by + * {@link Settings.Global#USE_OPEN_WIFI_PACKAGE} and the NetworkScoreManager + * has the package name set as the use open wifi package. + */ + private boolean isUseOpenWifiPackage(String packageName) { + if (TextUtils.isEmpty(packageName)) { + return false; + } + + // When the setting is enabled it's set to the package name of the use open wifi app. + final String useOpenWifiPkg = + mFrameworkFacade.getStringSetting(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE); + if (packageName.equals(useOpenWifiPkg)) { + // If the package name matches the setting then also confirm that the scorer is + // active and the package matches the expected use open wifi package from the scorer's + // perspective. The scorer can be active when the use open wifi feature is off so we + // can't rely on this check alone. + // TODO(b/67278755): Refactor this into an API similar to isCallerActiveScorer() + final NetworkScorerAppData appData; + final long token = Binder.clearCallingIdentity(); + try { + appData = mNetworkScoreManager.getActiveScorer(); + } finally { + Binder.restoreCallingIdentity(token); + } + if (appData != null) { + final ComponentName enableUseOpenWifiActivity = + appData.getEnableUseOpenWifiActivity(); + return enableUseOpenWifiActivity != null + && packageName.equals(enableUseOpenWifiActivity.getPackageName()); + } + } + + return false; + } + + /** * Returns true if Wifi scan operation is allowed for this caller * and package. */ |