tripwire-open-source/src/test-harness/tests/integritycheck.pm

440 lines
12 KiB
Perl
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use twtools;
package integritycheck;
######################################################################
# One time module initialization goes in here...
#
BEGIN
{
$description = "integrity check test";
# This is the root directory we will be integrity checking
#
$root = "$twtools::twcwd/$twtools::twrootdir/ic-test-a";
$root2 = "$twtools::twcwd/$twtools::twrootdir/ic-test-b";
# Here are the names of the report files this test will create
#
$report1 = "$twtools::twcwd/$twtools::twrootdir/report/ic-1.twr";
$report2 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-2.twr";
$report3 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-3.twr";
$report4 = "$twtools::twcwd/$twtools::twrootdir/report/dbupdate-4.twr";
}
######################################################################
# PolicyFileString -- return the policy text as a string
#
sub PolicyFileString
{
return <<POLICY_END;
# Policy file generated by integrity checks test
#
(rulename="RuleA", severity=30, emailto="elvis\@mars")
{
$root -> \$(ReadOnly) +S -ab; #read only plus SHA-1 minus atime & blocks
}
(rulename="RuleB", severity=200, emailto="elvis\@mars")
{
$root2 -> \$(ReadOnly) +S -ab; #read only plus SHA-1 minus atime & blocks
}
POLICY_END
}
######################################################################
# CreateFile -- create a file with the specified contents
#
# input: path -- path to the file; relative to $root
# contents -- string to put in the file
#
sub CreateFile
{
my ($path, $contents) = @_;
system( "echo $contents > $path" );
$? && die "Create file failed for $path\n";
}
######################################################################
# RemoveFile -- removes the named file
#
sub RemoveFile
{
my ($path) = @_;
if( -e "$path" )
{
system( "rm -f $path" );
}
$? && die "Remove file failed for $root/$path\n";
}
######################################################################
# CreateDir -- create a directory
#
sub CreateDir
{
my($dir) = @_;
# NOTE: mkdir fails if it is already a directory!
#
if( ! -d "$dir" )
{
system( "rm -f $dir" );
system( "mkdir -p $dir" );
$? && die "Mkdir failed for $root/$dir\n";
}
}
######################################################################
# MoveFile -- move a file from one place to another
# NOTE: file names are relative to $root
#
# input: old_name -- name of file to move
# new_name -- where it should be moved to
#
sub MoveFile
{
my($old, $new) = @_;
system( "mv $old $new" );
$? && die "mv $old $new failed!\n";
}
######################################################################
# PrintDatabase
#
sub PrintDatabase
{
system( "$twtools::twrootdir/bin/twprint -m d -c $twtools::twrootdir/tw.cfg" );
}
######################################################################
# PrintReport
#
sub PrintReport
{
my ($report) = @_;
system( "$twtools::twrootdir/bin/twprint -m r -c $twtools::twrootdir/tw.cfg -r $report" );
}
######################################################################
# PrepareForTest -- creates the files that each test will be
# integrity checking and initializes the database.
#
sub PrepareForTest
{
# make sure we are cleaned up...
#
cleanup();
# Make the files we will be using...
#
CreateDir ( "$root");
CreateDir ( "$root/subdir" );
CreateFile( "$root/subdir/modify.txt", "hello world" );
CreateFile( "$root/copy-src.txt", "asdf" );
CreateDir ( "$root2");
CreateFile( "$root2/deleteme.txt", "goodbye cruel world" );
# Initialize the database
#
twtools::InitializeDatabase();
}
######################################################################
#
# Run the test.
#
sub run
{
twtools::logStatus("*** Beginning $description\n");
printf("%-30s", "-- $description");
if ($^O eq "dragonfly") {
++$twtools::twskippedtests;
print "SKIPPED; TODO: DragonflyBSD has fewer expected changes here; refactor so we can test for correct values\n";
return;
}
my $twpassed = 1;
my $dir_mods = ($^O eq "skyos") ? 0 : 1;
PrepareForTest();
# make some violations...
#
MoveFile ( "$root/copy-src.txt", "$root/copy-dest.txt" );
CreateFile( "$root/subdir/modify.txt", "bark bark bark" );
RemoveFile( "$root2/deleteme.txt");
#######################################################
# First run a full IC
#
twtools::RunIntegrityCheck();
# Make sure we got 6 violations: 3 mod, 1 add, 2 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 6 : 4;
my $c_expected = $dir_mods ? 3 : 1;
if( ($n != $n_expected) || ($a != 1) || ($r != 2) || ($c != $c_expected) )
{
twtools::logStatus("Full IC failed: $n $a $r $c\n");
$twpassed = 0;
}
# TODO: Make RunReport+AnalyzeReport play nice with signed report files
#######################################################
# Do it again, but sign it this time.
#
#twtools::RunIntegrityCheck({trailing_opts => "-E -P $twtools::twlocalpass"});
# Make sure we got 6 violations: 3 mod, 1 add, 2 rm.
#
#my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
#if( ($n != 6) || ($a != 1) || ($r != 2) || ($c != 3) )
#{
# twtools::logStatus("Full IC with signing failed: $n $a $r $c\n");
# $twpassed = 0;
#}
#######################################################
# Now run 'just' the FS section, aka the whole policy
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck(trailing_opts => "-x FS");
# Make sure we got 6 violations: 3 mod, 1 add, 2 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 6 : 4;
my $c_expected = $dir_mods ? 3 : 1;
if( ($n != $n_expected) || ($a != 1) || ($r != 2) || ($c != $c_expected) )
{
twtools::logStatus("IC with FS section failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Now run a check ignoring the SHA attribute, should still return same changes
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck(trailing_opts => "-i S");
# Make sure we got 6 violations: 3 mod, 1 add, 2 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 6 : 4;
my $c_expected = $dir_mods ? 3 : 1;
if( ($n != $n_expected) || ($a != 1) || ($r != 2) || ($c != $c_expected) )
{
twtools::logStatus("IC with FS section failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Now just run RuleA
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "-R RuleA"});
# Make sure we got 4 violations this time: 2 mod, 1 add, 1 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 4 : 3;
my $c_expected = $dir_mods ? 2 : 1;
if( ($n != $n_expected) || ($a != 1) || ($r != 1) || ($c != $c_expected) )
{
twtools::logStatus("IC of Rule A failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Now run severity level 200, meaning RuleB
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "-l 200"});
# Make sure we got 2 violations this time: 1 mod, 0 add, 1 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 2 : 1;
my $c_expected = $dir_mods ? 1 : 0;
if( ($n != $n_expected) || ($a != 0) || ($r != 1) || ($c != $c_expected) )
{
twtools::logStatus("IC of severity 200+ failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Now run severity level "high", also meaning RuleB
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "-l high"});
# Make sure we got 2 violations this time: 1 mod, 0 add, 1 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 2 : 1;
my $c_expected = $dir_mods ? 1 : 0;
if( ($n != $n_expected) || ($a != 0) || ($r != 1) || ($c != $c_expected) )
{
twtools::logStatus("IC of severity 'high' failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Now run against one object, modify.txt
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "$root/subdir/modify.txt"});
# Make sure we got 1 violation this time: 1 mod, 0 add, 0 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
if( ($n != 1) || ($a != 0) || ($r != 0) || ($c != 1) )
{
twtools::logStatus("IC of single object modify.txt failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Run a few full check w/ email reporting, all the valid levels
# (we're configured to pipe to cat as a fake mailprogram)
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "-M -t 0"});
twtools::RunIntegrityCheck({trailing_opts => "-M -t 1"});
twtools::RunIntegrityCheck({trailing_opts => "-M -t 2"});
twtools::RunIntegrityCheck({trailing_opts => "-M -t 3"});
twtools::RunIntegrityCheck({trailing_opts => "-M -t 4"});
# Make sure we got 6 violations: 3 mod, 1 add, 2 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 6 : 4;
my $c_expected = $dir_mods ? 3 : 1;
if( ($n != $n_expected) || ($a != 1) || ($r != 2) || ($c != $c_expected) )
{
twtools::logStatus("Full IC failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Now run an interactive IC with cat as a fake editor, so DB gets auto updated.
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "-I -V cat -P $twtools::twlocalpass"});
# Make sure we got 6 violations: 3 mod, 1 add, 2 rm.
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
my $n_expected = $dir_mods ? 6 : 4;
my $c_expected = $dir_mods ? 3 : 1;
if( ($n != $n_expected) || ($a != 1) || ($r != 2) || ($c != $c_expected) )
{
twtools::logStatus("Interactive IC failed: $n $a $r $c\n");
$twpassed = 0;
}
#######################################################
# Finally run another full IC to verify db was updated
# + also exercise the verbose & hex output options since we don't elsewhere.
#
RemoveFile("$reportloc");
twtools::RunIntegrityCheck({trailing_opts => "-v -h"});
# Make sure we got no violations this time
#
my ($n, $a, $r, $c) = twtools::AnalyzeReport( twtools::RunReport() );
if( ($n != 0) || ($a != 0) || ($r != 0) || ($c != 0) )
{
twtools::logStatus("IC after interactive IC failed: $n $a $r $c\n");
$twpassed = 0;
}
#########################################################
#
# See if the tests all succeeded...
#
if ($twpassed) {
++$twtools::twpassedtests;
print "PASSED\n";
return 1;
}
else {
++$twtools::twfailedtests;
print "*FAILED*\n";
return 0;
}
}
######################################################################
#
# Initialize the test
#
sub initialize
{
# Make the policy file
#
twtools::GeneratePolicyFile( PolicyFileString() );
return 1;
}
sub cleanup
{
# remove all of the files we were integrity checking...
#
system( "rm -rf $root/*" );
system( "rm -rf $root2/*" );
$? && print "WARNING: IC cleanup failed.\n";
# remove the report files we created...
#
system( "rm -f $report1" ) if (-e $report1);
system( "rm -r $report2" ) if (-e $report2);
system( "rm -r $report3" ) if (-e $report3);
system( "rm -r $report4" ) if (-e $report4);
}
######################################################################
# One time module cleanup goes in here...
#
END
{
}
1;