Loading src/java/com/android/internal/telephony/SmsPermissions.java +36 −26 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.os.Binder; import android.service.carrier.CarrierMessagingService; import android.service.carrier.CarrierMessagingService; import android.util.Log; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.telephony.Rlog; import com.android.telephony.Rlog; /** /** Loading Loading @@ -138,21 +139,11 @@ public class SmsPermissions { */ */ public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { if (!isCallerDefaultSmsPackage(callingPackage)) { try { // Allow it with READ_PRIVILEGED_PHONE_STATE or Carrier Privileges TelephonyPermissions TelephonyPermissions .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications loge(message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE + ", or carrier privileges", e); return false; } } } return true; return true; } } Loading @@ -167,26 +158,45 @@ public class SmsPermissions { */ */ public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { if (!isCallerDefaultSmsPackage(callingPackage)) { try { // Allow it with MODIFY_PHONE_STATE or Carrier Privileges // Allow it with MODIFY_PHONE_STATE or Carrier Privileges TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications loge(message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.MODIFY_PHONE_STATE + ", or carrier privileges", e); return false; } } } return true; return true; } } /** Check if a package is default SMS app. */ /** Check if a package is default SMS app. */ public boolean isDefaultSmsPackage(String packageName) { @VisibleForTesting public boolean isCallerDefaultSmsPackage(String packageName) { if (packageNameMatchesCallingUid(packageName)) { return SmsApplication.isDefaultSmsApplication(mContext, packageName); return SmsApplication.isDefaultSmsApplication(mContext, packageName); } } return false; } /** * Check if the passed in packageName belongs to the calling uid. * @param packageName name of the package to check * @return true if package belongs to calling uid, false otherwise */ @VisibleForTesting public boolean packageNameMatchesCallingUid(String packageName) { try { if (Binder.getCallingUid() != mContext.getPackageManager().getPackageUid(packageName, 0)) { Log.e(LOG_TAG, "packageNameMatchesCallingUid: " + packageName + " uid " + mContext.getPackageManager().getPackageUid(packageName, 0) + " does not match calling uid " + Binder.getCallingUid()); return false; } } catch (PackageManager.NameNotFoundException ex) { Log.e(LOG_TAG, "packageNameMatchesCallingUid: packageName " + packageName + " not found"); return false; } return true; } @UnsupportedAppUsage @UnsupportedAppUsage protected void log(String msg) { protected void log(String msg) { Loading tests/telephonytests/src/com/android/internal/telephony/SmsPermissionsTest.java +47 −3 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,19 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assert.fail; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import android.Manifest; import android.Manifest; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.content.Context; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Binder; import android.os.Handler; import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.util.Log; import org.junit.After; import org.junit.After; import org.junit.Before; import org.junit.Before; Loading Loading @@ -76,7 +82,7 @@ public class SmsPermissionsTest extends TelephonyTest { } } @Override @Override public boolean isDefaultSmsPackage(String packageName) { public boolean isCallerDefaultSmsPackage(String packageName) { return mCallerIsDefaultSmsPackage; return mCallerIsDefaultSmsPackage; } } }; }; Loading Loading @@ -205,7 +211,12 @@ public class SmsPermissionsTest extends TelephonyTest { Mockito.when(mMockContext.checkCallingOrSelfPermission( Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); .thenReturn(PERMISSION_DENIED); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); try { mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE); fail(); } catch (SecurityException e) { // expected } } } @Test @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_defaultSmsApp() { public void testCheckCallingOrSelfCanSetSmscAddressPermissions_defaultSmsApp() { Loading @@ -231,6 +242,39 @@ public class SmsPermissionsTest extends TelephonyTest { mTelephonyManager); mTelephonyManager); Mockito.when(mMockContext.checkCallingOrSelfPermission( Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)).thenReturn(PERMISSION_DENIED); Manifest.permission.MODIFY_PHONE_STATE)).thenReturn(PERMISSION_DENIED); try { assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); fail(); } catch (SecurityException e) { // expected } } @Test public void testPackageNameMatchesCallingUid() { PackageManager mockPackageManager = mock(PackageManager.class); doReturn(mockPackageManager).when(mMockContext).getPackageManager(); // test matching case try { doReturn(Binder.getCallingUid()).when(mockPackageManager) .getPackageUid(eq(PACKAGE), anyInt()); } catch (Exception e) { Log.e(TAG, "testPackageNameMatchesCallingUid: unable to setup mocks"); fail(); } assertTrue(new SmsPermissions(mMockPhone, mMockContext, mMockAppOps) .packageNameMatchesCallingUid(PACKAGE)); // test mis-match case try { doReturn(Binder.getCallingUid() + 1).when(mockPackageManager) .getPackageUid(eq(PACKAGE), anyInt()); } catch (Exception e) { Log.e(TAG, "testPackageNameMatchesCallingUid: unable to setup mocks"); fail(); } assertFalse(new SmsPermissions(mMockPhone, mMockContext, mMockAppOps) .packageNameMatchesCallingUid(PACKAGE)); } } } } Loading
src/java/com/android/internal/telephony/SmsPermissions.java +36 −26 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.os.Binder; import android.service.carrier.CarrierMessagingService; import android.service.carrier.CarrierMessagingService; import android.util.Log; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.telephony.Rlog; import com.android.telephony.Rlog; /** /** Loading Loading @@ -138,21 +139,11 @@ public class SmsPermissions { */ */ public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { public boolean checkCallingOrSelfCanGetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { if (!isCallerDefaultSmsPackage(callingPackage)) { try { // Allow it with READ_PRIVILEGED_PHONE_STATE or Carrier Privileges TelephonyPermissions TelephonyPermissions .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications loge(message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE + ", or carrier privileges", e); return false; } } } return true; return true; } } Loading @@ -167,26 +158,45 @@ public class SmsPermissions { */ */ public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { public boolean checkCallingOrSelfCanSetSmscAddress(String callingPackage, String message) { // Allow it to the default SMS app always. // Allow it to the default SMS app always. if (!isDefaultSmsPackage(callingPackage)) { if (!isCallerDefaultSmsPackage(callingPackage)) { try { // Allow it with MODIFY_PHONE_STATE or Carrier Privileges // Allow it with MODIFY_PHONE_STATE or Carrier Privileges TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( mContext, mPhone.getSubId(), message); mContext, mPhone.getSubId(), message); } catch (SecurityException e) { // To avoid crashing applications loge(message + ": Neither " + callingPackage + " is the default SMS app" + " nor the caller has " + android.Manifest.permission.MODIFY_PHONE_STATE + ", or carrier privileges", e); return false; } } } return true; return true; } } /** Check if a package is default SMS app. */ /** Check if a package is default SMS app. */ public boolean isDefaultSmsPackage(String packageName) { @VisibleForTesting public boolean isCallerDefaultSmsPackage(String packageName) { if (packageNameMatchesCallingUid(packageName)) { return SmsApplication.isDefaultSmsApplication(mContext, packageName); return SmsApplication.isDefaultSmsApplication(mContext, packageName); } } return false; } /** * Check if the passed in packageName belongs to the calling uid. * @param packageName name of the package to check * @return true if package belongs to calling uid, false otherwise */ @VisibleForTesting public boolean packageNameMatchesCallingUid(String packageName) { try { if (Binder.getCallingUid() != mContext.getPackageManager().getPackageUid(packageName, 0)) { Log.e(LOG_TAG, "packageNameMatchesCallingUid: " + packageName + " uid " + mContext.getPackageManager().getPackageUid(packageName, 0) + " does not match calling uid " + Binder.getCallingUid()); return false; } } catch (PackageManager.NameNotFoundException ex) { Log.e(LOG_TAG, "packageNameMatchesCallingUid: packageName " + packageName + " not found"); return false; } return true; } @UnsupportedAppUsage @UnsupportedAppUsage protected void log(String msg) { protected void log(String msg) { Loading
tests/telephonytests/src/com/android/internal/telephony/SmsPermissionsTest.java +47 −3 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,19 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assert.fail; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import android.Manifest; import android.Manifest; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.content.Context; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Binder; import android.os.Handler; import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.util.Log; import org.junit.After; import org.junit.After; import org.junit.Before; import org.junit.Before; Loading Loading @@ -76,7 +82,7 @@ public class SmsPermissionsTest extends TelephonyTest { } } @Override @Override public boolean isDefaultSmsPackage(String packageName) { public boolean isCallerDefaultSmsPackage(String packageName) { return mCallerIsDefaultSmsPackage; return mCallerIsDefaultSmsPackage; } } }; }; Loading Loading @@ -205,7 +211,12 @@ public class SmsPermissionsTest extends TelephonyTest { Mockito.when(mMockContext.checkCallingOrSelfPermission( Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) .thenReturn(PERMISSION_DENIED); .thenReturn(PERMISSION_DENIED); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE)); try { mSmsPermissionsTest.checkCallingOrSelfCanGetSmscAddress(PACKAGE, MESSAGE); fail(); } catch (SecurityException e) { // expected } } } @Test @Test public void testCheckCallingOrSelfCanSetSmscAddressPermissions_defaultSmsApp() { public void testCheckCallingOrSelfCanSetSmscAddressPermissions_defaultSmsApp() { Loading @@ -231,6 +242,39 @@ public class SmsPermissionsTest extends TelephonyTest { mTelephonyManager); mTelephonyManager); Mockito.when(mMockContext.checkCallingOrSelfPermission( Mockito.when(mMockContext.checkCallingOrSelfPermission( Manifest.permission.MODIFY_PHONE_STATE)).thenReturn(PERMISSION_DENIED); Manifest.permission.MODIFY_PHONE_STATE)).thenReturn(PERMISSION_DENIED); try { assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); assertFalse(mSmsPermissionsTest.checkCallingOrSelfCanSetSmscAddress(PACKAGE, MESSAGE)); fail(); } catch (SecurityException e) { // expected } } @Test public void testPackageNameMatchesCallingUid() { PackageManager mockPackageManager = mock(PackageManager.class); doReturn(mockPackageManager).when(mMockContext).getPackageManager(); // test matching case try { doReturn(Binder.getCallingUid()).when(mockPackageManager) .getPackageUid(eq(PACKAGE), anyInt()); } catch (Exception e) { Log.e(TAG, "testPackageNameMatchesCallingUid: unable to setup mocks"); fail(); } assertTrue(new SmsPermissions(mMockPhone, mMockContext, mMockAppOps) .packageNameMatchesCallingUid(PACKAGE)); // test mis-match case try { doReturn(Binder.getCallingUid() + 1).when(mockPackageManager) .getPackageUid(eq(PACKAGE), anyInt()); } catch (Exception e) { Log.e(TAG, "testPackageNameMatchesCallingUid: unable to setup mocks"); fail(); } assertFalse(new SmsPermissions(mMockPhone, mMockContext, mMockAppOps) .packageNameMatchesCallingUid(PACKAGE)); } } } }