/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.integrity;

import static android.content.Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION;
import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
import static android.content.Intent.EXTRA_ORIGINATING_UID;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
import static android.content.integrity.InstallerAllowedByManifestFormula.INSTALLER_CERTIFICATE_NOT_EVALUATED;
import static android.content.integrity.IntegrityUtils.getHexDigest;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.IAppIntegrityManager;
import android.content.integrity.Rule;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
import android.content.pm.parsing.ApkParseUtils;
import android.content.pm.parsing.PackageInfoUtils;
import android.content.pm.parsing.ParsedPackage;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.LocalServices;
import com.android.server.integrity.engine.RuleEvaluationEngine;
import com.android.server.integrity.model.IntegrityCheckResult;
import com.android.server.integrity.model.RuleMetadata;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Implementation of {@link AppIntegrityManagerService}. */
public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
    /**
     * This string will be used as the "installer" for formula evaluation when the app's installer
     * cannot be determined.
     *
     * <p>This may happen for various reasons. e.g., the installing app's package name may not match
     * its UID.
     */
    private static final String UNKNOWN_INSTALLER = "";
    /**
     * This string will be used as the "installer" for formula evaluation when the app is being
     * installed via ADB.
     */
    public static final String ADB_INSTALLER = "adb";

    private static final String TAG = "AppIntegrityManagerServiceImpl";

    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
    private static final String PACKAGE_INSTALLER = "com.google.android.packageinstaller";
    private static final String BASE_APK_FILE = "base.apk";
    private static final String ALLOWED_INSTALLERS_METADATA_NAME = "allowed-installers";
    private static final String ALLOWED_INSTALLER_DELIMITER = ",";
    private static final String INSTALLER_PACKAGE_CERT_DELIMITER = "\\|";

    // Access to files inside mRulesDir is protected by mRulesLock;
    private final Context mContext;
    private final Handler mHandler;
    private final PackageManagerInternal mPackageManagerInternal;
    private final RuleEvaluationEngine mEvaluationEngine;
    private final IntegrityFileManager mIntegrityFileManager;

    private final boolean mCheckIntegrityForRuleProviders;

    /** Create an instance of {@link AppIntegrityManagerServiceImpl}. */
    public static AppIntegrityManagerServiceImpl create(Context context) {
        HandlerThread handlerThread = new HandlerThread("AppIntegrityManagerServiceHandler");
        handlerThread.start();

        return new AppIntegrityManagerServiceImpl(
                context,
                LocalServices.getService(PackageManagerInternal.class),
                RuleEvaluationEngine.getRuleEvaluationEngine(),
                IntegrityFileManager.getInstance(),
                handlerThread.getThreadHandler(),
                Settings.Global.getInt(
                        context.getContentResolver(),
                        Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
                        0)
                        == 1
        );
    }

    @VisibleForTesting
    AppIntegrityManagerServiceImpl(
            Context context,
            PackageManagerInternal packageManagerInternal,
            RuleEvaluationEngine evaluationEngine,
            IntegrityFileManager integrityFileManager,
            Handler handler,
            boolean checkIntegrityForRuleProviders) {
        mContext = context;
        mPackageManagerInternal = packageManagerInternal;
        mEvaluationEngine = evaluationEngine;
        mIntegrityFileManager = integrityFileManager;
        mHandler = handler;
        mCheckIntegrityForRuleProviders = checkIntegrityForRuleProviders;

        IntentFilter integrityVerificationFilter = new IntentFilter();
        integrityVerificationFilter.addAction(ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
        try {
            integrityVerificationFilter.addDataType(PACKAGE_MIME_TYPE);
        } catch (IntentFilter.MalformedMimeTypeException e) {
            throw new RuntimeException("Mime type malformed: should never happen.", e);
        }

        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        if (!ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION.equals(
                                intent.getAction())) {
                            return;
                        }
                        mHandler.post(() -> handleIntegrityVerification(intent));
                    }
                },
                integrityVerificationFilter,
                /* broadcastPermission= */ null,
                mHandler);
    }

    @Override
    public void updateRuleSet(
            String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver) {
        String ruleProvider = getCallerPackageNameOrThrow();

        mHandler.post(
                () -> {
                    boolean success = true;
                    try {
                        mIntegrityFileManager.writeRules(version, ruleProvider, rules.getList());
                    } catch (Exception e) {
                        Slog.e(TAG, "Error writing rules.", e);
                        success = false;
                    }

                    FrameworkStatsLog.write(FrameworkStatsLog.INTEGRITY_RULES_PUSHED, success,
                            ruleProvider, version);

                    Intent intent = new Intent();
                    intent.putExtra(EXTRA_STATUS, success ? STATUS_SUCCESS : STATUS_FAILURE);
                    try {
                        statusReceiver.sendIntent(
                                mContext,
                                /* code= */ 0,
                                intent,
                                /* onFinished= */ null,
                                /* handler= */ null);
                    } catch (IntentSender.SendIntentException e) {
                        Slog.e(TAG, "Error sending status feedback.", e);
                    }
                });
    }

    @Override
    public String getCurrentRuleSetVersion() {
        getCallerPackageNameOrThrow();

        RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
        return (ruleMetadata != null && ruleMetadata.getVersion() != null)
                ? ruleMetadata.getVersion()
                : "";
    }

    @Override
    public String getCurrentRuleSetProvider() {
        getCallerPackageNameOrThrow();

        RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
        return (ruleMetadata != null && ruleMetadata.getRuleProvider() != null)
                ? ruleMetadata.getRuleProvider()
                : "";
    }

    @Override
    public ParceledListSlice<Rule> getCurrentRules() {
        List<Rule> rules = Collections.emptyList();
        try {
            rules = mIntegrityFileManager.readRules(/* appInstallMetadata= */ null);
        } catch (Exception e) {
            Slog.e(TAG, "Error getting current rules", e);
        }
        return new ParceledListSlice<>(rules);
    }

    private void handleIntegrityVerification(Intent intent) {
        int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);

        try {
            Slog.i(TAG, "Received integrity verification intent " + intent.toString());
            Slog.i(TAG, "Extras " + intent.getExtras());

            String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);

            PackageInfo packageInfo = getPackageArchiveInfo(intent.getData());
            if (packageInfo == null) {
                Slog.w(TAG, "Cannot parse package " + packageName);
                // We can't parse the package.
                mPackageManagerInternal.setIntegrityVerificationResult(
                        verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
                return;
            }

            String installerPackageName = getInstallerPackageName(intent);

            // Skip integrity verification if the verifier is doing the install.
            if (!mCheckIntegrityForRuleProviders
                    && isRuleProvider(installerPackageName)) {
                Slog.i(TAG, "Verifier doing the install. Skipping integrity check.");
                mPackageManagerInternal.setIntegrityVerificationResult(
                        verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
                return;
            }

            List<String> appCertificates = getCertificateFingerprint(packageInfo);
            List<String> installerCertificates =
                    getInstallerCertificateFingerprint(installerPackageName);

            Slog.w(TAG, appCertificates.toString());

            AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder();

            builder.setPackageName(getPackageNameNormalized(packageName));
            builder.setAppCertificates(appCertificates);
            builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1));
            builder.setInstallerName(getPackageNameNormalized(installerPackageName));
            builder.setInstallerCertificates(installerCertificates);
            builder.setIsPreInstalled(isSystemApp(packageName));
            builder.setAllowedInstallersAndCert(getAllowedInstallers(packageInfo));

            AppInstallMetadata appInstallMetadata = builder.build();

            Slog.i(
                    TAG,
                    "To be verified: " + appInstallMetadata + " installers " + getAllowedInstallers(
                            packageInfo));
            IntegrityCheckResult result =
                    mEvaluationEngine.evaluate(appInstallMetadata);
            Slog.i(
                    TAG,
                    "Integrity check result: "
                            + result.getEffect()
                            + " due to "
                            + result.getMatchedRules());

            FrameworkStatsLog.write(
                    FrameworkStatsLog.INTEGRITY_CHECK_RESULT_REPORTED,
                    packageName,
                    appCertificates.toString(),
                    appInstallMetadata.getVersionCode(),
                    installerPackageName,
                    result.getLoggingResponse(),
                    result.isCausedByAppCertRule(),
                    result.isCausedByInstallerRule());
            mPackageManagerInternal.setIntegrityVerificationResult(
                    verificationId,
                    result.getEffect() == IntegrityCheckResult.Effect.ALLOW
                            ? PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW
                            : PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
        } catch (IllegalArgumentException e) {
            // This exception indicates something is wrong with the input passed by package manager.
            // e.g., someone trying to trick the system. We block installs in this case.
            Slog.e(TAG, "Invalid input to integrity verification", e);
            mPackageManagerInternal.setIntegrityVerificationResult(
                    verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
        } catch (Exception e) {
            // Other exceptions indicate an error within the integrity component implementation and
            // we allow them.
            Slog.e(TAG, "Error handling integrity verification", e);
            mPackageManagerInternal.setIntegrityVerificationResult(
                    verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
        }
    }

    /**
     * Verify the UID and return the installer package name.
     *
     * @return the package name of the installer, or null if it cannot be determined or it is
     * installed via adb.
     */
    @Nullable
    private String getInstallerPackageName(Intent intent) {
        String installer =
                intent.getStringExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE);
        if (installer == null) {
            return ADB_INSTALLER;
        }
        int installerUid = intent.getIntExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID, -1);
        if (installerUid < 0) {
            Slog.e(
                    TAG,
                    "Installer cannot be determined: installer: "
                            + installer
                            + " installer UID: "
                            + installerUid);
            return UNKNOWN_INSTALLER;
        }

        try {
            int actualInstallerUid =
                    mContext.getPackageManager().getPackageUid(installer, /* flags= */ 0);
            if (actualInstallerUid != installerUid) {
                // Installer package name can be faked but the installerUid cannot.
                Slog.e(
                        TAG,
                        "Installer "
                                + installer
                                + " has UID "
                                + actualInstallerUid
                                + " which doesn't match alleged installer UID "
                                + installerUid);
                return UNKNOWN_INSTALLER;
            }
        } catch (PackageManager.NameNotFoundException e) {
            Slog.e(TAG, "Installer package " + installer + " not found.");
            return UNKNOWN_INSTALLER;
        }

        // At this time we can trust "installer".

        // A common way for apps to install packages is to send an intent to PackageInstaller. In
        // that case, the installer will always show up as PackageInstaller which is not what we
        // want.
        if (installer.equals(PACKAGE_INSTALLER)) {
            int originatingUid = intent.getIntExtra(EXTRA_ORIGINATING_UID, -1);
            if (originatingUid < 0) {
                Slog.e(TAG, "Installer is package installer but originating UID not found.");
                return UNKNOWN_INSTALLER;
            }
            String[] installerPackages =
                    mContext.getPackageManager().getPackagesForUid(originatingUid);
            if (installerPackages == null || installerPackages.length == 0) {
                Slog.e(TAG, "No package found associated with originating UID " + originatingUid);
                return UNKNOWN_INSTALLER;
            }
            // In the case of multiple package sharing a UID, we just return the first one.
            return installerPackages[0];
        }

        return installer;
    }

    /** We will use the SHA256 digest of a package name if it is more than 32 bytes long. */
    private String getPackageNameNormalized(String packageName) {
        if (packageName.length() <= 32) {
            return packageName;
        }

        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = messageDigest.digest(packageName.getBytes(StandardCharsets.UTF_8));
            return getHexDigest(hashBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256 algorithm not found", e);
        }
    }

    private List<String> getInstallerCertificateFingerprint(String installer) {
        if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) {
            return Collections.emptyList();
        }
        try {
            PackageInfo installerInfo =
                    mContext.getPackageManager()
                            .getPackageInfo(installer, PackageManager.GET_SIGNING_CERTIFICATES);
            return getCertificateFingerprint(installerInfo);
        } catch (PackageManager.NameNotFoundException e) {
            Slog.i(TAG, "Installer package " + installer + " not found.");
            return Collections.emptyList();
        }
    }

    private List<String> getCertificateFingerprint(@NonNull PackageInfo packageInfo) {
        ArrayList<String> certificateFingerprints = new ArrayList();
        for (Signature signature : getSignatures(packageInfo)) {
            certificateFingerprints.add(getFingerprint(signature));
        }
        return certificateFingerprints;
    }

    /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */
    private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) {
        Map<String, String> packageCertMap = new HashMap<>();
        if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.metaData != null) {
            Bundle metaData = packageInfo.applicationInfo.metaData;
            String allowedInstallers = metaData.getString(ALLOWED_INSTALLERS_METADATA_NAME);
            if (allowedInstallers != null) {
                // parse the metadata for certs.
                String[] installerCertPairs = allowedInstallers.split(ALLOWED_INSTALLER_DELIMITER);
                for (String packageCertPair : installerCertPairs) {
                    String[] packageAndCert =
                            packageCertPair.split(INSTALLER_PACKAGE_CERT_DELIMITER);
                    if (packageAndCert.length == 2) {
                        String packageName = getPackageNameNormalized(packageAndCert[0]);
                        String cert = packageAndCert[1];
                        packageCertMap.put(packageName, cert);
                    } else if (packageAndCert.length == 1) {
                        packageCertMap.put(getPackageNameNormalized(packageAndCert[0]),
                                INSTALLER_CERTIFICATE_NOT_EVALUATED);
                    }
                }
            }
        }

        return packageCertMap;
    }

    private static Signature[] getSignatures(@NonNull PackageInfo packageInfo) {
        SigningInfo signingInfo = packageInfo.signingInfo;

        if (signingInfo == null || signingInfo.getApkContentsSigners().length < 1) {
            throw new IllegalArgumentException("Package signature not found in " + packageInfo);
        }

        // We are only interested in evaluating the active signatures.
        return signingInfo.getApkContentsSigners();
    }

    private static String getFingerprint(Signature cert) {
        InputStream input = new ByteArrayInputStream(cert.toByteArray());

        CertificateFactory factory;
        try {
            factory = CertificateFactory.getInstance("X509");
        } catch (CertificateException e) {
            throw new RuntimeException("Error getting CertificateFactory", e);
        }
        X509Certificate certificate = null;
        try {
            if (factory != null) {
                certificate = (X509Certificate) factory.generateCertificate(input);
            }
        } catch (CertificateException e) {
            throw new RuntimeException("Error getting X509Certificate", e);
        }

        if (certificate == null) {
            throw new RuntimeException("X509 Certificate not found");
        }

        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] publicKey = digest.digest(certificate.getEncoded());
            return getHexDigest(publicKey);
        } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
            throw new IllegalArgumentException("Error error computing fingerprint", e);
        }
    }

    private PackageInfo getPackageArchiveInfo(Uri dataUri) {
        File installationPath = getInstallationPath(dataUri);
        if (installationPath == null) {
            throw new IllegalArgumentException("Installation path is null, package not found");
        }

        PackageParser parser = new PackageParser();
        try {
            ParsedPackage pkg = parser.parseParsedPackage(installationPath, 0, false);
            int flags = PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA;
            ApkParseUtils.collectCertificates(pkg, false);
            return PackageInfoUtils.generate(pkg, null, flags, 0, 0, null, new PackageUserState(),
                    UserHandle.getCallingUserId());
        } catch (Exception e) {
            throw new IllegalArgumentException("Exception reading " + dataUri, e);
        }
    }

    private PackageInfo getMultiApkInfo(File multiApkDirectory) {
        // The base apk will normally be called base.apk
        File baseFile = new File(multiApkDirectory, BASE_APK_FILE);
        PackageInfo basePackageInfo =
                mContext.getPackageManager()
                        .getPackageArchiveInfo(
                                baseFile.getAbsolutePath(),
                                PackageManager.GET_SIGNING_CERTIFICATES
                                        | PackageManager.GET_META_DATA);

        if (basePackageInfo == null) {
            for (File apkFile : multiApkDirectory.listFiles()) {
                if (apkFile.isDirectory()) {
                    continue;
                }

                // If we didn't find a base.apk, then try to parse each apk until we find the one
                // that succeeds.
                basePackageInfo =
                        mContext.getPackageManager()
                                .getPackageArchiveInfo(
                                        apkFile.getAbsolutePath(),
                                        PackageManager.GET_SIGNING_CERTIFICATES
                                                | PackageManager.GET_META_DATA);
                if (basePackageInfo != null) {
                    Slog.i(TAG, "Found package info from " + apkFile);
                    break;
                }
            }
        }

        if (basePackageInfo == null) {
            throw new IllegalArgumentException(
                    "Base package info cannot be found from installation directory");
        }

        return basePackageInfo;
    }

    private File getInstallationPath(Uri dataUri) {
        if (dataUri == null) {
            throw new IllegalArgumentException("Null data uri");
        }

        String scheme = dataUri.getScheme();
        if (!"file".equalsIgnoreCase(scheme)) {
            throw new IllegalArgumentException("Unsupported scheme for " + dataUri);
        }

        File installationPath = new File(dataUri.getPath());
        if (!installationPath.exists()) {
            throw new IllegalArgumentException("Cannot find file for " + dataUri);
        }
        if (!installationPath.canRead()) {
            throw new IllegalArgumentException("Cannot read file for " + dataUri);
        }
        return installationPath;
    }

    private String getCallerPackageNameOrThrow() {
        String callerPackageName = getCallerPackageName();
        if (callerPackageName == null) {
            throw new SecurityException(
                    "Only system packages specified in config_integrityRuleProviderPackages are"
                            + " allowed to call this method.");
        }
        return callerPackageName;
    }

    private String getCallerPackageName() {
        final List<String> allowedRuleProviders = getAllowedRuleProviders();
        for (String packageName : allowedRuleProviders) {
            try {
                // At least in tests, getPackageUid gives "NameNotFound" but getPackagesFromUid
                // give the correct package name.
                int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
                if (uid == Binder.getCallingUid()) {
                    // Caller is allowed in the config.
                    if (isSystemApp(packageName)) {
                        return packageName;
                    }
                }
            } catch (PackageManager.NameNotFoundException e) {
                // Ignore the exception. We don't expect the app to be necessarily installed.
                Slog.i(TAG, "Rule provider package " + packageName + " not installed.");
            }
        }
        return null;
    }

    private boolean isSystemApp(String packageName) {
        try {
            PackageInfo existingPackageInfo =
                    mContext.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
            return existingPackageInfo.applicationInfo != null
                    && existingPackageInfo.applicationInfo.isSystemApp();
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

    private List<String> getAllowedRuleProviders() {
        return Arrays.asList(
                mContext.getResources()
                        .getStringArray(R.array.config_integrityRuleProviderPackages));
    }

    private boolean isRuleProvider(String installerPackageName) {
        return getAllowedRuleProviders().stream()
                .anyMatch(ruleProvider -> ruleProvider.equals(installerPackageName));
    }
}
