From bb5be240c0982f2e098978fec187fc735c0e7ad9 Mon Sep 17 00:00:00 2001 From: Hugh Chen Date: Thu, 29 Apr 2021 13:53:50 +0800 Subject: [PATCH] Fix unable to send file via OPP Bluetooth app will indicate BluetoothOppReceiver to receive device picker intent. But for fix the security issue we removed the setClassName() method in ag/14111132 to avoid attack. It causes BluetoothOppReceiver cannot receive the intent. This CL will compare to calling package name with launch package name. If they are not equal, the setClassName() will not invoke. Bug: 186490534 Bug: 179386960 Bug: 179386068 Test: make RunSettingsRoboTests -j56 Change-Id: Ia51528f2a44ab73edbc86899ca0846d3262fe1f0 --- .../bluetooth/DevicePickerFragment.java | 22 ++++++++++++++++ .../bluetooth/DevicePickerFragmentTest.java | 26 ++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/bluetooth/DevicePickerFragment.java b/src/com/android/settings/bluetooth/DevicePickerFragment.java index f60183b1c4f..02b5d5c90f0 100644 --- a/src/com/android/settings/bluetooth/DevicePickerFragment.java +++ b/src/com/android/settings/bluetooth/DevicePickerFragment.java @@ -27,12 +27,15 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.UserManager; +import android.util.Log; +import android.text.TextUtils; import android.view.Menu; import android.view.MenuInflater; import androidx.annotation.VisibleForTesting; import com.android.settings.R; +import com.android.settings.password.PasswordUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.AbstractPreferenceController; @@ -50,6 +53,12 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment { BluetoothProgressCategory mAvailableDevicesCategory; @VisibleForTesting Context mContext; + @VisibleForTesting + String mLaunchPackage; + @VisibleForTesting + String mLaunchClass; + @VisibleForTesting + String mCallingAppPackageName; private boolean mNeedAuth; private boolean mScanAllowed; @@ -64,6 +73,8 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment { mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false); setFilter(intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE, BluetoothDevicePicker.FILTER_TYPE_ALL)); + mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE); + mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS); mAvailableDevicesCategory = (BluetoothProgressCategory) findPreference(KEY_BT_DEVICE_LIST); } @@ -83,6 +94,12 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment { getActivity().setTitle(getString(R.string.device_picker)); UserManager um = (UserManager) getSystemService(Context.USER_SERVICE); mScanAllowed = !um.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH); + mCallingAppPackageName = PasswordUtils.getCallingAppPackageName( + getActivity().getActivityToken()); + if (!TextUtils.equals(mCallingAppPackageName, mLaunchPackage)) { + Log.w(TAG, "sendDevicePickedIntent() launch package name is not equivalent to" + + " calling package name!"); + } mContext = getContext(); setHasOptionsMenu(true); } @@ -189,6 +206,11 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment { private void sendDevicePickedIntent(BluetoothDevice device) { Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + if (mLaunchPackage != null && mLaunchClass != null) { + if (TextUtils.equals(mCallingAppPackageName, mLaunchPackage)) { + intent.setClassName(mLaunchPackage, mLaunchClass); + } + } mContext.sendBroadcast(intent, Manifest.permission.BLUETOOTH_ADMIN); } diff --git a/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java index d9e054d86a6..a05ec87b71b 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java @@ -16,8 +16,11 @@ package com.android.settings.bluetooth; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -66,16 +69,37 @@ public class DevicePickerFragmentTest { } @Test - public void sendBroadcastWithPermission() { + public void callingPackageIsEqualToLaunchPackage_sendBroadcastToLaunchPackage() { final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class); final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); when(cachedDevice.getDevice()).thenReturn(bluetoothDevice); mFragment.mSelectedDevice = bluetoothDevice; + mFragment.mLaunchPackage = "com.android.settings"; + mFragment.mLaunchClass = "com.android.settings.bluetooth.BluetoothPermissionActivity"; + mFragment.mCallingAppPackageName = "com.android.settings"; mFragment.onDeviceBondStateChanged(cachedDevice, BluetoothDevice.BOND_BONDED); verify(mContext).sendBroadcast(intentCaptor.capture(), eq("android.permission.BLUETOOTH_ADMIN")); + assertThat(intentCaptor.getValue().getComponent().getPackageName()) + .isEqualTo(mFragment.mLaunchPackage); + } + + @Test + public void callingPackageIsNotEqualToLaunchPackage_broadcastNotSend() { + final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); + final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class); + final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); + when(cachedDevice.getDevice()).thenReturn(bluetoothDevice); + mFragment.mSelectedDevice = bluetoothDevice; + mFragment.mLaunchPackage = "com.fake.settings"; + mFragment.mLaunchClass = "com.android.settings.bluetooth.BluetoothPermissionActivity"; + mFragment.mCallingAppPackageName = "com.android.settings"; + + mFragment.onDeviceBondStateChanged(cachedDevice, BluetoothDevice.BOND_BONDED); + + verify(mContext, never()).sendBroadcast(intentCaptor.capture()); } }