/*
 * Copyright (C) 2009 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.cts.appsecurity;

import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.result.TestResult.TestStatus;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Map;

/**
 * Set of tests that verify various security checks involving multiple apps are properly enforced.
 */
public class AppSecurityTests extends DeviceTestCase implements IBuildReceiver {

    // testSharedUidDifferentCerts constants
    private static final String SHARED_UI_APK = "CtsSharedUidInstall.apk";
    private static final String SHARED_UI_PKG = "com.android.cts.shareuidinstall";
    private static final String SHARED_UI_DIFF_CERT_APK = "CtsSharedUidInstallDiffCert.apk";
    private static final String SHARED_UI_DIFF_CERT_PKG =
        "com.android.cts.shareuidinstalldiffcert";

    // testAppUpgradeDifferentCerts constants
    private static final String SIMPLE_APP_APK = "CtsSimpleAppInstall.apk";
    private static final String SIMPLE_APP_PKG = "com.android.cts.simpleappinstall";
    private static final String SIMPLE_APP_DIFF_CERT_APK = "CtsSimpleAppInstallDiffCert.apk";

    // testAppFailAccessPrivateData constants
    private static final String APP_WITH_DATA_APK = "CtsAppWithData.apk";
    private static final String APP_WITH_DATA_PKG = "com.android.cts.appwithdata";
    private static final String APP_WITH_DATA_CLASS =
            "com.android.cts.appwithdata.CreatePrivateDataTest";
    private static final String APP_WITH_DATA_CREATE_METHOD =
            "testCreatePrivateData";
    private static final String APP_WITH_DATA_CHECK_NOEXIST_METHOD =
            "testEnsurePrivateDataNotExist";
    private static final String APP_ACCESS_DATA_APK = "CtsAppAccessData.apk";
    private static final String APP_ACCESS_DATA_PKG = "com.android.cts.appaccessdata";

    // External storage constants
    private static final String EXTERNAL_STORAGE_APP_APK = "CtsExternalStorageApp.apk";
    private static final String EXTERNAL_STORAGE_APP_PKG = "com.android.cts.externalstorageapp";
    private static final String EXTERNAL_STORAGE_APP_CLASS = EXTERNAL_STORAGE_APP_PKG
            + ".ExternalStorageTest";
    private static final String WRITE_EXTERNAL_STORAGE_APP_APK = "CtsWriteExternalStorageApp.apk";
    private static final String
            WRITE_EXTERNAL_STORAGE_APP_PKG = "com.android.cts.writeexternalstorageapp";
    private static final String WRITE_EXTERNAL_STORAGE_APP_CLASS = WRITE_EXTERNAL_STORAGE_APP_PKG
            + ".WriteExternalStorageTest";

    // testInstrumentationDiffCert constants
    private static final String TARGET_INSTRUMENT_APK = "CtsTargetInstrumentationApp.apk";
    private static final String TARGET_INSTRUMENT_PKG = "com.android.cts.targetinstrumentationapp";
    private static final String INSTRUMENT_DIFF_CERT_APK = "CtsInstrumentationAppDiffCert.apk";
    private static final String INSTRUMENT_DIFF_CERT_PKG =
        "com.android.cts.instrumentationdiffcertapp";

    // testPermissionDiffCert constants
    private static final String DECLARE_PERMISSION_APK = "CtsPermissionDeclareApp.apk";
    private static final String DECLARE_PERMISSION_PKG = "com.android.cts.permissiondeclareapp";
    private static final String DECLARE_PERMISSION_COMPAT_APK = "CtsPermissionDeclareAppCompat.apk";
    private static final String DECLARE_PERMISSION_COMPAT_PKG = "com.android.cts.permissiondeclareappcompat";

    private static final String PERMISSION_DIFF_CERT_APK = "CtsUsePermissionDiffCert.apk";
    private static final String PERMISSION_DIFF_CERT_PKG =
        "com.android.cts.usespermissiondiffcertapp";

    private static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";

    private static final String LOG_TAG = "AppSecurityTests";

    private CtsBuildHelper mCtsBuild;

    /**
     * {@inheritDoc}
     */
    @Override
    public void setBuild(IBuildInfo buildInfo) {
        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
    }

    private File getTestAppFile(String fileName) throws FileNotFoundException {
        return mCtsBuild.getTestApp(fileName);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        // ensure build has been set before test is run
        assertNotNull(mCtsBuild);
    }

    /**
     * Test that an app that declares the same shared uid as an existing app, cannot be installed
     * if it is signed with a different certificate.
     */
    public void testSharedUidDifferentCerts() throws Exception {
        Log.i(LOG_TAG, "installing apks with shared uid, but different certs");
        try {
            // cleanup test apps that might be installed from previous partial test run
            getDevice().uninstallPackage(SHARED_UI_PKG);
            getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);

            String installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_APK),
                    false);
            assertNull(String.format("failed to install shared uid app, Reason: %s", installResult),
                    installResult);
            installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_DIFF_CERT_APK),
                    false);
            assertNotNull("shared uid app with different cert than existing app installed " +
                    "successfully", installResult);
            assertEquals("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE", installResult);
        }
        finally {
            getDevice().uninstallPackage(SHARED_UI_PKG);
            getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);
        }
    }

    /**
     * Test that an app update cannot be installed over an existing app if it has a different
     * certificate.
     */
    public void testAppUpgradeDifferentCerts() throws Exception {
        Log.i(LOG_TAG, "installing app upgrade with different certs");
        try {
            // cleanup test app that might be installed from previous partial test run
            getDevice().uninstallPackage(SIMPLE_APP_PKG);

            String installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_APK),
                    false);
            assertNull(String.format("failed to install simple app. Reason: %s", installResult),
                    installResult);
            installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_DIFF_CERT_APK),
                    true /* reinstall */);
            assertNotNull("app upgrade with different cert than existing app installed " +
                    "successfully", installResult);
            assertEquals("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES", installResult);
        }
        finally {
            getDevice().uninstallPackage(SIMPLE_APP_PKG);
        }
    }

    /**
     * Test that an app cannot access another app's private data.
     */
    public void testAppFailAccessPrivateData() throws Exception {
        Log.i(LOG_TAG, "installing app that attempts to access another app's private data");
        try {
            // cleanup test app that might be installed from previous partial test run
            getDevice().uninstallPackage(APP_WITH_DATA_PKG);
            getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);

            String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
                    false);
            assertNull(String.format("failed to install app with data. Reason: %s", installResult),
                    installResult);
            // run appwithdata's tests to create private data
            assertTrue("failed to create app's private data", runDeviceTests(APP_WITH_DATA_PKG,
                    APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD));

            installResult = getDevice().installPackage(getTestAppFile(APP_ACCESS_DATA_APK),
                    false);
            assertNull(String.format("failed to install app access data. Reason: %s",
                    installResult), installResult);
            // run appaccessdata's tests which attempt to access appwithdata's private data
            assertTrue("could access app's private data", runDeviceTests(APP_ACCESS_DATA_PKG));
        }
        finally {
            getDevice().uninstallPackage(APP_WITH_DATA_PKG);
            getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
        }
    }

    /**
     * Test behavior when
     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} is unenforced.
     */
    public void testReadExternalStorageUnenforced() throws Exception {
        try {
            getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
            getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);

            // stage test file on external storage
            getDevice().pushString("CAEK",
                    getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE) + "/meow");

            // mark permission as not enforced
            setPermissionEnforced(getDevice(), READ_EXTERNAL_STORAGE, false);

            // install apps and run test
            assertNull(getDevice()
                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false));
            assertNull(getDevice()
                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false));

            // normal app should be able to read
            assertTrue("Normal app unable to read external storage", runDeviceTests(
                    EXTERNAL_STORAGE_APP_PKG, EXTERNAL_STORAGE_APP_CLASS,
                    "testReadExternalStorage"));

            // WRITE_EXTERNAL app should be able to read and write
            assertTrue("WRITE_EXTERNAL app unable to read external storage", runDeviceTests(
                    WRITE_EXTERNAL_STORAGE_APP_PKG, WRITE_EXTERNAL_STORAGE_APP_CLASS,
                    "testReadExternalStorage"));
            assertTrue("WRITE_EXTERNAL app unable to write external storage", runDeviceTests(
                    WRITE_EXTERNAL_STORAGE_APP_PKG, WRITE_EXTERNAL_STORAGE_APP_CLASS,
                    "testWriteExternalStorage"));

        } finally {
            getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
            getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
        }
    }

    /**
     * Test that uninstall of an app removes its private data.
     */
    public void testUninstallRemovesData() throws Exception {
        Log.i(LOG_TAG, "Uninstalling app, verifying data is removed.");
        try {
            // cleanup test app that might be installed from previous partial test run
            getDevice().uninstallPackage(APP_WITH_DATA_PKG);

            String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
                    false);
            assertNull(String.format("failed to install app with data. Reason: %s", installResult),
                    installResult);
            // run appwithdata's tests to create private data
            assertTrue("failed to create app's private data", runDeviceTests(APP_WITH_DATA_PKG,
                    APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD));

            getDevice().uninstallPackage(APP_WITH_DATA_PKG);

            installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
                    false);
            assertNull(String.format("failed to install app with data second time. Reason: %s",
                    installResult), installResult);
            // run appwithdata's 'check if file exists' test
            assertTrue("app's private data still exists after install", runDeviceTests(
                    APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CHECK_NOEXIST_METHOD));

        }
        finally {
            getDevice().uninstallPackage(APP_WITH_DATA_PKG);
        }
    }

    /**
     * Test that an app cannot instrument another app that is signed with different certificate.
     */
    public void testInstrumentationDiffCert() throws Exception {
        Log.i(LOG_TAG, "installing app that attempts to instrument another app");
        try {
            // cleanup test app that might be installed from previous partial test run
            getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
            getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);

            String installResult = getDevice().installPackage(
                    getTestAppFile(TARGET_INSTRUMENT_APK), false);
            assertNull(String.format("failed to install target instrumentation app. Reason: %s",
                    installResult), installResult);

            // the app will install, but will get error at runtime when starting instrumentation
            installResult = getDevice().installPackage(getTestAppFile(INSTRUMENT_DIFF_CERT_APK),
                    false);
            assertNull(String.format(
                    "failed to install instrumentation app with diff cert. Reason: %s",
                    installResult), installResult);
            // run INSTRUMENT_DIFF_CERT_PKG tests
            // this test will attempt to call startInstrumentation directly and verify
            // SecurityException is thrown
            assertTrue("running instrumentation with diff cert unexpectedly succeeded",
                    runDeviceTests(INSTRUMENT_DIFF_CERT_PKG));
        }
        finally {
            getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
            getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
        }
    }

    /**
     * Test that an app cannot use a signature-enforced permission if it is signed with a different
     * certificate than the app that declared the permission.
     */
    public void testPermissionDiffCert() throws Exception {
        Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
        try {
            // cleanup test app that might be installed from previous partial test run
            getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
            getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
            getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);

            String installResult = getDevice().installPackage(
                    getTestAppFile(DECLARE_PERMISSION_APK), false);
            assertNull(String.format("failed to install declare permission app. Reason: %s",
                    installResult), installResult);

            installResult = getDevice().installPackage(
                    getTestAppFile(DECLARE_PERMISSION_COMPAT_APK), false);
            assertNull(String.format("failed to install declare permission compat app. Reason: %s",
                    installResult), installResult);

            // the app will install, but will get error at runtime
            installResult = getDevice().installPackage(getTestAppFile(PERMISSION_DIFF_CERT_APK),
                    false);
            assertNull(String.format("failed to install permission app with diff cert. Reason: %s",
                    installResult), installResult);
            // run PERMISSION_DIFF_CERT_PKG tests which try to access the permission
            TestRunResult result = doRunTests(PERMISSION_DIFF_CERT_PKG, null, null);
            assertDeviceTestsPass(result);
        }
        finally {
            getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
            getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
            getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
        }
    }

    /**
     * Helper method that checks that all tests in given result passed, and attempts to generate
     * a meaningful error message if they failed.
     *
     * @param result
     */
    private void assertDeviceTestsPass(TestRunResult result) {
        // TODO: consider rerunning if this occurred
        assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
                result.getName(), result.getRunFailureMessage()), result.isRunFailure());

        if (result.hasFailedTests()) {
            // build a meaningful error message
            StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
                result.getTestResults().entrySet()) {
                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
                    errorBuilder.append(resultEntry.getKey().toString());
                    errorBuilder.append(":\n");
                    errorBuilder.append(resultEntry.getValue().getStackTrace());
                }
            }
            fail(errorBuilder.toString());
        }
    }

    /**
     * Helper method that will the specified packages tests on device.
     *
     * @param pkgName Android application package for tests
     * @return <code>true</code> if all tests passed.
     * @throws DeviceNotAvailableException if connection to device was lost.
     */
    private boolean runDeviceTests(String pkgName) throws DeviceNotAvailableException {
        return runDeviceTests(pkgName, null, null);
    }

    /**
     * Helper method that will the specified packages tests on device.
     *
     * @param pkgName Android application package for tests
     * @return <code>true</code> if all tests passed.
     * @throws DeviceNotAvailableException if connection to device was lost.
     */
    private boolean runDeviceTests(String pkgName, String testClassName, String testMethodName)
            throws DeviceNotAvailableException {
        TestRunResult runResult = doRunTests(pkgName, testClassName, testMethodName);
        return !runResult.hasFailedTests();
    }

    /**
     * Helper method to run tests and return the listener that collected the results.
     *
     * @param pkgName Android application package for tests
     * @return the {@link TestRunResult}
     * @throws DeviceNotAvailableException if connection to device was lost.
     */
    private TestRunResult doRunTests(String pkgName, String testClassName,
            String testMethodName) throws DeviceNotAvailableException {

        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
                getDevice().getIDevice());
        if (testClassName != null && testMethodName != null) {
            testRunner.setMethodName(testClassName, testMethodName);
        }
        CollectingTestListener listener = new CollectingTestListener();
        getDevice().runInstrumentationTests(testRunner, listener);
        return listener.getCurrentRunResults();
    }

    private static void setPermissionEnforced(
            ITestDevice device, String permission, boolean enforced)
            throws DeviceNotAvailableException {
        device.executeShellCommand("pm set-permission-enforced " + permission + " "
                + Boolean.toString(enforced));
    }
}
