diff options
author | Jeff Davidson <jpd@google.com> | 2018-02-12 18:39:42 -0800 |
---|---|---|
committer | Jeff Davidson <jpd@google.com> | 2018-03-09 20:32:40 +0000 |
commit | ae1f9edc0c877c2ccc32ae8b30de974271def420 (patch) | |
tree | a738a01bd1cc6ab0b8cdabfe9c729a634515b163 /src | |
parent | ba7155f8367a25deec2b16069241731ff92a7257 (diff) | |
download | ContactsProvider-ae1f9edc0c877c2ccc32ae8b30de974271def420.tar.gz |
Allow carrier-privileged apps to access voicemail provider.
Bug: 70041899
Test: TreeHugger + tests in CL topic
Change-Id: Icd80caa6f755f549f2433ac4dcacb4a77c962077
Merged-In: Icd80caa6f755f549f2433ac4dcacb4a77c962077
(cherry picked from commit 9c57007fb2e6bbb3d0303320ce6938751240c1c7)
Diffstat (limited to 'src')
3 files changed, 76 insertions, 22 deletions
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java index 01c10481..1ced1be6 100644 --- a/src/com/android/providers/contacts/VoicemailContentProvider.java +++ b/src/com/android/providers/contacts/VoicemailContentProvider.java @@ -15,6 +15,7 @@ */ package com.android.providers.contacts; +import static android.app.AppOpsManager.MODE_ALLOWED; import static android.provider.VoicemailContract.SOURCE_PACKAGE_FIELD; import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses; @@ -23,13 +24,13 @@ import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.ContentProvider; -import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Binder; +import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.provider.BaseColumns; import android.provider.VoicemailContract; @@ -50,7 +51,6 @@ import com.google.common.annotations.VisibleForTesting; import java.io.FileNotFoundException; import java.util.Arrays; import java.util.List; -import java.util.Set; /** * An implementation of the Voicemail content provider. This class in the entry point for both @@ -83,8 +83,15 @@ public class VoicemailContentProvider extends ContentProvider } Context context = context(); - // ADD_VOICEMAIL permission guards read and write. We do the same with app ops. - // The permission name doesn't reflect its function but we cannot rename it. + // Read and write permission requires ADD_VOICEMAIL or carrier privileges. We can't declare + // any permission entries in the manifest because carrier-privileged apps without + // ADD_VOICEMAIL would be blocked by the platform without even reaching our custom + // enforce{Read,Write}PermissionInner functions. These overrides are what allow carrier- + // privileged apps to bypass these runtime-configured permissions. + // TODO(b/74245334): See if these can be removed since individual operations perform their + // own checks. + setReadPermission(android.Manifest.permission.ADD_VOICEMAIL); + setWritePermission(android.Manifest.permission.ADD_VOICEMAIL); setAppOps(AppOpsManager.OP_ADD_VOICEMAIL, AppOpsManager.OP_ADD_VOICEMAIL); mVoicemailPermissions = new VoicemailPermissions(context); @@ -110,6 +117,27 @@ public class VoicemailContentProvider extends ContentProvider return true; } + @Override + protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) + throws SecurityException { + // Permit carrier-privileged apps regardless of ADD_VOICEMAIL permission state. + if (mVoicemailPermissions.callerHasCarrierPrivileges()) { + return MODE_ALLOWED; + } + return super.enforceReadPermissionInner(uri, callingPkg, callerToken); + } + + + @Override + protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) + throws SecurityException { + // Permit carrier-privileged apps regardless of ADD_VOICEMAIL permission state. + if (mVoicemailPermissions.callerHasCarrierPrivileges()) { + return MODE_ALLOWED; + } + return super.enforceWritePermissionInner(uri, callingPkg, callerToken); + } + @VisibleForTesting void scheduleScanStalePackages() { scheduleTask(BACKGROUND_TASK_SCAN_STALE_PACKAGES, null); diff --git a/src/com/android/providers/contacts/VoicemailNotifier.java b/src/com/android/providers/contacts/VoicemailNotifier.java index 04a9bd64..159cec73 100644 --- a/src/com/android/providers/contacts/VoicemailNotifier.java +++ b/src/com/android/providers/contacts/VoicemailNotifier.java @@ -1,8 +1,5 @@ package com.android.providers.contacts; -import static android.Manifest.permission.ADD_VOICEMAIL; -import static android.Manifest.permission.READ_VOICEMAIL; - import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -15,6 +12,7 @@ import android.util.ArraySet; import android.util.Log; import com.google.android.collect.Lists; + import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -68,11 +66,16 @@ public class VoicemailNotifier { intentAction, uri)); for (ComponentName component : getBroadcastReceiverComponents(intentAction, uri)) { - // Ignore any package that is not affected by the change and don't have full access - // either. - if (!mModifiedPackages.contains(component.getPackageName()) && - !mVoicemailPermissions.packageHasReadAccess( - component.getPackageName())) { + boolean hasFullReadAccess = + mVoicemailPermissions.packageHasReadAccess(component.getPackageName()); + boolean hasOwnAccess = + mVoicemailPermissions.packageHasOwnVoicemailAccess( + component.getPackageName()); + // If we don't have full access, ignore the broadcast if the package isn't affected + // by the change or doesn't have access to its own messages. + if (!hasFullReadAccess + && (!mModifiedPackages.contains(component.getPackageName()) + || !hasOwnAccess)) { continue; } @@ -82,12 +85,10 @@ public class VoicemailNotifier { intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE, callingPackages.contains(component.getPackageName())); } - String permissionNeeded = mModifiedPackages.contains(component.getPackageName()) ? - ADD_VOICEMAIL : READ_VOICEMAIL; - mContext.sendBroadcast(intent, permissionNeeded); - Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s, perm:%s," + + mContext.sendBroadcast(intent); + Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s," + " self_change:%s", intent.getAction(), intent.getData(), - component.getClassName(), permissionNeeded, + component.getClassName(), intent.hasExtra(VoicemailContract.EXTRA_SELF_CHANGE) ? intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false) : null)); diff --git a/src/com/android/providers/contacts/VoicemailPermissions.java b/src/com/android/providers/contacts/VoicemailPermissions.java index 50f2447a..ed3815dc 100644 --- a/src/com/android/providers/contacts/VoicemailPermissions.java +++ b/src/com/android/providers/contacts/VoicemailPermissions.java @@ -16,10 +16,12 @@ package com.android.providers.contacts; -import com.android.providers.contacts.util.ContactsPermissions; - import android.content.Context; +import android.os.Binder; import android.telecom.DefaultDialerManager; +import android.telephony.TelephonyManager; + +import com.android.providers.contacts.util.ContactsPermissions; /** * Provides method related to check various voicemail permissions under the @@ -35,7 +37,8 @@ public class VoicemailPermissions { /** Determines if the calling process has access to its own voicemails. */ public boolean callerHasOwnVoicemailAccess() { - return callerHasPermission(android.Manifest.permission.ADD_VOICEMAIL); + return callerHasPermission(android.Manifest.permission.ADD_VOICEMAIL) + || callerHasCarrierPrivileges(); } /** Determine if the calling process has full read access to all voicemails. */ @@ -63,7 +66,7 @@ public class VoicemailPermissions { public void checkCallerHasOwnVoicemailAccess() { if (!callerHasOwnVoicemailAccess()) { throw new SecurityException("The caller must have permission: " + - android.Manifest.permission.ADD_VOICEMAIL); + android.Manifest.permission.ADD_VOICEMAIL + " or carrier privileges"); } } @@ -91,7 +94,8 @@ public class VoicemailPermissions { /** Determines if the given package has access to its own voicemails. */ public boolean packageHasOwnVoicemailAccess(String packageName) { return packageHasPermission(packageName, - android.Manifest.permission.ADD_VOICEMAIL); + android.Manifest.permission.ADD_VOICEMAIL) + || packageHasCarrierPrivileges(packageName); } /** Determines if the given package has read access. */ @@ -113,4 +117,25 @@ public class VoicemailPermissions { private boolean callerHasPermission(String permission) { return ContactsPermissions.hasCallerOrSelfPermission(mContext, permission); } + + /** Determines if the calling process has carrier privileges. */ + public boolean callerHasCarrierPrivileges() { + TelephonyManager tm = + (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + String[] packages = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid()); + for (String packageName : packages) { + if (tm.checkCarrierPrivilegesForPackageAnyPhone(packageName) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return true; + } + } + return false; + } + + /** Determines if the given package has carrier privileges. */ + private boolean packageHasCarrierPrivileges(String packageName) { + TelephonyManager tm = + (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + return tm.getPackagesWithCarrierPrivileges().contains(packageName); + } } |