import os
import json

import infra.basetest


class TestHardeningBase(infra.basetest.BRTest):
    config = \
        """
        BR2_powerpc64=y
        BR2_powerpc_e5500=y
        BR2_TOOLCHAIN_EXTERNAL=y
        BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y
        BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y
        BR2_TOOLCHAIN_EXTERNAL_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64-e5500/tarballs/powerpc64-e5500--glibc--stable-2018.02-2.tar.bz2"
        BR2_TOOLCHAIN_EXTERNAL_GCC_6=y
        BR2_TOOLCHAIN_EXTERNAL_HEADERS_4_1=y
        BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y
        BR2_TOOLCHAIN_EXTERNAL_CXX=y
        BR2_PACKAGE_LIGHTTPD=y
        BR2_PACKAGE_HOST_CHECKSEC=y
        # BR2_TARGET_ROOTFS_TAR is not set
        """

    checksec_files = ["usr/sbin/lighttpd", "bin/busybox"]

    def checksec_run(self, target_file):
        filepath = os.path.join(self.builddir, "target", target_file)
        cmd = ["host/bin/checksec", "--format=json",
               "--file={}".format(filepath)]
        # Checksec is being used for elf file analysis only.  There are no
        # assumptions of target/run-time checks as part of this testing.
        ret = infra.run_cmd_on_host(self.builddir, cmd)
        return json.loads(ret)


class TestRelro(TestHardeningBase):
    config = TestHardeningBase.config + \
        """
        BR2_RELRO_FULL=y
        """

    def test_run(self):
        for f in self.checksec_files:
            out = self.checksec_run(f)
            filepath = os.path.join(self.builddir, "target", f)
            self.assertEqual(out[filepath]["relro"], "full")
            self.assertEqual(out[filepath]["pie"], "yes")


class TestRelroPartial(TestHardeningBase):
    config = TestHardeningBase.config + \
        """
        BR2_RELRO_PARTIAL=y
        """

    def test_run(self):
        for f in self.checksec_files:
            out = self.checksec_run(f)
            filepath = os.path.join(self.builddir, "target", f)
            self.assertEqual(out[filepath]["relro"], "partial")
            self.assertEqual(out[filepath]["pie"], "no")


class TestSspNone(TestHardeningBase):
    config = TestHardeningBase.config + \
        """
        BR2_SSP_NONE=y
        """

    def test_run(self):
        for f in self.checksec_files:
            out = self.checksec_run(f)
            filepath = os.path.join(self.builddir, "target", f)
            self.assertEqual(out[filepath]["canary"], "no")


class TestSspStrong(TestHardeningBase):
    config = TestHardeningBase.config + \
        """
        BR2_SSP_STRONG=y
        """

    def test_run(self):
        for f in self.checksec_files:
            out = self.checksec_run(f)
            filepath = os.path.join(self.builddir, "target", f)
            self.assertEqual(out[filepath]["canary"], "yes")


class TestFortifyNone(TestHardeningBase):
    config = TestHardeningBase.config + \
        """
        BR2_FORTIFY_SOURCE_NONE=y
        """

    def test_run(self):
        for f in self.checksec_files:
            out = self.checksec_run(f)
            filepath = os.path.join(self.builddir, "target", f)
            self.assertEqual(out[filepath]["fortified"], "0")


class TestFortifyConserv(TestHardeningBase):
    config = TestHardeningBase.config + \
        """
        BR2_FORTIFY_SOURCE_1=y
        """

    def test_run(self):
        for f in self.checksec_files:
            out = self.checksec_run(f)
            filepath = os.path.join(self.builddir, "target", f)
            self.assertNotEqual(out[filepath]["fortified"], "0")
