Merge "Protect invalid entitlement app configuration" into rvc-dev am: 06b2e1cb17
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11699076 Change-Id: Ida5076888f61e8e472e853ce1ee58f8106dacbb2
This commit is contained in:
@@ -19,42 +19,9 @@ import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.os.SystemProperties;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.telephony.CarrierConfigManager;
|
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
|
||||||
|
|
||||||
public class TetherUtil {
|
public class TetherUtil {
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
static boolean isEntitlementCheckRequired(Context context) {
|
|
||||||
final CarrierConfigManager configManager = (CarrierConfigManager) context
|
|
||||||
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
|
||||||
if (configManager == null || configManager.getConfig() == null) {
|
|
||||||
// return service default
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return configManager.getConfig().getBoolean(CarrierConfigManager
|
|
||||||
.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isProvisioningNeeded(Context context) {
|
|
||||||
// Keep in sync with other usage of config_mobile_hotspot_provision_app.
|
|
||||||
// ConnectivityManager#enforceTetherChangePermission
|
|
||||||
String[] provisionApp = context.getResources().getStringArray(
|
|
||||||
com.android.internal.R.array.config_mobile_hotspot_provision_app);
|
|
||||||
if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
|
|
||||||
|| provisionApp == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Check carrier config for entitlement checks
|
|
||||||
if (isEntitlementCheckRequired(context) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (provisionApp.length == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isTetherAvailable(Context context) {
|
public static boolean isTetherAvailable(Context context) {
|
||||||
final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||||
final boolean tetherConfigDisallowed = RestrictedLockUtilsInternal
|
final boolean tetherConfigDisallowed = RestrictedLockUtilsInternal
|
||||||
|
|||||||
@@ -59,13 +59,6 @@ public class TetherUtilTest {
|
|||||||
.when(mContext).getSystemService(Context.USER_SERVICE);
|
.when(mContext).getSystemService(Context.USER_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isEntitlementCheckRequired_noConfigManager_returnTrue() {
|
|
||||||
doReturn(null).when(mContext).getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
|
||||||
|
|
||||||
assertThat(TetherUtil.isEntitlementCheckRequired(mContext)).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isTetherAvailable_supported_configDisallowed_hasUserRestriction_returnTrue() {
|
public void isTetherAvailable_supported_configDisallowed_hasUserRestriction_returnTrue() {
|
||||||
setupIsTetherAvailable(true, true, true);
|
setupIsTetherAvailable(true, true, true);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.networkstack.tethering;
|
|||||||
|
|
||||||
import static android.Manifest.permission.NETWORK_SETTINGS;
|
import static android.Manifest.permission.NETWORK_SETTINGS;
|
||||||
import static android.Manifest.permission.NETWORK_STACK;
|
import static android.Manifest.permission.NETWORK_STACK;
|
||||||
|
import static android.content.pm.PackageManager.GET_ACTIVITIES;
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
||||||
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
||||||
@@ -70,6 +71,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.EthernetManager;
|
import android.net.EthernetManager;
|
||||||
@@ -109,7 +111,6 @@ import android.os.RemoteCallbackList;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.ServiceSpecificException;
|
import android.os.ServiceSpecificException;
|
||||||
import android.os.SystemProperties;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -782,11 +783,30 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isProvisioningNeededButUnavailable() {
|
||||||
|
return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
|
||||||
|
}
|
||||||
|
|
||||||
boolean isTetherProvisioningRequired() {
|
boolean isTetherProvisioningRequired() {
|
||||||
final TetheringConfiguration cfg = mConfig;
|
final TetheringConfiguration cfg = mConfig;
|
||||||
return mEntitlementMgr.isTetherProvisioningRequired(cfg);
|
return mEntitlementMgr.isTetherProvisioningRequired(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean doesEntitlementPackageExist() {
|
||||||
|
// provisioningApp must contain package and class name.
|
||||||
|
if (mConfig.provisioningApp.length != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
|
try {
|
||||||
|
pm.getPackageInfo(mConfig.provisioningApp[0], GET_ACTIVITIES);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Figure out how to update for local hotspot mode interfaces.
|
// TODO: Figure out how to update for local hotspot mode interfaces.
|
||||||
private void sendTetherStateChangedBroadcast() {
|
private void sendTetherStateChangedBroadcast() {
|
||||||
if (!isTetheringSupported()) return;
|
if (!isTetheringSupported()) return;
|
||||||
@@ -2145,14 +2165,14 @@ public class Tethering {
|
|||||||
// gservices could set the secure setting to 1 though to enable it on a build where it
|
// gservices could set the secure setting to 1 though to enable it on a build where it
|
||||||
// had previously been turned off.
|
// had previously been turned off.
|
||||||
boolean isTetheringSupported() {
|
boolean isTetheringSupported() {
|
||||||
final int defaultVal =
|
final int defaultVal = mDeps.isTetheringDenied() ? 0 : 1;
|
||||||
SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
|
|
||||||
final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
|
final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
|
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
|
||||||
final boolean tetherEnabledInSettings = tetherSupported
|
final boolean tetherEnabledInSettings = tetherSupported
|
||||||
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
|
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
|
||||||
|
|
||||||
return tetherEnabledInSettings && hasTetherableConfiguration();
|
return tetherEnabledInSettings && hasTetherableConfiguration()
|
||||||
|
&& !isProvisioningNeededButUnavailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
|
void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import android.net.util.SharedLog;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.os.SystemProperties;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@@ -150,4 +152,11 @@ public abstract class TetheringDependencies {
|
|||||||
* Get a reference to BluetoothAdapter to be used by tethering.
|
* Get a reference to BluetoothAdapter to be used by tethering.
|
||||||
*/
|
*/
|
||||||
public abstract BluetoothAdapter getBluetoothAdapter();
|
public abstract BluetoothAdapter getBluetoothAdapter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SystemProperties which indicate whether tethering is denied.
|
||||||
|
*/
|
||||||
|
public boolean isTetheringDenied() {
|
||||||
|
return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.networkstack.tethering;
|
package com.android.networkstack.tethering;
|
||||||
|
|
||||||
|
import static android.content.pm.PackageManager.GET_ACTIVITIES;
|
||||||
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
|
||||||
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
import static android.hardware.usb.UsbManager.USB_CONNECTED;
|
||||||
import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
|
import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
|
||||||
@@ -81,6 +82,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
@@ -204,6 +206,7 @@ public class TetheringTest {
|
|||||||
@Mock private EthernetManager mEm;
|
@Mock private EthernetManager mEm;
|
||||||
@Mock private TetheringNotificationUpdater mNotificationUpdater;
|
@Mock private TetheringNotificationUpdater mNotificationUpdater;
|
||||||
@Mock private BpfCoordinator mBpfCoordinator;
|
@Mock private BpfCoordinator mBpfCoordinator;
|
||||||
|
@Mock private PackageManager mPackageManager;
|
||||||
|
|
||||||
private final MockIpServerDependencies mIpServerDependencies =
|
private final MockIpServerDependencies mIpServerDependencies =
|
||||||
spy(new MockIpServerDependencies());
|
spy(new MockIpServerDependencies());
|
||||||
@@ -263,6 +266,11 @@ public class TetheringTest {
|
|||||||
return super.getSystemService(name);
|
return super.getSystemService(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PackageManager getPackageManager() {
|
||||||
|
return mPackageManager;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSystemServiceName(Class<?> serviceClass) {
|
public String getSystemServiceName(Class<?> serviceClass) {
|
||||||
if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
|
if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
|
||||||
@@ -425,6 +433,11 @@ public class TetheringTest {
|
|||||||
public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) {
|
public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) {
|
||||||
return mNotificationUpdater;
|
return mNotificationUpdater;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTetheringDenied() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
|
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
|
||||||
@@ -1951,6 +1964,23 @@ public class TetheringTest {
|
|||||||
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
|
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProvisioningNeededButUnavailable() throws Exception {
|
||||||
|
assertTrue(mTethering.isTetheringSupported());
|
||||||
|
verify(mPackageManager, never()).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
|
||||||
|
|
||||||
|
setupForRequiredProvisioning();
|
||||||
|
assertTrue(mTethering.isTetheringSupported());
|
||||||
|
verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
|
||||||
|
reset(mPackageManager);
|
||||||
|
|
||||||
|
doThrow(PackageManager.NameNotFoundException.class).when(mPackageManager).getPackageInfo(
|
||||||
|
PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
|
||||||
|
setupForRequiredProvisioning();
|
||||||
|
assertFalse(mTethering.isTetheringSupported());
|
||||||
|
verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
||||||
// already operating tethering mode interface.
|
// already operating tethering mode interface.
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user