allow pf firewall type to not require 'Chain' output in reports
authorMichael Rash <mbr@cipherdyne.org>
Sun, 8 Apr 2012 01:18:02 +0000 (21:18 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Sun, 8 Apr 2012 01:18:02 +0000 (21:18 -0400)
psad

diff --git a/psad b/psad
index 00770fe..95f7c10 100755 (executable)
--- a/psad
+++ b/psad
@@ -555,7 +555,8 @@ my %pkt_fw_init = (
     'udp_len'  => -1,
 
     ### extra fields for psad internals (DShield reporting, fwsnort
-    ### sid matching, iptables logging prefixes and chains, etc.)
+    ### sid matching, iptables logging prefixes and chains, pf rule
+    ### numbers, etc.)
     'fwsnort_sid'   => 0,
     'fwsnort_rnum'  => 0,
     'fwsnort_estab' => 0,
@@ -1320,6 +1321,7 @@ sub check_scan() {
         $scan{$pkt{'src'}}{$pkt{'dst'}}{'absnum'}++;
         $scan{$pkt{'src'}}{$pkt{'dst'}}{'chain'}
             {$pkt{'chain'}}{$pkt{'intf'}}{$pkt{'proto'}}++;
+
         $curr_scan{$pkt{'src'}}{$pkt{'dst'}}{$pkt{'proto'}}{'pkts'}++;
         $curr_scan{$pkt{'src'}}{$pkt{'dst'}}
             {$pkt{'proto'}}{'flags'}{$pkt{'flags'}}++ if $pkt{'flags'};
@@ -1332,28 +1334,26 @@ sub check_scan() {
         $curr_scan{$pkt{'src'}}{$pkt{'dst'}}{'syslog_host'}
             {$pkt{'syslog_host'}} = '' if $pkt{'syslog_host'};
 
-        if ($fw_type eq 'iptables') {
-            if ($pkt{'log_prefix'}) {
-                ### see if the logging prefix matches the blocking
-                ### regex, and if not the IP will not be blocked
-                if ($config{'ENABLE_AUTO_IDS'} eq 'Y'
-                        and $config{'ENABLE_AUTO_IDS_REGEX'} eq 'Y'
-                        and $config{'AUTO_BLOCK_REGEX'} ne 'NONE') {
-                    ### we require a match
-                    if (not defined $auto_block_regex_match{$pkt{'src'}}
+        if ($pkt{'log_prefix'}) {
+            ### see if the logging prefix matches the blocking
+            ### regex, and if not the IP will not be blocked
+            if ($config{'ENABLE_AUTO_IDS'} eq 'Y'
+                    and $config{'ENABLE_AUTO_IDS_REGEX'} eq 'Y'
+                    and $config{'AUTO_BLOCK_REGEX'} ne 'NONE') {
+                ### we require a match
+                if (not defined $auto_block_regex_match{$pkt{'src'}}
                         and $pkt{'log_prefix'} =~ /$config{'AUTO_BLOCK_REGEX'}/) {
-                        $auto_block_regex_match{$pkt{'src'}} = '';
-                    }
+                    $auto_block_regex_match{$pkt{'src'}} = '';
                 }
-            } else {
-                $pkt{'log_prefix'} = '*noprfx*';
             }
-
-            ### keep track of iptables chain and logging prefix
-            $curr_scan{$pkt{'src'}}{$pkt{'dst'}}{$pkt{'proto'}}{'chain'}
-                    {$pkt{'chain'}}{$pkt{'log_prefix'}}++;
+        } else {
+            $pkt{'log_prefix'} = '*noprfx*';
         }
 
+        ### keep track of iptables chain and logging prefix
+        $curr_scan{$pkt{'src'}}{$pkt{'dst'}}{$pkt{'proto'}}{'chain'}
+                {$pkt{'chain'}}{$pkt{'log_prefix'}}++;
+
         if ($pkt{'proto'} eq 'tcp' or $pkt{'proto'} eq 'udp'
                 or $pkt{'proto'} eq 'udplite') {
             ### initialize the start and end port for the scanned port range
@@ -1559,7 +1559,7 @@ sub parse_iptables_pkt_str() {
         $pkt_hr->{'syslog_host'} = $2;
     } else {
         $pkt_hr->{'timestamp'}   = localtime();
-        $pkt_hr->{'syslog_host'} = 'unknown';
+        $pkt_hr->{'syslog_host'} = '';
     }
 
     ### try to extract a snort sid (generated by fwsnort) from
@@ -1958,7 +1958,7 @@ sub parse_iptables_pkt_str() {
     return $PKT_SUCCESS;
 }
 
-sub parse_pf_pkt_str() {
+sub parse_tcpdump_pkt_str() {
     my ($pkt_hr, $pkt_str) = @_;
 
     my $is_ipv6    = 0;
@@ -1977,15 +1977,15 @@ sub parse_pf_pkt_str() {
     ### 0,nop,wscale 7> (DF) [tos 0x10] (ttl 64, id 13264, len 60)
 
     ### timestamp
-    if ($pkt_str =~ /^\s*(\w{3}\s\d{1,2}\s(?:\d{2}\:){2}\d{2}\.\d+)\s/) {
-        $pkt_hr->{'timestamp'} = $1;
-    }
-    $pkt_hr->{'syslog_host'} = 'unknown';
+    $pkt_hr->{'timestamp'} = $1
+        if $pkt_str =~ /^\s*(\w{3}\s\d{1,2}\s(?:\d{2}\:){2}\d{2}\.\d+)\s/;
+
+    $pkt_hr->{'syslog_host'} = '';
+    $pkt_hr->{'chain'}       = 'pf';  ### this is a hack to preserve hash structure
+    $pkt_hr->{'log_prefix'}  = 'pf';
 
     ### handle the interface
-    if ($pkt_str =~ /\son\s(\S+)\:/) {
-        $pkt_hr->{'intf'} = $1;
-    }
+    $pkt_hr->{'intf'} = $1 if $pkt_str =~ /\son\s(\S+)\:/;
     if (%ignore_interfaces) {
         for my $ignore_intf (keys %ignore_interfaces) {
             return $PKT_IGNORE if $pkt_hr->{'intf'} eq $ignore_intf;
@@ -2076,8 +2076,8 @@ sub set_fw_type() {
     if ($fw_type eq 'iptables') {
         $fw_parse_func = \&parse_iptables_pkt_str,
         $parse_tcp_options_func = \&parse_tcp_options_iptables;
-    } elsif ($fw_type eq 'pf') {
-        $fw_parse_func = \&parse_pf_pkt_str,
+    } elsif ($fw_type eq 'pf' or $fw_type eq 'tcpdump') {
+        $fw_parse_func = \&parse_tcpdump_pkt_str,
         $parse_tcp_options_func = \&parse_tcp_options_pf;
     } elsif ($fw_type eq 'ipfw') {
         $fw_parse_func = \&parse_ipfw_pkt_str,
@@ -5086,6 +5086,7 @@ sub write_global_packet_counters() {
 }
 
 sub write_prefix_counters() {
+    return unless $fw_type eq 'iptables';
     open P, "> $config{'IPT_PREFIX_COUNTER_FILE'}" or
         die "[*] Could not open $config{'IPT_PREFIX_COUNTER_FILE'}: $!";
     for my $prefix (keys %ipt_prefixes) {
@@ -5565,11 +5566,11 @@ sub scan_logr() {
                         $nmap_opts = '-sT or -sS';
                     } elsif ($flags eq 'FIN') {
                         $nmap_opts = '-sF';
-                    } elsif ($flags eq 'URG PSH FIN') {
+                    } elsif ($flags eq &std_tcp_flags_representation('URG PSH FIN')) {
                         $nmap_opts = '-sX';
                     } elsif ($flags eq 'NULL') {
                         $nmap_opts = '-sN';
-                    } elsif ($flags eq 'URG PSH SYN FIN') {
+                    } elsif ($flags eq &std_tcp_flags_representation('URG PSH SYN FIN')) {
                         $nmap_opts = '-O';
                     }
                     if ($nmap_opts) {
@@ -5673,7 +5674,8 @@ sub scan_logr() {
                 printf $fh "%${log_len}s%s\n", 'Complete UDP range: ',
                     "[$udp_absrange]";
             }
-            if (defined $curr_scan_hr->{$src}->{$dst}->{'syslog_host'}) {
+            if (defined $curr_scan_hr->{$src}->{$dst}->{'syslog_host'}
+                    and $curr_scan_hr->{$src}->{$dst}->{'syslog_host'}) {
                 my $syslog_hosts = '';
                 $syslog_hosts .= "$_, " for keys
                     %{$curr_scan_hr->{$src}->{$dst}->{'syslog_host'}};
@@ -8781,14 +8783,16 @@ sub print_scan_status() {
                                         {$proto}{'abs_ep'};
                                 my $ctr = $scan{$src}{$dst}{'chain'}{$chain}
                                         {$intf}{$proto};
+                                my $chain_str = "Chain: $chain, ";
+                                $chain_str = '' unless $fw_type eq 'iptables';
                                 if ($start_port == $end_port) {
                                     push @lines, "        Scanned ports: " .
                                         uc($proto) . " $start_port, Pkts: $ctr, " .
-                                        "Chain: $chain, Intf: $intf\n";
+                                        "${chain_str}Intf: $intf\n";
                                 } else {
                                     push @lines, "        Scanned ports: " .
                                         uc($proto) . " $start_port-$end_port, Pkts: " .
-                                        "$ctr, Chain: $chain, Intf: $intf\n";
+                                        "$ctr, ${chain_str}Intf: $intf\n";
                                 }
                             }
                         }
@@ -8816,9 +8820,11 @@ sub print_scan_status() {
                             my $matches = $scan{$src}{$dst}{$proto}
                                 {'sid'}{$sid}{$chain}{'pkts'};
 
+                            my $chain_str = "Chain: $chain, ";
+                            $chain_str = '' unless $fw_type eq 'iptables';
                             my $sig_str = qq|        Signature match: "$msg"\n| .
                                 "            " . uc($proto) .
-                                ", Chain: $chain, Count: $matches";
+                                ", ${chain_str}Count: $matches";
 
                             if ($proto eq 'tcp' or $proto eq 'udp'
                                     or $proto eq 'udplite') {
@@ -8845,8 +8851,10 @@ sub print_scan_status() {
                         for my $type (keys %$hr) {
                             for my $chain (keys %{$hr->{$type}}) {
                                 my $pkts = $hr->{$type}->{$chain}->{'pkts'};
+                                my $chain_str = "Chain: $chain, ";
+                                $chain_str = '' unless $fw_type eq 'iptables';
                                 push @lines, qq|        Invalid | . uc($proto) .
-                                    qq| type: "$type" Chain: $chain, Packets: | .
+                                    qq| type: "$type" ${chain_str}Packets: | .
                                     "$pkts\n";
                             }
                         }
@@ -8863,10 +8871,12 @@ sub print_scan_status() {
                                     } else {
                                         $type_text = $valid_icmp6_types{$type}{'text'};
                                     }
+                                    my $chain_str = "Chain: $chain, ";
+                                    $chain_str = '' unless $fw_type eq 'iptables';
                                     push @lines, qq|        Invalid | . uc($proto) .
                                         qq| code: "$code" for | . uc($proto) .
                                         qq| "$type_text" packet | .
-                                        qq|Chain: $chain, Packets: $pkts\n|;
+                                        qq|${chain_str}Packets: $pkts\n|;
                                 }
                             }
                         }
@@ -9059,6 +9069,7 @@ sub print_dshield_stats() {
 }
 
 sub import_ipt_prefixes() {
+    return unless $fw_type eq 'iptables';
     if (-e $config{'IPT_PREFIX_COUNTER_FILE'}) {
         open F, "< $config{'IPT_PREFIX_COUNTER_FILE'}" or die "[*] Could not ",
             "open $config{'IPT_PREFIX_COUNTER_FILE'}: $!";
@@ -9075,6 +9086,7 @@ sub import_ipt_prefixes() {
 }
 
 sub print_ipt_prefixes() {
+    return [] unless $fw_type eq 'iptables';
     my @lines = ();
     push @lines, "[+] iptables log prefix counters:\n";
     if (%ipt_prefixes) {