Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f012baa6 authored by Malcolm Chen's avatar Malcolm Chen
Browse files

Clear caller Identity in PhoneSubInfoController

In PhoneSubInfoController clear caller's identity after
permisison check.

Bug: 73136824
Test: cts test
Change-Id: I5464e4049e8f4e293cca4a9255a99051238101c5
Merged-In: I5464e4049e8f4e293cca4a9255a99051238101c5
parent 76c9a2fd
Loading
Loading
Loading
Loading
+214 −262
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.ImsiEncryptionInfo;
@@ -60,80 +61,35 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getDeviceIdForPhone(int phoneId, String callingPackage) {
        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
            phoneId = 0;
        }
        final Phone phone = mPhone[phoneId];
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, phone.getSubId(), callingPackage, "getDeviceId")) {
                return null;
            }
            return phone.getDeviceId();
        } else {
            loge("getDeviceIdForPhone phone " + phoneId + " is null");
            return null;
        }
        return callPhoneMethodForPhoneIdWithReadCheck(phoneId, callingPackage,
                "getDeviceId", (phone)-> phone.getDeviceId());
    }

    public String getNaiForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getNai")) {
                return null;
            }
            return phone.getNai();
        } else {
            loge("getNai phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getNai",
                (phone)-> phone.getNai());
    }

    public String getImeiForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getImei")) {
                return null;
            }
            return phone.getImei();
        } else {
            loge("getDeviceId phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getImei",
                (phone)-> phone.getImei());
    }

    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
                                                              String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage,
                    "getCarrierInfoForImsiEncryption")) {
                return null;
            }
            return phone.getCarrierInfoForImsiEncryption(keyType);
        } else {
            loge("getCarrierInfoForImsiEncryption phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
                "getCarrierInfoForImsiEncryption",
                (phone)-> phone.getCarrierInfoForImsiEncryption(keyType));
    }

    public void setCarrierInfoForImsiEncryption(int subId, String callingPackage,
                                                ImsiEncryptionInfo imsiEncryptionInfo) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "setCarrierInfoForImsiEncryption")) {
                return;
            }
            enforceModifyPermission();
        callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
                "setCarrierInfoForImsiEncryption",
                (phone)-> {
                    phone.setCarrierInfoForImsiEncryption(imsiEncryptionInfo);
        } else {
            loge("setCarrierInfoForImsiEncryption phone is null for Subscription:" + subId);
            return;
        }
                    return null;
                });
    }

    /**
@@ -144,15 +100,12 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
     *  @param callingPackage
     */
    public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            enforceModifyPermission();
        callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
                "setCarrierInfoForImsiEncryption",
                (phone)-> {
                    phone.resetCarrierKeysForImsiEncryption();
            return;
        } else {
            loge("resetCarrierKeysForImsiEncryption phone is null for Subscription:" + subId);
            return;
        }
                    return null;
                });
    }


@@ -161,17 +114,8 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getDeviceSvnUsingSubId(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getDeviceSvn")) {
                return null;
            }
            return phone.getDeviceSvn();
        } else {
            loge("getDeviceSvn phone is null");
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getDeviceSvn",
                (phone)-> phone.getDeviceSvn());
    }

    public String getSubscriberId(String callingPackage) {
@@ -179,17 +123,8 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getSubscriberIdForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getSubscriberId")) {
                return null;
            }
            return phone.getSubscriberId();
        } else {
            loge("getSubscriberId phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getSubscriberId",
                (phone)-> phone.getSubscriberId());
    }

    /**
@@ -200,17 +135,8 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getIccSerialNumberForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getIccSerialNumber")) {
                return null;
            }
            return phone.getIccSerialNumber();
        } else {
            loge("getIccSerialNumber phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getIccSerialNumber",
                (phone)-> phone.getIccSerialNumber());
    }

    public String getLine1Number(String callingPackage) {
@@ -218,18 +144,9 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getLine1NumberForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            // This is open to apps with WRITE_SMS.
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
                    mContext, subId, callingPackage, "getLine1Number")) {
                return null;
            }
            return phone.getLine1Number();
        } else {
            loge("getLine1Number phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadPhoneNumberCheck(
                subId, callingPackage, "getLine1Number",
                (phone)-> phone.getLine1Number());
    }

    public String getLine1AlphaTag(String callingPackage) {
@@ -237,17 +154,8 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getLine1AlphaTagForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getLine1AlphaTag")) {
                return null;
            }
            return phone.getLine1AlphaTag();
        } else {
            loge("getLine1AlphaTag phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getLine1AlphaTag",
                (phone)-> phone.getLine1AlphaTag());
    }

    public String getMsisdn(String callingPackage) {
@@ -255,17 +163,8 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getMsisdnForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getMsisdn")) {
                return null;
            }
            return phone.getMsisdn();
        } else {
            loge("getMsisdn phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, "getMsisdn",
                (phone)-> phone.getMsisdn());
    }

    public String getVoiceMailNumber(String callingPackage) {
@@ -273,19 +172,13 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getVoiceMailNumberForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getVoiceMailNumber")) {
                return null;
            }
            String number = PhoneNumberUtils.extractNetworkPortion(phone.getVoiceMailNumber());
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
                "getVoiceMailNumber", (phone)-> {
                    String number = PhoneNumberUtils.extractNetworkPortion(
                            phone.getVoiceMailNumber());
                    if (VDBG) log("VM: getVoiceMailNUmber: " + number);
                    return number;
        } else {
            loge("getVoiceMailNumber phone is null for Subscription:" + subId);
            return null;
        }
                });
    }

    // TODO: change getCompleteVoiceMailNumber() to require READ_PRIVILEGED_PHONE_STATE
@@ -311,17 +204,8 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
    }

    public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getVoiceMailAlphaTag")) {
                return null;
            }
            return phone.getVoiceMailAlphaTag();
        } else {
            loge("getVoiceMailAlphaTag phone is null for Subscription:" + subId);
            return null;
        }
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
                "getVoiceMailAlphaTag", (phone)-> phone.getVoiceMailAlphaTag());
    }

    /**
@@ -341,6 +225,9 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
     * @throws SecurityException if the caller does not have the required permission/privilege
     */
    private void enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message) {
        // TODO(b/73660190): Migrate to
        // TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivileges and delete
        // this helper method.
        int permissionResult = mContext.checkCallingOrSelfPermission(
                READ_PRIVILEGED_PHONE_STATE);
        if (permissionResult == PackageManager.PERMISSION_GRANTED) {
@@ -362,114 +249,84 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
        return  PhoneFactory.getDefaultSubscription();
    }


    /**
    * get the Isim Impi based on subId
    */
    public String getIsimImpi(int subId) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
                    "Requires READ_PRIVILEGED_PHONE_STATE");
        return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimImpi",
                (phone) -> {
                    IsimRecords isim = phone.getIsimRecords();
                    if (isim != null) {
                        return isim.getIsimImpi();
                    } else {
                        return null;
                    }
        } else {
            loge("getIsimImpi phone is null for Subscription:" + subId);
            return null;
        }
                });
    }

    /**
    * get the Isim Domain based on subId
    */
    public String getIsimDomain(int subId) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
                    "Requires READ_PRIVILEGED_PHONE_STATE");
        return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimDomain",
                (phone) -> {
                    IsimRecords isim = phone.getIsimRecords();
                    if (isim != null) {
                        return isim.getIsimDomain();
                    } else {
                        return null;
                    }
        } else {
            loge("getIsimDomain phone is null for Subscription:" + subId);
            return null;
        }
                });
    }

    /**
    * get the Isim Impu based on subId
    */
    public String[] getIsimImpu(int subId) {
        Phone phone = getPhone(subId);
        if (phone != null) {
            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
                    "Requires READ_PRIVILEGED_PHONE_STATE");
        return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimImpu",
                (phone) -> {
                    IsimRecords isim = phone.getIsimRecords();
                    if (isim != null) {
                        return isim.getIsimImpu();
                    } else {
                        return null;
                    }
        } else {
            loge("getIsimImpu phone is null for Subscription:" + subId);
            return null;
        }
                });
    }

    /**
    * get the Isim Ist based on subId
    */
    public String getIsimIst(int subId) throws RemoteException {
        Phone phone = getPhone(subId);
        if (phone != null) {
            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
                    "Requires READ_PRIVILEGED_PHONE_STATE");
        return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimIst",
                (phone) -> {
                    IsimRecords isim = phone.getIsimRecords();
                    if (isim != null) {
                        return isim.getIsimIst();
                    } else {
                        return null;
                    }
        } else {
            loge("getIsimIst phone is null for Subscription:" + subId);
            return null;
        }
                });
    }

    /**
    * get the Isim Pcscf based on subId
    */
    public String[] getIsimPcscf(int subId) throws RemoteException {
        Phone phone = getPhone(subId);
        if (phone != null) {
            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
                    "Requires READ_PRIVILEGED_PHONE_STATE");
        return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimPcscf",
                (phone) -> {
                    IsimRecords isim = phone.getIsimRecords();
                    if (isim != null) {
                        return isim.getIsimPcscf();
                    } else {
                        return null;
                    }
        } else {
            loge("getIsimPcscf phone is null for Subscription:" + subId);
            return null;
        }
                });
    }

    public String getIccSimChallengeResponse(int subId, int appType, int authType, String data)
            throws RemoteException {
        // TODO(b/73660190): Migrate to
        // TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivileges and delete
        // this helper method.
        enforcePrivilegedPermissionOrCarrierPrivilege(subId, "getIccSimChallengeResponse");
        Phone phone = getPhone(subId);
        CallPhoneMethodHelper<String> toExecute = (phone)-> {
            UiccCard uiccCard = phone.getUiccCard();
            if (uiccCard == null) {
                loge("getIccSimChallengeResponse() UiccCard is null");
@@ -478,35 +335,130 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {

            UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
            if (uiccApp == null) {
            loge("getIccSimChallengeResponse() no app with specified type -- " +
                    appType);
                loge("getIccSimChallengeResponse() no app with specified type -- " + appType);
                return null;
            } else {
                loge("getIccSimChallengeResponse() found app " + uiccApp.getAid()
                        + " specified type -- " + appType);
            }

        if(authType != UiccCardApplication.AUTH_CONTEXT_EAP_SIM &&
                authType != UiccCardApplication.AUTH_CONTEXT_EAP_AKA) {
            if (authType != UiccCardApplication.AUTH_CONTEXT_EAP_SIM
                    && authType != UiccCardApplication.AUTH_CONTEXT_EAP_AKA) {
                loge("getIccSimChallengeResponse() unsupported authType: " + authType);
                return null;
            }

            return uiccApp.getIccRecords().getIccSimChallengeResponse(authType, data);
        };

        return callPhoneMethodWithPermissionCheck(
                subId, null, "getIccSimChallengeResponse", toExecute,
                (aContext, aSubId, aCallingPackage, aMessage)-> {
                    enforcePrivilegedPermissionOrCarrierPrivilege(aSubId, aMessage);
                    return true;
                });
    }

    public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage) {
        return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
                "getGroupIdLevel1", (phone)-> phone.getGroupIdLevel1());
    }

    /** Below are utility methods that abstracts the flow that many public methods use:
     *  1. Check permission: pass, throw exception, or fails (returns false).
     *  2. clearCallingIdentity.
     *  3. Call a specified phone method and get return value.
     *  4. restoreCallingIdentity and return.
     */
    private interface CallPhoneMethodHelper<T> {
        T callMethod(Phone phone);
    }

    private interface PermissionCheckHelper {
        // Implemented to do whatever permission check it wants.
        // If passes, it should return true.
        // If permission is not granted, throws SecurityException.
        // If permission is revoked by AppOps, return false.
        boolean checkPermission(Context context, int subId, String callingPackage, String message);
    }

    // Base utility method that others use.
    private <T> T callPhoneMethodWithPermissionCheck(int subId, String callingPackage,
            String message, CallPhoneMethodHelper<T> callMethodHelper,
            PermissionCheckHelper permissionCheckHelper) {
        if (!permissionCheckHelper.checkPermission(mContext, subId, callingPackage, message)) {
            return null;
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            Phone phone = getPhone(subId);
            if (phone != null) {
            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                    mContext, subId, callingPackage, "getGroupIdLevel1")) {
                return callMethodHelper.callMethod(phone);
            } else {
                loge(message + " phone is null for Subscription:" + subId);
                return null;
            }
            return phone.getGroupIdLevel1();
        } else {
            loge("getGroupIdLevel1 phone is null for Subscription:" + subId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    private <T> T callPhoneMethodForSubIdWithReadCheck(int subId, String callingPackage,
            String message, CallPhoneMethodHelper<T> callMethodHelper) {
        return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
                (aContext, aSubId, aCallingPackage, aMessage)->
                        TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                                aContext, aSubId, aCallingPackage, aMessage));
    }

    private <T> T callPhoneMethodForSubIdWithPrivilegedCheck(
            int subId, String message, CallPhoneMethodHelper<T> callMethodHelper) {
        return callPhoneMethodWithPermissionCheck(subId, null, message, callMethodHelper,
                (aContext, aSubId, aCallingPackage, aMessage)-> {
                    mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message);
                    return true;
                });
    }

    private <T> T callPhoneMethodForSubIdWithModifyCheck(int subId, String callingPackage,
            String message, CallPhoneMethodHelper<T> callMethodHelper) {
        return callPhoneMethodWithPermissionCheck(subId, null, message, callMethodHelper,
                (aContext, aSubId, aCallingPackage, aMessage)-> {
                    enforceModifyPermission();
                    return true;
                });
    }

    private <T> T callPhoneMethodForSubIdWithReadPhoneNumberCheck(int subId, String callingPackage,
            String message, CallPhoneMethodHelper<T> callMethodHelper) {
        return callPhoneMethodWithPermissionCheck(subId, callingPackage, message, callMethodHelper,
                (aContext, aSubId, aCallingPackage, aMessage)->
                        TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
                                aContext, aSubId, aCallingPackage, aMessage));
    }

    private <T> T callPhoneMethodForPhoneIdWithReadCheck(int phoneId, String callingPackage,
            String message, CallPhoneMethodHelper<T> callMethodHelper) {
        // Getting subId before doing permission check.
        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
            phoneId = 0;
        }
        final Phone phone = mPhone[phoneId];
        if (phone == null) {
            return null;
        }

        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                mContext, phone.getSubId(), callingPackage, message)) {
            return null;
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            return callMethodHelper.callMethod(phone);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    private void log(String s) {