From 742c15b289d5c8551df2469b34d5279e3f460e4a Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sat, 16 Jan 2016 17:12:03 -0800 Subject: [PATCH] Improve @CALLER fix to create unique chains per caller Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Config.pm | 27 ++++++++--- Shorewall/Perl/Shorewall/Rules.pm | 73 ++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 21 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 3456b08ea..298fd05d8 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -185,6 +185,9 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script %helpers_aliases %actparms + + PARMSMODIFIED + USEDCALLER F_IPV4 F_IPV6 @@ -546,6 +549,7 @@ our %compiler_params; # our %actparms; our $parmsmodified; +our $usedcaller; our $inline_matches; our $currentline; # Current config file line image @@ -596,6 +600,9 @@ use constant { MIN_VERBOSITY => -1, F_IPV6 => 6, }; +use constant { PARMSMODIFIED => 1, + USEDCALLER => 2 }; + our %validlevels; # Valid log levels. # @@ -1045,6 +1052,7 @@ sub initialize( $;$$) { %actparms = ( 0 => 0, loglevel => '', logtag => '', chain => '', disposition => '', caller => '' ); $parmsmodified = 0; + $usedcaller = 0; %helpers_enabled = ( amanda => 1, @@ -2502,7 +2510,7 @@ sub evaluate_expression( $$$ ) { my ( $first, $var, $rest ) = ( $1, $3, $4); $var = numeric_value( $var ) if $var =~ /^\d/; $val = $var ? $actparms{$var} : $chain; - $parmsmodified ||= $var eq 'caller'; + $usedcaller = USEDCALLER if $var eq 'caller'; $expression = join_parts( $first, $val, $rest ); directive_error( "Variable Expansion Loop" , $filename, $linenumber ) if ++$count > 100; } @@ -2639,7 +2647,7 @@ sub process_compiler_directive( $$$$ ) { my $val = $actparms{$var} = evaluate_expression ( $expression, $filename, $linenumber ); - $parmsmodified = 1; + $parmsmodified = PARMSMODIFIED; } else { $variables{$2} = evaluate_expression( $expression, $filename, @@ -3174,11 +3182,13 @@ sub push_action_params( $$$$$$ ) { my ( $action, $chainref, $parms, $loglevel, $logtag, $caller ) = @_; my @parms = ( undef , split_list3( $parms , 'parameter' ) ); - $actparms{modified} = $parmsmodified; + $actparms{modified} = $parmsmodified; + $actparms{usedcaller} = $usedcaller; my %oldparms = %actparms; $parmsmodified = 0; + $usedcaller = 0; %actparms = (); @@ -3204,13 +3214,16 @@ sub push_action_params( $$$$$$ ) { # # Pop the action parameters using the passed hash reference -# Return true of the popped parameters were modified +# Return: +# 1 if the popped parameters were modified +# 2 if the action used @CALLER # sub pop_action_params( $ ) { my $oldparms = shift; %actparms = %$oldparms; - my $return = $parmsmodified; + my $return = $parmsmodified ? $parmsmodified : ( $usedcaller || 0 ); ( $parmsmodified ) = delete $actparms{modified}; + ( $usedcaller ) = delete $actparms{usedcaller}; $return; } @@ -3305,7 +3318,7 @@ sub expand_variables( \$ ) { $val = $variables{$var}; } elsif ( exists $actparms{$var} ) { $val = $actparms{$var}; - $parmsmodified = 1 if $var eq 'caller'; + $usedcaller = USEDCALLER if $var eq 'caller'; } else { fatal_error "Undefined shell variable (\$$var)" unless $config{IGNOREUNKNOWNVARIABLES} || exists $config{$var}; } @@ -3324,7 +3337,7 @@ sub expand_variables( \$ ) { while ( $$lineref =~ m( ^(.*?) \@({)? (\d+|[a-zA-Z_]\w*) (?(2)}) (.*)$ )x ) { my ( $first, $var, $rest ) = ( $1, $3, $4); my $val = $var ? $actparms{$var} : $actparms{chain}; - $parmsmodified = 1 if $var eq 'caller'; + $usedcaller = USEDCALLER if $var eq 'caller'; $val = '' unless defined $val; $$lineref = join( '', $first , $val , $rest ); fatal_error "Variable Expansion Loop" if ++$count > 100; diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index c9e29b6b8..9d7790fcf 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -560,7 +560,7 @@ sub process_a_policy() { require_capability 'AUDIT_TARGET', ":audit", "s" if $audit; - my ( $policy, $default, $level, $remainder ) = split( /:/, $originalpolicy, 4 ); + my ( $policy, $default, $level, undef, $remainder ) = split( /:/, $originalpolicy, 5 ); fatal_error "Invalid or missing POLICY ($originalpolicy)" unless $policy; @@ -944,7 +944,7 @@ sub complete_standard_chain ( $$$$ ) { ( $policy, $loglevel, $defaultaction ) = @{$policychainref}{'policy', 'loglevel', 'default' }; $stdchainref->{origin} = $policychainref->{origin}; } elsif ( $defaultaction !~ /:/ ) { - $defaultaction = join(":", $defaultaction, 'none', '', '' ); + $defaultaction = join(":", $defaultaction, 'none', '', '', '' ); } @@ -1169,14 +1169,15 @@ sub finish_section ( $ ) { # # Create a normalized action name from the passed pieces. # -# Internally, action invocations are uniquely identified by a 4-tuple that -# includes the action name, log level, log tag and params. The pieces of the tuple -# are separated by ":". +# Internally, action invocations are uniquely identified by a 5-tuple that +# includes the action name, log level, log tag, calling chain and params. +# The pieces of the tuple are separated by ":". # sub normalize_action( $$$ ) { my $action = shift; my $level = shift; my $param = shift; + my $caller = ''; #We assume that the function doesn't use @CALLER ( $level, my $tag ) = split ':', $level; @@ -1185,13 +1186,23 @@ sub normalize_action( $$$ ) { $param = '' unless defined $param; $param = '' if $param eq '-'; - join( ':', $action, $level, $tag, $param ); + join( ':', $action, $level, $tag, $caller, $param ); +} + +# +# Add the actual caller into an existing normalised name +# +sub insert_caller($$) { + my ( $normalized, $caller ) = @_; + + my ( $action, $level, $tag, undef, $param ) = split /:/, $normalized; + + join( ':', $action, $level, $tag, $caller, $param ); } # # Accepts a rule target and returns a normalized tuple # - sub normalize_action_name( $ ) { my $target = shift; my ( $action, $loglevel) = split_action $target; @@ -1203,7 +1214,7 @@ sub normalize_action_name( $ ) { # Produce a recognizable target from a normalized action # sub external_name( $ ) { - my ( $target, $level, $tag, $params ) = split /:/, shift, 4; + my ( $target, $level, $tag, undef, $params ) = split /:/, shift, 5; $target = join( '', $target, '(', $params , ')' ) if $params; $target .= ":$level" if $level && $level ne 'none'; @@ -1333,7 +1344,7 @@ sub createsimpleactionchain( $ ) { sub createactionchain( $ ) { my $normalized = shift; - my ( $target, $level, $tag, $param ) = split /:/, $normalized, 4; + my ( $target, $level, $tag, $caller, $param ) = split /:/, $normalized, 5; assert( defined $param ); @@ -1693,7 +1704,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$$ ); sub process_action($$) { my ( $chainref, $caller ) = @_; my $wholeaction = $chainref->{action}; - my ( $action, $level, $tag, $param ) = split /:/, $wholeaction, 4; + my ( $action, $level, $tag, undef, $param ) = split /:/, $wholeaction, 5; if ( $targets{$action} & BUILTIN ) { $level = '' if $level =~ /none!?/; @@ -1909,7 +1920,7 @@ sub process_actions() { sub use_policy_action( $$ ) { my $ref = use_action( $_[0] ); if ( $ref ) { - delete $usedactions{$ref->{action}} if process_action( $ref, $_[1] ); + delete $usedactions{$ref->{action}} if process_action( $ref, $_[1] ) & PARMSMODIFIED; } else { $ref = $usedactions{$_[0]}; } @@ -2661,7 +2672,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$$ ) { # # Handle actions # - my $delete_action; + my $delete_action = 0; if ( $actiontype & ACTION ) { # @@ -2678,7 +2689,41 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$$ ) { my $savestatematch = $statematch; $statematch = ''; - $delete_action = process_action( $ref, $chain ); + if ( ( $delete_action = process_action( $ref, $chain ) ) & USEDCALLER ) { + # + # The chain uses @CALLER but doesn't modify the action parameters. + # We need to see if this chain has already called this action + # + my $renormalized_target = insert_caller( $normalized_target, $chain ); + my $ref1 = $usedactions{$renormalized_target}; + + if ( $ref1 ) { + # + # It has -- use the prior chain + # + $ref = $ref1; + # + # We leave the new chain in place but delete it from %usedactions below + # + } else { + # + # This is the first time that the current chain has invoked this action + # + $usedactions{$renormalized_target} = $ref; + # + # Swap the action member + # + $ref->{action} = $renormalized_target; + } + # + # Delete the usedactions entry with the original normalized key + # + delete $usedactions{$normalized_target}; + # + # New normalized target + # + $normalized_target = $renormalized_target; + } # # Processing the action may determine that the action or one of it's dependents does NAT or HELPER, so: # @@ -2918,7 +2963,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$$ ) { unless unreachable_warning( $wildcard || $section == DEFAULTACTION_SECTION, $chainref ); } - delete $usedactions{$normalized_target} if $delete_action; + delete $usedactions{$normalized_target} if $delete_action & PARMSMODIFIED; return 1; }