From af2b7910bd7b53e097d2f2227b12bdaf54f69c0c Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 12 Aug 2015 12:33:09 -0700 Subject: [PATCH] Port update changes from 5.0.0 Signed-off-by: Tom Eastep --- Shorewall-core/lib.cli | 4 +- Shorewall/Perl/Shorewall/Compiler.pm | 21 +-- Shorewall/Perl/Shorewall/Config.pm | 9 +- Shorewall/Perl/Shorewall/Misc.pm | 189 +++++++++++++++++++++++++-- Shorewall/Perl/Shorewall/Raw.pm | 69 +++++++++- Shorewall/Perl/Shorewall/Tc.pm | 21 ++- Shorewall/Perl/compiler.pl | 8 ++ Shorewall/lib.cli-std | 12 ++ 8 files changed, 300 insertions(+), 33 deletions(-) diff --git a/Shorewall-core/lib.cli b/Shorewall-core/lib.cli index 28b36b2b3..5588b419b 100644 --- a/Shorewall-core/lib.cli +++ b/Shorewall-core/lib.cli @@ -3974,7 +3974,7 @@ usage() # $1 = exit status echo " status [ -i ]" echo " stop" ecko " try [ ]" - ecko " update [ -a ] [ -b ] [ -r ] [ -T ] [ -D ] [ -i ] [-t] [-A] [ ]" + ecko " update [ -a ] [ -b ] [ -r ] [ -T ] [ -D ] [ -i ] [-t] [-s] [-n] [-A] [ ]" echo " version [ -a ]" echo exit $1 @@ -4027,6 +4027,8 @@ shorewall_cli() { g_counters= g_loopback= g_compiled= + g_routestopped= + g_notrack= VERBOSE= VERBOSITY=1 diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 301d49ae0..0a8cf7edd 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -592,8 +592,8 @@ EOF # sub compiler { - my ( $scriptfilename, $directory, $verbosity, $timestamp , $debug, $chains , $log , $log_verbosity, $preview, $confess , $update , $annotate , $convert, $config_path, $shorewallrc , $shorewallrc1 , $directives, $inline, $tcrules ) = - ( '', '', -1, '', 0, '', '', -1, 0, 0, 0, 0, , 0 , '' , '/usr/share/shorewall/shorewallrc', '' , 0 , 0 , 0 ); + my ( $scriptfilename, $directory, $verbosity, $timestamp , $debug, $chains , $log , $log_verbosity, $preview, $confess , $update , $annotate , $convert, $config_path, $shorewallrc , $shorewallrc1 , $directives, $inline, $tcrules, $routestopped , $notrack ) = + ( '', '', -1, '', 0, '', '', -1, 0, 0, 0, 0, , 0 , '' , '/usr/share/shorewall/shorewallrc', '' , 0 , 0 , 0 , 0 , 0 ); $export = 0; $test = 0; @@ -634,6 +634,8 @@ sub compiler { inline => { store => \$inline, validate=> \&validate_boolean } , directives => { store => \$directives, validate=> \&validate_boolean } , tcrules => { store => \$tcrules, validate=> \&validate_boolean } , + routestopped => { store => \$routestopped, validate=> \&validate_boolean } , + notrack => { store => \$notrack, validate=> \&validate_boolean } , config_path => { store => \$config_path } , shorewallrc => { store => \$shorewallrc } , shorewallrc1 => { store => \$shorewallrc1 } , @@ -737,7 +739,7 @@ sub compiler { # # Do all of the zone-independent stuff (mostly /proc) # - add_common_rules( $convert, $tcrules ); + add_common_rules( $convert, $tcrules , $routestopped ); # # More /proc # @@ -844,7 +846,7 @@ sub compiler { # # Process the conntrack file # - setup_conntrack; + setup_conntrack( $notrack ); # # Add Tunnel rules. # @@ -911,7 +913,7 @@ sub compiler { # S T O P _ F I R E W A L L # (Writes the stop_firewall() function to the compiled script) # - compile_stop_firewall( $test, $export , $have_arptables ); + compile_stop_firewall( $test, $export , $have_arptables, $routestopped ); # # U P D O W N # (Writes the updown() function to the compiled script) @@ -976,14 +978,15 @@ sub compiler { initialize_chain_table(0); if ( $debug ) { - compile_stop_firewall( $test, $export, $have_arptables ); + compile_stop_firewall( $test, $export, $have_arptables, $routestopped ); disable_script; } else { # - # compile_stop_firewall() also validates the routestopped file. Since we don't - # call that function during normal 'check', we must validate routestopped here. + # compile_stop_firewall() also validates the stoppedrules file. Since we don't + # call that function during normal 'check', we must validate stoppedrules here. # - process_routestopped unless process_stoppedrules; + convert_routestopped if $routestopped; + process_stoppedrules; } # # Report used/required capabilities diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 276b60613..cd5b38f06 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -4837,7 +4837,8 @@ sub update_config_file( $$ ) { # $fn = $annotate ? "$globals{SHAREDIR}/configfiles/${product}.conf.annotated" : "$globals{SHAREDIR}/configfiles/${product}.conf"; } - if ( -f $fn ) { + + if ( -f $fn ) { my ( $template, $output ); open $template, '<' , $fn or fatal_error "Unable to open $fn: $!"; @@ -4925,8 +4926,10 @@ EOF } exit 0 unless ( $directives || - -f find_file 'blacklist' || - -f find_file 'tcrules' ); + -f find_file 'blacklist' || + -f find_file 'tcrules' || + -f find_file 'routestopped' + ); } } else { fatal_error "$fn does not exist"; diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 1e18f38b7..d194869e9 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -44,6 +44,7 @@ our @EXPORT = qw( process_tos setup_mac_lists process_routestopped process_stoppedrules + convert_routestopped compile_stop_firewall generate_matrix ); @@ -360,14 +361,16 @@ sub remove_blacklist( $ ) { while ( read_a_line( EMBEDDED_ENABLED | EXPAND_VARIABLES ) ) { my ( $rule, $comment ) = split '#', $currentline, 2; - if ( $rule =~ /blacklist/ ) { + if ( $rule && $rule =~ /blacklist/ ) { $changed = 1; if ( $comment ) { - $comment =~ s/^/ / while $rule =~ s/blacklist,//; + $comment =~ s/^/ / while $rule =~ s/blacklist,// || $rule =~ s/,blacklist//; $rule =~ s/blacklist/ /g; $currentline = join( '#', $rule, $comment ); } else { + $currentline =~ s/blacklist,//g; + $currentline =~ s/,blacklist//g; $currentline =~ s/blacklist/ /g; } } @@ -385,7 +388,7 @@ sub remove_blacklist( $ ) { } # -# Convert a pre-4.4.25 blacklist to a 4.4.25 blacklist +# Convert a pre-4.4.25 blacklist to a 4.4.25 blrules file # sub convert_blacklist() { my $zones = find_zones_by_option 'blacklist', 'in'; @@ -403,7 +406,19 @@ sub convert_blacklist() { $target = verify_audit( $disposition ); } - my $fn = open_file 'blacklist'; + my $fn = open_file( 'blacklist' ); + + unless ( $fn ) { + if ( -f ( $fn = find_file( 'blacklist' ) ) ) { + if ( unlink( $fn ) ) { + warning_message "Empty blacklist file ($fn) removed"; + } else { + warning_message "Unable to remove empty blacklist file $fn: $!"; + } + } + + return 0; + } first_entry "Converting $fn..."; @@ -682,6 +697,153 @@ sub process_routestopped() { } } +sub convert_routestopped() { + + if ( my $fn = open_file 'routestopped' ) { + my ( @allhosts, %source, %dest , %notrack, @rule ); + + my $seq = 0; + + my ( $stoppedrules, $fn1 ); + + if ( -f ( $fn1 = find_file( 'stoppedrules' ) ) ) { + open $stoppedrules, '>>', $fn1 or fatal_error "Unable to open $fn1: $!"; + } else { + open $stoppedrules, '>', $fn1 or fatal_error "Unable to open $fn1: $!"; + print $stoppedrules <<'EOF'; +# +# Shorewall version 4 - Stopped Rules File +# +# For information about entries in this file, type "man shorewall-stoppedrules" +# +# The manpage is also online at +# http://www.shorewall.net/manpages/shorewall-stoppedrules.html +# +# See http://shorewall.net/starting_and_stopping_shorewall.htm for additional +# information. +# +############################################################################### +#ACTION SOURCE DEST PROTO DEST SOURCE +# PORT(S) PORT(S) +EOF + } + + first_entry "$doing $fn..."; + + while ( read_a_line ( NORMAL_READ ) ) { + + my ($interface, $hosts, $options , $proto, $ports, $sports ) = + split_line( 'routestopped file', + { interface => 0, hosts => 1, options => 2, proto => 3, dport => 4, sport => 5 } ); + + my $interfaceref; + + fatal_error 'INTERFACE must be specified' if $interface eq '-'; + fatal_error "Unknown interface ($interface)" unless $interfaceref = known_interface $interface; + $hosts = ALLIP unless $hosts && $hosts ne '-'; + + my $routeback = 0; + + my @hosts; + + $seq++; + + my $rule = "$proto\t$ports\t$sports"; + + $hosts = ALLIP if $hosts eq '-'; + + for my $host ( split /,/, $hosts ) { + fatal_error "Ipsets not allowed with SAVE_IPSETS=Yes" if $host =~ /^!?\+/ && $config{SAVE_IPSETS}; + validate_host $host, 1; + push @hosts, "$interface|$host|$seq"; + push @rule, $rule; + } + + + unless ( $options eq '-' ) { + for my $option (split /,/, $options ) { + if ( $option eq 'routeback' ) { + if ( $routeback ) { + warning_message "Duplicate 'routeback' option ignored"; + } else { + $routeback = 1; + } + } elsif ( $option eq 'source' ) { + for my $host ( split /,/, $hosts ) { + $source{"$interface|$host|$seq"} = 1; + } + } elsif ( $option eq 'dest' ) { + for my $host ( split /,/, $hosts ) { + $dest{"$interface|$host|$seq"} = 1; + } + } elsif ( $option eq 'notrack' ) { + for my $host ( split /,/, $hosts ) { + $notrack{"$interface|$host|$seq"} = 1; + } + } else { + warning_message "Unknown routestopped option ( $option ) ignored" unless $option eq 'critical'; + warning_message "The 'critical' option is no longer supported (or needed)"; + } + } + } + + if ( $routeback || $interfaceref->{options}{routeback} ) { + my $chainref = $filter_table->{FORWARD}; + + for my $host ( split /,/, $hosts ) { + print $stoppedrules "ACCEPT\t$interface:$host\t$interface:$host\n"; + } + } + + push @allhosts, @hosts; + } + + for my $host ( @allhosts ) { + my ( $interface, $h, $seq ) = split /\|/, $host; + my $rule = shift @rule; + + print $stoppedrules "ACCEPT\t$interface:$h\t\$FW\t$rule\n"; + print $stoppedrules "ACCEPT\t\$FW\t$interface:$h\t$rule\n" unless $config{ADMINISABSENTMINDED}; + + my $matched = 0; + + if ( $source{$host} ) { + print $stoppedrules "ACCEPT\t$interface:$h\t-\t$rule\n"; + $matched = 1; + } + + if ( $dest{$host} ) { + print $stoppedrules "ACCEPT\t-\t$interface:$h\t$rule\n"; + $matched = 1; + } + + if ( $notrack{$host} ) { + print $stoppedrules "NOTRACK\t$interface:$h\t-\t$rule\n"; + print $stoppedrules "NOTRACK\t\$FW\t$interface:$h\t$rule\n"; + } + + unless ( $matched ) { + for my $host1 ( @allhosts ) { + unless ( $host eq $host1 ) { + my ( $interface1, $h1 , $seq1 ) = split /\|/, $host1; + print $stoppedrules "ACCEPT\t$interface:$h\t$interface1:$h1\t$rule\n"; + } + } + } + } + + rename $fn, "$fn.bak"; + progress_message2 "Routestopped file $fn saved in $fn.bak"; + close $stoppedrules; + } elsif ( -f ( my $fn1 = find_file( 'routestopped' ) ) ) { + if ( unlink( $fn1 ) ) { + warning_message "Empty routestopped file ($fn1) removed"; + } else { + warning_message "Unable to remove empty routestopped file $fn1: $!"; + } + } +} + # # Process the stoppedrules file. Returns true if the file was non-empty. # @@ -774,8 +936,8 @@ sub process_stoppedrules() { sub setup_mss(); -sub add_common_rules ( $$ ) { - my ( $upgrade_blacklist, $upgrade_tcrules ) = @_; +sub add_common_rules ( $$$ ) { + my ( $upgrade_blacklist, $upgrade_tcrules , $upgrade_routestopped ) = @_; my $interface; my $chainref; my $target; @@ -946,7 +1108,7 @@ sub add_common_rules ( $$ ) { run_user_exit1 'initdone'; if ( $upgrade_blacklist ) { - exit 0 unless convert_blacklist || $upgrade_tcrules; + exit 0 unless convert_blacklist || $upgrade_tcrules || $upgrade_routestopped; } else { setup_blacklist; } @@ -1826,7 +1988,7 @@ sub add_output_jumps( $$$$$$$ ) { our @vservers; our %output_jump_added; - my $chain1 = rules_target firewall_zone , $zone; + my $chain1 = rules_target( firewall_zone , $zone ); my $chain1ref = $filter_table->{$chain1}; my $nextchain = dest_exclusion( $exclusions, $chain1 ); my $outputref; @@ -2408,8 +2570,8 @@ sub setup_mss( ) { # # Compile the stop_firewall() function # -sub compile_stop_firewall( $$$ ) { - my ( $test, $export, $have_arptables ) = @_; +sub compile_stop_firewall( $$$$ ) { + my ( $test, $export, $have_arptables, $routestopped ) = @_; my $input = $filter_table->{INPUT}; my $output = $filter_table->{OUTPUT}; @@ -2598,7 +2760,12 @@ EOF } } - process_routestopped unless process_stoppedrules; + if ( $routestopped ) { + convert_routestopped; + process_stoppedrules; + } else { + process_routestopped unless process_stoppedrules; + } if ( have_capability 'IFACE_MATCH' ) { add_ijump $input, j => 'ACCEPT', iface => '--dev-in --loopback'; diff --git a/Shorewall/Perl/Shorewall/Raw.pm b/Shorewall/Perl/Shorewall/Raw.pm index 87b867856..d99e37a5d 100644 --- a/Shorewall/Perl/Shorewall/Raw.pm +++ b/Shorewall/Perl/Shorewall/Raw.pm @@ -275,11 +275,14 @@ sub process_format( $ ) { $file_format = $format; } -sub setup_conntrack() { +sub setup_conntrack($) { + my $convert = shift; + my $fn; + my @files = $convert ? ( qw/notrack conntrack/ ) : ( 'conntrack' ); - for my $name ( qw/notrack conntrack/ ) { + for my $name ( @files ) { - my $fn = open_file( $name, 3 , 1 ); + $fn = open_file( $name, 3 , 1 ); if ( $fn ) { @@ -341,12 +344,70 @@ sub setup_conntrack() { } else { warning_message "Unable to remove empty notrack file ($fn): $!"; } + $convert = undef; + } + } + } elsif ( $name eq 'notrack' ) { + $convert = undef; + + if ( -f ( my $fn1 = find_file( $name ) ) ) { + if ( unlink( $fn1 ) ) { + warning_message "Empty notrack file ($fn1) removed"; } else { - warning_message "Non-empty notrack file ($fn); please move its contents to the conntrack file"; + warning_message "Unable to remove empty notrack file ($fn1): $!"; } } } } + + if ( $convert ) { + my $conntrack; + my $empty = 1; + + if ( $fn ) { + open $conntrack, '>>', $fn or fatal_error "Unable to open $fn for notrack conversion: $!"; + } else { + open $conntrack, '>', $fn = find_file 'conntrack' or fatal_error "Unable to open $fn for notrack conversion: $!"; + + print $conntrack <<'EOF'; +# +# Shorewall version 5 - conntrack File +# +# For information about entries in this file, type "man shorewall-conntrack" +# +############################################################################################################## +EOF + print $conntrack '?' . "FORMAT 3\n"; + + print $conntrack <<'EOF'; +#ACTION SOURCE DESTINATION PROTO DEST SOURCE USER/ SWITCH +# PORT(S) PORT(S) GROUP +EOF + } + + $fn = open_file( 'notrack' , 3, 1 ) || fatal_error "Unable to open the notrack file for conversion: $!"; + + while ( read_a_line( PLAIN_READ ) ) { + # + # Don't copy the header comments from the old notrack file + # + next if $empty && ( $currentline =~ /^\s*#/ || $currentline =~ /^\s*$/ ); + + if ( $empty ) { + # + # First non-commentary line + # + $empty = undef; + + print $conntrack '?' . "FORMAT 1\n" unless $currentline =~ /^\s*\??FORMAT/i; + } + + print $conntrack "$currentline\n"; + } + + rename $fn, "$fn.bak" or fatal_error "Unable to rename $fn to $fn.bak: $!"; + progress_message2 "notrack file $fn saved in $fn.bak" + } } 1; diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm index f16ff6935..eab2a021b 100644 --- a/Shorewall/Perl/Shorewall/Tc.pm +++ b/Shorewall/Perl/Shorewall/Tc.pm @@ -27,7 +27,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see . # -# This module deals with Traffic Shaping and the tcrules file. +# This module deals with Traffic Shaping and the mangle file. # package Shorewall::Tc; require Exporter; @@ -3162,7 +3162,7 @@ sub process_secmark_rule() { } # -# Process the tcrules file and setup traffic shaping +# Process the mangle file and setup traffic shaping # sub setup_tc( $ ) { $tcrules = $_[0]; @@ -3243,11 +3243,22 @@ sub setup_tc( $ ) { fatal_error "Cannot Rename $fn to $fn.bak: $!"; } } else { - warning_message "Non-empty tcrules file ($fn); consider running '$product update -t'"; + if ( unlink $fn ) { + warning_message "Empty tcrules file ($fn) removed"; + } else { + warning_message "Unable to remove empty tcrules file $fn: $!"; + } + } + + close $mangle, directive_callback( 0 ) if $tcrules; + + } elsif ( $tcrules && -f ( my $fn = find_file( 'tcrules' ) ) ) { + if ( unlink $fn ) { + warning_message "Empty tcrules file ($fn) removed"; + } else { + warning_message "Unable to remove empty tcrules file $fn: $!"; } } - - close $mangle, directive_callback( 0 ) if $tcrules; } if ( my $fn = open_file( 'mangle', 1, 1 ) ) { diff --git a/Shorewall/Perl/compiler.pl b/Shorewall/Perl/compiler.pl index 94dd2b8d5..a2a71a220 100755 --- a/Shorewall/Perl/compiler.pl +++ b/Shorewall/Perl/compiler.pl @@ -42,6 +42,8 @@ # --config_path= # Search path for config files # --inline # Update alternative column specifications # --tcrules # Create mangle from tcrules +# --routestopped # Create stoppedrules from routestopped +# --notrack # Create conntrack from notrack # use strict; use FindBin; @@ -77,6 +79,8 @@ usage: compiler.pl [