Changeset 1009
- Timestamp:
- 02/24/08 12:50:36 (9 months ago)
- Files:
-
- fwknop/trunk/ChangeLog (modified) (2 diffs)
- fwknop/trunk/Digest-SHA (added)
- fwknop/trunk/Digest-SHA/Changes (added)
- fwknop/trunk/Digest-SHA/MANIFEST (added)
- fwknop/trunk/Digest-SHA/META.yml (added)
- fwknop/trunk/Digest-SHA/Makefile.PL (added)
- fwknop/trunk/Digest-SHA/README (added)
- fwknop/trunk/Digest-SHA/SHA.pm (added)
- fwknop/trunk/Digest-SHA/SHA.xs (added)
- fwknop/trunk/Digest-SHA/VERSION (added)
- fwknop/trunk/Digest-SHA/examples (added)
- fwknop/trunk/Digest-SHA/examples/dups (added)
- fwknop/trunk/Digest-SHA/shasum (added)
- fwknop/trunk/Digest-SHA/src (added)
- fwknop/trunk/Digest-SHA/src/hmac.c (added)
- fwknop/trunk/Digest-SHA/src/hmac.h (added)
- fwknop/trunk/Digest-SHA/src/hmacxtra.c (added)
- fwknop/trunk/Digest-SHA/src/sha.c (added)
- fwknop/trunk/Digest-SHA/src/sha.h (added)
- fwknop/trunk/Digest-SHA/src/sha64bit.c (added)
- fwknop/trunk/Digest-SHA/src/sha64bit.h (added)
- fwknop/trunk/Digest-SHA/src/shaxtra.c (added)
- fwknop/trunk/Digest-SHA/t (added)
- fwknop/trunk/Digest-SHA/t/allfcns.t (added)
- fwknop/trunk/Digest-SHA/t/base64.t (added)
- fwknop/trunk/Digest-SHA/t/bitbuf.t (added)
- fwknop/trunk/Digest-SHA/t/dumpload.t (added)
- fwknop/trunk/Digest-SHA/t/fips198.t (added)
- fwknop/trunk/Digest-SHA/t/gg.t (added)
- fwknop/trunk/Digest-SHA/t/gglong.t (added)
- fwknop/trunk/Digest-SHA/t/hmacsha.t (added)
- fwknop/trunk/Digest-SHA/t/ireland.t (added)
- fwknop/trunk/Digest-SHA/t/methods.t (added)
- fwknop/trunk/Digest-SHA/t/nistbit.t (added)
- fwknop/trunk/Digest-SHA/t/nistbyte.t (added)
- fwknop/trunk/Digest-SHA/t/pod.t (added)
- fwknop/trunk/Digest-SHA/t/podcover.t (added)
- fwknop/trunk/Digest-SHA/t/rfc2202.t (added)
- fwknop/trunk/Digest-SHA/t/sha1.t (added)
- fwknop/trunk/Digest-SHA/t/sha224.t (added)
- fwknop/trunk/Digest-SHA/t/sha256.t (added)
- fwknop/trunk/Digest-SHA/t/sha384.t (added)
- fwknop/trunk/Digest-SHA/t/sha512.t (added)
- fwknop/trunk/Digest-SHA/t/woodbury.t (added)
- fwknop/trunk/Digest-SHA/typemap (added)
- fwknop/trunk/fwknop (modified) (14 diffs)
- fwknop/trunk/fwknop.8 (modified) (4 diffs)
- fwknop/trunk/fwknop.conf (modified) (2 diffs)
- fwknop/trunk/fwknopd (modified) (26 diffs)
- fwknop/trunk/install.pl (modified) (5 diffs)
- fwknop/trunk/test/conf/default_fwknop.conf (modified) (2 diffs)
- fwknop/trunk/test/conf/forward_chain_fwknop.conf (modified) (2 diffs)
- fwknop/trunk/test/conf/md5_fwknop.conf (added)
- fwknop/trunk/test/conf/no_promisc_fwknop.conf (modified) (2 diffs)
- fwknop/trunk/test/conf/output_chain_fwknop.conf (modified) (2 diffs)
- fwknop/trunk/test/conf/pcap_file_fwknop.conf (modified) (2 diffs)
- fwknop/trunk/test/conf/sha1_fwknop.conf (added)
- fwknop/trunk/test/conf/sha256_fwknop.conf (added)
- fwknop/trunk/test/conf/spa_aging_fwknop.conf (modified) (2 diffs)
- fwknop/trunk/test/fwknop_test.pl (modified) (34 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
fwknop/trunk/ChangeLog
r1000 r1009 3 3 - (Grant Ferley) Submitted patch to handle Linux "cooked" interfaces for 4 4 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. 11 21 - Added full packet hex dumps (including packet headers) to fwknopd in 12 22 --debug --verbose mode. This is to help diagnose packet sniffing issues … … 16 26 local output/ directory in several of the test config files in the 17 27 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. 18 31 19 32 fwknop-1.9.1 (01/26/2008): fwknop/trunk/fwknop
r1006 r1009 42 42 use Net::IPv4Addr qw(ipv4_in_network); 43 43 use Net::Ping::External qw(ping); 44 use Digest::MD5 'md5_base64';45 44 use IO::Socket; 46 45 use IO::Handle; … … 73 72 my $server_proto = ''; 74 73 my $run_last_host = ''; 74 my $total_digest = ''; 75 75 my $show_last_host_cmd = ''; 76 76 my $show_last_cmd = 0; 77 my $use_md5 = 0; 78 my $use_sha1 = 0; 79 my $use_sha256 = 0; 77 80 my $gpg_home_dir = ''; 78 81 my $gpg_recipient = ''; … … 131 134 my $cmdl_fw_timeout = 0; 132 135 136 ### Digest types and command argument flags 137 my $MD5_DIGEST = 1; 138 my $SHA1_DIGEST = 2; 139 my $SHA256_DIGEST = 3; 140 my $digest_type = $SHA256_DIGEST; ### default 141 my $cmdl_digest_alg = ''; 142 133 143 ### default to root (client must run as root in this mode) 134 144 my $spoof_username = ''; … … 145 155 ### there is a constant "RIJNDAEL_KEYSIZE" in the Crypt::Rijndael sources, but 146 156 ### it is not used; a 16 byte key size is fine. 147 my $enc_keysize = 16;157 my $enc_keysize = 16; 148 158 149 159 my $enc_shared_secret = ''; … … 208 218 die "[*] Server auth method not supported in FORWARD access mode.\n" 209 219 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; 210 225 211 226 ### this is only necessary for older versions of perl (newer versions … … 374 389 375 390 sub pcap_build_enc_msg() { 376 377 my $msg = '';378 my $server_auth = ''; ### contains stuff after the md5 sum379 my $user = '';380 my $random_num = '';381 my $md5sum = '';382 my $timestamp = time();383 391 384 392 ### message format (all fields are separated by ":" characters … … 393 401 # 2 => forward access mode / IP,proto,port / internalIP,externalNATPort 394 402 # (optional) server_auth (post 0.9.2 release) 395 # message md5 sum 403 # message digest (SHA256 / SHA1 / MD5 ) 404 405 my $msg = ''; 396 406 397 407 unless ($quiet) { … … 429 439 $msg .= &SPA_client_timeout(); 430 440 431 ### append M D5 sum441 ### append Message Digest 432 442 $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 } 437 449 438 450 if ($gpg_signing_key or $gpg_default_key) { … … 532 544 533 545 sub SPA_client_timeout() { 534 return unless $cmdl_fw_timeout;546 return '' unless $cmdl_fw_timeout; 535 547 return ':' . $cmdl_fw_timeout; 536 548 } … … 559 571 } 560 572 561 sub SPA_ md5sum() {573 sub SPA_digest() { 562 574 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; 566 606 } 567 607 … … 1310 1350 'Spoof-proto=s' => \$spoof_proto, 1311 1351 'Save-packet' => \$save_packet_mode, 1312 'Save-packet-file=s' => \$save_packet_file,1352 'Save-packet-file=s' => \$save_packet_file, 1313 1353 'Save-dst' => \$save_destination, 1314 1354 'user-rc=s' => \$user_rc_file, … … 1319 1359 'gpg-default-key' => \$gpg_default_key, 1320 1360 '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, 1326 1366 'TCP-sock' => \$spa_established_tcp, 1327 1367 'Access=s' => \$access_str, 1328 1368 'fw-timeout=i' => \$cmdl_fw_timeout, 1329 1369 'allow-IP=s' => \$enc_allow_ip, 1370 'digest-alg=s' => \$cmdl_digest_alg, 1330 1371 'source-IP' => \$enc_source_ip, 1331 1372 'rotate-proto' => \$enc_rotate_proto, … … 1452 1493 unless ($forward_access_str =~ /^$ip_re,\d+$/) { 1453 1494 die "[*] Must specify '<internal_IP>,<external_port>'"; 1495 } 1496 return; 1497 } 1498 1499 sub 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"; 1454 1508 } 1455 1509 return; … … 1505 1559 http://www.whatismyip.org/ website. This is 1506 1560 useful if fwknop is deployed on an internal 1507 system behind a NAT device.1508 1561 -w, --whatismyip - (Synonym for --Resolve-external-IP option). 1509 1562 --URL <external IP URL> - Specify a URL from which to determine the fwknop/trunk/fwknop.8
r807 r1009 57 57 if command mode => command to execute 58 58 else access mode => IP,proto,port 59 MD5 sum59 message digest (SHA256 / SHA1 / MD5) 60 60 .PP 61 61 Each of the above fields are separated by a ":" character due to the 62 62 variable 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 64 in all versions of 65 .B fwknop 66 greater than 1.9.1) allows the server to check message integrity after decryption, 67 and the 16 bytes of random data ensures (with high probability) that no two messages 68 are identical. This ensures that replay attacks are not possible against fwknop. 69 For each packet coming from an 67 70 .B fwknop 68 71 client, the 69 72 .B fwknopd 70 server caches the MD5 sumcalculated over the entire packet and compares against71 previous MD5 sums in order to detect attempted replay attacks. The MD5 sum73 server caches the SHA256 digest calculated over the entire packet and compares against 74 previous packet digests in order to detect attempted replay attacks. The digest 72 75 cache file is located at 73 .I /var/log/fwknop/ md5sums76 .I /var/log/fwknop/digest.cache 74 77 and is not rotated so that the detection of duplicate SPA messages is maximized. 75 78 Both syslog and email alerts are generated if a replay is detected (although … … 455 458 client when creating a 'access mode' SPA packet: 456 459 .PP 457 Random data: 7457916043504181458 Username: user_name459 Timestamp: 1185272057460 Version: 1.8.1461 Action:1 (access mode)462 Access: NNN.NNN.NNN.NNN,tcp/22463 MD5 sum: 35rdd5f8tZTavUy0MuEdqw460 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: gngquSL8AuM7r27XsR4qPmJhuBo9pG2PYwII06AaJHw 464 467 .PP 465 468 … … 511 514 client when creating a 'command mode' SPA packet: 512 515 .PP 513 Random data: 1387393943305159514 Username: user_name515 Timestamp: 1185349703516 Version: 1.8.1517 Action:0 (command mode)518 Cmd: echo "The commands sent - minus quote charaters around the command" & sleep 10; echo "The End"519 MD5 sum: fJtQkAcK1A1XMRAHEG1UcA516 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 520 523 .PP 521 524 Instruct the fwknop server running at 10.0.0.123 to send a single ICMP … … 608 611 Michael Rash <mbr@cipherdyne.org> 609 612 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 614 Many people who are active in the open source community have contributed to fwknop. 615 See the 616 .B CREDITS 617 file in the fwknop sources, or visit 618 .B http://www.cipherdyne.org/fwknop/docs/contributors.html 619 to view the online list of contributors. 620 621 The phrase "Single Packet Authorization" was coined by MadHat and Simple 622 Nomad at the BlackHat Briefings of 2005 (see: http://www.nmrc.org/). 623 The term "port knocking" was coined by Martin Krzywinski (see: 624 http://www.portknocking.org/). The original p0f passive OS fingerprinter was 625 written by Michal Zalewski, and is available here: 617 626 .B http://lcamtuf.coredump.cx/p0f.shtml 618 627 fwknop/trunk/fwknop.conf
r880 r1009 63 63 MAX_SPA_PACKET_AGE 120; 64 64 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. 67 ENABLE_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". 72 DIGEST_TYPE ALL; 68 73 69 74 ### This variable controls whether fwknopd includes the source IP of each SPA 70 ### packet in the MD5store. If a replayed SPA message is detected, then75 ### packet in the DIGEST store. If a replayed SPA message is detected, then 71 76 ### having this information can provide information about which networks have 72 77 ### people sniffing your SPA packets. 73 ENABLE_ MD5_INCLUDE_SRCY;78 ENABLE_DIGEST_INCLUDE_SRC Y; 74 79 75 80 ### Allow SPA clients to request access to services through an iptables … … 225 230 ACCESS_CONF $FWKNOP_CONF_DIR/access.conf; 226 231 P0F_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 232 DIGEST_FILE $FWKNOP_DIR/digest.cache; 229 233 FWKNOP_PID_FILE $FWKNOP_RUN_DIR/fwknopd.pid; 230 234 FWKNOP_CMDLINE_FILE $FWKNOP_RUN_DIR/fwknopd.cmd; fwknop/trunk/fwknopd
r1006 r1009 51 51 use NetPacket::ICMP; 52 52 use NetPacket::Ethernet; 53 use Digest::MD5 'md5_base64';54 53 use IO::Socket; 55 54 use IO::Handle; … … 75 74 my %pid_files = (); 76 75 my %ip_sequences = (); 77 my % md5_msg_store = ();76 my %digest_store = (); 78 77 my %ipt_input = (); 79 78 my %ipt_forward = (); … … 117 116 ### ACCESS message: 118 117 ### random data :user : client_timestamp : client_version : \ 119 ### type (1) : access_request : MD5118 ### type (1) : access_request : digest 120 119 my $SPA_ACCESS_MODE = 1; ### default 121 120 122 121 ### COMMAND message: 123 122 ### random data :user : client_timestamp : client_version : \ 124 ### type (0) : command : MD5123 ### type (0) : command : digest 125 124 my $SPA_COMMAND_MODE = 0; 126 125 127 126 ### FORWARD ACCESS message: 128 127 ### random data :user : client_timestamp : client_version : \ 129 ### type (2) : access_request : NAT_info : MD5128 ### type (2) : access_request : NAT_info : digest 130 129 my $SPA_FORWARD_ACCESS_MODE = 2; 131 130 132 131 ### ACCESS message with client-defined firewall timeout: 133 132 ### random data :user : client_timestamp : client_version : \ 134 ### type (3) : access_request : timeout : MD5133 ### type (3) : access_request : timeout : digest 135 134 my $SPA_CLIENT_TIMEOUT_ACCESS_MODE = 3; 136 135 137 136 ### FORWARD ACCESS message with client-defined firewall timeout: 138 137 ### random data :user : client_timestamp : client_version : \ 139 ### type (4) : access_request : NAT_info : timeout : MD5138 ### type (4) : access_request : NAT_info : timeout : digest 140 139 my $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE = 4; 141 140 … … 154 153 ### there is a constant "RIJNDAEL_KEYSIZE" in the Crypt::Rijndael sources, but 155 154 ### it is not used; a 16 byte key size is fine. 156 my $enc_keysize = 16;155 my $enc_keysize = 16; 157 156 158 157 my $ALG_RIJNDAEL = 1; … … 167 166 ### Bool to detect Linux "Cooked" datalink layers 168 167 my $PCAP_COOKED_INTF = 0; 168 169 ### digest constants 170 my $SHA256_DIGEST_LEN = 43; 171 my $SHA1_DIGEST_LEN = 27; 172 my $MD5_DIGEST_LEN = 22; 169 173 170 174 ### logr constants … … 280 284 ### Check for "cooked" Linux datalink layers (i.e. rp-pppoe) 281 285 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 } 286 292 } 287 293 }; … … 488 494 489 495 ### check for replay attacks 490 my ($ md5sum_rv, $md5sum)496 my ($digest_rv, $digest) 491 497 = &check_replay_attack($decrypted_msg, $src_ip); 492 return if $ md5sum_rv;498 return if $digest_rv; 493 499 494 500 ### see if we have a syntactically valid message … … 524 530 525 531 if (&SPA_access($msg_hr, $src_ip, $decrypt_algo, 526 $gpg_sign_id, $ md5sum, $access_hr)) {532 $gpg_sign_id, $digest, $access_hr)) { 527 533 last SOURCE; 528 534 } else { … … 531 537 } elsif ($msg_hr->{'action_type'} == $SPA_COMMAND_MODE) { 532 538 if (&SPA_cmd($msg_hr, $src_ip, $decrypt_algo, 533 $gpg_sign_id, $ md5sum, $access_hr)) {539 $gpg_sign_id, $digest, $access_hr)) { 534 540 last SOURCE; 535 541 } else { … … 671 677 $msg_hr->{'forward_info'}; 672 678 } 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'}; 674 681 return; 675 682 } … … 736 743 sub SPA_access() { 737 744 my ($msg_hr, $src_ip, $decrypt_algo, $gpg_sign_id, 738 $ md5sum, $access_hr) = @_;745 $digest, $access_hr) = @_; 739 746 740 747 my $allow_src = ''; … … 909 916 } 910 917 911 ### cache the MD5 sum912 $ md5_msg_store{$md5sum} = $src_ip;913 914 ### write MD5 sumto disk915 &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'; 917 924 918 925 ### grant access through the firewall … … 924 931 sub SPA_cmd() { 925 932 my ($msg_hr, $src_ip, $decrypt_algo, $gpg_sign_id, 926 $ md5sum, $access_hr) = @_;933 $digest, $access_hr) = @_; 927 934 928 935 unless ($access_hr->{'ENABLE_CMD_EXEC'}) { … … 983 990 &logr('[+]', qq|executing command "$run_cmd" for $src_ip|, $SEND_MAIL); 984 991 985 ### cache the MD5 sum986 $ md5_msg_store{$md5sum} = $src_ip;987 988 ### write MD5 sumto disk989 &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'; 991 998 992 999 ### execute the command … … 1000 1007 1001 1008 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); 1027 1044 } 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; 1028 1058 } 1029 1059 } 1030 1060 } else { 1031 ### could not calculate the MD5 sumfor some reason; don't1061 ### could not calculate the digest for some reason; don't 1032 1062 ### 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); 1036 1065 $rv = 1; 1037 1066 } 1038 return $rv, $ md5sum;1067 return $rv, $disk_write_digest; 1039 1068 } 1040 1069 … … 1113 1142 'forward_info' => '', ### optional 1114 1143 'client_timeout' => -1, ### optional 1115 ' md5sum' => '',1144 'digest' => '', 1116 1145 ); 1117 1146 1118 ### the last field in the SPA packet is the MD5 sum, so see if it1119 ### checks out first (this is the internal SPA sum, not the sumthat1147 ### 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 1120 1149 ### guards against replay attacks). 1121 unless (&check_ md5sum($msg, \%msg_hsh)) {1150 unless (&check_digest($msg, \%msg_hsh)) { 1122 1151 print STDERR localtime() . " [-] Key mis-match or broken message ", 1123 1152 "checksum for SOURCE $access_hr->{'SOURCE'} ", … … 1257 1286 } 1258 1287 1259 print STDERR ":$msg_hsh{' md5sum'}\n";1288 print STDERR ":$msg_hsh{'digest'}\n"; 1260 1289 } 1261 1290 return 1, \%msg_hsh; … … 1291 1320 } 1292 1321 1293 sub check_ md5sum() {1322 sub check_digest() { 1294 1323 my ($msg_str, $hr) = @_; 1295 1324 1325 my $rv = 0; 1296 1326 if ($msg_str =~ /(.*):(\S+)/) { 1297 1327 my $msg = $1; 1298 1328 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; 1306 1350 } 1307 1351 … … 3439 3483 'Restart' => \$restart, 3440 3484 'Status' => \$status, 3485 'Linux-cooked-intf' => \$PCAP_COOKED_INTF, 3441 3486 'Include-all-config' => \$include_all_config_data, 3442 3487 'Test-mode' => \$test_mode, … … 3806 3851 3807 3852 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'; 3809 3854 } 3810 3855 … … 4257 4302 } 4258 4303 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"; 4304 sub 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"; 4266 4313 } else { 4267 print F $ md5_sum, "\n";4314 print F $digest, "\n"; 4268 4315 } 4269 4316 close F; … … 4271 4318 } 4272 4319 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} = ''; 4320 sub 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 } 4288 4342 } 4289 4343 } 4290 4344 close F; 4291 4345 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); 4294 4348 return; 4295 4349 } … … 4380 4434 } 4381 4435 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 4382 4461 return; 4383 4462 } … … 4462 4541 IPT_INPUT_ACCESS IPT_FORWARD_ACCESS AUTH_MODE PCAP_CMD_TIMEOUT 4463 4542 ENABLE_PCAP_PROMISC PCAP_FILTER KNOPTM_IP_TIMEOUT_SOCK 4464 ENABLE_ MD5_PERSISTENCE MD5_FILE FLUSH_IPT_AT_INIT PCAP_INTF4543 ENABLE_DIGEST_PERSISTENCE DIGEST_FILE FLUSH_IPT_AT_INIT PCAP_INTF 4465 4544 FWKNOP_ERR_DIR FWKNOP_RUN_DIR FWKNOP_LIB_DIR ENABLE_TCP_SERVER 4466 4545 TCPSERV_PORT TCPSERV_PID_FILE IPT_OUTPUT_FILE IPT_ERROR_FILE … … 4468 4547 KNOPTM_IPT_OUTPUT_FILE KNOPTM_IPT_ERROR_FILE FIREWALL_TYPE 4469 4548 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) { 4474 4554 4475 4555 die "[*] Required variable $var is not defined in $config_file" … … 4522 4602 key information) when running in --debug 4523 4603 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. 4524 4610 -d, --debug - Run fwknopd in debugging mode. 4525 4611 -v, --verbose - Verbose mode. fwknop/trunk/install.pl
r988 r1009 149 149 'mod-dir' => 'Net-Ping-External' 150 150 }, 151 { 'module' => 'Digest::SHA', 152 'force-install' => 0, 153 'client-mode-install' => 1, 154 'mod-dir' => 'Digest-SHA' 155 }, 151 156 { 'module' => 'Crypt::Rijndael', 152 157  
