From be4cb9d26a305afe8e3b929d98b5c38b4aa90496 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Fri, 23 Dec 2011 17:55:13 -0800 Subject: [PATCH] Validate helper<->protocol Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Chains.pm | 77 +++++++++++++++++++++-------- Shorewall/Perl/Shorewall/IPAddrs.pm | 2 + Shorewall/Perl/Shorewall/Raw.pm | 5 +- Shorewall/Perl/Shorewall/Tc.pm | 12 ++++- 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 0e8b582bb..7f17bb9b4 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -173,6 +173,7 @@ our %EXPORT_TAGS = ( do_tos do_connbytes do_helper + validate_helper do_headers do_condition have_ipset_rules @@ -558,19 +559,19 @@ sub initialize( $$$ ) { %ipset_exists = (); - %helpers = ( amanda => 1, - ftp => 1, - h323 => 1, - irc => 1, - netbios_ns => 1, - netlink => 1, - proto_gre => 1, - proto_sctp => 1, - pptp => 1, - proto_udplite => 1, - sane => 1, - sip => 1, - tftp => 1 ); + %helpers = ( amanda => TCP, + ftp => TCP, + h323 => [UDP,TCP], + irc => TCP, + netbios_ns => [UDP,TCP], + netlink => -1, + proto_gre => GRE, + proto_sctp => SCTP, + pptp => TCP, + proto_udplite => UDPLITE, + sane => TCP, + sip => UDP, + tftp => UDP); # # The chain table is initialized via a call to initialize_chain_table() after the configuration and capabilities have been determined. # @@ -4004,22 +4005,56 @@ sub do_connbytes( $ ) { } # -# Create a soft "-m helper" match for the passed argument +# Validate a helper/protocol pair # -sub do_helper( $ ) { - my $helper = shift; +sub validate_helper( $$ ) { + my ( $helper, $proto ) = @_; + my $helper_base = $helper; + $helper_base =~ s/-\d+$//; + my $protos = $helpers{$helper_base}; + + if ( $protos) { + # + # Recognized helper + # + my $protonum = resolve_proto( $proto ); + # + # Caller should have called do_proto() before this function + # + assert( defined $protonum ); + + my $found; + + if ( reftype $protos ) { + for ( @$protos ) { + $found |= ($_ == $protonum); + } + } elsif ( $protos == -1 ) { + $found = 1; + } else { + $found = ( $protos == $protonum ); + } + + fatal_error "Protocol $proto is not appropriate for helper $helper_base" unless $found; + } else { + warning_message "Unrecognized helper ($helper_base)"; + } +} + +# +# Create an "-m helper" match for the passed argument +# +sub do_helper( $$ ) { + my ( $helper, $proto ) = shift; return '' if $helper eq '-'; - my $helper_base = $helper; - - $helper_base =~ s/-\d+$//; - - warning_message "Unrecognized helper ($helper)" unless $helpers{$helper_base}; + validate_helper( $helper, $proto ); qq(-m helper --helper "$helper" ) if defined wantarray; } + # # Create a "-m length" match for the passed LENGTH # diff --git a/Shorewall/Perl/Shorewall/IPAddrs.pm b/Shorewall/Perl/Shorewall/IPAddrs.pm index ea5617bd9..7132d9141 100644 --- a/Shorewall/Perl/Shorewall/IPAddrs.pm +++ b/Shorewall/Perl/Shorewall/IPAddrs.pm @@ -55,6 +55,7 @@ our @EXPORT = qw( ALLIPv4 DCCP IPv6_ICMP SCTP + GRE validate_address validate_net @@ -117,6 +118,7 @@ use constant { ALLIPv4 => '0.0.0.0/0' , TCP => 6, UDP => 17, DCCP => 33, + GRE => 47, IPv6_ICMP => 58, SCTP => 132, UDPLITE => 136 }; diff --git a/Shorewall/Perl/Shorewall/Raw.pm b/Shorewall/Perl/Shorewall/Raw.pm index cebf8a147..af70825f1 100644 --- a/Shorewall/Perl/Shorewall/Raw.pm +++ b/Shorewall/Perl/Shorewall/Raw.pm @@ -59,6 +59,7 @@ sub process_notrack_rule( $$$$$$$ ) { my $target = $action; my $exception_rule = ''; + my $rule = do_proto( $proto, $ports, $sports ) . do_user ( $user ); unless ( $action eq 'NOTRACK' ) { ( $target, my ( $option, $args, $junk ) ) = split ':', $action, 4; @@ -76,7 +77,7 @@ sub process_notrack_rule( $$$$$$$ ) { if ( $option eq 'helper' ) { fatal_error "Invalid helper' ($args)" if $args =~ /,/; fatal_error "A protocol protocol is required in CT:helper rules" if $proto eq '-'; - do_helper( $args ); + validate_helper( $args, $proto ); $action = "CT --helper $args"; $exception_rule = do_proto( $proto, '-', '-' ); } elsif ( $option eq 'ctevents' ) { @@ -97,7 +98,7 @@ sub process_notrack_rule( $$$$$$$ ) { expand_rule( $chainref , $restriction , - do_proto( $proto, $ports, $sports ) . do_user ( $user ) , + $rule, $source , $dest , '' , diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm index f36e703eb..49ecd7e48 100644 --- a/Shorewall/Perl/Shorewall/Tc.pm +++ b/Shorewall/Perl/Shorewall/Tc.pm @@ -488,7 +488,7 @@ sub process_tc_rule( ) { do_length( $length ) . do_tos( $tos ) . do_connbytes( $connbytes ) . - do_helper( $helper ) . + do_helper( $helper, $proto ) . do_headers( $headers ) , $source , $dest , @@ -1451,7 +1451,15 @@ sub process_tc_priority() { fatal_error "Invalid PRIORITY ($band)" unless $val && $val <= 3; - my $rule = do_helper( $helper ) . "-j MARK --set-mark $band"; + my $rule; + + unless ( $helper eq '-' ) { + fatal_error( "A PROTO is required when a HELPER is specified" ) if $proto eq '-'; + fatal_error( "Unknown protocol" ) unless defined resolve_protocol( $proto ); + $rule = do_helper( $helper, $proto ) . "-j MARK --set-mark $band"; + } else { + $rule = ''; + } $rule .= join('', '/', in_hex( $globals{TC_MASK} ) ) if have_capability( 'EXMARK' );