diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-10-05 01:05:56 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-10-05 01:05:56 +0000 |
commit | db68688e4eeeeceb9ab1b3bc422f77458fba2f24 (patch) | |
tree | 43e4f1ce6bba8bacee47227c0cbc0fdba9ff125a /service | |
parent | 70954f46ffb95cbf3d6c9d12495be20edf2b3530 (diff) | |
parent | 1982ffd9f5a9434623e1e6229df9d23c506e7491 (diff) |
Merge "DO NOT MERGE Allow the USE_OPEN_WIFI_PACKAGE to access WifiInfo unfiltered." into oc-mr1-dev
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 9e124463d..e04d33e5b 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. */ |