/*
 * 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.Log;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
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.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;

import java.io.File;
import java.io.FileNotFoundException;

/**
 * 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 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", "/sdcard/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 behavior when
     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} is enforced.
     */
    public void testReadExternalStorageEnforced() 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", "/sdcard/meow");

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

            // 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 not be able to read
            assertTrue("Normal app able to read external storage", runDeviceTests(
                    EXTERNAL_STORAGE_APP_PKG, EXTERNAL_STORAGE_APP_CLASS,
                    "testFailReadExternalStorage"));

            // 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(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);

            // 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
            assertTrue("unexpected result when running permission tests",
                    runDeviceTests(PERMISSION_DIFF_CERT_PKG));
        }
        finally {
            getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
            getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
        }
    }

    /**
     * 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));
    }
}
