Merge branch 'master' into 4.4.16

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2010-12-27 12:32:28 -08:00
commit 6a7dad5e18
12 changed files with 243 additions and 131 deletions

View File

@ -119,8 +119,10 @@ fi
%doc COPYING changelog.txt releasenotes.txt
%changelog
* Wed Dec 22 2010 Tom Eastep tom@shorewall.net
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0RC1
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta7
* Mon Dec 20 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta6
* Fri Dec 10 2010 Tom Eastep tom@shorewall.net

View File

@ -102,8 +102,10 @@ fi
%doc COPYING changelog.txt releasenotes.txt
%changelog
* Wed Dec 22 2010 Tom Eastep tom@shorewall.net
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0RC1
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta7
* Mon Dec 20 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta6
* Fri Dec 10 2010 Tom Eastep tom@shorewall.net

View File

@ -2040,8 +2040,7 @@ sub logchain( $$$$$$ ) {
$logtag,
'add',
'' );
add_rule( $logchainref, $exceptionrule . $target );
add_jump( $logchainref, $target, 0, $exceptionrule );
}
$logchainref;
@ -3849,9 +3848,11 @@ sub expand_rule( $$$$$$$$$$;$ )
#
# Find/Create a chain that both logs and applies the target action
# and jump to the log chain if all of the rule's conditions are met
#
#
assert( $target );
add_jump( $chainref,
logchain( $chainref, $loglevel, $logtag, $exceptionrule , $disposition, $jump ),
logchain( $chainref, $loglevel, $logtag, $exceptionrule , $disposition, $target ),
$builtin_target{$disposition},
$matches,
1 );

View File

@ -637,6 +637,10 @@ sub compiler {
#
validate_policy;
#
# Process default actions
#
process_actions2;
#
# N O T R A C K
# (Produces no output to the compiled script)
#
@ -761,7 +765,6 @@ sub compiler {
#
# Post-rules action processing.
#
process_actions2;
process_actions3;
#
# MACLIST Filtration again

View File

@ -96,6 +96,8 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
close_file
push_open
pop_open
push_params
pop_params
read_a_line
validate_level
which
@ -274,6 +276,10 @@ our @openstack;
# From the params file
#
our %params;
#
# Action parameters
#
our %actparms;
our $currentline; # Current config file line image
our $currentfile; # File handle reference
@ -717,6 +723,8 @@ sub initialize( $ ) {
command => '',
files => '',
destination => '' );
%actparms = ();
}
my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
@ -1781,6 +1789,29 @@ sub embedded_perl( $ ) {
}
}
#
# Push/pop action params
#
sub push_params( $ ) {
my @params = split /,/, $_[0];
my $oldparams = \%actparms;
%actparms = ();
for ( my $i = 1; $i <= @params; $i++ ) {
my $val = $params[$i - 1];
$actparms{$i} = $val eq '-' ? '' : $val eq '--' ? '-' : $val;
}
$oldparams;
}
sub pop_params( $ ) {
my $oldparms = shift;
%actparms = %$oldparms;
}
#
# Read a line from the current include stack.
#
@ -1856,24 +1887,23 @@ sub read_a_line(;$) {
#
# Expand Shell Variables using %params and %ENV
#
# $1 $2 $3 - $4
# $1 $2 $3 - $4
while ( $currentline =~ m( ^(.*?) \$({)? (\w+) (?(2)}) (.*)$ )x ) {
unless ( exists $params{$3} ) {
#
# Given the way that getparams works, this should never help but better safe than sorry
#
$params{$3} = $ENV{$3} if exists $ENV{$3};
my ( $first, $var, $rest ) = ( $1, $3, $4);
my $val;
if ( $var =~ /^\d+$/ ) {
fatal_error "Undefined parameter (\$$var)" unless exists $actparms{$var};
$val = $actparms{$var};
} else {
fatal_error "Undefined shell variable (\$$var)" unless exists $params{$var};
$val = $params{$var};
}
my $val = $params{$3};
unless ( defined $val ) {
fatal_error "Undefined shell variable (\$$3)" unless exists $params{$3} || exists $ENV{$3};
$val = '';
}
$currentline = join( '', $1 , $val , $4 );
$val = '' unless defined $val;
$currentline = join( '', $first , $val , $rest );
fatal_error "Variable Expansion Loop" if ++$count > 100;
}
@ -2711,7 +2741,7 @@ sub ensure_config_path() {
open_file $f;
$ENV{CONFDIR} = $globals{CONFDIR};
$params{CONFDIR} = $globals{CONFDIR};
while ( read_a_line ) {
if ( $currentline =~ /^\s*([a-zA-Z]\w*)=(.*?)\s*$/ ) {

View File

@ -42,7 +42,7 @@ our @EXPORT = qw(
process_actions3
process_rules
);
);
our @EXPORT_OK = qw( initialize );
our $VERSION = '4.4_16';
@ -58,9 +58,10 @@ our @builtins;
#
our $rule_commands = { COMMENT => 0, FORMAT => 2 };
use constant { MAX_MACRO_NEST_LEVEL => 5 };
use constant { MAX_MACRO_NEST_LEVEL => 5 , MAX_ACTION_NEST_LEVEL => 5 };
our $macro_nest_level;
our $action_nest_level;
#
# Rather than initializing globals in an INIT block or during declaration,
@ -73,10 +74,10 @@ our $macro_nest_level;
# able to re-initialize its dependent modules' state.
#
sub initialize( $ ) {
$family = shift;
%macros = ();
$macro_nest_level = 0;
$family = shift;
%macros = ();
$macro_nest_level = 0;
$action_nest_level = 0;
if ( $family == F_IPV4 ) {
@builtins = qw/dropBcast allowBcast dropNotSyn rejNotSyn dropInvalid allowInvalid allowinUPnP forwardUPnP Limit/;
@ -202,15 +203,7 @@ sub new_action( $ ) {
my $action = $_[0];
$actions{$action} = { actchain => '', requires => {} };
}
#
# Record a 'requires' relationship between a pair of actions.
#
sub add_requiredby ( $$ ) {
my ($requiredby , $requires ) = @_;
$actions{$requires}{requires}{$requiredby} = 1;
$actions{$action} = { actchain => '' };
}
#
@ -248,17 +241,15 @@ sub map_old_actions( $ ) {
# to the target table (%Shorewall::Chains::targets) and actions table, then ${SHAREDIR}/actions.std and
# ${CONFDIR}/actions are scanned (in that order). For each action:
#
# a) The related action definition file is located and scanned.
# b) Forward and unresolved action references are trapped as errors.
# c) A dependency graph is created using the 'requires' field in the 'actions' table.
# a) The related action definition file is located.
# a) The action is added to the target table
#
# As the rules file is scanned, each action[:level[:tag]] is merged onto the 'usedactions' hash. When an <action>
# is merged into the hash, its action chain is created. Where logging is specified, a chain with the name
# %<action>n is used where the <action> name is truncated on the right where necessary to ensure that the total
# length of the chain name does not exceed 30 characters.
# The second phase (process_actions2) occurs after the policy file is scanned. Each default action's file
# is processed by process_action2(). That function recursively processes action files up the action
# invocation tree, adding to the %usedactions hash as each new action is discovered.
#
# The second phase (process_actions2) occurs after the rules file is scanned. The transitive closure of
# %usedactions is generated; again, as new actions are merged into the hash, their action chains are created.
# During rules file processing, process_action2() is called when a new action:level:tag:params is encountered.
# Again, each new such tupple is entered into the %usedactions hash.
#
# The final phase (process_actions3) traverses the keys of %usedactions populating each chain appropriately
# by reading the related action definition file and creating rules. Note that a given action definition file is
@ -269,7 +260,7 @@ sub process_rule_common ( $$$$$$$$$$$$$$$$ );
sub process_actions1() {
progress_message2 "Preprocessing Action Files...";
progress_message2 "Locating Action Files...";
#
# Add built-in actions to the target table and create those actions
#
@ -297,53 +288,11 @@ sub process_actions1() {
new_action $action;
$targets{$action} = ACTION;
my $actionfile = find_file "action.$action";
fatal_error "Missing Action File ($actionfile)" unless -f $actionfile;
progress_message2 " Pre-processing $actionfile...";
push_open( $actionfile );
#
# We defer assigning a type to the action until we've processed it's action file.
# This allows us to easily catch the case where an action invokes itself.
#
my $actiontype = 0;
while ( read_a_line ) {
my ($wholetarget, @rest ) = split_line1 1, 13, 'action file' , $rule_commands;
#
# When passed an action name in the first argument, process_rule_common() only
# deals with the target and the parameter. We pass undef for the rest so we'll
# know if we try to use one of them.
#
# process_rule_common() returns the NATONLY actiontype flag if the target
# of the rule includes NATRULE, NATONLY or NONAT. The flag is LORed into the
# action's type below.
#
$actiontype |= process_rule_common( $action ,
$wholetarget ,
'' , # Current Param
undef, # source
undef, # dest
undef, # proto
undef, # ports
undef, # sports
undef, # origdest
undef, # ratelimit
undef, # user
undef, # mark
undef, # connlimit
undef, # time
undef, # headers
undef # wildcard
) unless $wholetarget eq 'FORMAT' || $wholetarget eq 'COMMENT';
}
pop_open;
$targets{$action} = ACTION | $actiontype;
}
}
}
@ -373,22 +322,61 @@ sub merge_action_levels( $$ ) {
join ':', $action, $sublevel, $subtag, $subparam;
}
sub process_action2( $ ) {
my $wholeaction = shift;
my ( $action , $level, $tag, $param ) = split /:/, $wholeaction;
my $actionfile = find_file "action.$action";
fatal_error "Missing Action File ($actionfile)" unless -f $actionfile;
progress_message2 " Pre-processing $actionfile...";
fatal_error "Actions nested too deeply" if ++$action_nest_level > MAX_ACTION_NEST_LEVEL;
push_open( $actionfile );
my $oldparms = push_params( $param );
while ( read_a_line ) {
my ($wholetarget, @rest ) = split_line1 1, 13, 'action file' , $rule_commands;
#
# When passed an action name in the first argument, process_rule_common() only
# deals with the target and the parameter. We pass undef for the rest so we'll
# know if we try to use one of them.
#
process_rule_common( $wholeaction ,
$wholetarget ,
'' , # Current Param
undef, # source
undef, # dest
undef, # proto
undef, # ports
undef, # sports
undef, # origdest
undef, # ratelimit
undef, # user
undef, # mark
undef, # connlimit
undef, # time
undef, # headers
undef # wildcard
) unless $wholetarget eq 'FORMAT' || $wholetarget eq 'COMMENT';
}
pop_open;
--$action_nest_level;
pop_params( $oldparms );
}
sub process_actions2 () {
progress_message2 'Generating Transitive Closure of Used-action List...';
progress_message2 "Pre-processing default actions...";
my $changed = 1;
while ( $changed ) {
$changed = 0;
for my $target (keys %usedactions) {
my ( $action, $level, $tag, $param ) = split ':', $target;
my $actionref = $actions{$action};
assert( $actionref );
for my $action1 ( keys %{$actionref->{requires}} ) {
my $action2 = merge_action_levels( $target, $action1 );
$changed = 1 if use_action( $action2 );
}
}
for my $action ( keys %usedactions ) {
my ( $basic_action, undef, undef, undef ) = split /:/, $action;
process_action2( $action ) unless $targets{$basic_action} & BUILTIN;
}
}
@ -406,6 +394,8 @@ sub process_action3( $$$$$$ ) {
open_file $actionfile;
my $oldparms = push_params( $param );
while ( read_a_line ) {
my ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers );
@ -432,6 +422,8 @@ sub process_action3( $$$$$$ ) {
}
clear_comment;
pop_params( $oldparms );
}
#
@ -725,10 +717,18 @@ sub process_macro ( $$$$$$$$$$$$$$$$$ ) {
#
# Once a rule has been expanded via wildcards (source and/or dest zone eq 'all'), it is processed by this function. If
# the target is a macro, the macro is expanded and this function is called recursively for each rule in the expansion.
# Rules in both the rules file and in action bodies are processed here.
#
# This function may be called in three different ways:
#
# 1) $chainref undefined -- Being called to process a record in the rules file. All arguments are passed.
# 2) $chainref is a chain name -- Pre-proessing the records in an action file. Only $target is passed.
# 3) $chainref is a chain reference -- Processing the records in an action file. The chain is where the generated
# rules are added.
#
sub process_rule_common ( $$$$$$$$$$$$$$$$ ) {
my ( $chainref, #reference to Action Chain if we are being called from process_action3()
# if defined, we are being called from process_action1() and this is the name of the action
# if defined, we are being called from process_action2() and this is the name of the action
$target,
$current_param,
$source,
@ -749,15 +749,16 @@ sub process_rule_common ( $$$$$$$$$$$$$$$$ ) {
my ( $basictarget, $param ) = get_target_param $action;
my $rule = '';
my $optimize = $wildcard ? ( $basictarget =~ /!$/ ? 0 : $config{OPTIMIZE} & 1 ) : 0;
my $inaction1;
my $inaction1 = '';
my $inaction3;
my $normalized_target;
my $normalized_action;
if ( defined $chainref ) {
if ( reftype $chainref ) {
$inaction3 = 1;
} else {
$inaction1 = $chainref;
( $inaction1, undef, undef, undef ) = split /:/, $normalized_action = $chainref;
}
}
@ -772,7 +773,7 @@ sub process_rule_common ( $$$$$$$$$$$$$$$$ ) {
( $basictarget, $actiontype , $param ) = map_old_actions( $basictarget ) unless $actiontype || $param;
}
fatal_error "Unknown action ($action)" unless $actiontype;
fatal_error "Unknown ACTION ($action)" unless $actiontype;
if ( $actiontype == MACRO ) {
#
@ -832,21 +833,36 @@ sub process_rule_common ( $$$$$$$$$$$$$$$$ ) {
# Create the action:level:tag:param tupple.
#
$normalized_target = normalize_action( $basictarget, $loglevel, $param );
if ( $inaction1 ) {
add_requiredby( $normalized_target , $inaction1 );
} else {
unless ( $inaction3 ) {
fatal_error "An action may not invoke itself" if $basictarget eq $inaction1;
if ( my $ref = use_action( $normalized_target ) ) {
new_nat_chain $ref->{name} if $actiontype & ( NATRULE | NONAT | NATONLY );
#
# First reference to this tupple
#
unless ( $actiontype & BUILTIN ) {
#
# Not a built-in - do preprocessing
#
process_action2( $normalized_target );
#
# Preprocessing may determine that the chain or one of it's dependents does NAT. If so:
#
# - Refresh $actiontype
# - Create the associate nat table chain if appropriate.
#
ensure_chain( 'nat', $ref->{name} ) if ( $actiontype = $targets{$basictarget} ) & NATRULE;
}
}
}
$action = $basictarget; # Remove params, if any, from $action.
}
#
# Return the NATRULE flag to the caller who will eventually add it
# to $targets{$inaction1}
#
return ( $actiontype & ( NATRULE | NONAT | NATONLY ) ) ? NATRULE : 0 if $inaction1;
if ( $inaction1 ) {
$targets{$inaction1} |= NATRULE if $actiontype & (NATRULE | NONAT | NATONLY );
return 1;
}
#
# Take care of irregular syntax and targets
#
@ -1103,7 +1119,7 @@ sub process_rule_common ( $$$$$$$$$$$$$$$$ ) {
}
}
} elsif ( $actiontype & ACTION ) {
$target = $action;
$target = $usedactions{$normalized_target}->{name};
} else {
if ( $server eq '' ) {
fatal_error "A server and/or port must be specified in the DEST column in $action rules" unless $serverport;

View File

@ -1,3 +1,7 @@
Changes in Shorewall 4.4.16 RC 1
1) Complete parameterized actions.
Changes in Shorewall 4.4.16 Beta 6
1) Don't let root match wildcard.

View File

@ -1,6 +1,6 @@
----------------------------------------------------------------------------
S H O R E W A L L 4 . 4 . 1 6
R C 1
R C I
----------------------------------------------------------------------------
I. PROBLEMS CORRECTED IN THIS RELEASE
@ -14,6 +14,10 @@ VI. PROBLEMS CORRECTED AND NEW FEATURES IN PRIOR RELEASES
I. P R O B L E M S C O R R E C T E D I N T H I S R E L E A S E
----------------------------------------------------------------------------
Beta 7
None.
Beta 6
1) Previously, the root of a wildcard name erroneously matched that
@ -120,8 +124,17 @@ Beta 1
and in macros invoked from Actions. Additionally, Macros used in
Actions are now free to invoke other actions.
4) There is now limited support for parameterized actions. Currently,
the parameters are only available to extensions scripts. See
4) There is now support for parameterized actions. The parameters are
a comma-separated list enclosed in parentheses following the
action name (e.g., ACT(REDIRECT,192.168.1.4)). Within the action
body, the parameter values are available in $1, $2, etc.
You can 'omit' a parameter in the list by using '-' (e,g,
REDIRECT,-.info) would omit the second parameter (within the action
body, $2 would expand to nothing). If you want to specify '-' as an
parameter value, use '--'.
Parameter values are also available to extensions scripts. See
http://www.shorewall.net/Actions.html#Extension for more
information.

View File

@ -109,8 +109,10 @@ fi
%doc COPYING INSTALL changelog.txt releasenotes.txt Contrib/* Samples
%changelog
* Wed Dec 22 2010 Tom Eastep tom@shorewall.net
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0RC1
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta7
* Mon Dec 20 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta6
* Fri Dec 10 2010 Tom Eastep tom@shorewall.net

View File

@ -93,8 +93,10 @@ fi
%doc COPYING changelog.txt releasenotes.txt
%changelog
* Wed Dec 22 2010 Tom Eastep tom@shorewall.net
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0RC1
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta7
* Mon Dec 20 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta6
* Fri Dec 10 2010 Tom Eastep tom@shorewall.net

View File

@ -98,8 +98,10 @@ fi
%doc COPYING INSTALL changelog.txt releasenotes.txt tunnel ipsecvpn ipv6 Samples6
%changelog
* Wed Dec 22 2010 Tom Eastep tom@shorewall.net
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0RC1
* Sun Dec 26 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta7
* Mon Dec 20 2010 Tom Eastep tom@shorewall.net
- Updated to 4.4.16-0Beta6
* Fri Dec 10 2010 Tom Eastep tom@shorewall.net

View File

@ -227,6 +227,40 @@ ACCEPT - - tcp 135,139,445
<para>The SOURCE and DEST columns in the action file may not include
zone names; those are given when the action is invoked.</para>
<para>Additionally, it is possible to pass parameters to an action, when
it is invoked in the rules file or in another action.</para>
<para>Here's a trivial example:</para>
<para>/etc/shorewall/action.A:</para>
<programlisting>#TARGET SOURCE DEST PROTO DEST SOURCE ORIGINAL
# PORT(S) PORT(S) DEST
FORMAT 2
$1 - - tcp 80 - 1.2.3.4</programlisting>
<para>/etc/shorewall/rules:</para>
<programlisting>#TARGET SOURCE DEST PROTO DEST SOURCE ORIGINAL
# PORT(S) PORT(S) DEST
A(REDIRECT) net fw</programlisting>
<para>The above is equivalent to this rule:</para>
<programlisting>#TARGET SOURCE DEST PROTO DEST SOURCE ORIGINAL
# PORT(S) PORT(S) DEST
REDIRECT net - tcp 80 - 1.2.3.4</programlisting>
<para>You can 'omit' parameters by using '-'.</para>
<para>Example: ACTION(REDIRECT,-,info)</para>
<para>In the above example, $2 would expand to nothing.</para>
<para>If you want to make '-' a parameter value, use '--' (e.g.,
ACTION(REDIRECT,--.info)).</para>
</section>
<section>
@ -520,7 +554,8 @@ bar:debug</programlisting>
<listitem>
<para><emphasis role="bold">@params</emphasis> is the list of
parameter values (Shorewall 4.4.16 and later).</para>
parameter values (Shorewall 4.4.16 and later). 'Omitted' parameters
contain '-'.</para>
</listitem>
</itemizedlist>
@ -628,13 +663,13 @@ Limit(SSH,3,60):info net $FW tcp 22</programl
<programlisting>use Shorewall::Chains;
@params = split /,/, $tag unless @params;
@params = split( /,/, $tag ), $tag='' unless @params;
fatal_error 'Limit rules must include &lt;list name&gt;,&lt;max connections&gt;,&lt;interval&gt; as the log tag or params' unless @params == 3;
my $list = $tag[0];
my $list = $params[0];
for ( @tag[1,2] ) {
for ( @params[1,2] ) {
fatal_error 'Max connections and interval in Limit rules must be numeric (' . $_ . ')' unless /^\d+$/
}
@ -644,7 +679,7 @@ add_rule $chainref, "-m recent --name $list --set";
if ( $level ) {
my $xchainref = new_chain 'filter' , "$chainref-&gt;{name}%";
log_rule_limit $level, $xchainref, $params[0], 'DROP', '', '', 'add', '';
log_rule_limit $level, $xchainref, $params[0], 'DROP', $tag, '', 'add', '';
add_rule $xchainref, '-j DROP';
add_rule $chainref, "-m recent --name $list --update --seconds $params[2] --hitcount $count -j $xchainref-&gt;{name}";
} else {