7 use Getopt::Long 'GetOptions';
10 #==================== config =====================
11 my $logfile = 'test.log';
12 my $local_key_file = 'local_spa.key';
13 my $output_dir = 'output';
14 my $lib_dir = '../lib/.libs';
15 my $conf_dir = 'conf';
17 my $configure_path = '../configure';
18 my $cmd_out_tmp = 'cmd.out';
19 my $server_cmd_tmp = 'server_cmd.out';
20 my $gpg_client_home_dir = "$conf_dir/client-gpg";
21 my $gpg_client_home_dir_no_pw = "$conf_dir/client-gpg-no-pw";
24 'nat' => "$conf_dir/nat_fwknopd.conf",
25 'def' => "$conf_dir/default_fwknopd.conf",
26 'def_access' => "$conf_dir/default_access.conf",
27 'exp_access' => "$conf_dir/expired_stanza_access.conf",
28 'future_exp_access' => "$conf_dir/future_expired_stanza_access.conf",
29 'exp_epoch_access' => "$conf_dir/expired_epoch_stanza_access.conf",
30 'invalid_exp_access' => "$conf_dir/invalid_expire_access.conf",
31 'force_nat_access' => "$conf_dir/force_nat_access.conf",
32 'local_nat' => "$conf_dir/local_nat_fwknopd.conf",
33 'ipfw_active_expire' => "$conf_dir/ipfw_active_expire_equal_fwknopd.conf",
34 'dual_key_access' => "$conf_dir/dual_key_usage_access.conf",
35 'gpg_access' => "$conf_dir/gpg_access.conf",
36 'gpg_no_pw_access' => "$conf_dir/gpg_no_pw_access.conf",
37 'open_ports_access' => "$conf_dir/open_ports_access.conf",
38 'multi_gpg_access' => "$conf_dir/multi_gpg_access.conf",
39 'multi_stanza_access' => "$conf_dir/multi_stanzas_access.conf",
40 'broken_keys_access' => "$conf_dir/multi_stanzas_with_broken_keys.conf",
41 'open_ports_mismatch' => "$conf_dir/mismatch_open_ports_access.conf",
42 'require_user_access' => "$conf_dir/require_user_access.conf",
43 'user_mismatch_access' => "$conf_dir/mismatch_user_access.conf",
44 'require_src_access' => "$conf_dir/require_src_access.conf",
45 'no_src_match' => "$conf_dir/no_source_match_access.conf",
46 'no_subnet_match' => "$conf_dir/no_subnet_source_match_access.conf",
47 'no_multi_src' => "$conf_dir/no_multi_source_match_access.conf",
48 'multi_src_access' => "$conf_dir/multi_source_match_access.conf",
49 'ip_src_match' => "$conf_dir/ip_source_match_access.conf",
50 'subnet_src_match' => "$conf_dir/ip_source_match_access.conf",
51 'disable_aging' => "$conf_dir/disable_aging_fwknopd.conf",
52 'fuzz_source' => "$conf_dir/fuzzing_source_access.conf",
53 'fuzz_open_ports' => "$conf_dir/fuzzing_open_ports_access.conf",
54 'fuzz_restrict_ports' => "$conf_dir/fuzzing_restrict_ports_access.conf",
57 my $default_digest_file = "$run_dir/digest.cache";
58 my $default_pid_file = "$run_dir/fwknopd.pid";
60 my $fwknopCmd = '../client/.libs/fwknop';
61 my $fwknopdCmd = '../server/.libs/fwknopd';
62 my $libfko_bin = "$lib_dir/libfko.so"; ### this is usually a link
63 my $valgrindCmd = '/usr/bin/valgrind';
65 my $gpg_server_key = '361BBAD4';
66 my $gpg_client_key = '6A3FAD56';
68 my $loopback_ip = '127.0.0.1';
69 my $fake_ip = '127.0.0.2';
70 my $internal_nat_host = '192.168.1.2';
71 my $force_nat_host = '192.168.1.123';
72 my $default_spa_port = 62201;
73 my $non_std_spa_port = 12345;
75 my $spoof_user = 'testuser';
76 #================== end config ===================
81 my $test_include = '';
82 my @tests_to_include = ();
83 my $test_exclude = '';
84 my @tests_to_exclude = ();
85 my %valgrind_flagged_fcns = ();
86 my %valgrind_flagged_fcns_unique = ();
90 my $loopback_intf = '';
91 my $anonymize_results = 0;
92 my $current_test_file = "$output_dir/init";
93 my $tarfile = 'test_fwknop.tar.gz';
94 my $server_test_file = '';
96 my $valgrind_str = '';
97 my $enable_client_ip_resolve_test = 0;
98 my $saved_last_results = 0;
100 my $enable_recompilation_warnings_check = 0;
101 my $enable_make_distcheck = 0;
108 my $USE_PREDEF_PKTS = 1;
112 my $NEW_RULE_REQUIRED = 1;
113 my $REQUIRE_NO_NEW_RULE = 2;
114 my $NEW_RULE_REMOVED = 1;
115 my $REQUIRE_NO_NEW_REMOVED = 2;
123 my $ip_re = qr|(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}|; ### IPv4
127 exit 1 unless GetOptions(
128 'Anonymize-results' => \$anonymize_results,
129 'fwknop-path=s' => \$fwknopCmd,
130 'fwknopd-path=s' => \$fwknopdCmd,
131 'libfko-path=s' => \$libfko_bin,
132 'loopback-intf=s' => \$loopback_intf,
133 'test-include=s' => \$test_include,
134 'include=s' => \$test_include, ### synonym
135 'test-exclude=s' => \$test_exclude,
136 'exclude=s' => \$test_exclude, ### synonym
137 'enable-recompile-check' => \$enable_recompilation_warnings_check,
138 'enable-ip-resolve' => \$enable_client_ip_resolve_test,
139 'enable-distcheck' => \$enable_make_distcheck,
140 'List-mode' => \$list_mode,
141 'enable-valgrind' => \$use_valgrind,
142 'valgrind-path=s' => \$valgrindCmd,
143 'output-dir=s' => \$output_dir,
144 'diff' => \$diff_mode,
145 'diff-dir1=s' => \$diff_dir1,
146 'diff-dir2=s' => \$diff_dir2,
152 ### create an anonymized tar file of test suite results that can be
153 ### emailed around to assist in debugging fwknop communications
154 exit &anonymize_results() if $anonymize_results;
156 &identify_loopback_intf();
158 $valgrind_str = "$valgrindCmd --leak-check=full " .
159 "--show-reachable=yes --track-origins=yes" if $use_valgrind;
161 my $intf_str = "-i $loopback_intf --foreground --verbose --verbose";
163 my $default_client_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
164 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
165 "$local_key_file --verbose --verbose";
167 my $client_ip_resolve_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
168 "$fwknopCmd -A tcp/22 -R -D $loopback_ip --get-key " .
169 "$local_key_file --verbose --verbose";
171 my $default_client_gpg_args = "$default_client_args " .
172 "--gpg-recipient-key $gpg_server_key " .
173 "--gpg-signer-key $gpg_client_key " .
174 "--gpg-home-dir $gpg_client_home_dir";
176 my $default_client_gpg_args_no_homedir = "$default_client_args " .
177 "--gpg-recipient-key $gpg_server_key " .
178 "--gpg-signer-key $gpg_client_key ";
180 my $default_server_conf_args = "-c $cf{'def'} -a $cf{'def_access'} " .
181 "-d $default_digest_file -p $default_pid_file";
183 my $default_server_gpg_args = "LD_LIBRARY_PATH=$lib_dir " .
184 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
185 "-a $cf{'gpg_access'} $intf_str " .
186 "-d $default_digest_file -p $default_pid_file";
188 my $default_server_gpg_args_no_pw = "LD_LIBRARY_PATH=$lib_dir " .
189 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
190 "-a $cf{'gpg_no_pw_access'} $intf_str " .
191 "-d $default_digest_file -p $default_pid_file";
193 ### point the compiled binaries at the local libary path
194 ### instead of any installed libfko instance
195 $ENV{'LD_LIBRARY_PATH'} = $lib_dir;
197 ### main array that defines the tests we will run
200 'category' => 'recompilation',
201 'detail' => 'recompile and look for compilation warnings',
202 'err_msg' => 'compile warnings exist',
203 'function' => \&compile_warnings,
207 'category' => 'make distcheck',
208 'detail' => 'ensure proper distribution creation',
209 'err_msg' => 'could not create proper tarball',
210 'function' => \&make_distcheck,
214 'category' => 'build',
215 'subcategory' => 'client',
216 'detail' => 'binary exists',
217 'err_msg' => 'binary not found',
218 'function' => \&binary_exists,
219 'binary' => $fwknopCmd,
223 'category' => 'build security',
224 'subcategory' => 'client',
225 'detail' => 'Position Independent Executable (PIE)',
226 'err_msg' => 'non PIE binary (fwknop client)',
227 'function' => \&pie_binary,
228 'binary' => $fwknopCmd,
232 'category' => 'build security',
233 'subcategory' => 'client',
234 'detail' => 'stack protected binary',
235 'err_msg' => 'non stack protected binary (fwknop client)',
236 'function' => \&stack_protected_binary,
237 'binary' => $fwknopCmd,
241 'category' => 'build security',
242 'subcategory' => 'client',
243 'detail' => 'fortify source functions',
244 'err_msg' => 'source functions not fortified (fwknop client)',
245 'function' => \&fortify_source_functions,
246 'binary' => $fwknopCmd,
250 'category' => 'build security',
251 'subcategory' => 'client',
252 'detail' => 'read-only relocations',
253 'err_msg' => 'no read-only relocations (fwknop client)',
254 'function' => \&read_only_relocations,
255 'binary' => $fwknopCmd,
259 'category' => 'build security',
260 'subcategory' => 'client',
261 'detail' => 'immediate binding',
262 'err_msg' => 'no immediate binding (fwknop client)',
263 'function' => \&immediate_binding,
264 'binary' => $fwknopCmd,
269 'category' => 'build',
270 'subcategory' => 'server',
271 'detail' => 'binary exists',
272 'err_msg' => 'binary not found',
273 'function' => \&binary_exists,
274 'binary' => $fwknopdCmd,
279 'category' => 'build security',
280 'subcategory' => 'server',
281 'detail' => 'Position Independent Executable (PIE)',
282 'err_msg' => 'non PIE binary (fwknopd server)',
283 'function' => \&pie_binary,
284 'binary' => $fwknopdCmd,
288 'category' => 'build security',
289 'subcategory' => 'server',
290 'detail' => 'stack protected binary',
291 'err_msg' => 'non stack protected binary (fwknopd server)',
292 'function' => \&stack_protected_binary,
293 'binary' => $fwknopdCmd,
297 'category' => 'build security',
298 'subcategory' => 'server',
299 'detail' => 'fortify source functions',
300 'err_msg' => 'source functions not fortified (fwknopd server)',
301 'function' => \&fortify_source_functions,
302 'binary' => $fwknopdCmd,
306 'category' => 'build security',
307 'subcategory' => 'server',
308 'detail' => 'read-only relocations',
309 'err_msg' => 'no read-only relocations (fwknopd server)',
310 'function' => \&read_only_relocations,
311 'binary' => $fwknopdCmd,
315 'category' => 'build security',
316 'subcategory' => 'server',
317 'detail' => 'immediate binding',
318 'err_msg' => 'no immediate binding (fwknopd server)',
319 'function' => \&immediate_binding,
320 'binary' => $fwknopdCmd,
325 'category' => 'build',
326 'subcategory' => 'libfko',
327 'detail' => 'binary exists',
328 'err_msg' => 'binary not found',
329 'function' => \&binary_exists,
330 'binary' => $libfko_bin,
334 'category' => 'build security',
335 'subcategory' => 'libfko',
336 'detail' => 'stack protected binary',
337 'err_msg' => 'non stack protected binary (libfko)',
338 'function' => \&stack_protected_binary,
339 'binary' => $libfko_bin,
343 'category' => 'build security',
344 'subcategory' => 'libfko',
345 'detail' => 'fortify source functions',
346 'err_msg' => 'source functions not fortified (libfko)',
347 'function' => \&fortify_source_functions,
348 'binary' => $libfko_bin,
352 'category' => 'build security',
353 'subcategory' => 'libfko',
354 'detail' => 'read-only relocations',
355 'err_msg' => 'no read-only relocations (libfko)',
356 'function' => \&read_only_relocations,
357 'binary' => $libfko_bin,
361 'category' => 'build security',
362 'subcategory' => 'libfko',
363 'detail' => 'immediate binding',
364 'err_msg' => 'no immediate binding (libfko)',
365 'function' => \&immediate_binding,
366 'binary' => $libfko_bin,
371 'category' => 'preliminaries',
372 'subcategory' => 'client',
373 'detail' => 'usage info',
374 'err_msg' => 'could not get usage info',
375 'function' => \&generic_exec,
376 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd -h",
380 'category' => 'preliminaries',
381 'subcategory' => 'client',
382 'detail' => 'getopt() no such argument',
383 'err_msg' => 'getopt() allowed non-existant argument',
384 'function' => \&generic_exec,
385 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd --no-such-arg",
390 'category' => 'preliminaries',
391 'subcategory' => 'client',
392 'detail' => '--test mode, packet not sent',
393 'err_msg' => '--test mode, packet sent?',
394 'function' => \&generic_exec,
395 'positive_output_matches' => [qr/test\smode\senabled/],
396 'cmdline' => "$default_client_args --test",
401 'category' => 'preliminaries',
402 'subcategory' => 'client',
403 'detail' => 'expected code version',
404 'err_msg' => 'code version mis-match',
405 'function' => \&expected_code_version,
406 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd --version",
411 'category' => 'preliminaries',
412 'subcategory' => 'server',
413 'detail' => 'usage info',
414 'err_msg' => 'could not get usage info',
415 'function' => \&generic_exec,
416 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd -h",
420 'category' => 'preliminaries',
421 'subcategory' => 'server',
422 'detail' => 'getopt() no such argument',
423 'err_msg' => 'getopt() allowed non-existant argument',
424 'function' => \&generic_exec,
425 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd --no-such-arg",
431 'category' => 'preliminaries',
432 'subcategory' => 'server',
433 'detail' => 'expected code version',
434 'err_msg' => 'code version mis-match',
435 'function' => \&expected_code_version,
436 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
437 "$fwknopdCmd -c $cf{'def'} -a " .
438 "$cf{'def_access'} --version",
442 'category' => 'preliminaries',
443 'detail' => 'collecting system specifics',
444 'err_msg' => 'could not get complete system specs',
445 'function' => \&specs,
446 'binary' => $fwknopdCmd,
451 'category' => 'basic operations',
452 'detail' => 'dump config',
453 'err_msg' => 'could not dump configuration',
454 'function' => \&generic_exec,
455 'positive_output_matches' => [qr/SYSLOG_IDENTITY/],
457 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
458 "$fwknopdCmd -c $cf{'def'} " .
459 "-a $cf{'def_access'} --dump-config",
463 'category' => 'basic operations',
464 'detail' => 'override config',
465 'err_msg' => 'could not override configuration',
466 'function' => \&generic_exec,
467 'positive_output_matches' => [qr/ENABLE_PCAP_PROMISC.*\'Y\'/],
469 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
470 "$fwknopdCmd $default_server_conf_args " .
471 "-O $conf_dir/override_fwknopd.conf --dump-config",
476 'category' => 'basic operations',
477 'subcategory' => 'client',
478 'detail' => '--get-key path validation',
479 'err_msg' => 'accepted improper --get-key path',
480 'function' => \&generic_exec,
481 'positive_output_matches' => [qr/could\snot\sopen/i],
483 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
484 "$fwknopCmd -A tcp/22 -s $fake_ip " .
485 "-D $loopback_ip --get-key not/there",
489 'category' => 'basic operations',
490 'subcategory' => 'client',
491 'detail' => 'require [-s|-R|-a]',
492 'err_msg' => 'allowed null allow IP',
493 'function' => \&generic_exec,
494 'positive_output_matches' => [qr/must\suse\sone\sof/i],
496 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
497 "$fwknopCmd -D $loopback_ip",
501 'category' => 'basic operations',
502 'subcategory' => 'client',
503 'detail' => '--allow-ip <IP> valid IP',
504 'err_msg' => 'permitted invalid --allow-ip arg',
505 'function' => \&generic_exec,
506 'positive_output_matches' => [qr/Invalid\sallow\sIP\saddress/i],
508 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
509 "$fwknopCmd -A tcp/22 -a invalidIP -D $loopback_ip",
513 'category' => 'basic operations',
514 'subcategory' => 'client',
515 'detail' => '-A <proto>/<port> specification (proto)',
516 'err_msg' => 'permitted invalid -A <proto>/<port>',
517 'function' => \&generic_exec,
518 'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
520 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
521 "$fwknopCmd -A invalid/22 -a $fake_ip -D $loopback_ip",
525 'category' => 'basic operations',
526 'subcategory' => 'client',
527 'detail' => '-A <proto>/<port> specification (port)',
528 'err_msg' => 'permitted invalid -A <proto>/<port>',
529 'function' => \&generic_exec,
530 'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
532 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
533 "$fwknopCmd -A tcp/600001 -a $fake_ip -D $loopback_ip",
538 'category' => 'basic operations',
539 'subcategory' => 'client',
540 'detail' => 'generate SPA packet',
541 'err_msg' => 'could not generate SPA packet',
542 'function' => \&client_send_spa_packet,
543 'cmdline' => $default_client_args,
548 'category' => 'basic operations',
549 'subcategory' => 'server',
550 'detail' => 'list current fwknopd fw rules',
551 'err_msg' => 'could not list current fwknopd fw rules',
552 'function' => \&generic_exec,
553 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
554 "$fwknopdCmd $default_server_conf_args --fw-list",
558 'category' => 'basic operations',
559 'subcategory' => 'server',
560 'detail' => 'list all current fw rules',
561 'err_msg' => 'could not list all current fw rules',
562 'function' => \&generic_exec,
563 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
564 "$fwknopdCmd $default_server_conf_args --fw-list-all",
568 'category' => 'basic operations',
569 'subcategory' => 'server',
570 'detail' => 'flush current firewall rules',
571 'err_msg' => 'could not flush current fw rules',
572 'function' => \&generic_exec,
573 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
574 "$fwknopdCmd $default_server_conf_args --fw-flush",
579 'category' => 'basic operations',
580 'subcategory' => 'server',
582 'err_msg' => 'start error',
583 'function' => \&server_start,
584 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
585 "$fwknopdCmd $default_server_conf_args $intf_str",
589 'category' => 'basic operations',
590 'subcategory' => 'server',
592 'err_msg' => 'stop error',
593 'function' => \&server_stop,
594 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
595 "$fwknopdCmd $default_server_conf_args $intf_str",
599 'category' => 'basic operations',
600 'subcategory' => 'server',
601 'detail' => 'write PID',
602 'err_msg' => 'did not write PID',
603 'function' => \&write_pid,
604 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
605 "$fwknopdCmd $default_server_conf_args $intf_str",
610 'category' => 'basic operations',
611 'subcategory' => 'server',
612 'detail' => '--packet-limit 1 exit',
613 'err_msg' => 'did not exit after one packet',
614 'function' => \&server_packet_limit,
615 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
616 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
620 'category' => 'basic operations',
621 'subcategory' => 'server',
622 'detail' => 'ignore packets < min SPA len (140)',
623 'err_msg' => 'did not ignore small packets',
624 'function' => \&server_ignore_small_packets,
625 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
626 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
630 'category' => 'basic operations',
631 'subcategory' => 'server',
632 'detail' => '-P bpf filter ignore packet',
633 'err_msg' => 'filter did not ignore packet',
634 'function' => \&server_bpf_ignore_packet,
635 'cmdline' => $default_client_args,
636 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
637 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str " .
638 qq|-P "udp port $non_std_spa_port"|,
643 'category' => 'Rijndael SPA',
644 'subcategory' => 'client+server',
645 'detail' => 'complete cycle (tcp/22 ssh)',
646 'err_msg' => 'could not complete SPA cycle',
647 'function' => \&spa_cycle,
648 'cmdline' => $default_client_args,
649 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
650 "$fwknopdCmd $default_server_conf_args $intf_str",
651 'fw_rule_created' => $NEW_RULE_REQUIRED,
652 'fw_rule_removed' => $NEW_RULE_REMOVED,
656 'category' => 'Rijndael SPA',
657 'subcategory' => 'client+server',
658 'detail' => 'permissions check cycle (tcp/22)',
659 'err_msg' => 'could not complete SPA cycle',
660 'function' => \&permissions_check,
661 'cmdline' => $default_client_args,
662 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
663 "$fwknopdCmd $default_server_conf_args $intf_str",
664 'server_positive_output_matches' => [qr/permissions\sshould\sonly\sbe\suser/],
665 'fw_rule_created' => $NEW_RULE_REQUIRED,
666 'fw_rule_removed' => $NEW_RULE_REMOVED,
670 'category' => 'Rijndael SPA',
671 'subcategory' => 'client+server',
672 'detail' => 'client IP resolve (tcp/22 ssh)',
673 'err_msg' => 'could not complete SPA cycle',
674 'function' => \&spa_cycle,
675 'cmdline' => $client_ip_resolve_args,
677 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
678 "$fwknopdCmd $default_server_conf_args $intf_str",
679 'fw_rule_created' => $NEW_RULE_REQUIRED,
680 'fw_rule_removed' => $NEW_RULE_REMOVED,
685 'category' => 'Rijndael SPA',
686 'subcategory' => 'client+server',
687 'detail' => 'dual usage access key (tcp/80 http)',
688 'err_msg' => 'could not complete SPA cycle',
689 'function' => \&spa_cycle,
690 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
691 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
692 "$local_key_file --verbose --verbose",
693 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
694 "$fwknopdCmd -c $cf{'def'} -a $cf{'dual_key_access'} " .
695 "-d $default_digest_file -p $default_pid_file $intf_str",
696 ### check for the first stanza that does not allow tcp/80 - the
697 ### second stanza allows this
698 'server_positive_output_matches' => [qr/stanza #1\)\sOne\sor\smore\srequested\sprotocol\/ports\swas\sdenied/],
699 'fw_rule_created' => $NEW_RULE_REQUIRED,
700 'fw_rule_removed' => $NEW_RULE_REMOVED,
704 'category' => 'Rijndael SPA',
705 'subcategory' => 'client+server',
706 'detail' => 'packet aging (past) (tcp/22 ssh)',
707 'err_msg' => 'old SPA packet accepted',
708 'function' => \&spa_cycle,
709 'cmdline' => "$default_client_args --time-offset-minus 300s",
710 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
711 "$fwknopdCmd $default_server_conf_args $intf_str",
712 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
713 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
717 'category' => 'Rijndael SPA',
718 'subcategory' => 'client+server',
719 'detail' => 'packet aging (future) (tcp/22 ssh)',
720 'err_msg' => 'future SPA packet accepted',
721 'function' => \&spa_cycle,
722 'cmdline' => "$default_client_args --time-offset-plus 300s",
723 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
724 "$fwknopdCmd $default_server_conf_args $intf_str",
725 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
726 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
730 'category' => 'Rijndael SPA',
731 'subcategory' => 'client+server',
732 'detail' => 'expired stanza (tcp/22 ssh)',
733 'err_msg' => 'SPA packet accepted',
734 'function' => \&spa_cycle,
735 'cmdline' => $default_client_args,
736 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
737 "$fwknopdCmd -c $cf{'def'} -a $cf{'exp_access'} " .
738 "-d $default_digest_file -p $default_pid_file $intf_str",
739 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
740 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
744 'category' => 'Rijndael SPA',
745 'subcategory' => 'client+server',
746 'detail' => 'invalid expire date (tcp/22 ssh)',
747 'err_msg' => 'SPA packet accepted',
748 'function' => \&spa_cycle,
749 'cmdline' => $default_client_args,
750 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
751 "$fwknopdCmd -c $cf{'def'} -a $cf{'invalid_exp_access'} " .
752 "-d $default_digest_file -p $default_pid_file $intf_str",
753 'server_positive_output_matches' => [qr/invalid\sdate\svalue/],
754 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
758 'category' => 'Rijndael SPA',
759 'subcategory' => 'client+server',
760 'detail' => 'expired epoch stanza (tcp/22 ssh)',
761 'err_msg' => 'SPA packet accepted',
762 'function' => \&spa_cycle,
763 'cmdline' => $default_client_args,
764 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
765 "$fwknopdCmd -c $cf{'def'} -a $cf{'exp_epoch_access'} " .
766 "-d $default_digest_file -p $default_pid_file $intf_str",
767 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
768 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
772 'category' => 'Rijndael SPA',
773 'subcategory' => 'client+server',
774 'detail' => 'future expired stanza (tcp/22 ssh)',
775 'err_msg' => 'SPA packet not accepted',
776 'function' => \&spa_cycle,
777 'cmdline' => $default_client_args,
778 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
779 "$fwknopdCmd -c $cf{'def'} -a $cf{'future_exp_access'} " .
780 "-d $default_digest_file -p $default_pid_file $intf_str",
781 'fw_rule_created' => $NEW_RULE_REQUIRED,
782 'fw_rule_removed' => $NEW_RULE_REMOVED,
787 'category' => 'Rijndael SPA',
788 'subcategory' => 'client+server',
789 'detail' => 'OPEN_PORTS (tcp/22 ssh)',
790 'err_msg' => "improper OPEN_PORTS result",
791 'function' => \&spa_cycle,
792 'cmdline' => $default_client_args,
793 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
794 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_access'} " .
795 "-d $default_digest_file -p $default_pid_file $intf_str",
796 'fw_rule_created' => $NEW_RULE_REQUIRED,
797 'fw_rule_removed' => $NEW_RULE_REMOVED,
801 'category' => 'Rijndael SPA',
802 'subcategory' => 'client+server',
803 'detail' => 'OPEN_PORTS mismatch',
804 'err_msg' => "SPA packet accepted",
805 'function' => \&spa_cycle,
806 'cmdline' => $default_client_args,
807 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
808 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_mismatch'} " .
809 "-d $default_digest_file -p $default_pid_file $intf_str",
810 'server_positive_output_matches' => [qr/One\s+or\s+more\s+requested/],
811 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
815 'category' => 'Rijndael SPA',
816 'subcategory' => 'client+server',
817 'detail' => 'require user (tcp/22 ssh)',
818 'err_msg' => "missed require user criteria",
819 'function' => \&spa_cycle,
820 'cmdline' => "SPOOF_USER=$spoof_user $default_client_args",
821 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
822 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_user_access'} " .
823 "-d $default_digest_file -p $default_pid_file $intf_str",
824 'fw_rule_created' => $NEW_RULE_REQUIRED,
825 'fw_rule_removed' => $NEW_RULE_REMOVED,
829 'category' => 'Rijndael SPA',
830 'subcategory' => 'client+server',
831 'detail' => 'user mismatch (tcp/22 ssh)',
832 'err_msg' => "improper user accepted for access",
833 'function' => \&user_mismatch,
834 'function' => \&spa_cycle,
835 'cmdline' => $default_client_args,
836 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
837 "$fwknopdCmd -c $cf{'def'} -a $cf{'user_mismatch_access'} " .
838 "-d $default_digest_file -p $default_pid_file $intf_str",
839 'server_positive_output_matches' => [qr/Username\s+in\s+SPA\s+data/],
840 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
844 'category' => 'Rijndael SPA',
845 'subcategory' => 'client+server',
846 'detail' => 'require src (tcp/22 ssh)',
847 'err_msg' => "fw rule not created",
848 'function' => \&spa_cycle,
849 'cmdline' => $default_client_args,
850 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
851 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
852 "-d $default_digest_file -p $default_pid_file $intf_str",
853 'fw_rule_created' => $NEW_RULE_REQUIRED,
854 'fw_rule_removed' => $NEW_RULE_REMOVED,
858 'category' => 'Rijndael SPA',
859 'subcategory' => 'client+server',
860 'detail' => 'mismatch require src (tcp/22 ssh)',
861 'err_msg' => "fw rule created",
862 'function' => \&spa_cycle,
863 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
864 "$fwknopCmd -A tcp/22 -s -D $loopback_ip --get-key " .
865 "$local_key_file --verbose --verbose",
866 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
867 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
868 "-d $default_digest_file -p $default_pid_file $intf_str",
869 'server_positive_output_matches' => [qr/Got\s0.0.0.0\swhen\svalid\ssource\sIP/],
870 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
875 'category' => 'Rijndael SPA',
876 'subcategory' => 'client+server',
877 'detail' => 'IP filtering (tcp/22 ssh)',
878 'err_msg' => "did not filter $loopback_ip",
879 'function' => \&spa_cycle,
880 'cmdline' => $default_client_args,
881 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
882 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_src_match'} " .
883 "-d $default_digest_file -p $default_pid_file $intf_str",
884 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
885 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
889 'category' => 'Rijndael SPA',
890 'subcategory' => 'client+server',
891 'detail' => 'subnet filtering (tcp/22 ssh)',
892 'err_msg' => "did not filter $loopback_ip",
893 'function' => \&spa_cycle,
894 'cmdline' => $default_client_args,
895 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
896 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_subnet_match'} " .
897 "-d $default_digest_file -p $default_pid_file $intf_str",
898 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
899 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
903 'category' => 'Rijndael SPA',
904 'subcategory' => 'client+server',
905 'detail' => 'IP+subnet filtering (tcp/22 ssh)',
906 'err_msg' => "did not filter $loopback_ip",
907 'function' => \&spa_cycle,
908 'cmdline' => $default_client_args,
909 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
910 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_multi_src'} " .
911 "-d $default_digest_file -p $default_pid_file $intf_str",
912 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
913 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
917 'category' => 'Rijndael SPA',
918 'subcategory' => 'client+server',
919 'detail' => 'IP match (tcp/22 ssh)',
920 'err_msg' => "did not filter $loopback_ip",
921 'function' => \&spa_cycle,
922 'cmdline' => $default_client_args,
923 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
924 "$fwknopdCmd -c $cf{'def'} -a $cf{'ip_src_match'} " .
925 "-d $default_digest_file -p $default_pid_file $intf_str",
926 'fw_rule_created' => $NEW_RULE_REQUIRED,
927 'fw_rule_removed' => $NEW_RULE_REMOVED,
931 'category' => 'Rijndael SPA',
932 'subcategory' => 'client+server',
933 'detail' => 'subnet match (tcp/22 ssh)',
934 'err_msg' => "did not filter $loopback_ip",
935 'function' => \&spa_cycle,
936 'cmdline' => $default_client_args,
937 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
938 "$fwknopdCmd -c $cf{'def'} -a $cf{'subnet_src_match'} " .
939 "-d $default_digest_file -p $default_pid_file $intf_str",
940 'fw_rule_created' => $NEW_RULE_REQUIRED,
941 'fw_rule_removed' => $NEW_RULE_REMOVED,
945 'category' => 'Rijndael SPA',
946 'subcategory' => 'client+server',
947 'detail' => 'multi IP/net match (tcp/22 ssh)',
948 'err_msg' => "did not filter $loopback_ip",
949 'function' => \&spa_cycle,
950 'cmdline' => $default_client_args,
951 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
952 "$fwknopdCmd -c $cf{'def'} -a $cf{'multi_src_access'} " .
953 "-d $default_digest_file -p $default_pid_file $intf_str",
954 'fw_rule_created' => $NEW_RULE_REQUIRED,
955 'fw_rule_removed' => $NEW_RULE_REMOVED,
959 'category' => 'Rijndael SPA',
960 'subcategory' => 'client+server',
961 'detail' => 'multi access stanzas (tcp/22 ssh)',
962 'err_msg' => "could not complete SPA cycle",
963 'function' => \&spa_cycle,
964 'cmdline' => $default_client_args,
965 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
966 "$fwknopdCmd -c $cf{'def'} -a $cf{'multi_stanza_access'} " .
967 "-d $default_digest_file -p $default_pid_file $intf_str",
968 'fw_rule_created' => $NEW_RULE_REQUIRED,
969 'fw_rule_removed' => $NEW_RULE_REMOVED,
973 'category' => 'Rijndael SPA',
974 'subcategory' => 'client+server',
975 'detail' => 'bad/good key stanzas (tcp/22 ssh)',
976 'err_msg' => "could not complete SPA cycle",
977 'function' => \&spa_cycle,
978 'cmdline' => $default_client_args,
979 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
980 "$fwknopdCmd -c $cf{'def'} -a $cf{'broken_keys_access'} " .
981 "-d $default_digest_file -p $default_pid_file $intf_str",
982 'fw_rule_created' => $NEW_RULE_REQUIRED,
983 'fw_rule_removed' => $NEW_RULE_REMOVED,
988 'category' => 'Rijndael SPA',
989 'subcategory' => 'client+server',
990 'detail' => "non-enabled NAT (tcp/22 ssh)",
991 'err_msg' => "SPA packet not filtered",
992 'function' => \&spa_cycle,
993 'cmdline' => "$default_client_args -N $internal_nat_host:22",
994 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
995 "$fwknopdCmd $default_server_conf_args $intf_str",
996 'server_positive_output_matches' => [qr/requested\sNAT\saccess.*not\senabled/i],
997 'server_conf' => $cf{'nat'},
998 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1002 'category' => 'Rijndael SPA',
1003 'subcategory' => 'client+server',
1004 'detail' => "NAT to $internal_nat_host (tcp/22 ssh)",
1005 'err_msg' => "could not complete NAT SPA cycle",
1006 'function' => \&spa_cycle,
1007 'cmdline' => "$default_client_args -N $internal_nat_host:22",
1008 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1009 "$fwknopdCmd -c $cf{'nat'} -a $cf{'open_ports_access'} " .
1010 "-d $default_digest_file -p $default_pid_file $intf_str",
1011 'server_positive_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1012 'fw_rule_created' => $NEW_RULE_REQUIRED,
1013 'fw_rule_removed' => $NEW_RULE_REMOVED,
1014 'server_conf' => $cf{'nat'},
1018 'category' => 'Rijndael SPA',
1019 'subcategory' => 'client+server',
1020 'detail' => "force NAT $force_nat_host (tcp/22 ssh)",
1021 'err_msg' => "could not complete NAT SPA cycle",
1022 'function' => \&spa_cycle,
1023 'cmdline' => $default_client_args,
1024 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1025 "$fwknopdCmd -c $cf{'nat'} -a $cf{'force_nat_access'} " .
1026 "-d $default_digest_file -p $default_pid_file $intf_str",
1027 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i],
1028 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1029 'fw_rule_created' => $NEW_RULE_REQUIRED,
1030 'fw_rule_removed' => $NEW_RULE_REMOVED,
1031 'server_conf' => $cf{'nat'},
1035 'category' => 'Rijndael SPA',
1036 'subcategory' => 'client+server',
1037 'detail' => "local NAT $force_nat_host (tcp/22 ssh)",
1038 'err_msg' => "could not complete NAT SPA cycle",
1039 'function' => \&spa_cycle,
1040 'cmdline' => "$default_client_args --nat-local",
1041 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1042 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'force_nat_access'} " .
1043 "-d $default_digest_file -p $default_pid_file $intf_str",
1044 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i,
1045 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1046 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1047 'fw_rule_created' => $NEW_RULE_REQUIRED,
1048 'fw_rule_removed' => $NEW_RULE_REMOVED,
1049 'server_conf' => $cf{'nat'},
1053 'category' => 'Rijndael SPA',
1054 'subcategory' => 'client+server',
1055 'detail' => "local NAT non-FORCE_NAT (tcp/22 ssh)",
1056 'err_msg' => "could not complete NAT SPA cycle",
1057 'function' => \&spa_cycle,
1058 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1059 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
1060 "$local_key_file --verbose --verbose --nat-local --nat-port 22",
1061 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1062 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'def_access'} " .
1063 "-d $default_digest_file -p $default_pid_file $intf_str",
1064 'server_positive_output_matches' => [qr/to\:$loopback_ip\:22/i,
1065 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1066 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1067 'fw_rule_created' => $NEW_RULE_REQUIRED,
1068 'fw_rule_removed' => $NEW_RULE_REMOVED,
1069 'server_conf' => $cf{'nat'},
1074 'category' => 'Rijndael SPA',
1075 'subcategory' => 'client+server',
1076 'detail' => 'complete cycle (tcp/23 telnet)',
1077 'err_msg' => 'could not complete SPA cycle',
1078 'function' => \&spa_cycle,
1079 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1080 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1081 "$local_key_file --verbose --verbose",
1082 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1083 "$fwknopdCmd $default_server_conf_args $intf_str",
1084 'fw_rule_created' => $NEW_RULE_REQUIRED,
1085 'fw_rule_removed' => $NEW_RULE_REMOVED,
1089 'category' => 'Rijndael SPA',
1090 'subcategory' => 'client+server',
1091 'detail' => 'complete cycle (tcp/9418 git)',
1092 'err_msg' => 'could not complete SPA cycle',
1093 'function' => \&spa_cycle,
1094 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1095 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1096 "$local_key_file --verbose --verbose",
1097 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1098 "$fwknopdCmd $default_server_conf_args $intf_str",
1099 'fw_rule_created' => $NEW_RULE_REQUIRED,
1100 'fw_rule_removed' => $NEW_RULE_REMOVED,
1104 'category' => 'Rijndael SPA',
1105 'subcategory' => 'client+server',
1106 'detail' => 'complete cycle (tcp/60001)',
1107 'err_msg' => 'could not complete SPA cycle',
1108 'function' => \&spa_cycle,
1109 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1110 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1111 "$local_key_file --verbose --verbose",
1112 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1113 "$fwknopdCmd $default_server_conf_args $intf_str",
1114 'fw_rule_created' => $NEW_RULE_REQUIRED,
1115 'fw_rule_removed' => $NEW_RULE_REMOVED,
1119 'category' => 'Rijndael SPA',
1120 'subcategory' => 'client+server',
1121 'detail' => 'multi port (tcp/60001,udp/60001)',
1122 'err_msg' => 'could not complete SPA cycle',
1123 'function' => \&spa_cycle,
1124 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1125 "$fwknopCmd -A tcp/60001,udp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1126 "$local_key_file --verbose --verbose",
1127 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1128 "$fwknopdCmd $default_server_conf_args $intf_str",
1129 'fw_rule_created' => $NEW_RULE_REQUIRED,
1130 'fw_rule_removed' => $NEW_RULE_REMOVED,
1134 'category' => 'Rijndael SPA',
1135 'subcategory' => 'client+server',
1136 'detail' => 'multi port (tcp/22,udp/53,tcp/1234)',
1137 'err_msg' => 'could not complete SPA cycle',
1138 'function' => \&spa_cycle,
1139 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1140 "$fwknopCmd -A tcp/22,udp/53,tcp/1234 -a $fake_ip -D $loopback_ip --get-key " .
1141 "$local_key_file --verbose --verbose",
1142 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1143 "$fwknopdCmd $default_server_conf_args $intf_str",
1144 'fw_rule_created' => $NEW_RULE_REQUIRED,
1145 'fw_rule_removed' => $NEW_RULE_REMOVED,
1150 'category' => 'Rijndael SPA',
1151 'subcategory' => 'client+server',
1152 'detail' => 'complete cycle (udp/53 dns)',
1153 'err_msg' => 'could not complete SPA cycle',
1154 'function' => \&spa_cycle,
1155 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1156 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1157 "$local_key_file --verbose --verbose",
1158 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1159 "$fwknopdCmd $default_server_conf_args $intf_str",
1160 'fw_rule_created' => $NEW_RULE_REQUIRED,
1161 'fw_rule_removed' => $NEW_RULE_REMOVED,
1165 'category' => 'Rijndael SPA',
1166 'subcategory' => 'client+server',
1167 'detail' => "-P bpf SPA over port $non_std_spa_port",
1168 'err_msg' => 'could not complete SPA cycle',
1169 'function' => \&spa_cycle,
1170 'cmdline' => "$default_client_args --server-port $non_std_spa_port",
1171 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1172 "$fwknopdCmd $default_server_conf_args $intf_str " .
1173 qq|-P "udp port $non_std_spa_port"|,
1174 'server_positive_output_matches' => [qr/PCAP\sfilter.*\s$non_std_spa_port/],
1175 'fw_rule_created' => $NEW_RULE_REQUIRED,
1176 'fw_rule_removed' => $NEW_RULE_REMOVED,
1181 'category' => 'Rijndael SPA',
1182 'subcategory' => 'client+server',
1183 'detail' => 'random SPA port (tcp/22 ssh)',
1184 'err_msg' => 'could not complete SPA cycle',
1185 'function' => \&spa_cycle,
1186 'cmdline' => "$default_client_args -r",
1187 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1188 "$fwknopdCmd $default_server_conf_args $intf_str " .
1190 'fw_rule_created' => $NEW_RULE_REQUIRED,
1191 'fw_rule_removed' => $NEW_RULE_REMOVED,
1196 'category' => 'Rijndael SPA',
1197 'subcategory' => 'client+server',
1198 'detail' => 'spoof username (tcp/22)',
1199 'err_msg' => 'could not spoof username',
1200 'function' => \&spoof_username,
1201 'cmdline' => "SPOOF_USER=$spoof_user LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1202 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
1203 "$local_key_file --verbose --verbose",
1204 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1205 "$fwknopdCmd $default_server_conf_args $intf_str",
1210 'category' => 'Rijndael SPA',
1211 'subcategory' => 'client+server',
1212 'detail' => 'replay attack detection',
1213 'err_msg' => 'could not detect replay attack',
1214 'function' => \&replay_detection,
1215 'cmdline' => $default_client_args,
1216 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1217 "$fwknopdCmd $default_server_conf_args $intf_str",
1218 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1222 'category' => 'Rijndael SPA',
1223 'subcategory' => 'client+server',
1224 'detail' => 'replay detection (Rijndael prefix)',
1225 'err_msg' => 'could not detect replay attack',
1226 'function' => \&replay_detection,
1227 'pkt_prefix' => 'U2FsdGVkX1',
1228 'cmdline' => $default_client_args,
1229 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1230 "$fwknopdCmd $default_server_conf_args $intf_str",
1231 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1237 'category' => 'Rijndael SPA',
1238 'subcategory' => 'FUZZING',
1239 'detail' => 'overly long port value',
1240 'err_msg' => 'server crashed or did not detect error condition',
1241 'function' => \&fuzzer,
1242 ### this packet was generated with a modified fwknop client via the
1243 ### following command line:
1245 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1246 # "tcp/`perl -e '{print "1"x"40"}'`" -a 127.0.0.2 -D 127.0.0.1 \
1247 # --get-key local_spa.key --verbose --verbose
1249 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1250 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1251 # authenticated clients.
1254 '+JzxeTGlc6lwwzbJSrYChKx8bonWBIPajwGfEtGOaoglcMLbTY/GGXo/nxqiN1LykFS' .
1255 'lDFXgrkyx2emJ7NGzYqQPUYZxLdZRocR9aRIptvXLLIPBcIpJASi/TUiJlw7CDFMcj0' .
1256 'ptSBJJUZi0tozpKHETp3AgqfzyOy5FNs38aZsV5/sDl3Pt+kF7fTZJ+YLbmYY4yCUz2' .
1257 'ZUYoCaJ7X78ULyJTi5eT7nug',
1258 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1259 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1260 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1261 "-d $default_digest_file -p $default_pid_file $intf_str",
1265 'category' => 'Rijndael SPA',
1266 'subcategory' => 'FUZZING',
1267 'detail' => 'overly long proto value',
1268 'err_msg' => 'server crashed or did not detect error condition',
1269 'function' => \&fuzzer,
1270 ### this packet was generated with a modified fwknop client via the
1271 ### following command line:
1273 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1274 # "tcp`perl -e '{print "A"x"28"}'`/1" -a 127.0.0.2 -D 127.0.0.1 \
1275 # --get-key local_spa.key --verbose --verbose
1277 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1278 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1279 # authenticated clients.
1282 '/im5MiJQmOdzqrdWXv+AjEtAm/HsLrdaTFcSw3ZskqpGOdDIrSCz3VXbFfv7qDkc5Y4' .
1283 'q/k1mRXl9SGzpug87U5dZSyCdAr30z7/2kUFEPTGOQBi/x+L1t1pvdkm4xg13t09ldm' .
1284 '5OD8KiV6qzqLOvN4ULJjvvJJWBZ9qvo/f2Q9Wf67g2KHiwS6EeCINAuMoUw/mNRQMa4' .
1285 'oGnOXu3/DeWHJAwtSeh7EAr4',
1286 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1287 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1288 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1289 "-d $default_digest_file -p $default_pid_file $intf_str",
1293 'category' => 'Rijndael SPA',
1294 'subcategory' => 'FUZZING',
1295 'detail' => 'overly long IP value',
1296 'err_msg' => 'server crashed or did not detect error condition',
1297 'function' => \&fuzzer,
1298 ### this packet was generated with a modified fwknop client via the
1299 ### following command line:
1301 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1302 # -a `perl -e '{print "1"x"136"}'`.0.0.1 -D 127.0.0.1 \
1303 # --get-key local_spa.key --verbose --verbose
1305 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1306 # a condition in which pre-2.0.3 fwknopd servers fail to properly validate
1307 # allow IP addresses from malicious authenticated clients.
1310 '93f2rhsXLmBoPicWvYTqrbp+6lNqvWDc8dzmX2s3settwjBGRAXm33TB9agibEphrBu' .
1311 '3d+7DEsivZLDS6Kz0JwdjX7t0J9c8es+DVNjlLnPtVNcxhs+2kUzimNrgysIXQRJ+GF' .
1312 'GbhdxiXCqdy1vWxWpdoaZmY/CeGIkpoFJFPbJhCRLLX25UMvMF2wXj02MpI4d3t1/6W' .
1313 'DM3taM3kZsiFv6HxFjAhIEuQ1oAg2OgRGXkDmT3jDNZMHUm0d4Ahm9LonG7RbOxq/B0' .
1314 'qUvY8lkymbwvjelVok7Lvlc06cRhN4zm32D4V05g0vQS3PlX9C+mgph9DeAPVX+D8iZ' .
1315 '8lGrxcPSfbCOW61k0MP+q1EhLZkc1qAm5g2+2cLNZcoBNEdh3yj8OTPZJyBVw',
1316 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1317 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1318 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1319 "-d $default_digest_file -p $default_pid_file $intf_str",
1323 'category' => 'Rijndael SPA',
1324 'subcategory' => 'FUZZING',
1325 'detail' => 'negative port value',
1326 'err_msg' => 'server crashed or did not detect error condition',
1327 'function' => \&fuzzer,
1328 ### this packet was generated with a modified fwknop client via the
1329 ### following command line:
1331 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1332 # tcp/-33 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1333 # --verbose --verbose
1336 '/weoc+pEuQknZo8ImWTQBB+/PwSJ2/TcrmFoSkxpRXX4+jlUxoJakHrioxh8rhLmAD9' .
1337 '8E4lMnq+EbM2XYdhs2alpZ5bovAFojMsYRWwr/BvRO4Um4Fmo9z9sY3DR477TXNYXBR' .
1338 'iGXWxSL4u+AWSSePK3qiiYoRQVw',
1339 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1340 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1341 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1342 "-d $default_digest_file -p $default_pid_file $intf_str",
1346 'category' => 'Rijndael SPA',
1347 'subcategory' => 'FUZZING',
1348 'detail' => 'null port value',
1349 'err_msg' => 'server crashed or did not detect error condition',
1350 'function' => \&fuzzer,
1351 ### this packet was generated with a modified fwknop client via the
1352 ### following command line:
1354 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/ \
1355 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1356 # --verbose --verbose
1359 '94nu7hvq6V/3A27GzjHwfPnPCQfs44ySlraIFYHOAqy5YqjkrBS67nH35tX55N1BrYZ' .
1360 '07zvcT03keUhLE1Uo7Wme1nE7BfTOG5stmIK1UQI85sL52//lDHu+xCqNcL7GUKbVRz' .
1361 'ekw+EUscVvUkrsRcVtSvOm+fCNo',
1362 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1363 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1364 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1365 "-d $default_digest_file -p $default_pid_file $intf_str",
1369 'category' => 'Rijndael SPA',
1370 'subcategory' => 'FUZZING',
1371 'detail' => 'long FKO protocol value (enc mode trigger)',
1372 'err_msg' => 'server crashed or did not detect error condition',
1373 'function' => \&fuzzer,
1374 ### this packet was generated with a modified fwknop client via the
1375 ### following command line:
1377 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1378 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1380 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1381 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1382 # encrypted SPA packet
1385 '/ewH/k1XsDX+VQ8NlNvCZ4P2QOl/4IpJYXkq4TtAe3899OtApXJiTtPCuYW70XPuxge' .
1386 'MtFjc4UfslK/r9v+FYfyd3fIIHCz0Q0M4+nM3agTLmJj8nOxk6ZeBj82SDQWhHAxGdJ' .
1387 'IQALPve0ug4cuGxS3b4M+2Q/Av9i2tU3Lzlogw3sY0tk6wGf4zZk4UsviVXYpINniGT' .
1388 'RhYSIQ1dfdkng7hKiHMDaObYY1GFp4nxEt/QjasAwvE+7/iFyoKN+IRpGG4v4hGEPh2' .
1389 'vTDqmvfRuIHtgFD7NxZjt+m/jjcu0gkdWEoD4fenwGU35FlvchyM2AiAEw7yRzSABfn' .
1390 'R9d3sYZGMtyASw2O1vSluwIxUUnDop3gxEIhJEj8h+01pA3K+klSpALeY9EZgHqYC7E' .
1391 'ETuPS6dZ3764nWohtCY67JvNUX7TtNDNc2qrhrapdRP17+PT2Vh4s9m38V3WwVWC3uH' .
1392 'X/klLZcHIt+aRDV+uekw9GOKSgwFL2ekPpr3gXxigc3zrxel5hcsqLOpVUa4CP/0HkG' .
1393 'F0NPQvOT3ZvpeIJnirKP1ZX9gDFinqhuzL7oqktW61e1iwe7KZEdrZV0k2KZwyb8qU5' .
1395 'server_positive_output_matches' => [qr/No\sstanza\sencryption\smode\smatch/],
1396 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1397 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1398 "-d $default_digest_file -p $default_pid_file $intf_str",
1402 'category' => 'Rijndael SPA',
1403 'subcategory' => 'FUZZING',
1404 'detail' => 'long FKO protocol value (Rijndael trigger)',
1405 'err_msg' => 'server crashed or did not detect error condition',
1406 'function' => \&fuzzer,
1407 ### this packet was generated with a modified fwknop client via the
1408 ### following command line:
1410 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1411 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1413 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1414 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1415 # encrypted SPA packet
1418 '+YQNu4BFgiNeu8HeiBiNKriqCFSseALt9vJaKzkzK/OF4pjkJcvhGEOi7fEVXqn3VIdlGR' .
1419 'DmBul2I7H3z18U9E97bWGgT9NexKgEPCuekL18ZEPf5xR3JleNsNWatqYgAOkgN8ZWE69Q' .
1420 'qQUYYhxTvJHS6R+5JqFKB3A44hMXoICdYNkn9MAktHxk3PbbpQ+nA+jESwVCra2doAiLiM' .
1421 'ucvGIZZiTv0Mc1blFYIE2zqZ/C7ct1V+ukwSkUv0r87eA7uJhmlpThRsL0dN6iekJ6i87B' .
1422 'tE8QyuOXzOMftI11SUn/LwqD4RMdR21rvLrzR6ZB5eUX2UBpODyzX6n+PJJkTWCuFVT4z1' .
1424 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1425 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1426 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1427 "-d $default_digest_file -p $default_pid_file $intf_str",
1432 'category' => 'Rijndael SPA',
1433 'subcategory' => 'FUZZING',
1434 'detail' => 'null proto value',
1435 'err_msg' => 'server crashed or did not detect error condition',
1436 'function' => \&fuzzer,
1437 ### this packet was generated with a modified fwknop client via the
1438 ### following command line:
1440 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A /22 \
1441 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1442 # --verbose --verbose
1445 '/JT14qxh9P4iy+CuUZahThaQjoEuL2zd46a+jL6sTrBZJSa6faUX4dH5fte/4ZJv+9f' .
1446 'd/diWYKAUvdQ4DydPGlR7mwQa2W+obKpqrsTBz7D4054z6ATAOGpCtifakEVl1XRc2+' .
1447 'hW04WpY8mdUNu9i+PrfPr7/KxqU',
1448 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1449 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1450 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1451 "-d $default_digest_file -p $default_pid_file $intf_str",
1455 'category' => 'FUZZING',
1456 'subcategory' => 'server',
1457 'detail' => 'invalid SOURCE access.conf',
1458 'err_msg' => 'server crashed or did not detect error condition',
1459 'function' => \&generic_exec,
1460 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1461 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'fuzz_source'} " .
1462 "-d $default_digest_file -p $default_pid_file $intf_str",
1463 'positive_output_matches' => [qr/Fatal\sinvalid/],
1468 'category' => 'FUZZING',
1469 'subcategory' => 'server',
1470 'detail' => 'invalid OPEN_PORTS access.conf',
1471 'err_msg' => 'server crashed or did not detect error condition',
1472 'function' => \&generic_exec,
1473 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1474 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'fuzz_open_ports'} " .
1475 "-d $default_digest_file -p $default_pid_file $intf_str",
1476 'positive_output_matches' => [qr/Fatal\sinvalid/],
1481 'category' => 'FUZZING',
1482 'subcategory' => 'server',
1483 'detail' => 'invalid RESTRICT_PORTS access.conf',
1484 'err_msg' => 'server crashed or did not detect error condition',
1485 'function' => \&generic_exec,
1486 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1487 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'fuzz_restrict_ports'} " .
1488 "-d $default_digest_file -p $default_pid_file $intf_str",
1489 'positive_output_matches' => [qr/Fatal\sinvalid/],
1495 'category' => 'Rijndael SPA',
1496 'subcategory' => 'server',
1497 'detail' => 'digest cache structure',
1498 'err_msg' => 'improper digest cache structure',
1499 'function' => \&digest_cache_structure,
1504 'category' => 'Rijndael SPA',
1505 'subcategory' => 'server',
1506 'detail' => 'ipfw active/expire sets not equal',
1507 'err_msg' => 'allowed active/expire sets to be the same',
1508 'function' => \&spa_cycle,
1509 'cmdline' => $default_client_args,
1510 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1511 "$fwknopdCmd -c $cf{'ipfw_active_expire'} -a $cf{'def_access'} " .
1512 "-d $default_digest_file -p $default_pid_file $intf_str",
1513 'server_positive_output_matches' => [qr/Cannot\sset\sidentical\sipfw\sactive\sand\sexpire\ssets/],
1514 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1519 'category' => 'Rijndael SPA',
1520 'subcategory' => 'client+server',
1521 'detail' => 'non-base64 altered SPA data',
1522 'err_msg' => 'allowed improper SPA data',
1523 'function' => \&altered_non_base64_spa_data,
1524 'cmdline' => $default_client_args,
1525 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1526 "$fwknopdCmd $default_server_conf_args $intf_str",
1530 'category' => 'Rijndael SPA',
1531 'subcategory' => 'client+server',
1532 'detail' => 'base64 altered SPA data',
1533 'err_msg' => 'allowed improper SPA data',
1534 'function' => \&altered_base64_spa_data,
1535 'cmdline' => $default_client_args,
1536 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1537 "$fwknopdCmd $default_server_conf_args $intf_str",
1541 'category' => 'Rijndael SPA',
1542 'subcategory' => 'client+server',
1543 'detail' => 'appended data to SPA pkt',
1544 'err_msg' => 'allowed improper SPA data',
1545 'function' => \&appended_spa_data,
1546 'cmdline' => $default_client_args,
1547 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1548 "$fwknopdCmd $default_server_conf_args $intf_str",
1552 'category' => 'Rijndael SPA',
1553 'subcategory' => 'client+server',
1554 'detail' => 'prepended data to SPA pkt',
1555 'err_msg' => 'allowed improper SPA data',
1556 'function' => \&prepended_spa_data,
1557 'cmdline' => $default_client_args,
1558 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1559 "$fwknopdCmd $default_server_conf_args $intf_str",
1564 'category' => 'GPG (no pw) SPA',
1565 'subcategory' => 'client+server',
1566 'detail' => 'complete cycle (tcp/22 ssh)',
1567 'err_msg' => 'could not complete SPA cycle',
1568 'function' => \&spa_cycle,
1569 'cmdline' => "$default_client_gpg_args_no_homedir "
1570 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1571 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1572 'fw_rule_created' => $NEW_RULE_REQUIRED,
1573 'fw_rule_removed' => $NEW_RULE_REMOVED,
1577 'category' => 'GPG (no pw) SPA',
1578 'subcategory' => 'client+server',
1579 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1580 'err_msg' => 'could not complete SPA cycle',
1581 'function' => \&spa_cycle,
1582 'cmdline' => "$default_client_gpg_args_no_homedir "
1583 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1584 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1585 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1586 "-a $cf{'multi_gpg_access'} $intf_str " .
1587 "-d $default_digest_file -p $default_pid_file",
1588 'fw_rule_created' => $NEW_RULE_REQUIRED,
1589 'fw_rule_removed' => $NEW_RULE_REMOVED,
1594 'category' => 'GPG (no pw) SPA',
1595 'subcategory' => 'client+server',
1596 'detail' => 'complete cycle (tcp/23 telnet)',
1597 'err_msg' => 'could not complete SPA cycle',
1598 'function' => \&spa_cycle,
1599 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1600 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1601 "$local_key_file --verbose --verbose " .
1602 "--gpg-recipient-key $gpg_server_key " .
1603 "--gpg-signer-key $gpg_client_key " .
1604 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1605 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1606 'fw_rule_created' => $NEW_RULE_REQUIRED,
1607 'fw_rule_removed' => $NEW_RULE_REMOVED,
1611 'category' => 'GPG (no pw) SPA',
1612 'subcategory' => 'client+server',
1613 'detail' => 'complete cycle (tcp/9418 git)',
1614 'err_msg' => 'could not complete SPA cycle',
1615 'function' => \&spa_cycle,
1616 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1617 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1618 "$local_key_file --verbose --verbose " .
1619 "--gpg-recipient-key $gpg_server_key " .
1620 "--gpg-signer-key $gpg_client_key " .
1621 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1622 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1623 'fw_rule_created' => $NEW_RULE_REQUIRED,
1624 'fw_rule_removed' => $NEW_RULE_REMOVED,
1628 'category' => 'GPG (no pw) SPA',
1629 'subcategory' => 'client+server',
1630 'detail' => 'complete cycle (tcp/60001)',
1631 'err_msg' => 'could not complete SPA cycle',
1632 'function' => \&spa_cycle,
1633 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1634 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1635 "$local_key_file --verbose --verbose " .
1636 "--gpg-recipient-key $gpg_server_key " .
1637 "--gpg-signer-key $gpg_client_key " .
1638 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1639 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1640 'fw_rule_created' => $NEW_RULE_REQUIRED,
1641 'fw_rule_removed' => $NEW_RULE_REMOVED,
1646 'category' => 'GPG (no pw) SPA',
1647 'subcategory' => 'client+server',
1648 'detail' => 'complete cycle (udp/53 dns)',
1649 'err_msg' => 'could not complete SPA cycle',
1650 'function' => \&spa_cycle,
1651 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1652 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1653 "$local_key_file --verbose --verbose " .
1654 "--gpg-recipient-key $gpg_server_key " .
1655 "--gpg-signer-key $gpg_client_key " .
1656 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1657 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1658 'fw_rule_created' => $NEW_RULE_REQUIRED,
1659 'fw_rule_removed' => $NEW_RULE_REMOVED,
1664 'category' => 'GPG (no pw) SPA',
1665 'subcategory' => 'client+server',
1666 'detail' => 'replay attack detection',
1667 'err_msg' => 'could not detect replay attack',
1668 'function' => \&replay_detection,
1669 'cmdline' => "$default_client_gpg_args_no_homedir "
1670 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1671 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1672 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1676 'category' => 'GPG (no pw) SPA',
1677 'subcategory' => 'client+server',
1678 'detail' => 'replay detection (GnuPG prefix)',
1679 'err_msg' => 'could not detect replay attack',
1680 'function' => \&replay_detection,
1681 'pkt_prefix' => 'hQ',
1682 'cmdline' => "$default_client_gpg_args_no_homedir "
1683 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1684 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1685 "$fwknopdCmd $default_server_conf_args $intf_str",
1686 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1691 'category' => 'GPG (no pw) SPA',
1692 'subcategory' => 'client+server',
1693 'detail' => 'non-base64 altered SPA data',
1694 'err_msg' => 'allowed improper SPA data',
1695 'function' => \&altered_non_base64_spa_data,
1696 'cmdline' => "$default_client_gpg_args_no_homedir "
1697 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1698 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1702 'category' => 'GPG (no pw) SPA',
1703 'subcategory' => 'client+server',
1704 'detail' => 'base64 altered SPA data',
1705 'err_msg' => 'allowed improper SPA data',
1706 'function' => \&altered_base64_spa_data,
1707 'cmdline' => "$default_client_gpg_args_no_homedir "
1708 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1709 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1713 'category' => 'GPG (no pw) SPA',
1714 'subcategory' => 'client+server',
1715 'detail' => 'appended data to SPA pkt',
1716 'err_msg' => 'allowed improper SPA data',
1717 'function' => \&appended_spa_data,
1718 'cmdline' => "$default_client_gpg_args_no_homedir "
1719 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1720 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1724 'category' => 'GPG (no pw) SPA',
1725 'subcategory' => 'client+server',
1726 'detail' => 'prepended data to SPA pkt',
1727 'err_msg' => 'allowed improper SPA data',
1728 'function' => \&prepended_spa_data,
1729 'cmdline' => "$default_client_gpg_args_no_homedir "
1730 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1731 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1735 'category' => 'GPG (no pw) SPA',
1736 'subcategory' => 'client+server',
1737 'detail' => 'spoof username (tcp/22 ssh)',
1738 'err_msg' => 'could not spoof username',
1739 'function' => \&spoof_username,
1740 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args_no_homedir "
1741 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1742 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1747 'category' => 'GnuPG (GPG) SPA',
1748 'subcategory' => 'client+server',
1749 'detail' => 'complete cycle (tcp/22 ssh)',
1750 'err_msg' => 'could not complete SPA cycle',
1751 'function' => \&spa_cycle,
1752 'cmdline' => $default_client_gpg_args,
1753 'fwknopd_cmdline' => $default_server_gpg_args,
1754 'fw_rule_created' => $NEW_RULE_REQUIRED,
1755 'fw_rule_removed' => $NEW_RULE_REMOVED,
1759 'category' => 'GnuPG (GPG) SPA',
1760 'subcategory' => 'client+server',
1761 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1762 'err_msg' => 'could not complete SPA cycle',
1763 'function' => \&spa_cycle,
1764 'cmdline' => $default_client_gpg_args,
1765 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1766 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1767 "-a $cf{'multi_gpg_access'} $intf_str " .
1768 "-d $default_digest_file -p $default_pid_file",
1769 'fw_rule_created' => $NEW_RULE_REQUIRED,
1770 'fw_rule_removed' => $NEW_RULE_REMOVED,
1775 'category' => 'GnuPG (GPG) SPA',
1776 'subcategory' => 'client+server',
1777 'detail' => 'complete cycle (tcp/23 telnet)',
1778 'err_msg' => 'could not complete SPA cycle',
1779 'function' => \&spa_cycle,
1780 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1781 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1782 "$local_key_file --verbose --verbose " .
1783 "--gpg-recipient-key $gpg_server_key " .
1784 "--gpg-signer-key $gpg_client_key " .
1785 "--gpg-home-dir $gpg_client_home_dir",
1786 'fwknopd_cmdline' => $default_server_gpg_args,
1787 'fw_rule_created' => $NEW_RULE_REQUIRED,
1788 'fw_rule_removed' => $NEW_RULE_REMOVED,
1792 'category' => 'GnuPG (GPG) SPA',
1793 'subcategory' => 'client+server',
1794 'detail' => 'complete cycle (tcp/9418 git)',
1795 'err_msg' => 'could not complete SPA cycle',
1796 'function' => \&spa_cycle,
1797 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1798 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1799 "$local_key_file --verbose --verbose " .
1800 "--gpg-recipient-key $gpg_server_key " .
1801 "--gpg-signer-key $gpg_client_key " .
1802 "--gpg-home-dir $gpg_client_home_dir",
1803 'fwknopd_cmdline' => $default_server_gpg_args,
1804 'fw_rule_created' => $NEW_RULE_REQUIRED,
1805 'fw_rule_removed' => $NEW_RULE_REMOVED,
1809 'category' => 'GnuPG (GPG) SPA',
1810 'subcategory' => 'client+server',
1811 'detail' => 'complete cycle (tcp/60001)',
1812 'err_msg' => 'could not complete SPA cycle',
1813 'function' => \&spa_cycle,
1814 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1815 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1816 "$local_key_file --verbose --verbose " .
1817 "--gpg-recipient-key $gpg_server_key " .
1818 "--gpg-signer-key $gpg_client_key " .
1819 "--gpg-home-dir $gpg_client_home_dir",
1820 'fwknopd_cmdline' => $default_server_gpg_args,
1821 'fw_rule_created' => $NEW_RULE_REQUIRED,
1822 'fw_rule_removed' => $NEW_RULE_REMOVED,
1827 'category' => 'GnuPG (GPG) SPA',
1828 'subcategory' => 'client+server',
1829 'detail' => 'complete cycle (udp/53 dns)',
1830 'err_msg' => 'could not complete SPA cycle',
1831 'function' => \&spa_cycle,
1832 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1833 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1834 "$local_key_file --verbose --verbose " .
1835 "--gpg-recipient-key $gpg_server_key " .
1836 "--gpg-signer-key $gpg_client_key " .
1837 "--gpg-home-dir $gpg_client_home_dir",
1838 'fwknopd_cmdline' => $default_server_gpg_args,
1839 'fw_rule_created' => $NEW_RULE_REQUIRED,
1840 'fw_rule_removed' => $NEW_RULE_REMOVED,
1845 'category' => 'GnuPG (GPG) SPA',
1846 'subcategory' => 'client+server',
1847 'detail' => 'replay attack detection',
1848 'err_msg' => 'could not detect replay attack',
1849 'function' => \&replay_detection,
1850 'cmdline' => $default_client_gpg_args,
1851 'fwknopd_cmdline' => $default_server_gpg_args,
1852 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1856 'category' => 'GnuPG (GPG) SPA',
1857 'subcategory' => 'client+server',
1858 'detail' => 'replay detection (GnuPG prefix)',
1859 'err_msg' => 'could not detect replay attack',
1860 'function' => \&replay_detection,
1861 'pkt_prefix' => 'hQ',
1862 'cmdline' => $default_client_gpg_args,
1863 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1864 "$fwknopdCmd $default_server_conf_args $intf_str",
1865 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1870 'category' => 'GnuPG (GPG) SPA',
1871 'subcategory' => 'client+server',
1872 'detail' => 'non-base64 altered SPA data',
1873 'err_msg' => 'allowed improper SPA data',
1874 'function' => \&altered_non_base64_spa_data,
1875 'cmdline' => $default_client_gpg_args,
1876 'fwknopd_cmdline' => $default_server_gpg_args,
1880 'category' => 'GnuPG (GPG) SPA',
1881 'subcategory' => 'client+server',
1882 'detail' => 'base64 altered SPA data',
1883 'err_msg' => 'allowed improper SPA data',
1884 'function' => \&altered_base64_spa_data,
1885 'cmdline' => $default_client_gpg_args,
1886 'fwknopd_cmdline' => $default_server_gpg_args,
1890 'category' => 'GnuPG (GPG) SPA',
1891 'subcategory' => 'client+server',
1892 'detail' => 'appended data to SPA pkt',
1893 'err_msg' => 'allowed improper SPA data',
1894 'function' => \&appended_spa_data,
1895 'cmdline' => $default_client_gpg_args,
1896 'fwknopd_cmdline' => $default_server_gpg_args,
1900 'category' => 'GnuPG (GPG) SPA',
1901 'subcategory' => 'client+server',
1902 'detail' => 'prepended data to SPA pkt',
1903 'err_msg' => 'allowed improper SPA data',
1904 'function' => \&prepended_spa_data,
1905 'cmdline' => $default_client_gpg_args,
1906 'fwknopd_cmdline' => $default_server_gpg_args,
1910 'category' => 'GnuPG (GPG) SPA',
1911 'subcategory' => 'client+server',
1912 'detail' => 'spoof username (tcp/22 ssh)',
1913 'err_msg' => 'could not spoof username',
1914 'function' => \&spoof_username,
1915 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args",
1916 'fwknopd_cmdline' => $default_server_gpg_args,
1920 'category' => 'GnuPG (GPG) SPA',
1921 'subcategory' => 'server',
1922 'detail' => 'digest cache structure',
1923 'err_msg' => 'improper digest cache structure',
1924 'function' => \&digest_cache_structure,
1929 if ($use_valgrind) {
1932 'category' => 'valgrind output',
1933 'subcategory' => 'flagged functions',
1935 'err_msg' => 'could not parse flagged functions',
1936 'function' => \&parse_valgrind_flagged_functions,
1942 'category' => $REQUIRED,
1943 'subcategory' => $OPTIONAL,
1944 'detail' => $REQUIRED,
1945 'function' => $REQUIRED,
1946 'binary' => $OPTIONAL,
1947 'cmdline' => $OPTIONAL,
1948 'fwknopd_cmdline' => $OPTIONAL,
1949 'fatal' => $OPTIONAL,
1950 'exec_err' => $OPTIONAL,
1951 'fw_rule_created' => $OPTIONAL,
1952 'fw_rule_removed' => $OPTIONAL,
1953 'server_conf' => $OPTIONAL,
1954 'pkt_prefix' => $OPTIONAL,
1955 'no_ip_check' => $OPTIONAL,
1956 'positive_output_matches' => $OPTIONAL,
1957 'negative_output_matches' => $OPTIONAL,
1958 'server_positive_output_matches' => $OPTIONAL,
1959 'server_negative_output_matches' => $OPTIONAL,
1960 'replay_positive_output_matches' => $OPTIONAL,
1961 'replay_negative_output_matches' => $OPTIONAL,
1965 &diff_test_results();
1969 ### make sure everything looks as expected before continuing
1972 &logr("\n[+] Starting the fwknop test suite...\n\n" .
1973 " args: @args_cp\n\n"
1976 ### save the results from any previous test suite run
1977 ### so that we can potentially compare them with --diff
1978 if ($saved_last_results) {
1979 &logr(" Saved results from previous run " .
1980 "to: ${output_dir}.last/\n\n");
1983 ### main loop through all of the tests
1984 for my $test_hr (@tests) {
1985 &run_test($test_hr);
1988 &logr("\n[+] passed/failed/executed: $passed/$failed/$executed tests\n\n");
1990 copy $logfile, "$output_dir/$logfile" or die $!;
1994 #===================== end main =======================
1997 my $test_hr = shift;
1999 my $msg = "[$test_hr->{'category'}]";
2000 $msg .= " [$test_hr->{'subcategory'}]" if $test_hr->{'subcategory'};
2001 $msg .= " $test_hr->{'detail'}";
2003 return unless &process_include_exclude($msg);
2013 $current_test_file = "$output_dir/$executed.test";
2014 $server_test_file = "$output_dir/${executed}_fwknopd.test";
2016 &write_test_file("[+] TEST: $msg\n", $current_test_file);
2017 $test_hr->{'msg'} = $msg;
2018 if (&{$test_hr->{'function'}}($test_hr)) {
2019 &logr("pass ($executed)\n");
2022 &logr("fail ($executed)\n");
2025 if ($test_hr->{'fatal'} eq $YES) {
2026 die "[*] required test failed, exiting.";
2033 sub process_include_exclude() {
2036 ### inclusions/exclusions
2037 if (@tests_to_include) {
2039 for my $test (@tests_to_include) {
2040 if ($msg =~ $test or ($use_valgrind
2041 and $msg =~ /valgrind\soutput/)) {
2046 return 0 unless $found;
2048 if (@tests_to_exclude) {
2050 for my $test (@tests_to_exclude) {
2051 if ($msg =~ $test) {
2061 sub diff_test_results() {
2063 $diff_dir1 = "${output_dir}.last" unless $diff_dir1;
2064 $diff_dir2 = $output_dir unless $diff_dir2;
2066 die "[*] Need results from a previous run before running --diff"
2067 unless -d $diff_dir2;
2068 die "[*] Current results set does not exist." unless -d $diff_dir1;
2070 my %current_tests = ();
2071 my %previous_tests = ();
2073 ### Only diff results for matching tests (parse the logfile to see which
2074 ### test numbers match across the two test cycles).
2075 &build_results_hash(\%current_tests, $diff_dir1);
2076 &build_results_hash(\%previous_tests, $diff_dir2);
2078 for my $test_msg (sort {$current_tests{$a}{'num'} <=> $current_tests{$b}{'num'}}
2079 keys %current_tests) {
2080 my $current_result = $current_tests{$test_msg}{'pass_fail'};
2081 my $current_num = $current_tests{$test_msg}{'num'};
2082 if (defined $previous_tests{$test_msg}) {
2083 print "[+] Checking: $test_msg\n";
2084 my $previous_result = $previous_tests{$test_msg}{'pass_fail'};
2085 my $previous_num = $previous_tests{$test_msg}{'num'};
2086 if ($current_result ne $previous_result) {
2087 print " DIFF: **$current_result** $test_msg\n";
2090 &diff_results($previous_num, $current_num);
2098 sub diff_results() {
2099 my ($previous_num, $current_num) = @_;
2101 ### edit out any valgrind "==354==" prefixes
2102 my $valgrind_search_re = qr/^==\d+==\s/;
2104 ### remove CMD timestamps
2105 my $cmd_search_re = qr/^\S+\s.*?\s\d{4}\sCMD\:/;
2107 for my $file ("$diff_dir1/${previous_num}.test",
2108 "$diff_dir1/${previous_num}_fwknopd.test",
2109 "$diff_dir2/${current_num}.test",
2110 "$diff_dir2/${current_num}_fwknopd.test",
2112 system qq{perl -p -i -e 's|$valgrind_search_re||' $file} if -e $file;
2113 system qq{perl -p -i -e 's|$cmd_search_re|CMD:|' $file} if -e $file;
2116 if (-e "$diff_dir1/${previous_num}.test"
2117 and -e "$diff_dir2/${current_num}.test") {
2118 system "diff -u $diff_dir1/${previous_num}.test " .
2119 "$diff_dir2/${current_num}.test";
2122 if (-e "$diff_dir1/${previous_num}_fwknopd.test"
2123 and -e "$diff_dir2/${current_num}_fwknopd.test") {
2124 system "diff -u $diff_dir1/${previous_num}_fwknopd.test " .
2125 "$diff_dir2/${current_num}_fwknopd.test";
2131 sub build_results_hash() {
2132 my ($hr, $dir) = @_;
2134 open F, "< $dir/$logfile" or die $!;
2136 if (/^(.*?)\.\.\..*(pass|fail)\s\((\d+)\)/) {
2137 $hr->{$1}{'pass_fail'} = $2;
2138 $hr->{$1}{'num'} = $3;
2144 sub compile_warnings() {
2146 ### 'make clean' as root
2147 return 0 unless &run_cmd('make -C .. clean',
2148 $cmd_out_tmp, $current_test_file);
2151 my $username = getpwuid((stat($configure_path))[4]);
2152 die "[*] Could not determine $configure_path owner"
2155 return 0 unless &run_cmd("$sudo_path -u $username make -C ..",
2156 $cmd_out_tmp, $current_test_file);
2160 return 0 unless &run_cmd('make -C ..',
2161 $cmd_out_tmp, $current_test_file);
2165 ### look for compilation warnings - something like:
2166 ### warning: ‘test’ is used uninitialized in this function
2167 return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
2168 $MATCH_ANY, $current_test_file);
2170 ### the new binaries should exist
2171 unless (-e $fwknopCmd and -x $fwknopCmd) {
2172 &write_test_file("[-] $fwknopCmd does not exist or not executable.\n",
2173 $current_test_file);
2175 unless (-e $fwknopdCmd and -x $fwknopdCmd) {
2176 &write_test_file("[-] $fwknopdCmd does not exist or not executable.\n",
2177 $current_test_file);
2183 sub make_distcheck() {
2185 ### 'make clean' as root
2186 return 0 unless &run_cmd('make -C .. distcheck',
2187 $cmd_out_tmp, $current_test_file);
2189 ### look for compilation warnings - something like:
2190 ### warning: ‘test’ is used uninitialized in this function
2191 return 1 if &file_find_regex([qr/archives\sready\sfor\sdistribution/],
2192 $MATCH_ALL, $current_test_file);
2198 sub binary_exists() {
2199 my $test_hr = shift;
2200 return 0 unless $test_hr->{'binary'};
2202 ### account for different libfko.so paths (e.g. libfko.so.0.3 with no
2203 ### libfko.so link on OpenBSD, and libfko.dylib path on Mac OS X)
2205 if ($test_hr->{'binary'} =~ /libfko/) {
2206 unless (-e $test_hr->{'binary'}) {
2207 my $file = "$lib_dir/libfko.dylib";
2209 $test_hr->{'binary'} = $file;
2210 $libfko_bin = $file;
2212 for my $f (glob("$lib_dir/libfko.so*")) {
2213 if (-e $f and -x $f) {
2214 $test_hr->{'binary'} = $f;
2223 return 0 unless -e $test_hr->{'binary'} and -x $test_hr->{'binary'};
2227 sub expected_code_version() {
2228 my $test_hr = shift;
2230 unless (-e '../VERSION') {
2231 &write_test_file("[-] ../VERSION file does not exist.\n",
2232 $current_test_file);
2236 open F, '< ../VERSION' or die $!;
2239 if ($line =~ /(\d.*\d)/) {
2241 return 0 unless &run_cmd($test_hr->{'cmdline'},
2242 $cmd_out_tmp, $current_test_file);
2243 return 1 if &file_find_regex([qr/$version/],
2244 $MATCH_ALL, $current_test_file);
2249 sub client_send_spa_packet() {
2250 my $test_hr = shift;
2252 &write_key('fwknoptest', $local_key_file);
2254 return 0 unless &run_cmd($test_hr->{'cmdline'},
2255 $cmd_out_tmp, $current_test_file);
2256 return 0 unless &file_find_regex([qr/final\spacked/i],
2257 $MATCH_ALL, $current_test_file);
2262 sub permissions_check() {
2263 my $test_hr = shift;
2266 chmod 0777, $cf{'def'} or die $!;
2267 chmod 0777, $cf{'def_access'} or die $!;
2269 $rv = &spa_cycle($test_hr);
2271 chmod 0600, $cf{'def'} or die $!;
2272 chmod 0600, $cf{'def_access'} or die $!;
2274 if ($test_hr->{'server_positive_output_matches'}) {
2275 $rv = 0 unless &file_find_regex(
2276 $test_hr->{'server_positive_output_matches'},
2277 $MATCH_ALL, $server_test_file);
2283 my $test_hr = shift;
2285 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2286 = &client_server_interaction($test_hr, [], $USE_CLIENT);
2288 if ($test_hr->{'fw_rule_created'} eq $NEW_RULE_REQUIRED) {
2289 $rv = 0 unless $fw_rule_created;
2290 } elsif ($test_hr->{'fw_rule_created'} eq $REQUIRE_NO_NEW_RULE) {
2291 $rv = 0 if $fw_rule_created;
2294 if ($test_hr->{'fw_rule_removed'} eq $NEW_RULE_REMOVED) {
2295 $rv = 0 unless $fw_rule_removed;
2296 } elsif ($test_hr->{'fw_rule_removed'} eq $REQUIRE_NO_NEW_REMOVED) {
2297 $rv = 0 if $fw_rule_removed;
2300 if ($test_hr->{'server_positive_output_matches'}) {
2301 $rv = 0 unless &file_find_regex(
2302 $test_hr->{'server_positive_output_matches'},
2303 $MATCH_ALL, $server_test_file);
2306 if ($test_hr->{'server_negative_output_matches'}) {
2307 $rv = 0 if &file_find_regex(
2308 $test_hr->{'server_negative_output_matches'},
2309 $MATCH_ANY, $server_test_file);
2315 sub spoof_username() {
2316 my $test_hr = shift;
2318 my $rv = &spa_cycle($test_hr);
2320 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2321 $MATCH_ALL, $current_test_file)) {
2325 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2326 $MATCH_ALL, $server_test_file)) {
2333 sub replay_detection() {
2334 my $test_hr = shift;
2336 ### do a complete SPA cycle and then parse the SPA packet out of the
2337 ### current test file and re-send
2339 return 0 unless &spa_cycle($test_hr);
2341 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2344 &write_test_file("[-] could not get SPA packet " .
2345 "from file: $current_test_file\n",
2346 $current_test_file);
2350 if ($test_hr->{'pkt_prefix'}) {
2351 $spa_pkt = $test_hr->{'pkt_prefix'} . $spa_pkt;
2357 'port' => $default_spa_port,
2358 'dst_ip' => $loopback_ip,
2363 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2364 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2366 $rv = 0 unless $server_was_stopped;
2368 if ($test_hr->{'replay_positive_output_matches'}) {
2369 $rv = 0 unless &file_find_regex(
2370 $test_hr->{'replay_positive_output_matches'},
2371 $MATCH_ALL, $server_test_file);
2374 if ($test_hr->{'replay_negative_output_matches'}) {
2375 $rv = 0 if &file_find_regex(
2376 $test_hr->{'replay_negative_output_matches'},
2377 $MATCH_ANY, $server_test_file);
2383 sub digest_cache_structure() {
2384 my $test_hr = shift;
2387 &run_cmd("file $default_digest_file", $cmd_out_tmp, $current_test_file);
2389 if (&file_find_regex([qr/ASCII/i], $MATCH_ALL, $cmd_out_tmp)) {
2391 ### the format should be:
2392 ### <digest> <proto> <src_ip> <src_port> <dst_ip> <dst_port> <time>
2393 open F, "< $default_digest_file" or
2394 die "[*] could not open $default_digest_file: $!";
2398 unless (m|^\S+\s+\d+\s+$ip_re\s+\d+\s+$ip_re\s+\d+\s+\d+|) {
2399 &write_test_file("[-] invalid digest.cache line: $_",
2400 $current_test_file);
2406 } elsif (&file_find_regex([qr/dbm/i], $MATCH_ALL, $cmd_out_tmp)) {
2407 &write_test_file("[+] DBM digest file format, " .
2408 "assuming this is valid.\n", $current_test_file);
2410 ### don't know what kind of file the digest.cache is
2411 &write_test_file("[-] unrecognized file type for " .
2412 "$default_digest_file.\n", $current_test_file);
2417 &write_test_file("[+] valid digest.cache structure.\n",
2418 $current_test_file);
2424 sub server_bpf_ignore_packet() {
2425 my $test_hr = shift;
2428 my $server_was_stopped = 0;
2429 my $fw_rule_created = 0;
2430 my $fw_rule_removed = 0;
2432 unless (&client_send_spa_packet($test_hr)) {
2433 &write_test_file("[-] fwknop client execution error.\n",
2434 $current_test_file);
2438 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2441 &write_test_file("[-] could not get SPA packet " .
2442 "from file: $current_test_file\n", $current_test_file);
2449 'port' => $default_spa_port,
2450 'dst_ip' => $loopback_ip,
2455 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2456 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2458 unless (&file_find_regex([qr/PCAP\sfilter.*\s$non_std_spa_port/],
2459 $MATCH_ALL, $server_test_file)) {
2466 sub altered_non_base64_spa_data() {
2467 my $test_hr = shift;
2470 my $server_was_stopped = 0;
2471 my $fw_rule_created = 0;
2472 my $fw_rule_removed = 0;
2474 unless (&client_send_spa_packet($test_hr)) {
2475 &write_test_file("[-] fwknop client execution error.\n",
2476 $current_test_file);
2480 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2483 &write_test_file("[-] could not get SPA packet " .
2484 "from file: $current_test_file\n", $current_test_file);
2488 ### alter one byte (change to a ":")
2489 $spa_pkt =~ s|^(.{3}).|$1:|;
2494 'port' => $default_spa_port,
2495 'dst_ip' => $loopback_ip,
2500 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2501 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2503 $rv = 0 unless $server_was_stopped;
2509 my $test_hr = shift;
2512 my $server_was_stopped = 0;
2513 my $fw_rule_created = 0;
2514 my $fw_rule_removed = 0;
2519 'port' => $default_spa_port,
2520 'dst_ip' => $loopback_ip,
2521 'data' => $test_hr->{'fuzzing_pkt'},
2525 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2526 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2528 $rv = 0 unless $server_was_stopped;
2530 if ($fw_rule_created) {
2531 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2534 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2537 if ($test_hr->{'server_positive_output_matches'}) {
2538 $rv = 0 unless &file_find_regex(
2539 $test_hr->{'server_positive_output_matches'},
2540 $MATCH_ALL, $server_test_file);
2546 sub altered_base64_spa_data() {
2547 my $test_hr = shift;
2550 my $server_was_stopped = 0;
2551 my $fw_rule_created = 0;
2552 my $fw_rule_removed = 0;
2554 unless (&client_send_spa_packet($test_hr)) {
2555 &write_test_file("[-] fwknop client execution error.\n",
2556 $current_test_file);
2560 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2563 &write_test_file("[-] could not get SPA packet " .
2564 "from file: $current_test_file\n", $current_test_file);
2568 $spa_pkt =~ s|^(.{3}).|AAAA|;
2573 'port' => $default_spa_port,
2574 'dst_ip' => $loopback_ip,
2579 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2580 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2582 $rv = 0 unless $server_was_stopped;
2584 if ($fw_rule_created) {
2585 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2588 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2591 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2592 $MATCH_ALL, $server_test_file)) {
2599 sub appended_spa_data() {
2600 my $test_hr = shift;
2603 my $server_was_stopped = 0;
2604 my $fw_rule_created = 0;
2605 my $fw_rule_removed = 0;
2607 unless (&client_send_spa_packet($test_hr)) {
2608 &write_test_file("[-] fwknop client execution error.\n",
2609 $current_test_file);
2613 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2616 &write_test_file("[-] could not get SPA packet " .
2617 "from file: $current_test_file\n", $current_test_file);
2626 'port' => $default_spa_port,
2627 'dst_ip' => $loopback_ip,
2632 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2633 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2635 $rv = 0 unless $server_was_stopped;
2637 if ($fw_rule_created) {
2638 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2641 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2644 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2645 $MATCH_ALL, $server_test_file)) {
2652 sub prepended_spa_data() {
2653 my $test_hr = shift;
2656 my $server_was_stopped = 0;
2657 my $fw_rule_created = 0;
2658 my $fw_rule_removed = 0;
2660 unless (&client_send_spa_packet($test_hr)) {
2661 &write_test_file("[-] fwknop client execution error.\n",
2662 $current_test_file);
2666 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2669 &write_test_file("[-] could not get SPA packet " .
2670 "from file: $current_test_file\n", $current_test_file);
2674 $spa_pkt = 'AAAA' . $spa_pkt;
2679 'port' => $default_spa_port,
2680 'dst_ip' => $loopback_ip,
2685 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2686 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2688 $rv = 0 unless $server_was_stopped;
2690 if ($fw_rule_created) {
2691 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2694 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2697 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2698 $MATCH_ALL, $server_test_file)) {
2705 sub server_start() {
2706 my $test_hr = shift;
2708 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2709 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2711 unless (&file_find_regex([qr/Starting\sfwknopd\smain\sevent\sloop/],
2712 $MATCH_ALL, $server_test_file)) {
2716 $rv = 0 unless $server_was_stopped;
2722 my $test_hr = shift;
2724 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2725 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2727 $rv = 0 unless $server_was_stopped;
2732 sub server_packet_limit() {
2733 my $test_hr = shift;
2738 'port' => $default_spa_port,
2739 'dst_ip' => $loopback_ip,
2744 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2745 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2747 if (&is_fwknopd_running()) {
2752 unless (&file_find_regex([qr/count\slimit\sof\s1\sreached/],
2753 $MATCH_ALL, $server_test_file)) {
2757 unless (&file_find_regex([qr/Shutting\sDown\sfwknopd/i],
2758 $MATCH_ALL, $server_test_file)) {
2765 sub server_ignore_small_packets() {
2766 my $test_hr = shift;
2771 'port' => $default_spa_port,
2772 'dst_ip' => $loopback_ip,
2773 'data' => 'A'x120, ### < MIN_SPA_DATA_SIZE
2777 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2778 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2782 if (&is_fwknopd_running()) {
2790 sub client_server_interaction() {
2791 my ($test_hr, $pkts_hr, $spa_client_flag) = @_;
2794 my $server_was_stopped = 1;
2795 my $fw_rule_created = 1;
2796 my $fw_rule_removed = 0;
2798 ### start fwknopd to monitor for the SPA packet over the loopback interface
2799 my $fwknopd_parent_pid = &start_fwknopd($test_hr);
2801 ### give fwknopd a chance to parse its config and start sniffing
2802 ### on the loopback interface
2803 if ($use_valgrind) {
2809 ### send the SPA packet(s) to the server either manually using IO::Socket or
2810 ### with the fwknopd client
2811 if ($spa_client_flag == $USE_CLIENT) {
2812 unless (&client_send_spa_packet($test_hr)) {
2813 &write_test_file("[-] fwknop client execution error.\n",
2814 $current_test_file);
2818 &send_packets($pkts_hr);
2821 ### check to see if the SPA packet resulted in a new fw access rule
2823 while (not &is_fw_rule_active($test_hr)) {
2824 &write_test_file("[-] new fw rule does not exist.\n",
2825 $current_test_file);
2831 $fw_rule_created = 0;
2832 $fw_rule_removed = 0;
2835 &time_for_valgrind() if $use_valgrind;
2837 if ($fw_rule_created) {
2838 sleep 3; ### allow time for rule time out.
2839 if (&is_fw_rule_active($test_hr)) {
2840 &write_test_file("[-] new fw rule not timed out.\n",
2841 $current_test_file);
2844 &write_test_file("[+] new fw rule timed out.\n",
2845 $current_test_file);
2846 $fw_rule_removed = 1;
2850 if (&is_fwknopd_running()) {
2852 unless (&file_find_regex([qr/Got\sSIGTERM/],
2853 $MATCH_ALL, $server_test_file)) {
2854 $server_was_stopped = 0;
2857 &write_test_file("[-] server is not running.\n",
2858 $current_test_file);
2859 $server_was_stopped = 0;
2862 return ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed);
2865 sub get_spa_packet_from_file() {
2870 my $found_trigger_line = 0;
2871 open F, "< $file" or die "[*] Could not open file $file: $!";
2873 if (/final\spacked/i) {
2874 $found_trigger_line = 1;
2877 next unless $found_trigger_line;
2879 ### the next line with non whitespace is the SPA packet
2890 sub send_packets() {
2891 my $pkts_ar = shift;
2893 open F, ">> $current_test_file" or die $!;
2894 print F "[+] send_packets(): Sending the following packets...\n";
2895 print F Dumper $pkts_ar;
2898 for my $pkt_hr (@$pkts_ar) {
2899 if ($pkt_hr->{'proto'} eq 'tcp' or $pkt_hr->{'proto'} eq 'udp') {
2900 my $socket = IO::Socket::INET->new(
2901 PeerAddr => $pkt_hr->{'dst_ip'},
2902 PeerPort => $pkt_hr->{'port'},
2903 Proto => $pkt_hr->{'proto'},
2905 ) or die "[*] Could not acquire $pkt_hr->{'proto'}/$pkt_hr->{'port'} " .
2906 "socket to $pkt_hr->{'dst_ip'}: $!";
2908 $socket->send($pkt_hr->{'data'});
2911 } elsif ($pkt_hr->{'proto'} eq 'http') {
2913 } elsif ($pkt_hr->{'proto'} eq 'icmp') {
2917 sleep $pkt_hr->{'delay'} if defined $pkt_hr->{'delay'};
2922 sub generic_exec() {
2923 my $test_hr = shift;
2927 my $exec_rv = &run_cmd($test_hr->{'cmdline'},
2928 $cmd_out_tmp, $current_test_file);
2930 if ($test_hr->{'exec_err'} eq $YES) {
2931 $rv = 0 if $exec_rv;
2933 $rv = 0 unless $exec_rv;
2936 if ($test_hr->{'positive_output_matches'}) {
2937 $rv = 0 unless &file_find_regex(
2938 $test_hr->{'positive_output_matches'},
2939 $MATCH_ALL, $current_test_file);
2942 if ($test_hr->{'negative_output_matches'}) {
2943 $rv = 0 if &file_find_regex(
2944 $test_hr->{'negative_output_matches'},
2945 $MATCH_ANY, $current_test_file);
2953 my $test_hr = shift;
2954 return 0 unless $test_hr->{'binary'};
2955 &run_cmd("./hardening-check $test_hr->{'binary'}",
2956 $cmd_out_tmp, $current_test_file);
2957 return 0 if &file_find_regex([qr/Position\sIndependent.*:\sno/i],
2958 $MATCH_ALL, $current_test_file);
2962 ### check for stack protection
2963 sub stack_protected_binary() {
2964 my $test_hr = shift;
2965 return 0 unless $test_hr->{'binary'};
2966 &run_cmd("./hardening-check $test_hr->{'binary'}",
2967 $cmd_out_tmp, $current_test_file);
2968 return 0 if &file_find_regex([qr/Stack\sprotected.*:\sno/i],
2969 $MATCH_ALL, $current_test_file);
2973 ### check for fortified source functions
2974 sub fortify_source_functions() {
2975 my $test_hr = shift;
2976 return 0 unless $test_hr->{'binary'};
2977 &run_cmd("./hardening-check $test_hr->{'binary'}",
2978 $cmd_out_tmp, $current_test_file);
2979 return 0 if &file_find_regex([qr/Fortify\sSource\sfunctions:\sno/i],
2980 $MATCH_ALL, $current_test_file);
2984 ### check for read-only relocations
2985 sub read_only_relocations() {
2986 my $test_hr = shift;
2987 return 0 unless $test_hr->{'binary'};
2988 &run_cmd("./hardening-check $test_hr->{'binary'}",
2989 $cmd_out_tmp, $current_test_file);
2990 return 0 if &file_find_regex([qr/Read.only\srelocations:\sno/i],
2991 $MATCH_ALL, $current_test_file);
2995 ### check for immediate binding
2996 sub immediate_binding() {
2997 my $test_hr = shift;
2998 return 0 unless $test_hr->{'binary'};
2999 &run_cmd("./hardening-check $test_hr->{'binary'}",
3000 $cmd_out_tmp, $current_test_file);
3001 return 0 if &file_find_regex([qr/Immediate\sbinding:\sno/i],
3002 $MATCH_ALL, $current_test_file);
3008 &run_cmd("LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd " .
3009 "$default_server_conf_args --fw-list-all",
3010 $cmd_out_tmp, $current_test_file);
3018 'ls -l /etc', 'if [ -e /etc/issue ]; then cat /etc/issue; fi',
3019 'if [ `which iptables` ]; then iptables -V; fi',
3020 'if [ -e /proc/cpuinfo ]; then cat /proc/cpuinfo; fi',
3021 'if [ -e /proc/config.gz ]; then zcat /proc/config.gz; fi',
3022 'if [ `which gpg` ]; then gpg --version; fi',
3023 'if [ `which tcpdump` ]; then ldd `which tcpdump`; fi',
3027 'ls -l /usr/lib/*pcap*',
3028 'ls -l /usr/local/lib/*pcap*',
3029 'ls -l /usr/lib/*fko*',
3030 'ls -l /usr/local/lib/*fko*',
3032 &run_cmd($cmd, $cmd_out_tmp, $current_test_file);
3034 if ($cmd =~ /^ldd/) {
3035 $have_gpgme++ if &file_find_regex([qr/gpgme/],
3036 $MATCH_ALL, $cmd_out_tmp);
3040 ### all three of fwknop/fwknopd/libfko must link against gpgme in order
3041 ### to enable gpg tests
3042 unless ($have_gpgme == 3) {
3043 push @tests_to_exclude, qr/GPG/;
3049 sub time_for_valgrind() {
3051 while (&run_cmd("ps axuww | grep LD_LIBRARY_PATH | " .
3052 "grep valgrind |grep -v perl | grep -v grep",
3053 $cmd_out_tmp, $current_test_file)) {
3061 sub anonymize_results() {
3063 die "[*] $output_dir does not exist" unless -d $output_dir;
3064 die "[*] $logfile does not exist, has $0 been executed?"
3067 unlink $tarfile or die "[*] Could not unlink $tarfile: $!";
3070 ### remove non-loopback IP addresses
3071 my $search_re = qr/\b127\.0\.0\.1\b/;
3072 system "perl -p -i -e 's|$search_re|00MY1271STR00|g' $output_dir/*.test";
3073 $search_re = qr/\b127\.0\.0\.2\b/;
3074 system "perl -p -i -e 's|$search_re|00MY1272STR00|g' $output_dir/*.test";
3075 $search_re = qr/\b0\.0\.0\.0\b/;
3076 system "perl -p -i -e 's|$search_re|00MY0000STR00|g' $output_dir/*.test";
3077 $search_re = qr/\b(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}\b/;
3078 system "perl -p -i -e 's|$search_re|N.N.N.N|g' $output_dir/*.test";
3079 system "perl -p -i -e 's|00MY1271STR00|127.0.0.1|g' $output_dir/*.test";
3080 system "perl -p -i -e 's|00MY1272STR00|127.0.0.2|g' $output_dir/*.test";
3081 system "perl -p -i -e 's|00MY0000STR00|0.0.0.0|g' $output_dir/*.test";
3083 ### remove hostname from any uname output
3084 $search_re = qr/\suname\s+\-a\s*\n\s*(\S+)\s+\S+/;
3085 system "perl -p -i -e 'undef \$/; s|$search_re" .
3086 "| uname -a\n\$1 (removed)|s' $output_dir/*.test";
3088 $search_re = qr/uname=\x27(\S+)\s+\S+/;
3089 system "perl -p -i -e 's|$search_re|uname= \$1 (removed)|' $output_dir/*.test";
3092 system "tar cvfz $tarfile $logfile $output_dir";
3093 print "[+] Anonymized test results file: $tarfile\n";
3102 my $test_hr = shift;
3104 open F, "> $default_pid_file" or die $!;
3108 &server_start($test_hr);
3110 open F, "< $default_pid_file" or die $!;
3122 sub start_fwknopd() {
3123 my $test_hr = shift;
3125 &write_test_file("[+] TEST: $test_hr->{'msg'}\n", $server_test_file);
3128 die "[*] Could not fork: $!" unless defined $pid;
3132 ### we are the child, so start fwknopd
3133 exit &run_cmd($test_hr->{'fwknopd_cmdline'},
3134 $server_cmd_tmp, $server_test_file);
3140 my ($key, $file) = @_;
3142 open K, "> $file" or die "[*] Could not open $file: $!";
3143 print K "$loopback_ip: $key\n";
3144 print K "localhost: $key\n";
3145 print K "some.host.through.proxy.com: $key\n";
3151 open C, ">> $current_test_file"
3152 or die "[*] Could not open $current_test_file: $!";
3153 print C "\n" . localtime() . " [+] PID dump:\n";
3155 &run_cmd("ps auxww | grep knop |grep -v grep",
3156 $cmd_out_tmp, $current_test_file);
3161 my ($cmd, $cmd_out, $file) = @_;
3165 or die "[*] Could not open $file: $!";
3166 print F localtime() . " CMD: $cmd\n";
3170 or die "[*] Could not open $file: $!";
3171 print F localtime() . " CMD: $cmd\n";
3175 ### copy original file descriptors (credit: Perl Cookbook)
3176 open OLDOUT, ">&STDOUT";
3177 open OLDERR, ">&STDERR";
3179 ### redirect command output
3180 open STDOUT, "> $cmd_out" or die "[*] Could not redirect stdout: $!";
3181 open STDERR, ">&STDOUT" or die "[*] Could not dup stdout: $!";
3183 my $rv = ((system $cmd) >> 8);
3185 close STDOUT or die "[*] Could not close STDOUT: $!";
3186 close STDERR or die "[*] Could not close STDERR: $!";
3188 ### restore original filehandles
3189 open STDERR, ">&OLDERR" or die "[*] Could not restore stderr: $!";
3190 open STDOUT, ">&OLDOUT" or die "[*] Could not restore stdout: $!";
3192 ### close the old copies
3193 close OLDOUT or die "[*] Could not close OLDOUT: $!";
3194 close OLDERR or die "[*] Could not close OLDERR: $!";
3196 open C, "< $cmd_out" or die "[*] Could not open $cmd_out: $!";
3197 my @cmd_lines = <C>;
3200 open F, ">> $file" or die "[*] Could not open $file: $!";
3201 print F $_ for @cmd_lines;
3214 for (my $i=length($msg); $i < $PRINT_LEN; $i++) {
3223 $|++; ### turn off buffering
3225 $< == 0 && $> == 0 or
3226 die "[*] $0: You must be root (or equivalent ",
3227 "UID 0 account) to effectively test fwknop";
3229 ### validate test hashes
3231 for my $test_hr (@tests) {
3232 for my $key (keys %test_keys) {
3233 if ($test_keys{$key} == $REQUIRED) {
3234 die "[*] Missing '$key' element in hash: $hash_num"
3235 unless defined $test_hr->{$key};
3237 $test_hr->{$key} = '' unless defined $test_hr->{$key};
3243 if ($use_valgrind) {
3244 die "[*] $valgrindCmd exec problem, use --valgrind-path"
3245 unless -e $valgrindCmd and -x $valgrindCmd;
3248 die "[*] $conf_dir directory does not exist." unless -d $conf_dir;
3249 die "[*] $lib_dir directory does not exist." unless -d $lib_dir;
3251 for my $name (keys %cf) {
3252 die "[*] $cf{$name} does not exist" unless -e $cf{$name};
3253 chmod 0600, $cf{$name} or die "[*] Could not chmod 0600 $cf{$name}";
3256 if (-d $output_dir) {
3257 if (-d "${output_dir}.last") {
3258 rmtree "${output_dir}.last"
3259 or die "[*] rmtree ${output_dir}.last $!";
3261 mkdir "${output_dir}.last"
3262 or die "[*] ${output_dir}.last: $!";
3263 for my $file (glob("$output_dir/*.test")) {
3264 if ($file =~ m|.*/(.*)|) {
3265 copy $file, "${output_dir}.last/$1" or die $!;
3268 if (-e "$output_dir/init") {
3269 copy "$output_dir/init", "${output_dir}.last/init";
3272 copy $logfile, "${output_dir}.last/$logfile" or die $!;
3274 $saved_last_results = 1;
3276 mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!";
3280 rmtree $run_dir or die $!;
3282 mkdir $run_dir or die "[*] Could not mkdir $run_dir: $!";
3284 for my $file (glob("$output_dir/*.test")) {
3285 unlink $file or die "[*] Could not unlink($file)";
3287 if (-e "$output_dir/init") {
3288 unlink "$output_dir/init" or die $!;
3292 unlink $logfile or die $!;
3295 if ($test_include) {
3296 for my $re (split /\s*,\s*/, $test_include) {
3297 push @tests_to_include, qr/$re/;
3300 if ($test_exclude) {
3301 for my $re (split /\s*,\s*/, $test_exclude) {
3302 push @tests_to_exclude, qr/$re/;
3306 ### make sure no fwknopd instance is currently running
3307 die "[*] Please stop the running fwknopd instance."
3308 if &is_fwknopd_running();
3310 unless ($enable_recompilation_warnings_check) {
3311 push @tests_to_exclude, qr/recompilation/;
3314 unless ($enable_make_distcheck) {
3315 push @tests_to_exclude, qr/distcheck/;
3318 unless ($enable_client_ip_resolve_test) {
3319 push @tests_to_exclude, qr/IP resolve/;
3322 $sudo_path = &find_command('sudo');
3324 unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
3325 ### disable compilation checks
3326 push @tests_to_exclude, qr/recompilation/;
3329 open UNAME, "uname |" or die "[*] Could not execute uname: $!";
3334 } elsif (/freebsd/i) {
3335 $platform = $FREEBSD;
3341 unless ($platform eq $LINUX) {
3342 push @tests_to_exclude, qr/NAT/;
3344 unless ($platform eq $FREEBSD or $platform eq $MACOSX) {
3345 push @tests_to_exclude, qr|active/expire sets|;
3348 if (-e $default_digest_file) {
3349 unlink $default_digest_file;
3355 sub identify_loopback_intf() {
3356 return if $loopback_intf;
3360 ### lo Link encap:Local Loopback
3361 ### inet addr:127.0.0.1 Mask:255.0.0.0
3362 ### inet6 addr: ::1/128 Scope:Host
3363 ### UP LOOPBACK RUNNING MTU:16436 Metric:1
3364 ### RX packets:534709 errors:0 dropped:0 overruns:0 frame:0
3365 ### TX packets:534709 errors:0 dropped:0 overruns:0 carrier:0
3366 ### collisions:0 txqueuelen:0
3367 ### RX bytes:101110617 (101.1 MB) TX bytes:101110617 (101.1 MB)
3371 ### lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
3372 ### options=3<RXCSUM,TXCSUM>
3373 ### inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
3374 ### inet6 ::1 prefixlen 128
3375 ### inet 127.0.0.1 netmask 0xff000000
3376 ### nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
3379 my $found_loopback_intf = 0;
3381 my $cmd = 'ifconfig -a';
3382 open C, "$cmd |" or die "[*] (use --loopback <name>) $cmd: $!";
3384 if (/^(\S+?):?\s+.*loopback/i) {
3388 if (/^\S/ and $intf and not $found_loopback_intf) {
3389 ### should not happen
3392 if ($intf and /\b127\.0\.0\.1\b/) {
3393 $found_loopback_intf = 1;
3399 die "[*] could not determine loopback interface, use --loopback <name>"
3400 unless $found_loopback_intf;
3402 $loopback_intf = $intf;