From a3232516bbe59aeaf28d65ffd49e41cfd7e222aa Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 9 Feb 2011 15:34:13 -0800 Subject: [PATCH] Detect loops in accounting chain jumps --- Shorewall/Perl/Shorewall/Accounting.pm | 37 +++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Accounting.pm b/Shorewall/Perl/Shorewall/Accounting.pm index 8075c37c3..110f2478d 100644 --- a/Shorewall/Perl/Shorewall/Accounting.pm +++ b/Shorewall/Perl/Shorewall/Accounting.pm @@ -46,9 +46,9 @@ our %tables; # Called by the compiler to [re-]initialize this module's state # sub initialize() { - our $jumpchainref; - $jumpchainref = undef; - %tables = (); + our $jumpchainref = undef; + %tables = (); + our %accountingjumps = (); } # @@ -56,7 +56,8 @@ sub initialize() { # sub process_accounting_rule( ) { - our $jumpchainref; + our $jumpchainref = 0; + our %accountingjumps; my ($action, $chain, $source, $dest, $proto, $ports, $sports, $user, $mark, $ipsec, $headers ) = split_line1 1, 11, 'Accounting File'; @@ -208,6 +209,8 @@ sub process_accounting_rule( ) { $rule .= do_ipsec( $dir , $ipsec ); } + $accountingjumps{$jumpchainref->{name}}{$chain} = 1 if $jumpchainref; + fatal_error "$chain is not an accounting chain" unless $chainref->{accounting}; $restriction = $dir eq 'in' ? INPUT_RESTRICT : OUTPUT_RESTRICT if $dir; @@ -259,6 +262,8 @@ sub process_accounting_rule( ) { sub setup_accounting() { + our %accountingjumps; + if ( my $fn = open_file 'accounting' ) { first_entry "$doing $fn..."; @@ -300,6 +305,30 @@ sub setup_accounting() { for ( accounting_chainrefs ) { warning_message "Accounting chain $_->{name} has no references" unless keys %{$_->{references}}; } + + if ( my $chainswithjumps = keys %accountingjumps ) { + my $progress = 1; + + while ( $chainswithjumps && $progress ) { + $progress = 0; + for my $chain1 ( keys %accountingjumps ) { + if ( keys %{$accountingjumps{$chain1}} ) { + for my $chain2 ( keys %{$accountingjumps{$chain1}} ) { + delete $accountingjumps{$chain1}{$chain2}, $progress = 1 unless $accountingjumps{$chain2}; + } + } else { + delete $accountingjumps{$chain1}; + $chainswithjumps--; + $progress = 1; + } + } + } + + if ( $chainswithjumps ) { + my @chainswithjumps = keys %accountingjumps; + fatal_error "Jump loop involving the following chains: @chainswithjumps"; + } + } } }