mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2026-01-13 06:57:10 +03:00
Cleanup regression suite to make it a bit more user-friendly.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
type => "misc",
|
type => "misc",
|
||||||
comment => "tfncache - simple fully cached",
|
comment => "tfncache (simple fully cached)",
|
||||||
conf => qq(
|
conf => qq(
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
SecDebugLog $ENV{DEBUG_LOG}
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type => "misc",
|
type => "misc",
|
||||||
comment => "tfncache - simple partially cached",
|
comment => "tfncache (simple partially cached)",
|
||||||
conf => qq(
|
conf => qq(
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
SecDebugLog $ENV{DEBUG_LOG}
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type => "misc",
|
type => "misc",
|
||||||
comment => "tfncache - separate phases",
|
comment => "tfncache (separate phases)",
|
||||||
conf => qq(
|
conf => qq(
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
SecDebugLog $ENV{DEBUG_LOG}
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type => "misc",
|
type => "misc",
|
||||||
comment => "tfncache - non-modifying tfns cached",
|
comment => "tfncache (non-modifying tfns cached)",
|
||||||
conf => qq(
|
conf => qq(
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
SecDebugLog $ENV{DEBUG_LOG}
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type => "misc",
|
type => "misc",
|
||||||
comment => "tfncache - unique keys",
|
comment => "tfncache (unique keys)",
|
||||||
conf => qq(
|
conf => qq(
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
SecDebugLog $ENV{DEBUG_LOG}
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type => "misc",
|
type => "misc",
|
||||||
comment => "tfncache - large cache",
|
comment => "tfncache (large cache)",
|
||||||
conf => qq(
|
conf => qq(
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
SecDebugLog $ENV{DEBUG_LOG}
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
SecRule ARGS "foobar" "phase:4,t:none,t:removeWhiteSpace,t:lowercase,deny"
|
SecRule ARGS "foobar" "phase:4,t:none,t:removeWhiteSpace,t:lowercase,deny"
|
||||||
),
|
),
|
||||||
match_log => {
|
match_log => {
|
||||||
debug => [ qr/Adding request argument \(BODY\): name "test", value "Foo Bar"/, 60 ],
|
debug => [ qr/Adding request argument \(BODY\): name "test", value "Foo Bar"/, 60, "Waiting for httpd to process request: "],
|
||||||
-error => [ qr/segmentation fault/i, 60 ],
|
-error => [ qr/segmentation fault/i, 60 ],
|
||||||
},
|
},
|
||||||
match_response => {
|
match_response => {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ $SIG{TERM} = $SIG{INT} = \&handle_interrupt;
|
|||||||
my %opt;
|
my %opt;
|
||||||
getopts('A:E:D:C:T:H:a:p:dvh', \%opt);
|
getopts('A:E:D:C:T:H:a:p:dvh', \%opt);
|
||||||
|
|
||||||
if ($opt{D}) {
|
if ($opt{d}) {
|
||||||
$Data::Dumper::Indent = 1;
|
$Data::Dumper::Indent = 1;
|
||||||
$Data::Dumper::Terse = 1;
|
$Data::Dumper::Terse = 1;
|
||||||
$Data::Dumper::Pad = "";
|
$Data::Dumper::Pad = "";
|
||||||
@@ -73,8 +73,8 @@ Usage: $SCRIPT [options] [file [N]]
|
|||||||
-S path Specify Apache httpd server root path.
|
-S path Specify Apache httpd server root path.
|
||||||
-a file Specify Apache httpd binary (default: httpd)
|
-a file Specify Apache httpd binary (default: httpd)
|
||||||
-p port Specify Apache httpd port (default: 8088)
|
-p port Specify Apache httpd port (default: 8088)
|
||||||
-d Enable debugging.
|
-v Enable verbose output (details on failure).
|
||||||
-v Enable verbose debugging.
|
-d Enable debugging output.
|
||||||
-h This help.
|
-h This help.
|
||||||
|
|
||||||
EOT
|
EOT
|
||||||
@@ -100,6 +100,7 @@ $opt{E} = "$FILES_DIR/error.log" unless (defined $opt{E});
|
|||||||
$opt{C} = "$CONF_DIR/httpd.conf" unless (defined $opt{C});
|
$opt{C} = "$CONF_DIR/httpd.conf" unless (defined $opt{C});
|
||||||
$opt{H} = "$SROOT_DIR/htdocs" unless (defined $opt{H});
|
$opt{H} = "$SROOT_DIR/htdocs" unless (defined $opt{H});
|
||||||
$opt{p} = 8088 unless (defined $opt{p});
|
$opt{p} = 8088 unless (defined $opt{p});
|
||||||
|
$opt{v} = 1 if ($opt{d});
|
||||||
|
|
||||||
unless (defined $opt{S}) {
|
unless (defined $opt{S}) {
|
||||||
my $httpd_root = `$HTTPD -V`;
|
my $httpd_root = `$HTTPD -V`;
|
||||||
@@ -196,7 +197,7 @@ sub runfile {
|
|||||||
if (exists $t{conf} and defined $t{conf}) {
|
if (exists $t{conf} and defined $t{conf}) {
|
||||||
$conf_fn = sprintf "%s/%s_%s_%06d.conf",
|
$conf_fn = sprintf "%s/%s_%s_%06d.conf",
|
||||||
$CONF_DIR, $t{type}, $cfg, $n;
|
$CONF_DIR, $t{type}, $cfg, $n;
|
||||||
# dbg("Writing test config to: $conf_fn");
|
#dbg("Writing test config to: $conf_fn");
|
||||||
open(CONF, ">$conf_fn") or die "Failed to open conf \"$conf_fn\": $!\n";
|
open(CONF, ">$conf_fn") or die "Failed to open conf \"$conf_fn\": $!\n";
|
||||||
print CONF (ref $t{conf} eq "CODE" ? eval { &{$t{conf}} } : $t{conf});
|
print CONF (ref $t{conf} eq "CODE" ? eval { &{$t{conf}} } : $t{conf});
|
||||||
msg("$@") if ($@);
|
msg("$@") if ($@);
|
||||||
@@ -209,9 +210,9 @@ sub runfile {
|
|||||||
|
|
||||||
# Run any prerun setup
|
# Run any prerun setup
|
||||||
if ($rc == 0 and exists $t{prerun} and defined $t{prerun}) {
|
if ($rc == 0 and exists $t{prerun} and defined $t{prerun}) {
|
||||||
dbg("Executing perl prerun...");
|
vrb("Executing perl prerun...");
|
||||||
$rc = &{$t{prerun}};
|
$rc = &{$t{prerun}};
|
||||||
dbg("Perl prerun returned: $rc");
|
vrb("Perl prerun returned: $rc");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($httpd_up) {
|
if ($httpd_up) {
|
||||||
@@ -220,7 +221,7 @@ sub runfile {
|
|||||||
my $resp = do_request($t{request});
|
my $resp = do_request($t{request});
|
||||||
if (!$resp) {
|
if (!$resp) {
|
||||||
msg("invalid response");
|
msg("invalid response");
|
||||||
dbg("RESPONSE: ", $resp);
|
vrb("RESPONSE: ", $resp);
|
||||||
$rc = 1;
|
$rc = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -231,13 +232,13 @@ sub runfile {
|
|||||||
if ($neg and defined $match) {
|
if ($neg and defined $match) {
|
||||||
$rc = 1;
|
$rc = 1;
|
||||||
msg("response $mtype matched: $m");
|
msg("response $mtype matched: $m");
|
||||||
dbg($resp);
|
vrb($resp);
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
elsif (!$neg and !defined $match) {
|
elsif (!$neg and !defined $match) {
|
||||||
$rc = 1;
|
$rc = 1;
|
||||||
msg("response $mtype failed to match: $m");
|
msg("response $mtype failed to match: $m");
|
||||||
dbg($resp);
|
vrb($resp);
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,13 +247,13 @@ sub runfile {
|
|||||||
|
|
||||||
# Run any arbitrary perl tests
|
# Run any arbitrary perl tests
|
||||||
if ($rc == 0 and exists $t{test} and defined $t{test}) {
|
if ($rc == 0 and exists $t{test} and defined $t{test}) {
|
||||||
dbg("Executing perl test(s)...") if ($opt{v});
|
dbg("Executing perl test(s)...");
|
||||||
$rc = eval { &{$t{test}} };
|
$rc = eval { &{$t{test}} };
|
||||||
if (! defined $rc) {
|
if (! defined $rc) {
|
||||||
msg("Error running test: $@");
|
msg("Error running test: $@");
|
||||||
$rc = -1;
|
$rc = -1;
|
||||||
}
|
}
|
||||||
dbg("Perl tests returned: $rc") if ($opt{v});
|
dbg("Perl tests returned: $rc");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Search for all log matches
|
# Search for all log matches
|
||||||
@@ -303,13 +304,11 @@ sub runfile {
|
|||||||
$pass++;
|
$pass++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($opt{d}) {
|
vrb("Test Config: $conf_fn");
|
||||||
dbg("Test Config: $conf_fn");
|
vrb("Debug Log: $FILE{debug}{fn}");
|
||||||
dbg("Debug Log: $FILE{debug}{fn}");
|
dbg(escape("$FILE{debug}{buf}"));
|
||||||
dbg(escape("$FILE{debug}{buf}")) if ($opt{v});
|
vrb("Error Log: $FILE{error}{fn}");
|
||||||
dbg("Error Log: $FILE{error}{fn}");
|
dbg(escape("$FILE{error}{buf}"));
|
||||||
dbg(escape("$FILE{error}{buf}")) if ($opt{v});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg(sprintf("%s) %s%s: %s%s", $id, $t{type}, (exists($t{comment}) ? " - $t{comment}" : ""), ($rc ? "failed" : "passed"), ((defined($out) && $out ne "")? " ($out)" : "")));
|
msg(sprintf("%s) %s%s: %s%s", $id, $t{type}, (exists($t{comment}) ? " - $t{comment}" : ""), ($rc ? "failed" : "passed"), ((defined($out) && $out ne "")? " ($out)" : "")));
|
||||||
@@ -353,7 +352,7 @@ sub do_raw_request {
|
|||||||
|
|
||||||
# Join togeather the request
|
# Join togeather the request
|
||||||
my $r = join("", @_);
|
my $r = join("", @_);
|
||||||
dbg($r) if ($opt{v});
|
dbg($r);
|
||||||
|
|
||||||
# Write to socket
|
# Write to socket
|
||||||
print $sock "$r";
|
print $sock "$r";
|
||||||
@@ -377,9 +376,7 @@ sub do_request {
|
|||||||
|
|
||||||
if (ref $r eq "HTTP::Request") {
|
if (ref $r eq "HTTP::Request") {
|
||||||
my $resp = $UA->request($r);
|
my $resp = $UA->request($r);
|
||||||
if ($opt{d} and $opt{v}) {
|
dbg($resp->request()->as_string()) if ($opt{d});
|
||||||
dbg($resp->request()->as_string());
|
|
||||||
}
|
|
||||||
return $resp
|
return $resp
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -418,6 +415,7 @@ sub match_log {
|
|||||||
my $t0 = gettimeofday;
|
my $t0 = gettimeofday;
|
||||||
my($fh,$rbuf) = ($FILE{$name}{fd}, \$FILE{$name}{buf});
|
my($fh,$rbuf) = ($FILE{$name}{fd}, \$FILE{$name}{buf});
|
||||||
my $n = length($$rbuf);
|
my $n = length($$rbuf);
|
||||||
|
my $rc = undef;
|
||||||
|
|
||||||
unless (defined $fh) {
|
unless (defined $fh) {
|
||||||
msg("Error: File \"$name\" is not opened for matching.");
|
msg("Error: File \"$name\" is not opened for matching.");
|
||||||
@@ -427,36 +425,44 @@ sub match_log {
|
|||||||
$timeout = 0 unless (defined $timeout);
|
$timeout = 0 unless (defined $timeout);
|
||||||
|
|
||||||
my $i = 0;
|
my $i = 0;
|
||||||
do {
|
my $graphed = 0;
|
||||||
my $nbytes = $fh->sysread($$rbuf, $BUFSIZ, $n);
|
READ: {
|
||||||
if (!defined($nbytes)) {
|
do {
|
||||||
msg("Error: Could not read \"$name\" log: $!");
|
my $nbytes = $fh->sysread($$rbuf, $BUFSIZ, $n);
|
||||||
last;
|
if (!defined($nbytes)) {
|
||||||
}
|
msg("Error: Could not read \"$name\" log: $!");
|
||||||
elsif (!defined($re) and $nbytes == 0) {
|
last;
|
||||||
last;
|
}
|
||||||
}
|
elsif (!defined($re) and $nbytes == 0) {
|
||||||
|
last;
|
||||||
# Remove APR pool debugging
|
|
||||||
$$rbuf =~ s/POOL DEBUG:[^\n]+PALLOC[^\n]+\n//sg;
|
|
||||||
|
|
||||||
$n = length($$rbuf);
|
|
||||||
|
|
||||||
#dbg("Match \"$re\" in $name \"$$rbuf\" ($n)");
|
|
||||||
return $& if ($$rbuf =~ m/$re/m);
|
|
||||||
# TODO: Use select()/poll()
|
|
||||||
sleep 0.1 unless ($nbytes == $BUFSIZ);
|
|
||||||
if ($graph and $opt{v}) {
|
|
||||||
$i++;
|
|
||||||
if ($i == 10) {
|
|
||||||
$i=0;
|
|
||||||
print STDERR "."
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} while (gettimeofday - $t0 < $timeout);
|
|
||||||
print STDERR "\n" if ($graph and $opt{v});
|
|
||||||
|
|
||||||
return;
|
# Remove APR pool debugging
|
||||||
|
$$rbuf =~ s/POOL DEBUG:[^\n]+PALLOC[^\n]+\n//sg;
|
||||||
|
|
||||||
|
$n = length($$rbuf);
|
||||||
|
|
||||||
|
#dbg("Match \"$re\" in $name \"$$rbuf\" ($n)");
|
||||||
|
if ($$rbuf =~ m/$re/m) {
|
||||||
|
$rc = $&;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
# TODO: Use select()/poll()
|
||||||
|
sleep 0.1 unless ($nbytes == $BUFSIZ);
|
||||||
|
if ($graph and $opt{d}) {
|
||||||
|
$i++;
|
||||||
|
if ($i == 10) {
|
||||||
|
$graphed++;
|
||||||
|
$i=0;
|
||||||
|
print STDERR $graph if ($graphed == 1);
|
||||||
|
print STDERR "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (gettimeofday - $t0 < $timeout);
|
||||||
|
}
|
||||||
|
print STDERR "\n" if ($graphed);
|
||||||
|
|
||||||
|
return $rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub match_file {
|
sub match_file {
|
||||||
@@ -501,6 +507,11 @@ sub dbg {
|
|||||||
print STDOUT "$out\n";
|
print STDOUT "$out\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub vrb {
|
||||||
|
return unless(@_ and $opt{v});
|
||||||
|
msg(@_);
|
||||||
|
}
|
||||||
|
|
||||||
sub msg {
|
sub msg {
|
||||||
return unless(@_);
|
return unless(@_);
|
||||||
my $out = join "", map {
|
my $out = join "", map {
|
||||||
@@ -555,7 +566,7 @@ sub httpd_start {
|
|||||||
my $rc = $?;
|
my $rc = $?;
|
||||||
if ( WIFEXITED($rc) ) {
|
if ( WIFEXITED($rc) ) {
|
||||||
$rc = WEXITSTATUS($rc);
|
$rc = WEXITSTATUS($rc);
|
||||||
dbg("Httpd start returned with $rc.") if ($rc);
|
vrb("Httpd start returned with $rc.") if ($rc);
|
||||||
}
|
}
|
||||||
elsif( WIFSIGNALED($rc) ) {
|
elsif( WIFSIGNALED($rc) ) {
|
||||||
msg("Httpd start failed with signal " . WTERMSIG($rc) . ".");
|
msg("Httpd start failed with signal " . WTERMSIG($rc) . ".");
|
||||||
@@ -567,15 +578,15 @@ sub httpd_start {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (defined $out and $out ne "") {
|
if (defined $out and $out ne "") {
|
||||||
dbg(join(" ", map { quote_shell($_) } @p));
|
vrb(join(" ", map { quote_shell($_) } @p));
|
||||||
msg("Httpd start failed with error messages:\n$out");
|
msg("Httpd start failed with error messages:\n$out");
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Look for startup msg
|
# Look for startup msg
|
||||||
unless (defined match_log("error", qr/resuming normal operations/, 60, $opt{d})) {
|
unless (defined match_log("error", qr/resuming normal operations/, 60, "Waiting on httpd to start: ")) {
|
||||||
dbg(join(" ", map { quote_shell($_) } @p));
|
vrb(join(" ", map { quote_shell($_) } @p));
|
||||||
dbg(match_log("error", qr/(^.*ModSecurity: .*)/sm, 10));
|
vrb(match_log("error", qr/(^.*ModSecurity: .*)/sm, 10));
|
||||||
msg("Httpd server failed to start.");
|
msg("Httpd server failed to start.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -607,7 +618,7 @@ sub httpd_stop {
|
|||||||
my $rc = $?;
|
my $rc = $?;
|
||||||
if ( WIFEXITED($rc) ) {
|
if ( WIFEXITED($rc) ) {
|
||||||
$rc = WEXITSTATUS($rc);
|
$rc = WEXITSTATUS($rc);
|
||||||
dbg("Httpd stop returned with $rc.") if ($rc);
|
vrb("Httpd stop returned with $rc.") if ($rc);
|
||||||
}
|
}
|
||||||
elsif( WIFSIGNALED($rc) ) {
|
elsif( WIFSIGNALED($rc) ) {
|
||||||
msg("Httpd stop failed with signal " . WTERMSIG($rc) . ".");
|
msg("Httpd stop failed with signal " . WTERMSIG($rc) . ".");
|
||||||
@@ -619,8 +630,8 @@ sub httpd_stop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Look for startup msg
|
# Look for startup msg
|
||||||
unless (defined match_log("error", qr/caught SIG[A-Z]+, shutting down/, 60, $opt{d})) {
|
unless (defined match_log("error", qr/caught SIG[A-Z]+, shutting down/, 60, "Waiting on httpd to stop: ")) {
|
||||||
dbg(join(" ", map { quote_shell($_) } @p));
|
vrb(join(" ", map { quote_shell($_) } @p));
|
||||||
msg("Httpd server failed to shutdown.");
|
msg("Httpd server failed to shutdown.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -653,7 +664,7 @@ sub httpd_reload {
|
|||||||
my $rc = $?;
|
my $rc = $?;
|
||||||
if ( WIFEXITED($rc) ) {
|
if ( WIFEXITED($rc) ) {
|
||||||
$rc = WEXITSTATUS($rc);
|
$rc = WEXITSTATUS($rc);
|
||||||
dbg("Httpd reload returned with $rc.") if ($rc);
|
vrb("Httpd reload returned with $rc.") if ($rc);
|
||||||
}
|
}
|
||||||
elsif( WIFSIGNALED($rc) ) {
|
elsif( WIFSIGNALED($rc) ) {
|
||||||
msg("Httpd reload failed with signal " . WTERMSIG($rc) . ".");
|
msg("Httpd reload failed with signal " . WTERMSIG($rc) . ".");
|
||||||
@@ -665,8 +676,8 @@ sub httpd_reload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Look for startup msg
|
# Look for startup msg
|
||||||
unless (defined match_log("error", qr/resuming normal operations/, 60, $opt{d})) {
|
unless (defined match_log("error", qr/resuming normal operations/, 60, "Waiting on httpd to restart: ")) {
|
||||||
dbg(join(" ", map { quote_shell($_) } @p));
|
vrb(join(" ", map { quote_shell($_) } @p));
|
||||||
msg("Httpd server failed to reload.");
|
msg("Httpd server failed to reload.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user