#!/bin/sh
# ------------------------------------------------------------------
#
#    Copyright (C) 2013-2014 Canonical Ltd.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of version 2 of the GNU General Public
#    License published by the Free Software Foundation.
#
# ------------------------------------------------------------------

set -e

rc="0"
created_frameworks=""
tested_frameworks="ubuntu-sdk-13.10 ubuntu-sdk-14.04-dev ubuntu-sdk-14.04-dev1 ubuntu-sdk-14.04-html-dev1 ubuntu-sdk-14.04-html ubuntu-sdk-14.04-papi-dev1 ubuntu-sdk-14.04-papi ubuntu-sdk-14.04-qml-dev3 ubuntu-sdk-14.04-qml"
prefix="com.example.click-apparmor-test"

user="$USER"
if [ -n "$SUDO_USER" ]; then
    user="$SUDO_USER"
fi
if [ -z "$user" ]; then
    echo "Couldn't detect user" >&2
    exit 1
fi

click list

cleanup() {
    mv -f /sbin/apparmor_parser.orig /sbin/apparmor_parser
    mv -f /usr/lib/python3/dist-packages/apparmor/click.py.orig /usr/lib/python3/dist-packages/apparmor/click.py

    for f in $created_frameworks ; do
        rm -f /usr/share/click/frameworks/${f}.framework
    done

    click list | grep "$prefix" | while read line ; do
        pkgname=`echo $line | awk '{print $1}'`
        pkgvers=`echo $line | awk '{print $2}'`
        click unregister --user=$user $pkgname $pkgvers
        echo "Removed: $pkgname $pkgvers"

        app_id="${p}_app1_${v}"
        rm -f "/var/cache/apparmor/click_${app_id}"
        rm -f "/var/lib/apparmor/clicks/${app_id}.json"
        rm -f "/var/lib/apparmor/profiles/click_${app_id}"
    done
}
trap cleanup EXIT HUP INT QUIT TERM

unpack_dir=`pwd`

cp -a ./debian/tests/data "$ADTTMP"

get_policy_version() {
    aa-clickquery --click-framework="$1" -q policy_version
}

#
# Main
#
# divert apparmor_parser and substitute /bin/true so we don't need to load
# policy into the kernel
cp -f /sbin/apparmor_parser /sbin/apparmor_parser.orig
cp -f /bin/true /sbin/apparmor_parser
cp -f /usr/lib/python3/dist-packages/apparmor/click.py /usr/lib/python3/dist-packages/apparmor/click.py.orig
sed -i 's/^mock_testenv = False/mock_testenv = True/' /usr/lib/python3/dist-packages/apparmor/click.py

# Good frameworks/manifests

# For now, just create these. We may want to install the packages that creates
# them, but for now, do this
for i in $tested_frameworks ; do
    framework_file="/usr/share/click/frameworks/$i.framework"
    if [ -e "$framework_file" ]; then
        continue
    fi
    # FIXME: this won't work when we move to libclick (ie, we will need
    # metadata in these files)
    touch /usr/share/click/frameworks/$i.framework
    created_frameworks="$created_frameworks $i"
done

for fr in $tested_frameworks ; do
    # update framework
    pv=`get_policy_version "$fr"`
    for dir in `ls -1d ./debian/tests/data/${prefix}_*` ; do
        c=`basename $dir`
        cat "./debian/tests/data/$c/manifest.json" | sed "s/@@@FRAMEWORK@@@/$fr/" > "$ADTTMP/data/$c/manifest.json"
        cat "./debian/tests/data/$c/apparmor.json" | sed "s/@@@POLICYVERSION@@@/$pv/" > "$ADTTMP/data/$c/apparmor.json"

        cd "$ADTTMP"
        click build "$ADTTMP/data/$c"
        cd "$unpack_dir"

        click install --user=$user "$ADTTMP/${c}_all.click"
        echo -n "Installing: "
        p=`echo "$c" | cut -d '_' -f 1`
        v=`echo "$c" | cut -d '_' -f 2`
        echo -n "$p $c ($fr $pv): "

        # make sure click-apparmor did its job
        app_id="${p}_app1_${v}"

        this_rc="0"
        for f in /var/lib/apparmor/clicks/${app_id}.json /var/lib/apparmor/profiles/click_${app_id} ; do
            test -e "$f" || {
                rc="1"
                echo "'$f' does not exist"
                this_rc="1"
            }
            test -s "/var/lib/apparmor/clicks/${app_id}.json" || {
                rc="1"
                echo "'/var/lib/apparmor/clicks/${app_id}.json' is empty"
                this_rc="1"
            }
        done

        if [ "$this_rc" = "0" ]; then
            echo PASS
        else
            echo FAIL
        fi
        echo "Click manifest:"
        cat "$ADTTMP/data/$c/manifest.json"
        echo "Security manifest:"
        cat "$ADTTMP/data/$c/apparmor.json"
        echo ""

        # cleanup
        click unregister --user=$user "$p" "$v"
    done
done


# Bad frameworks/manifests
fr="ubuntu-nonexistent-13.10"
echo "Test ubuntu-nonexistent-13.10 (aa-clickquery, EXFAIL)"
this_rc="0"
get_policy_version "$fr" && this_rc="1"
if [ "$this_rc" = "0" ]; then
    echo PASS
else
    echo FAIL
    rc="1"
fi

for fr in ubuntu-nonexistent-13.10 ubuntu-sdk-13.10 ubuntu-sdk-14.04-qml ; do
    for pv in 0.1 1.0 1.1 ; do
        # these are valid, so skip them
        if [ "$fr" = "ubuntu-sdk-13.10" ] && [ "$pv" = "1.0" ]; then
            continue
        elif [ "$fr" = "ubuntu-sdk-14.04-qml" ] && [ "$pv" = "1.1" ]; then
            continue
        fi

        for dir in `ls -1d ./debian/tests/data/${prefix}_*` ; do
            c=`basename $dir`
            cat "./debian/tests/data/$c/manifest.json" | sed "s/@@@FRAMEWORK@@@/$fr/" > "$ADTTMP/data/$c/manifest.json"
            cat "./debian/tests/data/$c/apparmor.json" | sed "s/@@@POLICYVERSION@@@/$pv/" > "$ADTTMP/data/$c/apparmor.json"

            cd "$ADTTMP"
            click build "$ADTTMP/data/$c"
            cd "$unpack_dir"

            extra_args=
            if [ "$fr" = "ubuntu-nonexistent-13.10" ]; then
                extra_args="--force-missing-framework"
            fi
            click install $extra_args --user=$user "$ADTTMP/${c}_all.click"
            echo -n "Installing: "
            p=`echo "$c" | cut -d '_' -f 1`
            v=`echo "$c" | cut -d '_' -f 2`
            echo -n "$p $c (EXFAIL, $fr $pv): "

            # make sure click-apparmor did its job
            app_id="${p}_app1_${v}"

            this_rc="0"
            f="/var/lib/apparmor/clicks/${app_id}.json"
            test -e "$f" || {
                rc="1"
                echo "'$f' does not exist"
                this_rc="1"
            }
            test -s "/var/lib/apparmor/clicks/${app_id}.json" || {
                rc="1"
                echo "'/var/lib/apparmor/clicks/${app_id}.json' is empty"
                this_rc="1"
            }

            f="/var/lib/apparmor/profiles/click_${app_id}"
            test -e "$f" && {
                rc="1"
                echo "'$f' exists, but shouldn't"
                this_rc="1"
            }

            this_rc="0"
            if [ "$fr" = "ubuntu-nonexistent-13.10" ]; then
                aa-clickhook 2>&1 | grep -q "Could not find framework for '$app_id" || {
                    rc="1"
                    echo "Could not find \"Could not find framework for '$app_id\""
                    this_rc="1"
                }
            else
                aa-clickhook 2>&1 | grep -q "Invalid policy version for '$app_id" || {
                    rc="1"
                    echo "Could not find \"Invalid policy version for '$app_id\""
                    this_rc="1"
                }
            fi

            if [ "$this_rc" = "0" ]; then
                echo PASS
            else
                echo FAIL
            fi
            echo "Click manifest:"
            cat "$ADTTMP/data/$c/manifest.json"
            echo "Security manifest:"
            cat "$ADTTMP/data/$c/apparmor.json"
            echo ""

            # cleanup
            click unregister --user=$user "$p" "$v"
        done
    done
done

if [ "$rc" = "0" ]; then
    echo "PASS (all tests)"
else
    echo "FAIL (one or more failed tests)"
fi

exit $rc
