diff --git a/New/Shorewall/Chains.pm b/New/Shorewall/Chains.pm index ed9f15bd0..ad2a761af 100644 --- a/New/Shorewall/Chains.pm +++ b/New/Shorewall/Chains.pm @@ -15,11 +15,19 @@ our @EXPORT = qw( add_rule dynamic_fwd dynamic_in dynamic_out - cynamic_chains + dynamic_chains dnat_chain snat_chain ecn_chain first_chains + new_chain + ensure_chain + ensure_filter_chain + new_standard_chain + new_builtin_chain + initialize_chain_table + dump_chain_table + finish_section @policy_chains %chain_table @@ -224,4 +232,191 @@ sub first_chains( $ ) #$1 = interface [ $c . '_fwd', $c . '_in' ]; } +# +# Create a new chain and return a reference to it. +# +sub new_chain($$) +{ + my ($table, $chain) = @_; + my %ch; + my @rules; + + $ch{name} = $chain; + $ch{log} = 1 if $env{LOGRULENUMBERS}; + $ch{rules} = \@rules; + $ch{table} = $table; + $chain_table{$table}{$chain} = \%ch; + \%ch; +} + +# +# Create a chain if it doesn't exist already +# +sub ensure_chain($$) +{ + my ($table, $chain) = @_; + + my $ref = $chain_table{$table}{$chain}; + + return $ref if $ref; + + new_chain $table, $chain; +} + +sub finish_chain_section( $$ ); + +# +# Create a filter chain if necessary. Optionally populate it with the appropriate ESTABLISHED,RELATED rule(s) and perform SYN rate limiting. +# +sub ensure_filter_chain( $$ ) +{ + my ($chain, $populate) = @_; + + my $chainref = $filter_table->{$chain}; + + $chainref = new_chain 'filter' , $chain unless $chainref; + + if ( $populate and ! $chainref->{referenced} ) { + if ( $section eq 'NEW' or $section eq 'DONE' ) { + finish_chain_section $chainref , 'ESTABLISHED,RELATED'; + } elsif ( $section eq 'ESTABLISHED' ) { + finish_chain_section $chainref , 'ESTABLISHED'; + } + } + + $chainref->{referenced} = 1; + + $chainref; +} + +# +# Add a builtin chain +# +sub new_builtin_chain($$$) +{ + my $chainref = new_chain $_[0],$_[1]; + $chainref->{referenced} = 1; + $chainref->{policy} = $_[2]; + $chainref->{builtin} = 1; +} + +sub new_standard_chain($) { + my $chainref = new_chain 'filter' ,$_[0]; + $chainref->{referenced} = 1; + $chainref; +} + +# +# Add all builtin chains to the chain table +# +# +sub initialize_chain_table() +{ + for my $chain qw/OUTPUT PREROUTING/ { + new_builtin_chain 'raw', $chain, 'ACCEPT'; + } + + for my $chain qw/INPUT OUTPUT FORWARD/ { + new_builtin_chain 'filter', $chain, 'DROP'; + } + + for my $chain qw/PREROUTING POSTROUTING OUTPUT/ { + new_builtin_chain 'nat', $chain, 'ACCEPT'; + } + + for my $chain qw/PREROUTING INPUT FORWARD OUTPUT POSTROUTING/ { + new_builtin_chain 'mangle', $chain, 'ACCEPT'; + } + + if ( $capabilities{MANGLE_FORWARD} ) { + for my $chain qw/ FORWARD POSTROUTING / { + new_builtin_chain 'mangle', $chain, 'ACCEPT'; + } + } +} + +# +# Dump the contents of the Chain Table +# +sub dump_chain_table() +{ + print "\n"; + + for my $table qw/filter nat mangle/ { + print "Table: $table\n"; + + for my $chain ( sort keys %{$chain_table{$table}} ) { + my $chainref = $chain_table{$table}{$chain}; + print " Chain $chain:\n"; + + if ( $chainref->{is_policy} ) { + print " This is a policy chain\n"; + my $val = $chainref->{is_optional} ? 'Yes' : 'No'; + print " Optional: $val\n"; + print " Log Level: $chainref->{loglevel}\n" if $chainref->{loglevel}; + print " Syn Parms: $chainref->{synparams}\n" if $chainref->{synparams}; + print " Default: $chainref->{default}\n" if $chainref->{default}; + } + + print " Policy chain: $chainref->{policychain}{name}\n" if $chainref->{policychain} ; + print " Policy: $chainref->{policy}\n" if $chainref->{policy}; + print " Referenced\n" if $chainref->{referenced}; + + if ( @{$chainref->{rules}} ) { + print " Rules:\n"; + for my $rule ( @{$chainref->{rules}} ) { + print " $rule\n"; + } + } + } + } +} + +# +# Add ESTABLISHED,RELATED rules and synparam jumps to the passed chain +# +sub finish_chain_section ($$) { + my ($chainref, $state ) = @_; + my $chain = $chainref->{name}; + + add_rule $chainref, "-m state --state $state -j ACCEPT" unless $config{FASTACCEPT}; + + if ($sections{RELATED} ) { + if ( $chainref->{is_policy} ) { + if ( $chainref->{synparams} ) { + my $synchainref = ensure_chain 'filter', "\@$chain"; + if ( $section eq 'DONE' ) { + if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE)$/ ) { + add_rule $chainref, "-p tcp --syn -j $synchainref->{name}"; + } + } else { + add_rule $chainref, "-p tcp --syn -j $synchainref->{name}"; + } + } + } else { + my $policychainref = $chainref->{policychain}; + if ( $policychainref->{synparams} ) { + my $synchainref = ensure_chain 'filter', "\@$policychainref->{name}"; + add_rule $synchainref, "-p tcp --syn -j $synchainref->{name}"; + } + } + } +} + +# +# Do section-end processing +# +sub finish_section ( $ ) { + my $sections = $_[0]; + + for my $zone ( @zones ) { + for my $zone1 ( @zones ) { + my $chainref = $chain_table{'filter'}{"${zone}2${zone1}"}; + if ( $chainref->{referenced} ) { + finish_chain_section $chainref, $sections; + } + } + } +} + 1; diff --git a/New/Shorewall/Common.pm b/New/Shorewall/Common.pm index 5bb7240fd..e48f4260d 100644 --- a/New/Shorewall/Common.pm +++ b/New/Shorewall/Common.pm @@ -1,9 +1,11 @@ package Shorewall::Common; require Exporter; +use File::Temp qw/ tempfile tempdir /; our @ISA = qw(Exporter); our @EXPORT = qw(warning_message fatal_error + create_temp_object emit emit_unindented save_progress_message @@ -15,9 +17,9 @@ our @EXPORT = qw(warning_message pop_indent copy copy1 - append_file - $line $object $lastlineblank); + $line + $lastlineblank); our @EXPORT_OK = (); our @VERSION = 1.00; @@ -45,6 +47,18 @@ sub fatal_error die; } +sub create_temp_object() { + my $tempfile; + + eval { + ( $object, $tempfile ) = tempfile ( 'tempfileXXXX' , DIR => $dir ); + }; + + fatal_error "$@" if $@; + + return $tempfile; +} + # # Write the argument to the object file (if any) with the current indentation. # @@ -127,49 +141,42 @@ sub save_progress_message_short( $ ) { # Functions for copying files into the object # sub copy( $ ) { - my $file = $_[0]; + if ( $object ) { + my $file = $_[0]; - open IF , $file or fatal_error "Unable to open $file: $!"; + open IF , $file or fatal_error "Unable to open $file: $!"; - while ( my $line = ) { - $line =~ s/^/$indent/ if $indent; - print $object $line; + while ( my $line = ) { + $line =~ s/^/$indent/ if $indent; + print $object $line; + } + + close IF; } - - close IF; } sub copy1( $ ) { - my $file = $_[0]; + if ( $object ) { + my $file = $_[0]; - open IF , $file or fatal_error "Unable to open $file: $!"; + open IF , $file or fatal_error "Unable to open $file: $!"; - my $do_indent = 1; + my $do_indent = 1; - while ( my $line = ) { - if ( $line =~ /^\s+$/ ) { - print $object "\n"; - $do_indent = 1; - next; + while ( my $line = ) { + if ( $line =~ /^\s+$/ ) { + print $object "\n"; + $do_indent = 1; + next; + } + + $line =~ s/^/$indent/ if $indent && $do_indent; + print $object $line; + $do_indent = ! ( $line =~ /\\$/ ); } - - $line =~ s/^/$indent/ if $indent && $do_indent; - print $object $line; - $do_indent = ! ( $line =~ /\\$/ ); + + close IF; } - - close IF; -} - -sub append_file( $ ) { - my $user_exit = find_file $_[0]; - - unless ( $user_exit =~ /$env{SHAREDIR}/ ) { - if ( -f $user_exit ) { - save_progress_message "Processing $user_exit ..."; - copy1 $user_exit; - } - } } 1; diff --git a/New/Shorewall/Config.pm b/New/Shorewall/Config.pm index 3768a6fec..b4af6be98 100644 --- a/New/Shorewall/Config.pm +++ b/New/Shorewall/Config.pm @@ -5,14 +5,14 @@ use warnings; use Shorewall::Common; our @ISA = qw(Exporter); -our @EXPORT = qw(find_file do_initialize report_capabilities propagateconfig %config %env %capabilities ); +our @EXPORT = qw(find_file do_initialize report_capabilities propagateconfig append_file %config %env %capabilities ); our @EXPORT_OK = (); our @VERSION = 1.00; # # From shorewall.conf file # -my %config = +our %config = ( STARTUP_ENABLED => undef, VERBOSITY => undef, # @@ -102,7 +102,7 @@ my @propagateenv = qw/ LOGLIMIT LOGTAGONLY LOGRULENUMBERS /; # Misc Globals # -my %env = ( SHAREDIR => '/usr/share/shorewall' , +our %env = ( SHAREDIR => '/usr/share/shorewall' , CONFDIR => '/etc/shorewall', LOGPARMS => '', VERSION => '3.9.0', @@ -111,7 +111,7 @@ my %env = ( SHAREDIR => '/usr/share/shorewall' , # # From parsing the capabilities file # -my %capabilities = +our %capabilities = ( NAT_ENABLED => undef, MANGLE_ENABLED => undef, MULTIPORT => undef, @@ -491,4 +491,15 @@ sub propagateconfig() { } } -1; +sub append_file( $ ) { + my $user_exit = find_file $_[0]; + + unless ( $user_exit =~ /$env{SHAREDIR}/ ) { + if ( -f $user_exit ) { + save_progress_message "Processing $user_exit ..."; + copy1 $user_exit; + } + } +} + +; diff --git a/New/compiler.pl b/New/compiler.pl index 9ed19db48..3dbca07b5 100755 --- a/New/compiler.pl +++ b/New/compiler.pl @@ -134,146 +134,6 @@ my %default_actions = ( DROP => 'none' , QUEUE => 'none' ); -# -# Create a new chain and return a reference to it. -# -sub new_chain($$) -{ - my ($table, $chain) = @_; - my %ch; - my @rules; - - $ch{name} = $chain; - $ch{log} = 1 if $env{LOGRULENUMBERS}; - $ch{rules} = \@rules; - $ch{table} = $table; - $chain_table{$table}{$chain} = \%ch; - \%ch; -} - -# -# Create a chain if it doesn't exist already -# -sub ensure_chain($$) -{ - my ($table, $chain) = @_; - - my $ref = $chain_table{$table}{$chain}; - - return $ref if $ref; - - new_chain $table, $chain; -} - -sub finish_chain_section( $$ ); - -# -# Create a filter chain if necessary. Optionally populate it with the appropriate ESTABLISHED,RELATED rule(s) and perform SYN rate limiting. -# -sub ensure_filter_chain( $$ ) -{ - my ($chain, $populate) = @_; - - my $chainref = $filter_table->{$chain}; - - $chainref = new_chain 'filter' , $chain unless $chainref; - - if ( $populate and ! $chainref->{referenced} ) { - if ( $section eq 'NEW' or $section eq 'DONE' ) { - finish_chain_section $chainref , 'ESTABLISHED,RELATED'; - } elsif ( $section eq 'ESTABLISHED' ) { - finish_chain_section $chainref , 'ESTABLISHED'; - } - } - - $chainref->{referenced} = 1; - - $chainref; -} - -# -# Add a builtin chain -# -sub new_builtin_chain($$$) -{ - my $chainref = new_chain $_[0],$_[1]; - $chainref->{referenced} = 1; - $chainref->{policy} = $_[2]; - $chainref->{builtin} = 1; -} - -sub new_standard_chain($) { - my $chainref = new_chain 'filter' ,$_[0]; - $chainref->{referenced} = 1; - $chainref; -} - -# -# Add all builtin chains to the chain table -# -# -sub initialize_chain_table() -{ - for my $chain qw/OUTPUT PREROUTING/ { - new_builtin_chain 'raw', $chain, 'ACCEPT'; - } - - for my $chain qw/INPUT OUTPUT FORWARD/ { - new_builtin_chain 'filter', $chain, 'DROP'; - } - - for my $chain qw/PREROUTING POSTROUTING OUTPUT/ { - new_builtin_chain 'nat', $chain, 'ACCEPT'; - } - - for my $chain qw/PREROUTING INPUT FORWARD OUTPUT POSTROUTING/ { - new_builtin_chain 'mangle', $chain, 'ACCEPT'; - } - - if ( $capabilities{MANGLE_FORWARD} ) { - for my $chain qw/ FORWARD POSTROUTING / { - new_builtin_chain 'mangle', $chain, 'ACCEPT'; - } - } -} - -# -# Dump the contents of the Chain Table -# -sub dump_chain_table() -{ - print "\n"; - - for my $table qw/filter nat mangle/ { - print "Table: $table\n"; - - for my $chain ( sort keys %{$chain_table{$table}} ) { - my $chainref = $chain_table{$table}{$chain}; - print " Chain $chain:\n"; - - if ( $chainref->{is_policy} ) { - print " This is a policy chain\n"; - my $val = $chainref->{is_optional} ? 'Yes' : 'No'; - print " Optional: $val\n"; - print " Log Level: $chainref->{loglevel}\n" if $chainref->{loglevel}; - print " Syn Parms: $chainref->{synparams}\n" if $chainref->{synparams}; - print " Default: $chainref->{default}\n" if $chainref->{default}; - } - - print " Policy chain: $chainref->{policychain}{name}\n" if $chainref->{policychain} ; - print " Policy: $chainref->{policy}\n" if $chainref->{policy}; - print " Referenced\n" if $chainref->{referenced}; - - if ( @{$chainref->{rules}} ) { - print " Rules:\n"; - for my $rule ( @{$chainref->{rules}} ) { - print " $rule\n"; - } - } - } - } -} - # # This function determines the logging for a subordinate action or a rule within a subordinate action # @@ -2378,52 +2238,6 @@ sub setup_mac_lists( $ ) { } } -# -# Add ESTABLISHED,RELATED rules and synparam jumps to the passed chain -# -sub finish_chain_section ($$) { - my ($chainref, $state ) = @_; - my $chain = $chainref->{name}; - - add_rule $chainref, "-m state --state $state -j ACCEPT" unless $config{FASTACCEPT}; - - if ($sections{RELATED} ) { - if ( $chainref->{is_policy} ) { - if ( $chainref->{synparams} ) { - my $synchainref = ensure_chain 'filter', "\@$chain"; - if ( $section eq 'DONE' ) { - if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE)$/ ) { - add_rule $chainref, "-p tcp --syn -j $synchainref->{name}"; - } - } else { - add_rule $chainref, "-p tcp --syn -j $synchainref->{name}"; - } - } - } else { - my $policychainref = $chainref->{policychain}; - if ( $policychainref->{synparams} ) { - my $synchainref = ensure_chain 'filter', "\@$policychainref->{name}"; - add_rule $synchainref, "-p tcp --syn -j $synchainref->{name}"; - } - } - } -} - -# -# Do section-end processing -# -sub finish_section ( $ ) { - my $sections = $_[0]; - - for my $zone ( @zones ) { - for my $zone1 ( @zones ) { - my $chainref = $chain_table{'filter'}{"${zone}2${zone1}"}; - if ( $chainref->{referenced} ) { - finish_chain_section $chainref, $sections; - } - } - } -} # # Macro and action files can have shell variables embedded. This function expands them from %ENV. @@ -4600,7 +4414,7 @@ sub generate_script_2 () { open MF, $mf or fatal_error "Unable to open $mf: $!"; - while ( $line = ) { print $object $line if $line =~ /^\s*loadmodule\b/; } + while ( $line = ) { emit_unindented $line if $line =~ /^\s*loadmodule\b/; } close MF; @@ -4677,13 +4491,9 @@ sub compile_firewall( $ ) { }; fatal_error "$@" if $@; + + $tempfile = create_temp_object; - eval { - ( $object, $tempfile ) = tempfile ( 'tempfileXXXX' , DIR => $dir ); - }; - - fatal_error "$@" if $@; - generate_script_1; }