Changeset 1648

Show
Ignore:
Timestamp:
11/09/06 16:10:56 (2 years ago)
Author:
mbr
Message:

merged r1564:1647 from trunk

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • psad/branches/sigdevel/CREDITS

    r1517 r1648  
    1 Manual Caphina 
    2     - Greatly assisting in the first version of Bastille-NIDS which 
    3       eventually became psad. 
    4  
    5 Tim Schaller 
    6     - Identifying and submitting a patch for a particularly nasty bug for 
    7       multiple scanned IPs. 
    8  
    9 Bruce Meyer 
    10     - Psad testing and suggestions. 
    11  
    12 Peter Watkins 
    13     - (Bastille Linux) psad/iptables interaction. 
    14  
    15 Sweth Chandramouli 
    16     - (Bastille Linux) Various suggestions for psad and install.pl, 
    17       including help with various Perl vagaries. 
    18  
    19 Jay Beale 
    20     - (Bastille Linux) Excellent suggestions for psad reporting and enhanced 
    21       security, and also for integrating psad with Bastille. 
    22  
    23 Ramiro Morales 
    24     - Developed all pre-1.0 rpm packages of psad (see: 
    25       http://rmrpms.tripod.com/psad/). 
    26     - Various suggestions for psad installation (such as FHS compatibility). 
    27     - Implemented init script patches. 
    28  
    29 Alexander Hoff 
    30     - Psad stress testing for kmsgsd. 
    31  
    32 Ryan Delany 
    33     - diskmond testing to help track down the "rdev" bug. 
    34  
    35 Damien Stuart 
    36     - Suggested the zombie reaper code for whois processes, and uid/gid 
    37       check. 
    38     - Excellent suggestions for coding practices and strategies. 
    39  
    40 Donnie Armstrong 
    41     - Suggested fix for incorrectly parsing ifconfig output (might have 
    42       previously included ipv6 interfaces). 
    43  
    44 Ryan Bebeau 
    45     - Suggested fix for AF_INET protocol error. 
    46  
    47 Cliff Rayman 
    48     - Helped track down a nasty bug in which psad would parse iptables 
    49       messages that included a dns name instead of just an ip address for 
    50       the src and dst. 
    51     - Performed lots of excellent testing and 
    52       troubleshooting. 
    53  
    54 Henry Jobst 
    55     - Bugfix in install.pl for chomp error. 
    56  
    57 Ray Curtis 
    58     - Found bug in kmsgsd for undefined $service lines. 
    59     - Comprehensive testing to help remove bugs including a difficult one in 
    60       which psad gets periodically restarted. 
    61  
    62 Manuel Santos 
    63     - Contributed the first bug report to help troublehshoot a potential bug 
    64       in psad/whois interaction. 
    65     - Suggested the auto blocking code should include support for tcp 
    66       wrappers, and that the auto-blocking alerts should be configurable. 
    67  
    68 L-P Sundqvist 
    69     - Suggested fix for tab vs. space bug in install.pl for 
    70       /etc/syslog.conf. 
    71     - Contributed design ideas to make psad run on linux distros that use 
    72       BSD-style init scripts. 
    73  
    74 Eric Sawler 
    75     - Suggested the ability to retain auto-blocked IPs even after a reboot. 
    76  
    77 C.Holman 
    78     - Found, reported, and helped troubleshoot a bug in the ipchains 
    79       protocol number to name mapping. 
    80  
    81 Mike McCandless 
    82     - Asked whether or not there is documentation for the various psad 
    83       configuration variables in psad.conf.  The "PSAD CONFIGURATION 
    84       VARIABLES" section of the man page was the result. 
    85  
    86 Jason Czerak 
    87     - Found and submitted a fix for a bug in which an IP would not be 
    88       ignored even if it was given a 0 danger level in psad_auto_ips. 
    89     - Suggested using the PREROUTING iptables chain along with "-t mangle" 
    90       for the auto-blocking code. 
    91  
    92 Colin Rose 
    93     - Discovered and helped troubleshoot a bug introduced when psad and 
    94       bastille are installed on the same machine (bastille installs an older 
    95       version of psad). 
    96  
    97 Ugo Viti 
    98     - Discovered bug in auto-blocking code where the subject line would 
    99       incorrectly identify the action that had been taken. 
    100     - Discovered bug in subject line for alert emails not including the 
    101       source IP if reverse dns did not work. 
    102     - Suggested adding the FORWARD chain to the auto blocking code. 
    103     - Found bug for email alert being reached prematurely. 
    104  
    105 Leif Westlye 
    106     - Discovered a bug where psad would not allow commands to be different 
    107       than the <cmd>Cmd name.  The bugfix allows someone to specify 
    108       "/usr/bin/mailto" for the mailCmd for example. 
    109  
    110 Daniel Gubser 
    111     - Wrote the diskmond, kmsgsd, and psadwatchd man pages. 
    112     - Suggested compatibility mods for syslog-ng. 
    113     - Develops and maintains Debian builds. 
    114  
    115 Amelia Lewis 
    116     - Provided information on syslog-ng configs. 
    117  
    118 Nick Temple 
    119     - Suggested sending alerts to abuse.net. 
    120  
    121 James N. Winner 
    122     - Discovered bug that prevented psad from detecting scans through the 
    123       iptables FORWARD chain. 
    124  
    1251Albert E. Whale 
    1262    - Discovered bug in 1.1 that made fw_check() too strict with looking for 
     
    14319      root access on some systems to help troubleshoot. 
    14420    - Suggested socket communication in --fw-block mode. 
     21    - Contributed the logrotate.psad file. 
     22 
     23Manual Caphina 
     24    - Greatly assisting in the first version of Bastille-NIDS which 
     25      eventually became psad. 
     26 
     27Tim Schaller 
     28    - Identifying and submitting a patch for a particularly nasty bug for 
     29      multiple scanned IPs. 
     30 
     31Bruce Meyer 
     32    - Psad testing and suggestions. 
     33 
     34Peter Watkins 
     35    - (Bastille Linux) psad/iptables interaction. 
     36 
     37Sweth Chandramouli 
     38    - (Bastille Linux) Various suggestions for psad and install.pl, 
     39      including help with various Perl vagaries. 
     40 
     41Jay Beale 
     42    - (Bastille Linux) Excellent suggestions for psad reporting and enhanced 
     43      security, and also for integrating psad with Bastille. 
     44 
     45Ramiro Morales 
     46    - Developed all pre-1.0 rpm packages of psad (see: 
     47      http://rmrpms.tripod.com/psad/). 
     48    - Various suggestions for psad installation (such as FHS compatibility). 
     49    - Implemented init script patches. 
     50 
     51Alexander Hoff 
     52    - Psad stress testing for kmsgsd. 
     53 
     54Ryan Delany 
     55    - diskmond testing to help track down the "rdev" bug. 
     56 
     57Damien Stuart 
     58    - Suggested the zombie reaper code for whois processes, and uid/gid 
     59      check. 
     60    - Excellent suggestions for coding practices and strategies. 
     61 
     62Donnie Armstrong 
     63    - Suggested fix for incorrectly parsing ifconfig output (might have 
     64      previously included ipv6 interfaces). 
     65 
     66Ryan Bebeau 
     67    - Suggested fix for AF_INET protocol error. 
     68 
     69Cliff Rayman 
     70    - Helped track down a nasty bug in which psad would parse iptables 
     71      messages that included a dns name instead of just an ip address for 
     72      the src and dst. 
     73    - Performed lots of excellent testing and 
     74      troubleshooting. 
     75 
     76Henry Jobst 
     77    - Bugfix in install.pl for chomp error. 
     78 
     79Ray Curtis 
     80    - Found bug in kmsgsd for undefined $service lines. 
     81    - Comprehensive testing to help remove bugs including a difficult one in 
     82      which psad gets periodically restarted. 
     83 
     84Manuel Santos 
     85    - Contributed the first bug report to help troublehshoot a potential bug 
     86      in psad/whois interaction. 
     87    - Suggested the auto blocking code should include support for tcp 
     88      wrappers, and that the auto-blocking alerts should be configurable. 
     89 
     90L-P Sundqvist 
     91    - Suggested fix for tab vs. space bug in install.pl for 
     92      /etc/syslog.conf. 
     93    - Contributed design ideas to make psad run on linux distros that use 
     94      BSD-style init scripts. 
     95 
     96Eric Sawler 
     97    - Suggested the ability to retain auto-blocked IPs even after a reboot. 
     98 
     99C.Holman 
     100    - Found, reported, and helped troubleshoot a bug in the ipchains 
     101      protocol number to name mapping. 
     102 
     103Mike McCandless 
     104    - Asked whether or not there is documentation for the various psad 
     105      configuration variables in psad.conf.  The "PSAD CONFIGURATION 
     106      VARIABLES" section of the man page was the result. 
     107 
     108Jason Czerak 
     109    - Found and submitted a fix for a bug in which an IP would not be 
     110      ignored even if it was given a 0 danger level in psad_auto_ips. 
     111    - Suggested using the PREROUTING iptables chain along with "-t mangle" 
     112      for the auto-blocking code. 
     113 
     114Colin Rose 
     115    - Discovered and helped troubleshoot a bug introduced when psad and 
     116      bastille are installed on the same machine (bastille installs an older 
     117      version of psad). 
     118 
     119Ugo Viti 
     120    - Discovered bug in auto-blocking code where the subject line would 
     121      incorrectly identify the action that had been taken. 
     122    - Discovered bug in subject line for alert emails not including the 
     123      source IP if reverse dns did not work. 
     124    - Suggested adding the FORWARD chain to the auto blocking code. 
     125    - Found bug for email alert being reached prematurely. 
     126 
     127Leif Westlye 
     128    - Discovered a bug where psad would not allow commands to be different 
     129      than the <cmd>Cmd name.  The bugfix allows someone to specify 
     130      "/usr/bin/mailto" for the mailCmd for example. 
     131 
     132Daniel Gubser 
     133    - Wrote the diskmond, kmsgsd, and psadwatchd man pages. 
     134    - Suggested compatibility mods for syslog-ng. 
     135    - Develops and maintains Debian builds. 
     136 
     137Amelia Lewis 
     138    - Provided information on syslog-ng configs. 
     139 
     140Nick Temple 
     141    - Suggested sending alerts to abuse.net. 
     142 
     143James N. Winner 
     144    - Discovered bug that prevented psad from detecting scans through the 
     145      iptables FORWARD chain. 
    145146 
    146147David Krider 
     
    228229 
    229230Mate Wierdl 
    230     - Found bug in EMAIL_ADDRESSES format (psad needed to allow addressed 
     231    - Found bug in EMAIL_ADDRESSES format (psad needed to allow addresses 
    231232      separated by commas). 
    232233    - Submitted patch for new init-scripts directory for psad.spec file. 
     234    - Contributed patch for building the psad RPM on x86_64 platforms. 
    233235 
    234236Stefan <unknown> 
     
    309311      addition to the protocol in auto_dl.  Suggested better sweep detection 
    310312      by calculating scan danger levels over all destinations (i.e. 5 packets 
    311       to different detestinations should trigger danger level 1). 
     313      to different destinations should trigger danger level 1). 
    312314 
    313315SiO 
    314316    - Reported bug with zero masks in auto_dl file. 
     317 
     318Jeroen Vermeulen 
     319    - Suggested that psad collect and report errors that are returned by 
     320      broken iptables commands to the user. This resulted in a redesign of the 
     321      IPTables::ChaingMgr module to collect both stdout and stderr from all 
     322      iptables commands. 
     323    - Found bug where IPTABLES_AUTO_RULENUM misled the user into thinking that 
     324      it governed where the jump rule into a custom chain is added within the 
     325      calling chain.  This resulted in the IPT_AUTO_CHAIN{n} variables being 
     326      updated to support the rule position for both the jump rule and any new 
     327      rules within the chain. 
     328 
     329Adam Mottershead 
     330    - Suggested the ability to disable psad email alerts about auto-blocking 
     331      events. 
  • psad/branches/sigdevel/ChangeLog

    r1563 r1648  
    1 psad-1.4.7 (//2006): 
     1psad-1.4.9 (11//2006): 
     2    - Added the ability to expand embedded variables within the psad 
     3      configuration files.  For example, the path to the FW_DATA_FILE is 
     4      defined in psad.conf as "$PSAD_DIR/fwdata", which resolves to 
     5      /var/log/psad/fwdata when the PSAD_DIR variable is expanded.  This 
     6      feature allows a consistent set of file paths to easily be defined 
     7      instead of using the full path for each file path. 
     8    - Better validation of IPT_AUTO_CHAIN{n} variables so that the from_chain 
     9      cannot be identical to the to_chain. 
     10    - Added dump_config() to psadwatchd.c and kmsgsd.c when compiled with 
     11      debugging support. 
     12 
     13psad-1.4.8 (10/15/2006): 
     14    - Added the ability to get the auto-blocking status for a specific IP 
     15      address in --status-ip mode. 
     16    - Bugfix to use the IPT_OUTPUT_FILE and IPT_ERROR_FILE configuration 
     17      variables. 
     18    - Bugfix to restore "start" functionality in Gentoo init script. 
     19    - Added the ability to selectively disable psad auto-blocking emails. 
     20    - Added more rigorous IP matching regex from Sebastien J. (contributed 
     21      originally for fwknop). 
     22 
     23psad-1.4.7 (09/10/2006): 
     24    - Completely re-worked IPTables::ChainMgr to support the return of 
     25      iptables error messages that are collected via stderr.  This is critical 
     26      to fixing a bug where psad would sometimes die on an iptables command 
     27      but no information would be returned to the user. 
     28    - Added the ability to specify the position for both the jump rule into 
     29      the psad chains as well as the position for new rules within the psad 
     30      chains via the -I argument to iptables.  This fixes a bug where the user 
     31      was given the impression that the IPTABLES_AUTO_RULENUM would accomplish 
     32      this. 
     33    - Populated the _debug option in the IPTables::ChainMgr module, and also 
     34      added a _verbose option so that the specific iptables commands can 
     35      actually be seen as IPTables::ChainMgr functions are called. 
     36    - Added code to install.pl to ask the user if a manual restart of syslog 
     37      is ok upon an unsuccessful test of the syslog reconfiguration.  This 
     38      fixes a bug where some syslog daemons might not re-import their 
     39      configurations after receiving a HUP signal. 
    240    - Bugfix for incorrect config variable name that gated Netfilter 
    341      prerequisite checks. 
     42    - Added code to install.pl to update command paths in psad.conf and 
     43      psadwatchd.conf if any of the paths are broken (i.e. the local system 
     44      does not conform to the default paths).  By default this only happens if 
     45      the user does not want old configs to be merged, but to override this 
     46      use the new --path-update command line argument to install.pl. 
     47    - Added the --Skip-mod-install command line argument to install.pl to 
     48      allow all perl module installs to be skipped. 
     49    - Added the --force-mod-regex command line argument to install.pl to allow 
     50      a regex match on perl module names to force matching modules to be 
     51      installed. 
     52    - Added the logrotate.psad file (contributed by Albert Whale). 
    453 
    554psad-1.4.6 (06/13/2006): 
  • psad/branches/sigdevel/IPTables-ChainMgr/VERSION

    r1362 r1648  
    1 0.2 
     10.4 
  • psad/branches/sigdevel/IPTables-ChainMgr/lib/IPTables/ChainMgr.pm

    r1506 r1648  
    1111# Author: Michael Rash (mbr@cipherdyne.org) 
    1212# 
    13 # Version: 0.1 
     13# Version: 0.4 
    1414# 
    1515############################################################################# 
     
    2828use vars qw($VERSION); 
    2929 
    30 $VERSION = '0.2'; 
     30$VERSION = '0.4'; 
    3131 
    3232sub new() { 
     
    3636    my $self = { 
    3737        _iptables => $args{'iptables'} || '/sbin/iptables', 
    38         _debug    => $args{'debug'}    || 0 
     38        _iptout   => $args{'iptout'}   || '/tmp/ipt.out', 
     39        _ipterr   => $args{'ipterr'}   || '/tmp/ipt.err', 
     40        _debug    => $args{'debug'}    || 0, 
     41        _verbose  => $args{'verbose'}  || 0, 
    3942    }; 
    40     croak "[*] $self->{'_iptables'} incorrect path.\n" 
     43    croak "[*] $self->{'_iptables'} incorrect iptables path.\n" 
    4144        unless -e $self->{'_iptables'}; 
    4245    croak "[*] $self->{'_iptables'} not executable.\n" 
     
    5154    my $iptables = $self->{'_iptables'}; 
    5255 
    53     if ($self->run_ipt_cmd("$iptables -t $table -n -L $chain") == 0) { 
    54         return 1; 
    55     } 
    56     return 0; 
     56    ### see if the chain exists 
     57    return $self->run_ipt_cmd("$iptables -t $table -n -L $chain"); 
    5758} 
    5859 
     
    6364    my $iptables = $self->{'_iptables'}; 
    6465 
    65     if ($self->chain_exists($table, $chain, $iptables)) { 
    66         ### the chain already exists 
    67         return 1, "Table: $table, chain: $chain, already exists."; 
    68     } else { 
    69         ### create the chain 
    70         if ($self->run_ipt_cmd("$iptables -t $table -N $chain") == 0) { 
    71             return 1, "Table: $table, chain: $chain, created."; 
    72         } else { 
    73             ### could not create the chain 
    74             return 0, "Table: $table, chain: $chain, could not create."; 
    75         } 
    76     } 
     66    ### see if the chain exists first 
     67    my ($rv, $out_aref, $err_aref) = $self->chain_exists($table, $chain); 
     68 
     69    ### the chain already exists 
     70    return 1, $out_aref, $err_aref if $rv; 
     71 
     72    ### create the chain 
     73    return $self->run_ipt_cmd("$iptables -t $table -N $chain"); 
    7774} 
    7875 
     
    8380    my $iptables = $self->{'_iptables'}; 
    8481 
    85     if ($self->run_ipt_cmd("$iptables -t $table -F $chain") == 0) { 
    86         return 1; 
    87     } 
    88     return 0; 
     82    ### flush the chain 
     83    return $self->run_ipt_cmd("$iptables -t $table -F $chain"); 
    8984} 
    9085 
     
    9994 
    10095    ### see if the chain exists first 
    101     if ($self->run_ipt_cmd("$iptables -t $table -n -L $del_chain") == 0) { 
    102         ### flush the chain 
    103         if ($self->flush_chain($table, $del_chain, $iptables)) { 
    104             ### find and delete jump rules to this chain (we can't delete 
    105             ### the chain until there are no references to it) 
    106             my $rulenum = $self->find_ip_rule('0.0.0.0/0', 
    107                 '0.0.0.0/0', $table, $jump_from_chain, $del_chain, {}); 
    108             if ($rulenum) { 
    109                 $self->run_ipt_cmd("$iptables -t $table " . 
    110                     "-D $jump_from_chain $rulenum"); 
    111             } 
    112             ### note that we try to delete the chain now regardless 
    113             ### of whether their were jump rules above (should probably 
    114             ### parse for the "0 references" under the -nL <chain> output). 
    115             if ($self->run_ipt_cmd("$iptables -t $table " . 
    116                     "-X $del_chain") == 0) { 
    117                 return 1, "Table: $table, chain: $del_chain, deleted."; 
    118             } else { 
    119                 return 0, "Table: $table, chain: $del_chain, " . 
    120                     "could not delete."; 
    121             } 
    122         } else { 
    123             return 0, "Table: $table, chain: $del_chain, " . 
    124                 "could not flush."; 
    125         } 
    126     } else { 
    127         return 0, "Table: $table, chain: $del_chain, does not exist"; 
    128     } 
     96    my ($rv, $out_aref, $err_aref) = $self->chain_exists($table, $del_chain); 
     97 
     98    ### return true if the chain doesn't exist (it is not an error condition) 
     99    return 1, $out_aref, $err_aref unless $rv; 
     100 
     101    ### flush the chain 
     102    ($rv, $out_aref, $err_aref) 
     103        = $self->flush_chain($table, $del_chain, $iptables); 
     104 
     105    ### could not flush the chain 
     106    return 0, $out_aref, $err_aref unless $rv; 
     107 
     108    ### find and delete jump rules to this chain (we can't delete 
     109    ### the chain until there are no references to it) 
     110    my ($rulenum, $num_chain_rules) 
     111        = $self->find_ip_rule('0.0.0.0/0', 
     112            '0.0.0.0/0', $table, $jump_from_chain, $del_chain, {}); 
     113 
     114    if ($rulenum) { 
     115        $self->run_ipt_cmd( 
     116            "$iptables -t $table -D $jump_from_chain $rulenum"); 
     117    } 
     118 
     119    ### note that we try to delete the chain now regardless 
     120    ### of whether their were jump rules above (should probably 
     121    ### parse for the "0 references" under the -nL <chain> output). 
     122    return $self->run_ipt_cmd("$iptables -t $table -X $del_chain"); 
    129123} 
    130124 
     
    142136    my $iptables = $self->{'_iptables'}; 
    143137 
    144     ### regex to match an IP address 
    145     my $ip_re = '(?:\d{1,3}\.){3}\d{1,3}'; 
    146  
    147     ### normalize src network if necessary; this is because Netfilter 
     138    ### normalize src/dst if necessary; this is because Netfilter 
    148139    ### always reports network address for subnets 
    149     my $normalized_src = ''; 
    150     if ($src =~ m|($ip_re)/($ip_re)|) { 
    151         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    152         $normalized_src = "$net_addr/$cidr"; 
    153     } elsif ($src =~ m|($ip_re)/(\d+)|) { 
    154         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    155         $normalized_src = "$net_addr/$cidr"; 
    156     } else { 
    157         ### it is a hostname or an individual IP 
    158         $normalized_src = $src; 
    159     } 
    160  
    161     ### normalize dst network if necessary; this is because Netfilter 
    162     ### always reports network address for subnets 
    163     my $normalized_dst = ''; 
    164     if ($dst =~ m|($ip_re)/($ip_re)|) { 
    165         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    166         $normalized_dst = "$net_addr/$cidr"; 
    167     } elsif ($dst =~ m|($ip_re)/(\d+)|) { 
    168         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    169         $normalized_dst = "$net_addr/$cidr"; 
    170     } else { 
    171         ### it is a hostname or an individual IP 
    172         $normalized_dst = $dst; 
    173     } 
     140    my $normalized_src = $self->normalize_net($src); 
     141    my $normalized_dst = $self->normalize_net($dst); 
    174142 
    175143    ### first check to see if this rule already exists 
    176     if ($self->find_ip_rule($normalized_src, $normalized_dst, $table, 
    177             $chain, $target, $extended_href)) { 
     144    my ($rule_position, $num_chain_rules) 
     145            = $self->find_ip_rule($normalized_src, $normalized_dst, $table, 
     146                $chain, $target, $extended_href); 
     147 
     148    if ($rule_position) { 
    178149        my $msg = ''; 
    179150        if ($extended_href) { 
     
    189160                "$normalized_dst rule already exists."; 
    190161        } 
    191         return 1, $msg; 
     162        return 1, [$msg], []; 
     163    } 
     164 
     165    ### we need to add the rule 
     166    my $ipt_cmd = ''; 
     167    my $msg     = ''; 
     168    my $idx_err = ''; 
     169 
     170    ### check to see if the insertion index ($rulenum) is too big 
     171    $rulenum = 1 if $rulenum <= 0; 
     172    if ($rulenum > $num_chain_rules+1) { 
     173        $idx_err = "Rule position $rulenum is past end of $chain " . 
     174            "chain ($num_chain_rules rules), compensating." 
     175            if $num_chain_rules > 0; 
     176        $rulenum = $num_chain_rules + 1; 
     177    } 
     178    $rulenum = 1 if $rulenum == 0; 
     179 
     180    if ($extended_href) { 
     181        $ipt_cmd = "$iptables -t $table -I $chain $rulenum "; 
     182        $ipt_cmd .= "-p $extended_href->{'protocol'} " 
     183            if defined $extended_href->{'protocol'}; 
     184        $ipt_cmd .= "-s $normalized_src "; 
     185        $ipt_cmd .= "--sport $extended_href->{'s_port'} " 
     186            if defined $extended_href->{'s_port'}; 
     187        $ipt_cmd .= "-d $normalized_dst "; 
     188        $ipt_cmd .= "--dport $extended_href->{'d_port'} " 
     189            if defined $extended_href->{'d_port'}; 
     190        $ipt_cmd .= "-j $target"; 
     191        $msg = "Table: $table, chain: $chain, added $normalized_src " . 
     192            "-> $normalized_dst "; 
     193        for my $key qw(protocol s_port d_port) { 
     194            $msg .= "$key $extended_href->{$key} " 
     195                if defined $extended_href->{$key}; 
     196        } 
     197        $msg =~ s/\s*$//; 
    192198    } else { 
    193         ### we need to add the rule 
    194         my $ipt_cmd = ''; 
    195         my $msg     = ''; 
    196         my $err_msg = ''; 
    197         if ($extended_href) { 
    198             $ipt_cmd = "$iptables -t $table -I $chain $rulenum "; 
    199             $ipt_cmd .= "-p $extended_href->{'protocol'} " 
    200                 if defined $extended_href->{'protocol'}; 
    201             $ipt_cmd .= "-s $normalized_src "; 
    202             $ipt_cmd .= "--sport $extended_href->{'s_port'} " 
    203                 if defined $extended_href->{'s_port'}; 
    204             $ipt_cmd .= "-d $normalized_dst "; 
    205             $ipt_cmd .= "--dport $extended_href->{'d_port'} " 
    206                 if defined $extended_href->{'d_port'}; 
    207             $ipt_cmd .= "-j $target"; 
    208             $msg = "Table: $table, chain: $chain, added $normalized_src " . 
    209                 "-> $normalized_dst "; 
    210             for my $key qw(protocol s_port d_port) { 
    211                 $msg .= "$key $extended_href->{$key} " 
    212                     if defined $extended_href->{$key}; 
    213             } 
    214             $msg =~ s/\s*$//; 
    215             $err_msg = "Table: $table, chain: $chain, could not add $target " . 
    216                 "rule for $normalized_src -> $normalized_dst"; 
    217             for my $key qw(protocol s_port d_port) { 
    218                 $err_msg .= "$key $extended_href->{$key} " 
    219                     if defined $extended_href->{$key}; 
    220             } 
    221             $err_msg =~ s/\s*$//; 
    222         } else { 
    223             $ipt_cmd = "$iptables -t $table -I $chain $rulenum " . 
    224                 "-s $normalized_src -d $normalized_dst -j $target"; 
    225             $msg = "Table: $table, chain: $chain, added $normalized_src " . 
    226                 "-> $normalized_dst"; 
    227             $err_msg = "Table: $table, chain: $chain, could not add $target " . 
    228                 "rule for $normalized_src -> $normalized_dst"; 
    229         } 
    230         if ($self->run_ipt_cmd($ipt_cmd) == 0) { 
    231             return 1, $msg; 
    232         } else { 
    233             return 0, $err_msg; 
    234         } 
    235     } 
     199        $ipt_cmd = "$iptables -t $table -I $chain $rulenum " . 
     200            "-s $normalized_src -d $normalized_dst -j $target"; 
     201        $msg = "Table: $table, chain: $chain, added $normalized_src " . 
     202            "-> $normalized_dst"; 
     203    } 
     204    my ($rv, $out_aref, $err_aref) = $self->run_ipt_cmd($ipt_cmd); 
     205    if ($rv) { 
     206        push @$out_aref, $msg if $msg; 
     207    } 
     208    push @$err_aref, $idx_err if $idx_err; 
     209    return $rv, $out_aref, $err_aref; 
    236210} 
    237211 
     
    248222    my $iptables = $self->{'_iptables'}; 
    249223 
    250     ### regex to match an IP address 
    251     my $ip_re = '(?:\d{1,3}\.){3}\d{1,3}'; 
    252  
    253     ### normalize src network if necessary; this is because Netfilter 
     224    ### normalize src/dst if necessary; this is because Netfilter 
    254225    ### always reports network address for subnets 
    255     my $normalized_src = ''; 
    256     if ($src =~ m|($ip_re)/($ip_re)|) { 
    257         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    258         $normalized_src = "$net_addr/$cidr"; 
    259     } elsif ($src =~ m|($ip_re)/(\d+)|) { 
    260         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    261         $normalized_src = "$net_addr/$cidr"; 
    262     } else { 
    263         ### it is a hostname or an individual IP 
    264         $normalized_src = $src; 
    265     } 
    266  
    267     ### normalize dst network if necessary; this is because Netfilter 
    268     ### always reports network address for subnets 
    269     my $normalized_dst = ''; 
    270     if ($dst =~ m|($ip_re)/($ip_re)|) { 
    271         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    272         $normalized_dst = "$net_addr/$cidr"; 
    273     } elsif ($dst =~ m|($ip_re)/(\d+)|) { 
    274         my ($net_addr, $cidr) = ipv4_network($1, $2); 
    275         $normalized_dst = "$net_addr/$cidr"; 
    276     } else { 
    277         ### it is a hostname or an individual IP 
    278         $normalized_dst = $dst; 
    279     } 
     226    my $normalized_src = $self->normalize_net($src); 
     227    my $normalized_dst = $self->normalize_net($dst); 
    280228 
    281229    ### first check to see if this rule already exists 
    282     my $rulenum = $self->find_ip_rule($normalized_src, 
    283         $normalized_dst, $table, $chain, $target, $extended_href); 
     230    my ($rulenum, $num_chain_rules) 
     231        = $self->find_ip_rule($normalized_src, 
     232            $normalized_dst, $table, $chain, $target, $extended_href); 
     233 
    284234    if ($rulenum) { 
    285235        ### we need to delete the rule 
    286         if ($self->run_ipt_cmd("$iptables " . 
    287             "-t $table -D $chain $rulenum") == 0) { 
    288             return 1, "Table: $table, chain: $chain, deleted rule #$rulenum"; 
    289         } else { 
    290             my $extended_msg = '.'; 
    291             if ($extended_href) { 
    292                 for my $key qw(protocol s_port d_port) { 
    293                     $extended_msg .= "$key: $extended_href->{$key} " 
    294                         if defined $extended_href->{$key}; 
    295                 } 
    296             } 
    297             $extended_msg =~ s/\s*$//; 
    298             return 0, "Table: $table, chain: $chain, could not delete " . 
    299                 "$target rule #$rulenum for $normalized_src -> " . 
    300                 "$normalized_dst $extended_msg"; 
    301         } 
    302     } else { 
    303         my $extended_msg = ''; 
    304         if ($extended_href) { 
    305             for my $key qw(protocol s_port d_port) { 
    306                 $extended_msg .= "$key: $extended_href->{$key} " 
    307                     if defined $extended_href->{$key}; 
    308             } 
    309         } 
    310         $extended_msg =~ s/\s*$//; 
    311         return 0, "Table: $table, chain: $chain, rule $normalized_src -> " . 
    312             "$normalized_dst $extended_msg does not exist."; 
    313     } 
     236        return $self->run_ipt_cmd("$iptables -t $table -D $chain $rulenum"); 
     237    } 
     238 
     239    my $extended_msg = ''; 
     240    if ($extended_href) { 
     241        for my $key qw(protocol s_port d_port) { 
     242            $extended_msg .= "$key: $extended_href->{$key} " 
     243                if defined $extended_href->{$key}; 
     244        } 
     245    } 
     246    $extended_msg =~ s/\s*$//; 
     247    return 0, [], ["Table: $table, chain: $chain, rule $normalized_src " . 
     248        "-> $normalized_dst $extended_msg does not exist."]; 
    314249} 
    315250 
     
    329264        or croak "[*] Could not acquire IPTables::Parse object"; 
    330265 
    331     my $chain_aref = $ipt_parse->chain_action_rules($table, $chain); 
     266    my $chain_aref = $ipt_parse->chain_rules($table, $chain); 
    332267 
    333268    my $rulenum = 1; 
     
    350285                    } 
    351286                } 
    352                 return $rulenum if $found; 
     287                return $rulenum, $#$chain_aref+1 if $found; 
    353288            } else { 
    354289                if ($rule_href->{'protocol'} eq 'all') { 
     
    356291                        ### built-in LOG and ULOG target rules always 
    357292                        ### have extended information 
    358                         return $rulenum
     293                        return $rulenum, $#$chain_aref+1
    359294                    } elsif (not $rule_href->{'extended'}) { 
    360295                        ### don't want any additional criteria (such as 
    361296                        ### port numbers) in the rule. Note that we are 
    362297                        ### also not checking interfaces 
    363                         return $rulenum
     298                        return $rulenum, $#$chain_aref+1
    364299                    } 
    365300                } 
     
    368303        $rulenum++; 
    369304    } 
    370     return 0; 
     305    return 0, $#$chain_aref+1; 
     306
     307 
     308sub normalize_net() { 
     309    my $self = shift; 
     310    my $net  = shift || croak '[*] Must specify net.'; 
     311 
     312    ### regex to match an IP address 
     313    my $ip_re = '(?:\d{1,3}\.){3}\d{1,3}'; 
     314 
     315    my $normalized_net = ''; 
     316    if ($net =~ m|($ip_re)/($ip_re)|) { 
     317        my ($net_addr, $cidr) = ipv4_network($1, $2); 
     318        $normalized_net = "$net_addr/$cidr"; 
     319    } elsif ($net =~ m|($ip_re)/(\d+)|) { 
     320        my ($net_addr, $cidr) = ipv4_network($1, $2); 
     321        $normalized_net = "$net_addr/$cidr"; 
     322    } else { 
     323        ### it is a hostname or an individual IP 
     324        $normalized_net = $net; 
     325    } 
     326    return $normalized_net; 
    371327} 
    372328 
     
    375331    my $table = shift || croak '[-] Must specify a table, e.g. "filter".'; 
    376332    my $from_chain = shift || croak '[-] Must specify chain to jump from.'; 
     333    my $rulenum    = shift || croak '[-] Must specify jump rule chain position'; 
    377334    my $to_chain   = shift || croak '[-] Must specify chain to jump to.'; 
    378335    my $iptables = $self->{'_iptables'}; 
     336    my $idx_err = ''; 
     337 
     338    if ($from_chain eq $to_chain) { 
     339        return 0, ["Identical from_chain and to_chain ($from_chain) " . 
     340            "not allowed."], []; 
     341    } 
    379342 
    380343    ### first check to see if the jump rule already exists 
    381     if ($self->find_ip_rule('0.0.0.0/0', '0.0.0.0/0', $table, 
    382             $from_chain, $to_chain, {})) { 
    383         return 1, "Table: $table, chain: $to_chain, jump rule already exists."; 
    384     } else { 
    385         ### we need to add the rule 
    386         if ($self->run_ipt_cmd("$iptables " . 
    387             "-t $table -I $from_chain 1 -j $to_chain") == 0) { 
    388             return 1, "Table: $table, chain: $to_chain, added jump rule."; 
    389         } else { 
    390             return 0, "Table: $table, chain: $to_chain, could not add jump."; 
    391         } 
    392     } 
     344    my ($rule_position, $num_chain_rules) 
     345        = $self->find_ip_rule('0.0.0.0/0', '0.0.0.0/0', $table, 
     346            $from_chain, $to_chain, {}); 
     347 
     348    ### check to see if the insertion index ($rulenum) is too big 
     349    $rulenum = 1 if $rulenum <= 0; 
     350    if ($rulenum > $num_chain_rules+1) { 
     351        $idx_err = "Rule position $rulenum is past end of $from_chain " . 
     352            "chain ($num_chain_rules rules), compensating." 
     353            if $num_chain_rules > 0; 
     354        $rulenum = $num_chain_rules + 1; 
     355    } 
     356    $rulenum = 1 if $rulenum == 0; 
     357 
     358    if ($rule_position) { 
     359        ### the rule already exists 
     360        return 1, 
     361            ["Table: $table, chain: $to_chain, jump rule already exists."], []; 
     362    } 
     363 
     364    ### we need to add the rule 
     365    my ($rv, $out_aref, $err_aref) = $self->run_ipt_cmd( 
     366        "$iptables -t $table -I $from_chain $rulenum -j $to_chain"); 
     367    push @$err_aref, $idx_err if $idx_err; 
     368    return $rv, $out_aref, $err_aref; 
    393369} 
    394370 
     
    397373    my $cmd = shift || croak '[*] Must specify an iptables command to run.'; 
    398374    my $iptables = $self->{'_iptables'}; 
     375    my $iptout   = $self->{'_iptout'}; 
     376    my $ipterr   = $self->{'_ipterr'}; 
     377    my $debug    = $self->{'_debug'}; 
     378    my $verbose  = $self->{'_verbose'}; 
    399379    croak "[*] $cmd does not look like an iptables command." 
    400         unless $cmd =~ /iptables/; 
    401  
    402     return (system "$cmd > /dev/null 2>&1") >> 8; 
    403 
    404  
    405 sub run_ipt_cmd_output() { 
    406     my $self  = shift; 
    407     my $cmd = shift || croak '[*] Must specify an iptables command to run.'; 
    408     my $iptables = $self->{'_iptables'}; 
    409     croak "[*] $cmd does not look like an iptables command." 
    410         unless $cmd =~ /iptables/; 
    411  
    412     my @output = (); 
    413     my $rv = 0; 
    414     eval { 
    415         open IPT, "$cmd |" 
    416             or croak "[*] Could not execute $cmd: $!"; 
    417         @output = <IPT>; 
    418         close IPT or croak "[*] Could not close command $cmd: $!"; 
    419         $rv = $?; 
    420     }; 
    421     if ($rv == 0) { 
    422         return 1, \@output; 
    423     } 
    424     return 0, \@output; 
     380        unless $cmd =~ m|^\s*iptables| or $cmd =~ m|^\S+/iptables|; 
     381 
     382    if ($verbose) { 
     383        print STDOUT $cmd, "\n"; 
     384    } elsif ($debug) { 
     385        print STDERR $cmd, "\n"; 
     386    } 
     387 
     388    ### run the command and collect both stdout and stderr 
     389    system "$cmd > $iptout 2> $ipterr"; 
     390 
     391    my $rv = 1; 
     392    my @stdout = (); 
     393    my @stderr = (); 
     394 
     395    if (-e $iptout) { 
     396        open F, "< $iptout" or croak "[*] Could not open $iptout"; 
     397        @stdout = <F>; 
     398        close F; 
     399    } 
     400    if (-e $ipterr) { 
     401        open F, "< $ipterr" or croak "[*] Could not open $ipterr"; 
     402        @stderr = <F>; 
     403        close F; 
     404 
     405        $rv = 0 if @stderr; 
     406    } 
     407 
     408    if ($debug and $verbose) { 
     409        print "[+] iptables command stdout:\n"; 
     410        for my $line (@stdout) { 
     411            if ($line =~ /\n$/) { 
     412                print $line; 
     413            } else { 
     414                print $line, "\n"; 
     415            } 
     416        } 
     417        print "[+] iptables command stderr:\n"; 
     418        for my $line (@stderr) { 
     419            if ($line =~ /\n$/) { 
     420                print $line; 
     421            } else { 
     422                print $line, "\n"; 
     423            } 
     424        } 
     425    } 
     426 
     427    return $rv, \@stdout, \@stderr; 
    425428} 
    426429 
  • psad/branches/sigdevel/IPTables-Parse/VERSION

    r1501 r1648  
    1 0.3 
     10.4 
  • psad/branches/sigdevel/IPTables-Parse/lib/IPTables/Parse.pm

    r1501 r1648  
    88# Author: Michael Rash (mbr@cipherdyne.org) 
    99# 
    10 # Version: 0.3 
     10# Version: 0.4 
    1111# 
    1212################################################################## 
     
    2323use vars qw($VERSION); 
    2424 
    25 $VERSION = '0.3'; 
     25$VERSION = '0.4'; 
    2626 
    2727sub new() { 
     
    3939} 
    4040 
    41 sub chain_action_rules() { 
     41sub chain_policy() { 
    4242    my $self   = shift; 
    4343    my $table  = shift || croak '[*] Specify a table, e.g. "nat"'; 
     
    6262    } 
    6363 
     64    my $policy = ''; 
     65 
     66    for my $line (@ipt_lines) {&nb