#!/bin/sh audit_control="/etc/security/audit_control" text='templogs' touch ${text} open_binary='open' read_binary='readlink' templog='/tmp/templog' symlink='/tmp/templog1' temp='/tmp/ERROR' # Array containing all network system calls to be tested syscalls="open(2) openat(2) readlink(2) readlinkat(2)" # Fetches the location of Audit trails # Default: /var/audit auditdir=$(cat ${audit_control} | grep "dir:" | cut -d ':' -f 2) echo "Audit Directory: ${auditdir} .. ✔" # Create files to be tested with open and readlink setup_env() { # Unlink ERROR in current directory if [ -f ${temp} ]; then rm ${temp} fi # Create a file and its symbolic link in /tmp touch ${templog} if [ ! -L ${symlink} ]; then ln -s ${templog} ${symlink} fi return } # Start audit daemon and catch the generated trails start_audit() { # Start audit daemon and setup a new trail local init="service auditd start" local newt="audit -n" eval ${init}; eval ${newt} echo "Audit daemon and new trail started .. ✔" return } # Stop Audit daemon stop_audit() { local stop="audit -t" eval ${stop} echo "Audit daemon stopped .. ✔" return } # Launch the system calls launch_syscalls() { if [ ! -f ${open_binary} ] && [ ! -f ${read_binary} ]; then echo "Please run 'make' first .. ✘" stop_audit exit 1 fi local open="./${open_binary}" local readlink="./${read_binary}" eval ${open}; eval ${readlink} echo "Launching system calls .. ✔" return } # Prints the result of testing print_statistics() { no_of_tests_passed=$(wc -l ${text} | sed -e 's/^[[:space:]]*//' | cut -d ' ' -f 1) no_of_syscalls=$(echo ${syscalls} | wc -w) no_of_tests_expected=$(( 2 * ${no_of_syscalls} )) printf "\n------------------Statistics-------------------\n" printf "Tests evaluated: ${no_of_tests_expected}\n" printf "Tests passed: ${no_of_tests_passed}\n" return } # Loops through all syscalls and searches for presence of # both success and failure mode in the trail. If found, the test # for that particular mode passes. test_syscalls() { local main_trail=$1 local fullpath="${auditdir}/${main_trail}" # Loop through the lines of $fullpath and check success # and failure condition of each syscall for syscall in ${syscalls}; do printf "===============================================\n" echo "Testing ${syscall}.." success_mode="Success mode passed: ${syscall}" failure_mode="Failure mode passed: ${syscall}" praudit -l ${fullpath} | grep ${syscall} | while read -r find_syscall; do # Check for success and failure mode check_success=$(echo ${find_syscall} | grep -E "templog.*return,success") check_failure=$(echo ${find_syscall} | grep -E "ERROR.*return,failure") # Can add tests for arguments, file descriptors etc if [ "$check_success" != "" ] && [ "$pass_once" != 1 ]; then echo "$success_mode .. ✔" echo "$success_mode" >> ${text} export pass_once=1 fi if [ "$check_failure" != "" ] && [ "$fail_once" != 1 ]; then echo "$failure_mode .. ✔" echo "$failure_mode" >> ${text} export fail_once=1 fi done check_passed=$(cat ${text} | grep "${success_mode}") check_failed=$(cat ${text} | grep "${failure_mode}") if [ "$check_passed" = "" ]; then echo "Success mode failed: ${syscall} .. ✘" fi if [ "$check_failed" = "" ]; then echo "Failure mode failed: ${syscall} .. ✘" fi done print_statistics return } # Cleans up the trails and the log files cleanup() { rm -f "$auditdir/$1" rm ${text} ${templog} ${symlink} return } # Main function to launch all the functions above main() { setup_env start_audit launch_syscalls # Fetch the trail corresponding to trail catched earlier local current_trail=$(ls ${auditdir} | grep ".not_terminated") local init_name=$(echo ${current_trail} | cut -d '.' -f 1) stop_audit; printf "\n" local main_trail=$(ls ${auditdir} | grep ${init_name}) test_syscalls ${main_trail} cleanup ${main_trail} return } main