#!/bin/sh
# This script is supposed to test cacti a little bit. At least each page and
# each link is tried. I mean to add checks for new CVE's (at least those that I
# can trigger with wget) as well.

# Catch any error
set -e

save_log_files() {
    # add timestamp to log file name as subsequent runs share the same
    # artifacts directory
    echo "Copying /var/log/cacti/cacti.log to artifacts"
    cp /var/log/cacti/cacti.log cacti_$(date --iso-8601=minutes).log
    if [ -f /var/log/apache2/access.log ] ; then
        echo "Copying /var/log/apache2/access.log to artifacts"
        cp /var/log/apache2/access.log apache_access_$(date --iso-8601=minutes).log
    fi
    if [ -f /var/log/apache2/error.log ] ; then
        echo "Copying /var/log/apache2/error.log to artifacts"
        cp -f /var/log/apache2/error.log apache_error_$(date --iso-8601=minutes).log
    fi
    if [ -f /var/log/lighttpd/error.log ] ; then
        echo "Copying /var/log/lighttpd/error.log to artifacts"
        cp -f /var/log/lighttpd/error.log lighty_error_$(date --iso-8601=minutes).log
    fi
    chmod a+r *.log
}

# Get the current database password, which by default is also used for the
# admin.
database_pw=$(grep database_password /etc/cacti/debian.php | awk '{print $3}')
database_pw=${database_pw%%\";}
database_pw=${database_pw#\"}

# To make sure that the autopkgtest/CI sites store the information
if [ -n "${AUTOPKGTEST_ARTIFACTS}" ] ; then
    cd "${AUTOPKGTEST_ARTIFACTS}"
    trap save_log_files 0
fi

# Lighttpd is not the default httpd for cacti. If we are testing for it, we
# need to enable the conf first.
if [ -n "$(which lighttpd-enable-mod)" ] ; then
    lighttpd-enable-mod cacti
    /etc/init.d/lighttpd force-reload
fi

tmpFile1=$(mktemp)
tmpFile2=$(mktemp)
cookieFile=$(mktemp)
loadSaveCookie="--load-cookies $cookieFile --keep-session-cookies --save-cookies $cookieFile"

# Make sure we get the magic, this is stored in the cookies for future use.
wget --keep-session-cookies --save-cookies "$cookieFile" --output-document="$tmpFile1" http://localhost/cacti/index.php
magic=$(grep "name='__csrf_magic' value=" "$tmpFile1" | sed "s/.*__csrf_magic' value=\"//" | sed "s/\" \/>//")
postData="action=login&login_username=admin&login_password=${database_pw}&__csrf_magic=${magic}"
wget $loadSaveCookie --post-data="$postData" --output-document="$tmpFile2" http://localhost/cacti/index.php

# Now loop over all the available links (but don't log out and don't delete or
# remove stuff.
wget $loadSaveCookie --reject-regex="(logout\.php|remove|delete)" --recursive --level=0 http://localhost/cacti/index.php

# Check for the existance of at least one of the files, as unauthorized access
# still gets http OK back.
if [ ! -f localhost/cacti/graphs.php ] ; then
    echo "localhost/cacti/graphs.php not found"
    return 179
fi

# SQL injection CVE's
# Well, the idea is simple, try to trigger the CVE and inject a long
# sleep. Make sure the timeout is below the sleep. 

# CVE-2016-3172 I would like to put the request in --post-data, but I don't
# seem to manage that properly.
wget $loadSaveCookie --timeout=10 --tries=1 "http://localhost/cacti/tree.php?action=item_edit&tree_id=1&parent_id=7%20and%20sleep%28100%29"
# Extra check
echo -n "Checking tree.php for Validation error ... " 
grep -q "Validation error." tree.php*
echo done.

# CVE-2016-3659 Unfortunately, I am not able to trigger the issue
#wget $loadSaveCookie --timeout=10 --tries=1 "http://localhost/cacti/graph_view.php?action=tree&tree_id=1&leaf_id=7&nodeid=node1_7&host_group_data=graph_template:1 union select case when ord(substring((select version()) from 1 for 1)) between 53 and 53 then sleep(100) else 0 end"
#wget $loadSaveCookie --timeout=10 --tries=1 --post-data="__csrf_magic=${magic}&action=tree&tree_id=1&leaf_id=7&nodeid=node1_7&host_group_data=graph_template:1%20union%20select%20case%20when%20ord(substring((select%20version())%20from%201%20for%201))%20between%2053%20and%2053%20then%20sleep(100)%20else%200%20end" "http://localhost/cacti/graph_view.php"

# Finally check the cacti log for unexpected items (unfortunately we always get
# some errors; I still need to check 1054/1064).
# 1054 ER_BAD_FIELD_ERROR: Unknown column '%s' in '%s'
# 1062 ER_DUP_ENTRY: Duplicate entry '%s' for key %d
# 1064 ER_PARSE_ERROR: %s near '%s' at line %d
FILTERED_LOG="$(grep -v \
     -e "SYSTEM STATS: Time:" \
     -e "AUTH LOGIN: User 'admin' Authenticated" \
     -e "WARNING: Cron is out of sync" \
     -e Error:\'1054\' \
     -e Error:\'1062\' \
     -e Error:\'1064\' \
     /var/log/cacti/cacti.log)" || true

if [ -n "${FILTERED_LOG}" ] ; then
    echo "Unexpected output in /var/log/cacti/cacti.log:"
    echo "${FILTERED_LOG}"
    return 17976
else
    echo "No unexpected output in /var/log/cacti/cacti.log"
fi
