Changeset 1009

Show
Ignore:
Timestamp:
02/24/08 12:50:36 (9 months ago)
Author:
mbr
Message:

This is a major commit to add support for the usage of multiple digest
algorithm for replay attack detection and for message integrity.

- (SPAPICT Group) Submitted patches to include support for the SHA1 digest
algorithm for SPA packet replay attack detection. I modified these
patches for maximum configurability (see the --digest-alg argument on
the fwknop command line), and the ability to use the SHA256 algorithm as
well. The default path to the /var/log/fwknop/md5sums file has been
changed to /var/log/fwknop/digest.cache, and the default digest
algorithm is now SHA256 (but this is tunable via the DIGEST_TYPE
variable in the fwknop.conf file).
- Added the Digest::SHA perl module in support of the SHA1 and SHA256
digest algorithms for replay attack detection and SPA message integrity.
- (Test suite) Added several tests for configurable digest algorithms in
support for the SHA256, SHA1, and MD5 digest changes made by the SPAPICT
Group.
- Bugfix in install.pl to not test for the iptable command on non-Linux
systems, and to not test for the ipfw command on systems that are Linux.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • fwknop/trunk/ChangeLog

    r1000 r1009  
    33    - (Grant Ferley) Submitted patch to handle Linux "cooked" interfaces for 
    44      packet capture (e.g. rp-pppoe interfaces). 
    5     - Applied modified version of the client-defined access timeout patches 
    6       submitted by the PICT SPA Group.  There are two new message types to 
    7       facilitate client timeouts; one for normal access mode, and the other 
    8       for the FORWARD access mode.  In the access.conf file, there is also a 
    9       new variable "PERMIT_CLIENT_TIMEOUT" to allow each SOURCE stanza to 
    10       allow client-defined timeouts or not. 
     5    - (SPAPICT Group) Applied modified version of the client-defined access 
     6      timeout patches submitted by the PICT SPA Group.  There are two new 
     7      message types to facilitate client timeouts; one for normal access mode, 
     8      and the other for the FORWARD access mode.  In the access.conf file, 
     9      there is also a new variable "PERMIT_CLIENT_TIMEOUT" to allow each 
     10      SOURCE stanza to allow client-defined timeouts or not. 
     11    - (SPAPICT Group) Submitted patches to include support for the SHA1 digest 
     12      algorithm for SPA packet replay attack detection.  I modified these 
     13      patches for maximum configurability (see the --digest-alg argument on 
     14      the fwknop command line), and the ability to use the SHA256 algorithm as 
     15      well.  The default path to the /var/log/fwknop/md5sums file has been 
     16      changed to /var/log/fwknop/digest.cache, and the default digest 
     17      algorithm is now SHA256 (but this is tunable via the DIGEST_TYPE 
     18      variable in the fwknop.conf file). 
     19    - Added the Digest::SHA perl module in support of the SHA1 and SHA256 
     20      digest algorithms for replay attack detection and SPA message integrity. 
    1121    - Added full packet hex dumps (including packet headers) to fwknopd in 
    1222      --debug --verbose mode.  This is to help diagnose packet sniffing issues 
     
    1626      local output/ directory in several of the test config files in the 
    1727      test/conf/ directory. 
     28    - (Test suite) Added several tests for configurable digest algorithms in 
     29      support for the SHA256, SHA1, and MD5 digest changes made by the SPAPICT 
     30      Group. 
    1831 
    1932fwknop-1.9.1 (01/26/2008): 
  • fwknop/trunk/fwknop

    r1006 r1009  
    4242use Net::IPv4Addr qw(ipv4_in_network); 
    4343use Net::Ping::External qw(ping); 
    44 use Digest::MD5 'md5_base64'; 
    4544use IO::Socket; 
    4645use IO::Handle; 
     
    7372my $server_proto  = ''; 
    7473my $run_last_host = ''; 
     74my $total_digest  = ''; 
    7575my $show_last_host_cmd = ''; 
    7676my $show_last_cmd = 0; 
     77my $use_md5       = 0; 
     78my $use_sha1      = 0; 
     79my $use_sha256    = 0; 
    7780my $gpg_home_dir  = ''; 
    7881my $gpg_recipient = ''; 
     
    131134my $cmdl_fw_timeout = 0; 
    132135 
     136### Digest types and command argument flags 
     137my $MD5_DIGEST    = 1; 
     138my $SHA1_DIGEST   = 2; 
     139my $SHA256_DIGEST = 3; 
     140my $digest_type = $SHA256_DIGEST; ### default 
     141my $cmdl_digest_alg = ''; 
     142 
    133143### default to root (client must run as root in this mode) 
    134144my $spoof_username = ''; 
     
    145155### there is a constant "RIJNDAEL_KEYSIZE" in the Crypt::Rijndael sources, but 
    146156### it is not used; a 16 byte key size is fine. 
    147 my $enc_keysize       = 16; 
     157my $enc_keysize = 16; 
    148158 
    149159my $enc_shared_secret = ''; 
     
    208218die "[*] Server auth method not supported in FORWARD access mode.\n" 
    209219    if $server_auth_method and $forward_access_str; 
     220 
     221&set_digest_type() if $cmdl_digest_alg; 
     222$digest_type = $MD5_DIGEST    if $use_md5; 
     223$digest_type = $SHA1_DIGEST   if $use_sha1; 
     224$digest_type = $SHA256_DIGEST if $use_sha256; 
    210225 
    211226### this is only necessary for older versions of perl (newer versions 
     
    374389 
    375390sub pcap_build_enc_msg() { 
    376  
    377     my $msg         = ''; 
    378     my $server_auth = '';  ### contains stuff after the md5 sum 
    379     my $user        = ''; 
    380     my $random_num  = ''; 
    381     my $md5sum      = ''; 
    382     my $timestamp   = time(); 
    383391 
    384392    ### message format (all fields are separated by ":" characters 
     
    393401    #    2 => forward access mode / IP,proto,port / internalIP,externalNATPort 
    394402    #  (optional) server_auth (post 0.9.2 release) 
    395     #  message md5 sum 
     403    #  message digest (SHA256 / SHA1 / MD5 ) 
     404 
     405    my $msg = ''; 
    396406 
    397407    unless ($quiet) { 
     
    429439    $msg .= &SPA_client_timeout(); 
    430440 
    431     ### append MD5 sum 
     441    ### append Message Digest 
    432442    $msg =~ s/\n//g; 
    433     $msg .= &SPA_md5sum($msg); 
    434  
    435     print "\n[+] Clear text message (fields base64 encoded): $msg\n" 
    436         if $debug; 
     443    $msg .= &SPA_digest($msg); 
     444 
     445    if ($debug) { 
     446        print "\n[+] Clear text message (fields base64 encoded): $msg\n", 
     447            "    Digest: $total_digest\n"; 
     448    } 
    437449 
    438450    if ($gpg_signing_key or $gpg_default_key) { 
     
    532544 
    533545sub SPA_client_timeout() { 
    534     return unless $cmdl_fw_timeout; 
     546    return '' unless $cmdl_fw_timeout; 
    535547    return ':' . $cmdl_fw_timeout; 
    536548} 
     
    559571} 
    560572 
    561 sub SPA_md5sum() { 
     573sub SPA_digest() { 
    562574    my $msg = shift; 
    563     my $sum = md5_base64($msg); 
    564     print "        MD5 sum:        $sum\n" unless $quiet; 
    565     return ':' . $sum; 
     575 
     576    my $digest = ''; 
     577 
     578    if ($digest_type == $MD5_DIGEST) { 
     579        require Digest::MD5; 
     580        Digest::MD5->import(qw(md5_base64)); 
     581        $digest = md5_base64($msg); 
     582        print "        MD5 digest:     $digest\n" unless $quiet; 
     583        if ($debug) { 
     584            $total_digest = md5_base64("$msg:$digest"); 
     585        } 
     586    } elsif ($digest_type == $SHA1_DIGEST) { 
     587        require Digest::SHA; 
     588        Digest::SHA->import(qw(sha1_base64)); 
     589        $digest = sha1_base64($msg); 
     590        print "        SHA1 digest:    $digest\n" unless $quiet; 
     591        if ($debug) { 
     592            $total_digest = sha1_base64("$msg:$digest"); 
     593        } 
     594    } elsif ($digest_type == $SHA256_DIGEST) { 
     595        require Digest::SHA; 
     596        Digest::SHA->import(qw(sha256_base64)); 
     597        $digest = sha256_base64($msg); 
     598        print "        SHA256 digest:  $digest\n" unless $quiet; 
     599        if ($debug) { 
     600            $total_digest = sha256_base64("$msg:$digest"); 
     601        } 
     602    } else { 
     603        die "[*] Improper digest algorithm, use --help"; 
     604    } 
     605    return ':' . $digest; 
    566606} 
    567607 
     
    13101350        'Spoof-proto=s'  => \$spoof_proto, 
    13111351        'Save-packet'    => \$save_packet_mode, 
    1312         'Save-packet-file=s' => \$save_packet_file, 
     1352        'Save-packet-file=s' => \$save_packet_file, 
    13131353        'Save-dst'       => \$save_destination, 
    13141354        'user-rc=s'      => \$user_rc_file, 
     
    13191359        'gpg-default-key'   => \$gpg_default_key, 
    13201360        'gpg-home-dir=s'    => \$gpg_home_dir, 
    1321         'gpg-verbose'    => \$gpg_verbose, 
    1322         'gpg-agent'      => \$use_gpg_agent, 
    1323         'gpg-agent-info=s' => \$gpg_agent_info, 
    1324         'quiet'          => \$quiet, 
    1325         'Forward-access=s' => \$forward_access_str, 
     1361        'gpg-verbose'       => \$gpg_verbose, 
     1362        'gpg-agent'         => \$use_gpg_agent, 
     1363        'gpg-agent-info=s' => \$gpg_agent_info, 
     1364        'quiet'             => \$quiet, 
     1365        'Forward-access=s' => \$forward_access_str, 
    13261366        'TCP-sock'       => \$spa_established_tcp, 
    13271367        'Access=s'       => \$access_str, 
    13281368        'fw-timeout=i'   => \$cmdl_fw_timeout, 
    13291369        'allow-IP=s'     => \$enc_allow_ip, 
     1370        'digest-alg=s'   => \$cmdl_digest_alg, 
    13301371        'source-IP'      => \$enc_source_ip, 
    13311372        'rotate-proto'   => \$enc_rotate_proto, 
     
    14521493    unless ($forward_access_str =~ /^$ip_re,\d+$/) { 
    14531494        die "[*] Must specify '<internal_IP>,<external_port>'"; 
     1495    } 
     1496    return; 
     1497} 
     1498 
     1499sub set_digest_type() { 
     1500    if ($cmdl_digest_alg =~ /sha256/i) { 
     1501        $digest_type = $SHA256_DIGEST; 
     1502    } elsif ($cmdl_digest_alg =~ /sha1/i) { 
     1503        $digest_type = $SHA1_DIGEST; 
     1504    } elsif ($cmdl_digest_alg =~ /md5/i) { 
     1505        $digest_type = $MD5_DIGEST; 
     1506    } else { 
     1507        die "[*] --digest-alg can accept one of MD5, SHA1, or SHA256"; 
    14541508    } 
    14551509    return; 
     
    15051559                                 http://www.whatismyip.org/ website. This is 
    15061560                                 useful if fwknop is deployed on an internal 
    1507                                  system behind a NAT device. 
    15081561    -w, --whatismyip           - (Synonym for --Resolve-external-IP option). 
    15091562    --URL <external IP URL>    - Specify a URL from which to determine the 
  • fwknop/trunk/fwknop.8

    r807 r1009  
    5757    if command mode => command to execute 
    5858    else access mode  => IP,proto,port 
    59     MD5 sum 
     59    message digest (SHA256 / SHA1 / MD5) 
    6060.PP 
    6161Each of the above fields are separated by a ":" character due to the 
    6262variable length of several of the fields, and those that might contain 
    63 ":" characters are base64 encoded.  The MD5 message sum allows the 
    64 server to check message integrity after decryption, and the 16 bytes 
    65 of random data ensures (with high probability) that no two messages are 
    66 identical.  For each packet coming from an 
     63":" characters are base64 encoded.  The message digest (SHA256 by default 
     64in all versions of 
     65.B fwknop 
     66greater than 1.9.1) allows the server to check message integrity after decryption, 
     67and the 16 bytes of random data ensures (with high probability) that no two messages 
     68are identical.  This ensures that replay attacks are not possible against fwknop. 
     69For each packet coming from an 
    6770.B fwknop 
    6871client, the 
    6972.B fwknopd 
    70 server caches the MD5 sum calculated over the entire packet and compares against 
    71 previous MD5 sums in order to detect attempted replay attacks.  The MD5 sum 
     73server caches the SHA256 digest calculated over the entire packet and compares against 
     74previous packet digests in order to detect attempted replay attacks.  The digest 
    7275cache file is located at 
    73 .I /var/log/fwknop/md5sums 
     76.I /var/log/fwknop/digest.cache 
    7477and is not rotated so that the detection of duplicate SPA messages is maximized. 
    7578Both syslog and email alerts are generated if a replay is detected (although 
     
    455458client when creating a 'access mode' SPA packet: 
    456459.PP 
    457         Random data: 7457916043504181 
    458         Username:    user_name 
    459         Timestamp:   1185272057 
    460         Version:     1.8.1 
    461         Action:      1 (access mode) 
    462         Access:      NNN.NNN.NNN.NNN,tcp/22 
    463         MD5 sum:     35rdd5f8tZTavUy0MuEdq
     460        Random data:    6565240948266426 
     461        Username:       mbr 
     462        Timestamp:      1203863233 
     463        Version:        1.9.2 
     464        Type:           1 (access mode) 
     465        Access:         127.0.0.2,tcp/22 
     466        SHA256 sum:     gngquSL8AuM7r27XsR4qPmJhuBo9pG2PYwII06AaJH
    464467.PP 
    465468 
     
    511514client when creating a 'command mode' SPA packet: 
    512515.PP 
    513         Random data: 1387393943305159 
    514         Username:    user_name 
    515         Timestamp:   1185349703 
    516         Version:     1.8.1 
    517         Action:      0 (command mode) 
    518         Cmd:         echo "The commands sent - minus quote charaters around the command" & sleep 10; echo "The End" 
    519         MD5 sum:     fJtQkAcK1A1XMRAHEG1UcA 
     516        Random data:    4621962433020664 
     517        Username:       mbr 
     518        Timestamp:      1203864394 
     519        Version:        1.9.2 
     520        Type:           0 (command mode) 
     521        Cmd:            echo "The commands sent - minus quote charaters around the command" & sleep 10; echo "The End" 
     522        SHA256 sum:     eN8c8mNArZxF066iulbxlTK4Gt/EO0ALLYwzVzCkXww 
    520523.PP 
    521524Instruct the fwknop server running at 10.0.0.123 to send a single ICMP 
     
    608611Michael Rash <mbr@cipherdyne.org> 
    609612 
    610 .SH CREDITS 
    611 The phrase "Single Packet Authorization" was coined by MadHat, see: 
    612 .B http://www.nmrc.org/ 
    613 The term "port knocking" was coined by Martin Krzywinski, see: 
    614 .B http://www.portknocking.org/ 
    615  The original p0f passive OS fingerprinter was written by Michal Zalewski, and is 
    616 available here: 
     613.SH CONTRIBUTORS 
     614Many people who are active in the open source community have contributed to fwknop. 
     615See the 
     616.B CREDITS 
     617file in the fwknop sources, or visit 
     618.B http://www.cipherdyne.org/fwknop/docs/contributors.html 
     619to view the online list of contributors. 
     620 
     621The phrase "Single Packet Authorization" was coined by MadHat and Simple 
     622Nomad at the BlackHat Briefings of 2005 (see: http://www.nmrc.org/). 
     623The term "port knocking" was coined by Martin Krzywinski (see: 
     624http://www.portknocking.org/).  The original p0f passive OS fingerprinter was 
     625written by Michal Zalewski, and is available here: 
    617626.B http://lcamtuf.coredump.cx/p0f.shtml 
    618627 
  • fwknop/trunk/fwknop.conf

    r880 r1009  
    6363MAX_SPA_PACKET_AGE          120; 
    6464 
    65 ### Track md5 sums associated with previous fwknop process.  This allows 
    66 ### md5 sums to remain persistent across executions of fwknop. 
    67 ENABLE_MD5_PERSISTENCE      Y; 
     65### Track digest sums associated with previous fwknop process.  This allows 
     66### digest sums to remain persistent across executions of fwknop. 
     67ENABLE_DIGEST_PERSISTENCE   Y; 
     68 
     69### Default to using all three of SHA256, SHA1, and MD5 for SPA replay attack 
     70### detection.  This overkill, but performance is not usually a concern. 
     71### Further, the variable can also be set to "SHA1" or "MD5". 
     72DIGEST_TYPE                 ALL; 
    6873 
    6974### This variable controls whether fwknopd includes the source IP of each SPA 
    70 ### packet in the MD5 store. If a replayed SPA message is detected, then 
     75### packet in the DIGEST store. If a replayed SPA message is detected, then 
    7176### having this information can provide information about which networks have 
    7277### people sniffing your SPA packets. 
    73 ENABLE_MD5_INCLUDE_SRC      Y; 
     78ENABLE_DIGEST_INCLUDE_SRC   Y; 
    7479 
    7580### Allow SPA clients to request access to services through an iptables 
     
    225230ACCESS_CONF                 $FWKNOP_CONF_DIR/access.conf; 
    226231P0F_FILE                    $FWKNOP_CONF_DIR/pf.os;   ### p0f-based fingerprints 
    227 MD5_FILE                    $FWKNOP_DIR/md5sums; 
    228 KNOPTM_TIMEOUT_FILE         $FWKNOP_DIR/knoptm.cache;  ### timeout cache 
     232DIGEST_FILE                 $FWKNOP_DIR/digest.cache; 
    229233FWKNOP_PID_FILE             $FWKNOP_RUN_DIR/fwknopd.pid; 
    230234FWKNOP_CMDLINE_FILE         $FWKNOP_RUN_DIR/fwknopd.cmd; 
  • fwknop/trunk/fwknopd

    r1006 r1009  
    5151use NetPacket::ICMP; 
    5252use NetPacket::Ethernet; 
    53 use Digest::MD5 'md5_base64'; 
    5453use IO::Socket; 
    5554use IO::Handle; 
     
    7574my %pid_files = (); 
    7675my %ip_sequences  = (); 
    77 my %md5_msg_store = (); 
     76my %digest_store = (); 
    7877my %ipt_input   = (); 
    7978my %ipt_forward = (); 
     
    117116### ACCESS message: 
    118117###     random data :user : client_timestamp : client_version : \ 
    119 ###     type (1) : access_request : MD5 
     118###     type (1) : access_request : digest 
    120119my $SPA_ACCESS_MODE  = 1;  ### default 
    121120 
    122121### COMMAND message: 
    123122###     random data :user : client_timestamp : client_version : \ 
    124 ###     type (0) : command : MD5 
     123###     type (0) : command : digest 
    125124my $SPA_COMMAND_MODE = 0; 
    126125 
    127126### FORWARD ACCESS message: 
    128127###     random data :user : client_timestamp : client_version : \ 
    129 ###     type (2) : access_request : NAT_info : MD5 
     128###     type (2) : access_request : NAT_info : digest 
    130129my $SPA_FORWARD_ACCESS_MODE = 2; 
    131130 
    132131### ACCESS message with client-defined firewall timeout: 
    133132###     random data :user : client_timestamp : client_version : \ 
    134 ###     type (3) : access_request : timeout : MD5 
     133###     type (3) : access_request : timeout : digest 
    135134my $SPA_CLIENT_TIMEOUT_ACCESS_MODE = 3; 
    136135 
    137136### FORWARD ACCESS message with client-defined firewall timeout: 
    138137###     random data :user : client_timestamp : client_version : \ 
    139 ###     type (4) : access_request : NAT_info : timeout : MD5 
     138###     type (4) : access_request : NAT_info : timeout : digest 
    140139my $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE = 4; 
    141140 
     
    154153### there is a constant "RIJNDAEL_KEYSIZE" in the Crypt::Rijndael sources, but 
    155154### it is not used; a 16 byte key size is fine. 
    156 my $enc_keysize       = 16; 
     155my $enc_keysize = 16; 
    157156 
    158157my $ALG_RIJNDAEL = 1; 
     
    167166### Bool to detect Linux "Cooked" datalink layers 
    168167my $PCAP_COOKED_INTF = 0; 
     168 
     169### digest constants 
     170my $SHA256_DIGEST_LEN = 43; 
     171my $SHA1_DIGEST_LEN   = 27; 
     172my $MD5_DIGEST_LEN    = 22; 
    169173 
    170174### logr constants 
     
    280284    ### Check for "cooked" Linux datalink layers (i.e. rp-pppoe) 
    281285    eval { 
    282         if (Net::Pcap::pcap_datalink_val_to_name( 
    283                 Net::Pcap::pcap_datalink($pcap_t)) eq 'LINUX_SLL') { 
    284             print STDERR "[+] Detected Linux Cooked Interface.\n" if $debug; 
    285             $PCAP_COOKED_INTF = 1; 
     286        if (not $PCAP_COOKED_INTF and $Net::Pcap::VERSION > 0.05) { 
     287            if (Net::Pcap::pcap_datalink_val_to_name( 
     288                    Net::Pcap::pcap_datalink($pcap_t)) eq 'LINUX_SLL') { 
     289                print STDERR "[+] Detected Linux Cooked Interface.\n" if $debug; 
     290                $PCAP_COOKED_INTF = 1; 
     291            } 
    286292        } 
    287293    }; 
     
    488494 
    489495            ### check for replay attacks 
    490             my ($md5sum_rv, $md5sum
     496            my ($digest_rv, $digest
    491497                = &check_replay_attack($decrypted_msg, $src_ip); 
    492             return if $md5sum_rv; 
     498            return if $digest_rv; 
    493499 
    494500            ### see if we have a syntactically valid message 
     
    524530 
    525531                if (&SPA_access($msg_hr, $src_ip, $decrypt_algo, 
    526                         $gpg_sign_id, $md5sum, $access_hr)) { 
     532                        $gpg_sign_id, $digest, $access_hr)) { 
    527533                    last SOURCE; 
    528534                } else { 
     
    531537            } elsif ($msg_hr->{'action_type'} == $SPA_COMMAND_MODE) { 
    532538                if (&SPA_cmd($msg_hr, $src_ip, $decrypt_algo, 
    533                         $gpg_sign_id, $md5sum, $access_hr)) { 
     539                        $gpg_sign_id, $digest, $access_hr)) { 
    534540                    last SOURCE; 
    535541                } else { 
     
    671677            $msg_hr->{'forward_info'}; 
    672678    } 
    673     printf STDERR "    %-16s %s\n", 'MD5 sum:', $msg_hr->{'md5sum'}; 
     679    printf STDERR "    %-16s %s\n", "$msg_hr->{'digest_str'} digest:", 
     680        $msg_hr->{'digest'}; 
    674681    return; 
    675682} 
     
    736743sub SPA_access() { 
    737744    my ($msg_hr, $src_ip, $decrypt_algo, $gpg_sign_id, 
    738         $md5sum, $access_hr) = @_; 
     745        $digest, $access_hr) = @_; 
    739746 
    740747    my $allow_src    = ''; 
     
    909916    } 
    910917 
    911     ### cache the MD5 sum 
    912     $md5_msg_store{$md5sum} = $src_ip; 
    913  
    914     ### write MD5 sum to disk 
    915     &diskwrite_md5_sum($md5sum, $src_ip) 
    916         if $config{'ENABLE_MD5_PERSISTENCE'} eq 'Y'; 
     918    ### cache the digest 
     919    $digest_store{$digest} = $src_ip; 
     920 
     921    ### write digest to disk 
     922    &diskwrite_digest($digest, $src_ip) 
     923        if $config{'ENABLE_DIGEST_PERSISTENCE'} eq 'Y'; 
    917924 
    918925    ### grant access through the firewall 
     
    924931sub SPA_cmd() { 
    925932    my ($msg_hr, $src_ip, $decrypt_algo, $gpg_sign_id, 
    926         $md5sum, $access_hr) = @_; 
     933        $digest, $access_hr) = @_; 
    927934 
    928935    unless ($access_hr->{'ENABLE_CMD_EXEC'}) { 
     
    983990    &logr('[+]', qq|executing command "$run_cmd" for $src_ip|, $SEND_MAIL); 
    984991 
    985     ### cache the MD5 sum 
    986     $md5_msg_store{$md5sum} = $src_ip; 
    987  
    988     ### write MD5 sum to disk 
    989     &diskwrite_md5_sum($md5sum, $src_ip) 
    990         if $config{'ENABLE_MD5_PERSISTENCE'} eq 'Y'; 
     992    ### cache the digest 
     993    $digest_store{$digest} = $src_ip; 
     994 
     995    ### write the digest to disk 
     996    &diskwrite_digest($digest, $src_ip) 
     997        if $config{'ENABLE_DIGEST_PERSISTENCE'} eq 'Y'; 
    991998 
    992999    ### execute the command 
     
    10001007 
    10011008    my $rv = 0; 
    1002  
    1003     my $md5sum = md5_base64($decrypted_data); 
    1004  
    1005     if (defined $md5sum and $md5sum =~ /\S/) { 
    1006         if (defined $md5_msg_store{$md5sum}) { 
    1007             ### Bad!  Send warning email and return. 
    1008             if ($md5_msg_store{$md5sum}) { 
    1009                 &logr('[-]', "attempted SPA packet replay from: $src_ip " . 
    1010                     "(original SPA src: $md5_msg_store{$md5sum}, MD5: $md5sum)", 
    1011                     $SEND_MAIL); 
    1012             } else { 
    1013                 &logr('[-]', "attempted SPA packet replay from: $src_ip " . 
    1014                     "(MD5: $md5sum)", $SEND_MAIL); 
    1015             } 
    1016             $md5sum = ''; 
    1017             $rv = 1; 
    1018  
    1019             ### see if we need to exit if the packet limit (set with -C on the 
    1020             ### command line) has been reached 
    1021             if ($packet_limit) { 
    1022                 $packet_ctr++; 
    1023                 if ($packet_ctr >= $packet_limit) { 
    1024                     &logr('[+]', "packet limit ($packet_limit) reached, exiting.", 
    1025                         $NO_MAIL); 
    1026                     exit 0; 
     1009    my @digests = (); 
     1010    my $disk_write_digest = ''; 
     1011 
     1012    if ($config{'DIGEST_TYPE'} eq 'ALL') { 
     1013        push @digests, sha256_base64($decrypted_data); 
     1014        push @digests, sha1_base64($decrypted_data); 
     1015        push @digests, md5_base64($decrypted_data); 
     1016    } else { 
     1017        if ($config{'DIGEST_TYPE'} =~ /SHA256/) { 
     1018            push @digests, sha256_base64($decrypted_data); 
     1019        } 
     1020        if ($config{'DIGEST_TYPE'} =~ /SHA1/) { 
     1021            push @digests, sha1_base64($decrypted_data); 
     1022        } 
     1023        if ($config{'DIGEST_TYPE'} =~ /MD5/) { 
     1024            push @digests, md5_base64($decrypted_data); 
     1025        } 
     1026    } 
     1027 
     1028    if (@digests) { 
     1029 
     1030        ### this prefers SHA256 because of the ordering above. 
     1031        $disk_write_digest = $digests[0]; 
     1032 
     1033        for my $digest (@digests) { 
     1034            if (defined $digest_store{$digest}) { 
     1035                ### Replay attack!  Send warning email and return. 
     1036                if ($digest_store{$digest}) { 
     1037                    &logr('[-]', "attempted SPA packet replay from: $src_ip " . 
     1038                        "(original SPA src: $digest_store{$digest}, " . 
     1039                        "digest: $digest)", 
     1040                        $SEND_MAIL); 
     1041                } else { 
     1042                    &logr('[-]', "attempted SPA packet replay from: $src_ip " . 
     1043                        "($digest: $digest)", $SEND_MAIL); 
    10271044                } 
     1045 
     1046                ### see if we need to exit if the packet limit (set with -C on the 
     1047                ### command line) has been reached 
     1048                if ($packet_limit) { 
     1049                    $packet_ctr++; 
     1050                    if ($packet_ctr >= $packet_limit) { 
     1051                        &logr('[+]', "packet limit ($packet_limit) reached, " . 
     1052                            "exiting.", $NO_MAIL); 
     1053                        exit 0; 
     1054                    } 
     1055                } 
     1056                $rv = 1; 
     1057                last; 
    10281058            } 
    10291059        } 
    10301060    } else { 
    1031         ### could not calculate the MD5 sum for some reason; don't 
     1061        ### could not calculate the digest for some reason; don't 
    10321062        ### trust the packet 
    1033         &logr('[-]', "could not calculate md5 sum for SPA " . 
    1034             "packet from: $src_ip", $SEND_MAIL); 
    1035         $md5sum = ''; 
     1063        &logr('[-]', "could not calculate digest " . 
     1064            "for SPA packet from: $src_ip", $SEND_MAIL); 
    10361065        $rv = 1; 
    10371066    } 
    1038     return $rv, $md5sum
     1067    return $rv, $disk_write_digest
    10391068} 
    10401069 
     
    11131142        'forward_info'    => '',  ### optional 
    11141143        'client_timeout'  => -1,  ### optional 
    1115         'md5sum'          => '', 
     1144        'digest'          => '', 
    11161145    ); 
    11171146 
    1118     ### the last field in the SPA packet is the MD5 sum, so see if it 
    1119     ### checks out first (this is the internal SPA sum, not the sum that 
     1147    ### the last field in the SPA packet is the digest, so see if it 
     1148    ### checks out first (this is the internal digest, not the digest that 
    11201149    ### guards against replay attacks). 
    1121     unless (&check_md5sum($msg, \%msg_hsh)) { 
     1150    unless (&check_digest($msg, \%msg_hsh)) { 
    11221151        print STDERR localtime() . " [-] Key mis-match or broken message ", 
    11231152            "checksum for SOURCE $access_hr->{'SOURCE'} ", 
     
    12571286        } 
    12581287 
    1259         print STDERR ":$msg_hsh{'md5sum'}\n"; 
     1288        print STDERR ":$msg_hsh{'digest'}\n"; 
    12601289    } 
    12611290    return 1, \%msg_hsh; 
     
    12911320} 
    12921321 
    1293 sub check_md5sum() { 
     1322sub check_digest() { 
    12941323    my ($msg_str, $hr) = @_; 
    12951324 
     1325    my $rv = 0; 
    12961326    if ($msg_str =~ /(.*):(\S+)/) { 
    12971327        my $msg = $1; 
    12981328        my $sum = $2; 
    1299  
    1300         if ($sum eq md5_base64($msg)) { 
    1301             $hr->{'md5sum'} = $sum; 
    1302             return 1; 
    1303         } 
    1304     } 
    1305     return 0; 
     1329        if (length($sum) == $SHA256_DIGEST_LEN) { 
     1330            if ($sum eq sha256_base64($msg)) { 
     1331                $hr->{'digest_str'} = 'SHA256'; 
     1332                $hr->{'digest'} = $sum; 
     1333                $rv = 1; 
     1334            } 
     1335        } elsif (length($sum) == $SHA1_DIGEST_LEN) { 
     1336            if ($sum eq sha1_base64($msg)) { 
     1337                $hr->{'digest_str'} = 'SHA1'; 
     1338                $hr->{'digest'} = $sum; 
     1339                $rv = 1; 
     1340            } 
     1341        } elsif (length($sum) == $MD5_DIGEST_LEN) { 
     1342            if ($sum eq md5_base64($msg)) { 
     1343                $hr->{'digest_str'} = 'MD5'; 
     1344                $hr->{'digest'} = $sum; 
     1345                $rv = 1; 
     1346            } 
     1347        } 
     1348    } 
     1349    return $rv; 
    13061350} 
    13071351 
     
    34393483        'Restart'        => \$restart, 
    34403484        'Status'         => \$status, 
     3485        'Linux-cooked-intf'  => \$PCAP_COOKED_INTF, 
    34413486        'Include-all-config' => \$include_all_config_data, 
    34423487        'Test-mode'      => \$test_mode, 
     
    38063851 
    38073852    if ($config{'AUTH_MODE'} =~ /PCAP/) { 
    3808         &import_md5_sums() if $config{'ENABLE_MD5_PERSISTENCE'} eq 'Y'; 
     3853        &import_digests() if $config{'ENABLE_DIGEST_PERSISTENCE'} eq 'Y'; 
    38093854    } 
    38103855 
     
    42574302} 
    42584303 
    4259 sub diskwrite_md5_sum() { 
    4260     my ($md5_sum, $src_ip) = @_; 
    4261  
    4262     open F, ">> $config{'MD5_FILE'}" or die "[*] Could not open ", 
    4263         "$config{'MD5_FILE'}: $!"; 
    4264     if ($config{'ENABLE_MD5_INCLUDE_SRC'} eq 'Y') { 
    4265         print F "$src_ip $md5_sum [" . localtime() . "]\n"; 
     4304sub diskwrite_digest() { 
     4305    my ($digest, $src_ip) = @_; 
     4306 
     4307    print STDERR localtime() . " [+] Calculated digest: $digest for SPA ", 
     4308        "packet from: $src_ip\n" if $debug; 
     4309    open F, ">> $config{'DIGEST_FILE'}" or die "[*] Could not open ", 
     4310        "$config{'DIGEST_FILE'}: $!"; 
     4311    if ($config{'ENABLE_DIGEST_INCLUDE_SRC'} eq 'Y') { 
     4312        print F "$src_ip $digest [" . localtime() . "]\n"; 
    42664313    } else { 
    4267         print F $md5_sum, "\n"; 
     4314        print F $digest, "\n"; 
    42684315    } 
    42694316    close F; 
     
    42714318} 
    42724319 
    4273 sub import_md5_sums() { 
    4274     return unless -e $config{'MD5_FILE'}; 
    4275     open F, "< $config{'MD5_FILE'}" or die "[*] Could not open ", 
    4276         "$config{'MD5_FILE'}: $!"; 
    4277     while (<F>) { 
    4278         if (/^\s*($ip_re)\s+(\S+)\s+\[.{15,25}\s\d{4}\]/) { 
    4279             ### 127.0.0.1 36wD3+KXHLuqqp18D0qODA [Wed Nov 28 09:13:31 2007] 
    4280             ### Date tracking was added in 1.8.4 
    4281             $md5_msg_store{$2} = $1; 
    4282         } elsif (/^\s*($ip_re)\s+(\S+)$/) {  ### 127.0.0.1 36wD3+KXHLuqqp18D0qODA 
    4283             ### version 1.8.3 includes the source IP address for each 
    4284             ### SPA packet (unless ENABLE_MD5_INCLUDE_SRC is disabled) 
    4285             $md5_msg_store{$2} = $1; 
    4286         } elsif (/^\s*(\S+)$/) { 
    4287             $md5_msg_store{$1} = ''; 
     4320sub import_digests() { 
     4321 
     4322    %digest_store = (); 
     4323 
     4324    for my $digest_file ($config{'DIGEST_FILE'}, 
     4325            "$config{'FWKNOP_DIR'}/md5sums") { 
     4326        next unless -e $digest_file; 
     4327 
     4328        open F, "< $digest_file" or die "[*] Could not open ", 
     4329            "$digest_file: $!"; 
     4330        while (<F>) { 
     4331            if (/^\s*($ip_re)\s+(\S+)\s+\[.{15,25}\s\d{4}\]/) { 
     4332                ### 127.0.0.1 36wD3+KXHLuqqp18D0qODA [Wed Nov 28 09:13:31 2007] 
     4333                ### Date tracking was added in 1.8.4 
     4334                $digest_store{$2} = $1; 
     4335            } elsif (/^\s*($ip_re)\s+(\S+)$/) {  ### 127.0.0.1 36wD3+KXHLuqqp18D0qODA 
     4336                ### version 1.8.3 includes the source IP address for each 
     4337                ### SPA packet (unless ENABLE_DIGEST_INCLUDE_SRC is disabled) 
     4338                $digest_store{$2} = $1; 
     4339            } elsif (/^\s*(\S+)$/) { 
     4340                $digest_store{$1} = ''; 
     4341            } 
    42884342        } 
    42894343    } 
    42904344    close F; 
    42914345 
    4292     &logr('[+]', "imported previous md5 sums from disk " . 
    4293         "cache: $config{'MD5_FILE'}", $NO_MAIL); 
     4346    &logr('[+]', "imported previous tracking digests from disk " . 
     4347        "cache: $config{'DIGEST_FILE'}", $NO_MAIL); 
    42944348    return; 
    42954349} 
     
    43804434    } 
    43814435 
     4436    my $found_digest = 0; 
     4437    if ($config{'DIGEST_TYPE'} eq 'ALL') { 
     4438        $found_digest = 1; 
     4439    } else { 
     4440        if ($config{'DIGEST_TYPE'} =~ /SHA256/) { 
     4441            $found_digest = 1; 
     4442        } 
     4443        if ($config{'DIGEST_TYPE'} =~ /SHA1/) { 
     4444            $found_digest = 1; 
     4445        } 
     4446        if ($config{'DIGEST_TYPE'} =~ /MD5/) { 
     4447            $found_digest = 1; 
     4448        } 
     4449    } 
     4450    unless ($found_digest) { 
     4451        die "[*] DIGEST_TYPE must be one of ALL, SHA256, SHA1, or MD5"; 
     4452    } 
     4453 
     4454    ### an old fwknop client can send an SPA packet with an 
     4455    ### MD5 sum 
     4456    require Digest::MD5; 
     4457    require Digest::SHA; 
     4458    Digest::MD5->import(qw(md5_base64)); 
     4459    Digest::SHA->import(qw(sha1_base64 sha256_base64)); 
     4460 
    43824461    return; 
    43834462} 
     
    44624541            IPT_INPUT_ACCESS IPT_FORWARD_ACCESS AUTH_MODE PCAP_CMD_TIMEOUT 
    44634542            ENABLE_PCAP_PROMISC PCAP_FILTER KNOPTM_IP_TIMEOUT_SOCK 
    4464             ENABLE_MD5_PERSISTENCE MD5_FILE FLUSH_IPT_AT_INIT PCAP_INTF 
     4543            ENABLE_DIGEST_PERSISTENCE DIGEST_FILE FLUSH_IPT_AT_INIT PCAP_INTF 
    44654544            FWKNOP_ERR_DIR FWKNOP_RUN_DIR FWKNOP_LIB_DIR ENABLE_TCP_SERVER 
    44664545            TCPSERV_PORT TCPSERV_PID_FILE IPT_OUTPUT_FILE IPT_ERROR_FILE 
     
    44684547            KNOPTM_IPT_OUTPUT_FILE KNOPTM_IPT_ERROR_FILE FIREWALL_TYPE 
    44694548            IPFW_RULE_NUM SYSLOG_IDENTITY SYSLOG_FACILITY SYSLOG_PRIORITY 
    4470             MIN_GNUPG_MSG_SIZE ENABLE_MD5_INCLUDE_SRC ENABLE_VOLUNTARY_EXITS 
    4471             EXIT_INTERVAL KNOPTM_SYSLOG_IDENTITY KNOPTM_SYSLOG_FACILITY 
    4472             KNOPTM_SYSLOG_PRIORITY ENABLE_IPT_FORWARDING ENABLE_IPT_OUTPUT 
    4473             IPT_OUTPUT_ACCESS IPT_DNAT_ACCESS) { 
     4549            MIN_GNUPG_MSG_SIZE ENABLE_DIGEST_INCLUDE_SRC 
     4550            ENABLE_VOLUNTARY_EXITS EXIT_INTERVAL KNOPTM_SYSLOG_IDENTITY 
     4551            KNOPTM_SYSLOG_FACILITY KNOPTM_SYSLOG_PRIORITY 
     4552            ENABLE_IPT_FORWARDING ENABLE_IPT_OUTPUT IPT_OUTPUT_ACCESS 
     4553            IPT_DNAT_ACCESS) { 
    44744554 
    44754555        die "[*] Required variable $var is not defined in $config_file" 
     
    45224602                                 key information) when running in --debug 
    45234603                                 and --verbose mode. 
     4604    -L, --Linux-cooked-intf    - Force fwknopd to assume that the sniffing 
     4605                                 interface is a "Linux Cooked" interface. 
     4606                                 This is useful when fwknopd uses a version 
     4607                                 of Net::Pcap that does not implement the 
     4608                                 pcap_datalink_val_to_name() function or 
     4609                                 have the pcap_datali.al file. 
    45244610    -d, --debug                - Run fwknopd in debugging mode. 
    45254611    -v, --verbose              - Verbose mode. 
  • fwknop/trunk/install.pl

    r988 r1009  
    149149        'mod-dir'             => 'Net-Ping-External' 
    150150    }, 
     151    {   'module'              => 'Digest::SHA', 
     152        'force-install'       => 0, 
     153        'client-mode-install' => 1, 
     154        'mod-dir'             => 'Digest-SHA' 
     155    }, 
    151156    {   'module'              => 'Crypt::Rijndael', 
    152157