Improve @CALLER fix to create unique chains per caller

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2016-01-16 17:12:03 -08:00
parent 9aa915a5e0
commit 742c15b289
2 changed files with 79 additions and 21 deletions

View File

@ -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;

View File

@ -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;
}