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 'cmd_access' => "$conf_dir/cmd_access.conf",
33 'local_nat' => "$conf_dir/local_nat_fwknopd.conf",
34 'ipfw_active_expire' => "$conf_dir/ipfw_active_expire_equal_fwknopd.conf",
35 'dual_key_access' => "$conf_dir/dual_key_usage_access.conf",
36 'gpg_access' => "$conf_dir/gpg_access.conf",
37 'gpg_no_pw_access' => "$conf_dir/gpg_no_pw_access.conf",
38 'open_ports_access' => "$conf_dir/open_ports_access.conf",
39 'multi_gpg_access' => "$conf_dir/multi_gpg_access.conf",
40 'multi_stanza_access' => "$conf_dir/multi_stanzas_access.conf",
41 'broken_keys_access' => "$conf_dir/multi_stanzas_with_broken_keys.conf",
42 'open_ports_mismatch' => "$conf_dir/mismatch_open_ports_access.conf",
43 'require_user_access' => "$conf_dir/require_user_access.conf",
44 'user_mismatch_access' => "$conf_dir/mismatch_user_access.conf",
45 'require_src_access' => "$conf_dir/require_src_access.conf",
46 'no_src_match' => "$conf_dir/no_source_match_access.conf",
47 'no_subnet_match' => "$conf_dir/no_subnet_source_match_access.conf",
48 'no_multi_src' => "$conf_dir/no_multi_source_match_access.conf",
49 'multi_src_access' => "$conf_dir/multi_source_match_access.conf",
50 'ip_src_match' => "$conf_dir/ip_source_match_access.conf",
51 'subnet_src_match' => "$conf_dir/ip_source_match_access.conf",
52 'disable_aging' => "$conf_dir/disable_aging_fwknopd.conf",
53 'fuzz_source' => "$conf_dir/fuzzing_source_access.conf",
54 'fuzz_open_ports' => "$conf_dir/fuzzing_open_ports_access.conf",
55 'fuzz_restrict_ports' => "$conf_dir/fuzzing_restrict_ports_access.conf",
58 my $default_digest_file = "$run_dir/digest.cache";
59 my $default_pid_file = "$run_dir/fwknopd.pid";
61 my $fwknopCmd = '../client/.libs/fwknop';
62 my $fwknopdCmd = '../server/.libs/fwknopd';
63 my $libfko_bin = "$lib_dir/libfko.so"; ### this is usually a link
64 my $valgrindCmd = '/usr/bin/valgrind';
66 my $gpg_server_key = '361BBAD4';
67 my $gpg_client_key = '6A3FAD56';
69 my $loopback_ip = '127.0.0.1';
70 my $fake_ip = '127.0.0.2';
71 my $internal_nat_host = '192.168.1.2';
72 my $force_nat_host = '192.168.1.123';
73 my $default_spa_port = 62201;
74 my $non_std_spa_port = 12345;
76 my $spoof_user = 'testuser';
77 my $cmd_exec_test_file = '/tmp/fwknoptest';
78 #================== end config ===================
83 my $test_include = '';
84 my @tests_to_include = ();
85 my $test_exclude = '';
86 my @tests_to_exclude = ();
87 my %valgrind_flagged_fcns = ();
88 my %valgrind_flagged_fcns_unique = ();
92 my $loopback_intf = '';
93 my $anonymize_results = 0;
94 my $current_test_file = "$output_dir/init";
95 my $tarfile = 'test_fwknop.tar.gz';
96 my $server_test_file = '';
98 my $valgrind_str = '';
99 my $enable_client_ip_resolve_test = 0;
100 my $saved_last_results = 0;
102 my $enable_recompilation_warnings_check = 0;
103 my $enable_make_distcheck = 0;
110 my $USE_PREDEF_PKTS = 1;
114 my $NEW_RULE_REQUIRED = 1;
115 my $REQUIRE_NO_NEW_RULE = 2;
116 my $NEW_RULE_REMOVED = 1;
117 my $REQUIRE_NO_NEW_REMOVED = 2;
125 my $ip_re = qr|(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}|; ### IPv4
129 exit 1 unless GetOptions(
130 'Anonymize-results' => \$anonymize_results,
131 'fwknop-path=s' => \$fwknopCmd,
132 'fwknopd-path=s' => \$fwknopdCmd,
133 'libfko-path=s' => \$libfko_bin,
134 'loopback-intf=s' => \$loopback_intf,
135 'test-include=s' => \$test_include,
136 'include=s' => \$test_include, ### synonym
137 'test-exclude=s' => \$test_exclude,
138 'exclude=s' => \$test_exclude, ### synonym
139 'enable-recompile-check' => \$enable_recompilation_warnings_check,
140 'enable-ip-resolve' => \$enable_client_ip_resolve_test,
141 'enable-distcheck' => \$enable_make_distcheck,
142 'List-mode' => \$list_mode,
143 'enable-valgrind' => \$use_valgrind,
144 'valgrind-path=s' => \$valgrindCmd,
145 'output-dir=s' => \$output_dir,
146 'diff' => \$diff_mode,
147 'diff-dir1=s' => \$diff_dir1,
148 'diff-dir2=s' => \$diff_dir2,
154 ### create an anonymized tar file of test suite results that can be
155 ### emailed around to assist in debugging fwknop communications
156 exit &anonymize_results() if $anonymize_results;
158 &identify_loopback_intf();
160 $valgrind_str = "$valgrindCmd --leak-check=full " .
161 "--show-reachable=yes --track-origins=yes" if $use_valgrind;
163 my $intf_str = "-i $loopback_intf --foreground --verbose --verbose";
165 my $default_client_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
166 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
167 "$local_key_file --verbose --verbose";
169 my $client_ip_resolve_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
170 "$fwknopCmd -A tcp/22 -R -D $loopback_ip --get-key " .
171 "$local_key_file --verbose --verbose";
173 my $default_client_gpg_args = "$default_client_args " .
174 "--gpg-recipient-key $gpg_server_key " .
175 "--gpg-signer-key $gpg_client_key " .
176 "--gpg-home-dir $gpg_client_home_dir";
178 my $default_client_gpg_args_no_homedir = "$default_client_args " .
179 "--gpg-recipient-key $gpg_server_key " .
180 "--gpg-signer-key $gpg_client_key ";
182 my $default_server_conf_args = "-c $cf{'def'} -a $cf{'def_access'} " .
183 "-d $default_digest_file -p $default_pid_file";
185 my $default_server_gpg_args = "LD_LIBRARY_PATH=$lib_dir " .
186 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
187 "-a $cf{'gpg_access'} $intf_str " .
188 "-d $default_digest_file -p $default_pid_file";
190 my $default_server_gpg_args_no_pw = "LD_LIBRARY_PATH=$lib_dir " .
191 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
192 "-a $cf{'gpg_no_pw_access'} $intf_str " .
193 "-d $default_digest_file -p $default_pid_file";
195 ### point the compiled binaries at the local libary path
196 ### instead of any installed libfko instance
197 $ENV{'LD_LIBRARY_PATH'} = $lib_dir;
199 ### main array that defines the tests we will run
202 'category' => 'recompilation',
203 'detail' => 'recompile and look for compilation warnings',
204 'err_msg' => 'compile warnings exist',
205 'function' => \&compile_warnings,
209 'category' => 'make distcheck',
210 'detail' => 'ensure proper distribution creation',
211 'err_msg' => 'could not create proper tarball',
212 'function' => \&make_distcheck,
216 'category' => 'build',
217 'subcategory' => 'client',
218 'detail' => 'binary exists',
219 'err_msg' => 'binary not found',
220 'function' => \&binary_exists,
221 'binary' => $fwknopCmd,
225 'category' => 'build security',
226 'subcategory' => 'client',
227 'detail' => 'Position Independent Executable (PIE)',
228 'err_msg' => 'non PIE binary (fwknop client)',
229 'function' => \&pie_binary,
230 'binary' => $fwknopCmd,
234 'category' => 'build security',
235 'subcategory' => 'client',
236 'detail' => 'stack protected binary',
237 'err_msg' => 'non stack protected binary (fwknop client)',
238 'function' => \&stack_protected_binary,
239 'binary' => $fwknopCmd,
243 'category' => 'build security',
244 'subcategory' => 'client',
245 'detail' => 'fortify source functions',
246 'err_msg' => 'source functions not fortified (fwknop client)',
247 'function' => \&fortify_source_functions,
248 'binary' => $fwknopCmd,
252 'category' => 'build security',
253 'subcategory' => 'client',
254 'detail' => 'read-only relocations',
255 'err_msg' => 'no read-only relocations (fwknop client)',
256 'function' => \&read_only_relocations,
257 'binary' => $fwknopCmd,
261 'category' => 'build security',
262 'subcategory' => 'client',
263 'detail' => 'immediate binding',
264 'err_msg' => 'no immediate binding (fwknop client)',
265 'function' => \&immediate_binding,
266 'binary' => $fwknopCmd,
271 'category' => 'build',
272 'subcategory' => 'server',
273 'detail' => 'binary exists',
274 'err_msg' => 'binary not found',
275 'function' => \&binary_exists,
276 'binary' => $fwknopdCmd,
281 'category' => 'build security',
282 'subcategory' => 'server',
283 'detail' => 'Position Independent Executable (PIE)',
284 'err_msg' => 'non PIE binary (fwknopd server)',
285 'function' => \&pie_binary,
286 'binary' => $fwknopdCmd,
290 'category' => 'build security',
291 'subcategory' => 'server',
292 'detail' => 'stack protected binary',
293 'err_msg' => 'non stack protected binary (fwknopd server)',
294 'function' => \&stack_protected_binary,
295 'binary' => $fwknopdCmd,
299 'category' => 'build security',
300 'subcategory' => 'server',
301 'detail' => 'fortify source functions',
302 'err_msg' => 'source functions not fortified (fwknopd server)',
303 'function' => \&fortify_source_functions,
304 'binary' => $fwknopdCmd,
308 'category' => 'build security',
309 'subcategory' => 'server',
310 'detail' => 'read-only relocations',
311 'err_msg' => 'no read-only relocations (fwknopd server)',
312 'function' => \&read_only_relocations,
313 'binary' => $fwknopdCmd,
317 'category' => 'build security',
318 'subcategory' => 'server',
319 'detail' => 'immediate binding',
320 'err_msg' => 'no immediate binding (fwknopd server)',
321 'function' => \&immediate_binding,
322 'binary' => $fwknopdCmd,
327 'category' => 'build',
328 'subcategory' => 'libfko',
329 'detail' => 'binary exists',
330 'err_msg' => 'binary not found',
331 'function' => \&binary_exists,
332 'binary' => $libfko_bin,
336 'category' => 'build security',
337 'subcategory' => 'libfko',
338 'detail' => 'stack protected binary',
339 'err_msg' => 'non stack protected binary (libfko)',
340 'function' => \&stack_protected_binary,
341 'binary' => $libfko_bin,
345 'category' => 'build security',
346 'subcategory' => 'libfko',
347 'detail' => 'fortify source functions',
348 'err_msg' => 'source functions not fortified (libfko)',
349 'function' => \&fortify_source_functions,
350 'binary' => $libfko_bin,
354 'category' => 'build security',
355 'subcategory' => 'libfko',
356 'detail' => 'read-only relocations',
357 'err_msg' => 'no read-only relocations (libfko)',
358 'function' => \&read_only_relocations,
359 'binary' => $libfko_bin,
363 'category' => 'build security',
364 'subcategory' => 'libfko',
365 'detail' => 'immediate binding',
366 'err_msg' => 'no immediate binding (libfko)',
367 'function' => \&immediate_binding,
368 'binary' => $libfko_bin,
373 'category' => 'preliminaries',
374 'subcategory' => 'client',
375 'detail' => 'usage info',
376 'err_msg' => 'could not get usage info',
377 'function' => \&generic_exec,
378 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd -h",
382 'category' => 'preliminaries',
383 'subcategory' => 'client',
384 'detail' => 'getopt() no such argument',
385 'err_msg' => 'getopt() allowed non-existant argument',
386 'function' => \&generic_exec,
387 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd --no-such-arg",
392 'category' => 'preliminaries',
393 'subcategory' => 'client',
394 'detail' => '--test mode, packet not sent',
395 'err_msg' => '--test mode, packet sent?',
396 'function' => \&generic_exec,
397 'positive_output_matches' => [qr/test\smode\senabled/],
398 'cmdline' => "$default_client_args --test",
403 'category' => 'preliminaries',
404 'subcategory' => 'client',
405 'detail' => 'expected code version',
406 'err_msg' => 'code version mis-match',
407 'function' => \&expected_code_version,
408 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd --version",
413 'category' => 'preliminaries',
414 'subcategory' => 'server',
415 'detail' => 'usage info',
416 'err_msg' => 'could not get usage info',
417 'function' => \&generic_exec,
418 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd -h",
422 'category' => 'preliminaries',
423 'subcategory' => 'server',
424 'detail' => 'getopt() no such argument',
425 'err_msg' => 'getopt() allowed non-existant argument',
426 'function' => \&generic_exec,
427 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd --no-such-arg",
433 'category' => 'preliminaries',
434 'subcategory' => 'server',
435 'detail' => 'expected code version',
436 'err_msg' => 'code version mis-match',
437 'function' => \&expected_code_version,
438 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
439 "$fwknopdCmd -c $cf{'def'} -a " .
440 "$cf{'def_access'} --version",
444 'category' => 'preliminaries',
445 'detail' => 'collecting system specifics',
446 'err_msg' => 'could not get complete system specs',
447 'function' => \&specs,
448 'binary' => $fwknopdCmd,
453 'category' => 'basic operations',
454 'detail' => 'dump config',
455 'err_msg' => 'could not dump configuration',
456 'function' => \&generic_exec,
457 'positive_output_matches' => [qr/SYSLOG_IDENTITY/],
459 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
460 "$fwknopdCmd -c $cf{'def'} " .
461 "-a $cf{'def_access'} --dump-config",
465 'category' => 'basic operations',
466 'detail' => 'override config',
467 'err_msg' => 'could not override configuration',
468 'function' => \&generic_exec,
469 'positive_output_matches' => [qr/ENABLE_PCAP_PROMISC.*\'Y\'/],
471 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
472 "$fwknopdCmd $default_server_conf_args " .
473 "-O $conf_dir/override_fwknopd.conf --dump-config",
478 'category' => 'basic operations',
479 'subcategory' => 'client',
480 'detail' => '--get-key path validation',
481 'err_msg' => 'accepted improper --get-key path',
482 'function' => \&generic_exec,
483 'positive_output_matches' => [qr/could\snot\sopen/i],
485 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
486 "$fwknopCmd -A tcp/22 -s $fake_ip " .
487 "-D $loopback_ip --get-key not/there",
491 'category' => 'basic operations',
492 'subcategory' => 'client',
493 'detail' => 'require [-s|-R|-a]',
494 'err_msg' => 'allowed null allow IP',
495 'function' => \&generic_exec,
496 'positive_output_matches' => [qr/must\suse\sone\sof/i],
498 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
499 "$fwknopCmd -D $loopback_ip",
503 'category' => 'basic operations',
504 'subcategory' => 'client',
505 'detail' => '--allow-ip <IP> valid IP',
506 'err_msg' => 'permitted invalid --allow-ip arg',
507 'function' => \&generic_exec,
508 'positive_output_matches' => [qr/Invalid\sallow\sIP\saddress/i],
510 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
511 "$fwknopCmd -A tcp/22 -a invalidIP -D $loopback_ip",
515 'category' => 'basic operations',
516 'subcategory' => 'client',
517 'detail' => '-A <proto>/<port> specification (proto)',
518 'err_msg' => 'permitted invalid -A <proto>/<port>',
519 'function' => \&generic_exec,
520 'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
522 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
523 "$fwknopCmd -A invalid/22 -a $fake_ip -D $loopback_ip",
527 'category' => 'basic operations',
528 'subcategory' => 'client',
529 'detail' => '-A <proto>/<port> specification (port)',
530 'err_msg' => 'permitted invalid -A <proto>/<port>',
531 'function' => \&generic_exec,
532 'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
534 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
535 "$fwknopCmd -A tcp/600001 -a $fake_ip -D $loopback_ip",
540 'category' => 'basic operations',
541 'subcategory' => 'client',
542 'detail' => 'generate SPA packet',
543 'err_msg' => 'could not generate SPA packet',
544 'function' => \&client_send_spa_packet,
545 'cmdline' => $default_client_args,
550 'category' => 'basic operations',
551 'subcategory' => 'server',
552 'detail' => 'list current fwknopd fw rules',
553 'err_msg' => 'could not list current fwknopd fw rules',
554 'function' => \&generic_exec,
555 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
556 "$fwknopdCmd $default_server_conf_args --fw-list",
560 'category' => 'basic operations',
561 'subcategory' => 'server',
562 'detail' => 'list all current fw rules',
563 'err_msg' => 'could not list all current fw rules',
564 'function' => \&generic_exec,
565 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
566 "$fwknopdCmd $default_server_conf_args --fw-list-all",
570 'category' => 'basic operations',
571 'subcategory' => 'server',
572 'detail' => 'flush current firewall rules',
573 'err_msg' => 'could not flush current fw rules',
574 'function' => \&generic_exec,
575 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
576 "$fwknopdCmd $default_server_conf_args --fw-flush",
581 'category' => 'basic operations',
582 'subcategory' => 'server',
584 'err_msg' => 'start error',
585 'function' => \&server_start,
586 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
587 "$fwknopdCmd $default_server_conf_args $intf_str",
591 'category' => 'basic operations',
592 'subcategory' => 'server',
594 'err_msg' => 'stop error',
595 'function' => \&server_stop,
596 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
597 "$fwknopdCmd $default_server_conf_args $intf_str",
601 'category' => 'basic operations',
602 'subcategory' => 'server',
603 'detail' => 'write PID',
604 'err_msg' => 'did not write PID',
605 'function' => \&write_pid,
606 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
607 "$fwknopdCmd $default_server_conf_args $intf_str",
612 'category' => 'basic operations',
613 'subcategory' => 'server',
614 'detail' => '--packet-limit 1 exit',
615 'err_msg' => 'did not exit after one packet',
616 'function' => \&server_packet_limit,
617 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
618 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
622 'category' => 'basic operations',
623 'subcategory' => 'server',
624 'detail' => 'ignore packets < min SPA len (140)',
625 'err_msg' => 'did not ignore small packets',
626 'function' => \&server_ignore_small_packets,
627 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
628 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
632 'category' => 'basic operations',
633 'subcategory' => 'server',
634 'detail' => '-P bpf filter ignore packet',
635 'err_msg' => 'filter did not ignore packet',
636 'function' => \&server_bpf_ignore_packet,
637 'cmdline' => $default_client_args,
638 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
639 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str " .
640 qq|-P "udp port $non_std_spa_port"|,
645 'category' => 'Rijndael SPA',
646 'subcategory' => 'client+server',
647 'detail' => 'complete cycle (tcp/22 ssh)',
648 'err_msg' => 'could not complete SPA cycle',
649 'function' => \&spa_cycle,
650 'cmdline' => $default_client_args,
651 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
652 "$fwknopdCmd $default_server_conf_args $intf_str",
653 'fw_rule_created' => $NEW_RULE_REQUIRED,
654 'fw_rule_removed' => $NEW_RULE_REMOVED,
658 'category' => 'Rijndael SPA',
659 'subcategory' => 'client+server',
660 'detail' => 'permissions check cycle (tcp/22)',
661 'err_msg' => 'could not complete SPA cycle',
662 'function' => \&permissions_check,
663 'cmdline' => $default_client_args,
664 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
665 "$fwknopdCmd $default_server_conf_args $intf_str",
666 'server_positive_output_matches' => [qr/permissions\sshould\sonly\sbe\suser/],
667 'fw_rule_created' => $NEW_RULE_REQUIRED,
668 'fw_rule_removed' => $NEW_RULE_REMOVED,
672 'category' => 'Rijndael SPA',
673 'subcategory' => 'client+server',
674 'detail' => 'client IP resolve (tcp/22 ssh)',
675 'err_msg' => 'could not complete SPA cycle',
676 'function' => \&spa_cycle,
677 'cmdline' => $client_ip_resolve_args,
679 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
680 "$fwknopdCmd $default_server_conf_args $intf_str",
681 'fw_rule_created' => $NEW_RULE_REQUIRED,
682 'fw_rule_removed' => $NEW_RULE_REMOVED,
687 'category' => 'Rijndael SPA',
688 'subcategory' => 'client+server',
689 'detail' => 'dual usage access key (tcp/80 http)',
690 'err_msg' => 'could not complete SPA cycle',
691 'function' => \&spa_cycle,
692 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
693 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
694 "$local_key_file --verbose --verbose",
695 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
696 "$fwknopdCmd -c $cf{'def'} -a $cf{'dual_key_access'} " .
697 "-d $default_digest_file -p $default_pid_file $intf_str",
698 ### check for the first stanza that does not allow tcp/80 - the
699 ### second stanza allows this
700 'server_positive_output_matches' => [qr/stanza #1\)\sOne\sor\smore\srequested\sprotocol\/ports\swas\sdenied/],
701 'fw_rule_created' => $NEW_RULE_REQUIRED,
702 'fw_rule_removed' => $NEW_RULE_REMOVED,
706 'category' => 'Rijndael SPA',
707 'subcategory' => 'client+server',
708 'detail' => 'packet aging (past) (tcp/22 ssh)',
709 'err_msg' => 'old SPA packet accepted',
710 'function' => \&spa_cycle,
711 'cmdline' => "$default_client_args --time-offset-minus 300s",
712 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
713 "$fwknopdCmd $default_server_conf_args $intf_str",
714 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
715 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
719 'category' => 'Rijndael SPA',
720 'subcategory' => 'client+server',
721 'detail' => 'packet aging (future) (tcp/22 ssh)',
722 'err_msg' => 'future SPA packet accepted',
723 'function' => \&spa_cycle,
724 'cmdline' => "$default_client_args --time-offset-plus 300s",
725 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
726 "$fwknopdCmd $default_server_conf_args $intf_str",
727 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
728 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
732 'category' => 'Rijndael SPA',
733 'subcategory' => 'client+server',
734 'detail' => 'expired stanza (tcp/22 ssh)',
735 'err_msg' => 'SPA packet accepted',
736 'function' => \&spa_cycle,
737 'cmdline' => $default_client_args,
738 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
739 "$fwknopdCmd -c $cf{'def'} -a $cf{'exp_access'} " .
740 "-d $default_digest_file -p $default_pid_file $intf_str",
741 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
742 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
746 'category' => 'Rijndael SPA',
747 'subcategory' => 'client+server',
748 'detail' => 'invalid expire date (tcp/22 ssh)',
749 'err_msg' => 'SPA packet accepted',
750 'function' => \&spa_cycle,
751 'cmdline' => $default_client_args,
752 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
753 "$fwknopdCmd -c $cf{'def'} -a $cf{'invalid_exp_access'} " .
754 "-d $default_digest_file -p $default_pid_file $intf_str",
755 'server_positive_output_matches' => [qr/invalid\sdate\svalue/],
756 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
760 'category' => 'Rijndael SPA',
761 'subcategory' => 'client+server',
762 'detail' => 'expired epoch stanza (tcp/22 ssh)',
763 'err_msg' => 'SPA packet accepted',
764 'function' => \&spa_cycle,
765 'cmdline' => $default_client_args,
766 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
767 "$fwknopdCmd -c $cf{'def'} -a $cf{'exp_epoch_access'} " .
768 "-d $default_digest_file -p $default_pid_file $intf_str",
769 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
770 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
774 'category' => 'Rijndael SPA',
775 'subcategory' => 'client+server',
776 'detail' => 'future expired stanza (tcp/22 ssh)',
777 'err_msg' => 'SPA packet not accepted',
778 'function' => \&spa_cycle,
779 'cmdline' => $default_client_args,
780 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
781 "$fwknopdCmd -c $cf{'def'} -a $cf{'future_exp_access'} " .
782 "-d $default_digest_file -p $default_pid_file $intf_str",
783 'fw_rule_created' => $NEW_RULE_REQUIRED,
784 'fw_rule_removed' => $NEW_RULE_REMOVED,
789 'category' => 'Rijndael SPA',
790 'subcategory' => 'client+server',
791 'detail' => 'OPEN_PORTS (tcp/22 ssh)',
792 'err_msg' => "improper OPEN_PORTS result",
793 'function' => \&spa_cycle,
794 'cmdline' => $default_client_args,
795 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
796 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_access'} " .
797 "-d $default_digest_file -p $default_pid_file $intf_str",
798 'fw_rule_created' => $NEW_RULE_REQUIRED,
799 'fw_rule_removed' => $NEW_RULE_REMOVED,
803 'category' => 'Rijndael SPA',
804 'subcategory' => 'client+server',
805 'detail' => 'OPEN_PORTS mismatch',
806 'err_msg' => "SPA packet accepted",
807 'function' => \&spa_cycle,
808 'cmdline' => $default_client_args,
809 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
810 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_mismatch'} " .
811 "-d $default_digest_file -p $default_pid_file $intf_str",
812 'server_positive_output_matches' => [qr/One\s+or\s+more\s+requested/],
813 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
817 'category' => 'Rijndael SPA',
818 'subcategory' => 'client+server',
819 'detail' => 'require user (tcp/22 ssh)',
820 'err_msg' => "missed require user criteria",
821 'function' => \&spa_cycle,
822 'cmdline' => "SPOOF_USER=$spoof_user $default_client_args",
823 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
824 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_user_access'} " .
825 "-d $default_digest_file -p $default_pid_file $intf_str",
826 'fw_rule_created' => $NEW_RULE_REQUIRED,
827 'fw_rule_removed' => $NEW_RULE_REMOVED,
831 'category' => 'Rijndael SPA',
832 'subcategory' => 'client+server',
833 'detail' => 'user mismatch (tcp/22 ssh)',
834 'err_msg' => "improper user accepted for access",
835 'function' => \&user_mismatch,
836 'function' => \&spa_cycle,
837 'cmdline' => $default_client_args,
838 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
839 "$fwknopdCmd -c $cf{'def'} -a $cf{'user_mismatch_access'} " .
840 "-d $default_digest_file -p $default_pid_file $intf_str",
841 'server_positive_output_matches' => [qr/Username\s+in\s+SPA\s+data/],
842 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
846 'category' => 'Rijndael SPA',
847 'subcategory' => 'client+server',
848 'detail' => 'require src (tcp/22 ssh)',
849 'err_msg' => "fw rule not created",
850 'function' => \&spa_cycle,
851 'cmdline' => $default_client_args,
852 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
853 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
854 "-d $default_digest_file -p $default_pid_file $intf_str",
855 'fw_rule_created' => $NEW_RULE_REQUIRED,
856 'fw_rule_removed' => $NEW_RULE_REMOVED,
860 'category' => 'Rijndael SPA',
861 'subcategory' => 'client+server',
862 'detail' => 'mismatch require src (tcp/22 ssh)',
863 'err_msg' => "fw rule created",
864 'function' => \&spa_cycle,
865 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
866 "$fwknopCmd -A tcp/22 -s -D $loopback_ip --get-key " .
867 "$local_key_file --verbose --verbose",
868 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
869 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
870 "-d $default_digest_file -p $default_pid_file $intf_str",
871 'server_positive_output_matches' => [qr/Got\s0.0.0.0\swhen\svalid\ssource\sIP/],
872 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
877 'category' => 'Rijndael SPA',
878 'subcategory' => 'client+server',
879 'detail' => 'IP filtering (tcp/22 ssh)',
880 'err_msg' => "did not filter $loopback_ip",
881 'function' => \&spa_cycle,
882 'cmdline' => $default_client_args,
883 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
884 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_src_match'} " .
885 "-d $default_digest_file -p $default_pid_file $intf_str",
886 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
887 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
891 'category' => 'Rijndael SPA',
892 'subcategory' => 'client+server',
893 'detail' => 'subnet filtering (tcp/22 ssh)',
894 'err_msg' => "did not filter $loopback_ip",
895 'function' => \&spa_cycle,
896 'cmdline' => $default_client_args,
897 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
898 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_subnet_match'} " .
899 "-d $default_digest_file -p $default_pid_file $intf_str",
900 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
901 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
905 'category' => 'Rijndael SPA',
906 'subcategory' => 'client+server',
907 'detail' => 'IP+subnet filtering (tcp/22 ssh)',
908 'err_msg' => "did not filter $loopback_ip",
909 'function' => \&spa_cycle,
910 'cmdline' => $default_client_args,
911 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
912 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_multi_src'} " .
913 "-d $default_digest_file -p $default_pid_file $intf_str",
914 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
915 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
919 'category' => 'Rijndael SPA',
920 'subcategory' => 'client+server',
921 'detail' => 'IP match (tcp/22 ssh)',
922 'err_msg' => "did not filter $loopback_ip",
923 'function' => \&spa_cycle,
924 'cmdline' => $default_client_args,
925 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
926 "$fwknopdCmd -c $cf{'def'} -a $cf{'ip_src_match'} " .
927 "-d $default_digest_file -p $default_pid_file $intf_str",
928 'fw_rule_created' => $NEW_RULE_REQUIRED,
929 'fw_rule_removed' => $NEW_RULE_REMOVED,
933 'category' => 'Rijndael SPA',
934 'subcategory' => 'client+server',
935 'detail' => 'subnet match (tcp/22 ssh)',
936 'err_msg' => "did not filter $loopback_ip",
937 'function' => \&spa_cycle,
938 'cmdline' => $default_client_args,
939 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
940 "$fwknopdCmd -c $cf{'def'} -a $cf{'subnet_src_match'} " .
941 "-d $default_digest_file -p $default_pid_file $intf_str",
942 'fw_rule_created' => $NEW_RULE_REQUIRED,
943 'fw_rule_removed' => $NEW_RULE_REMOVED,
947 'category' => 'Rijndael SPA',
948 'subcategory' => 'client+server',
949 'detail' => 'multi IP/net match (tcp/22 ssh)',
950 'err_msg' => "did not filter $loopback_ip",
951 'function' => \&spa_cycle,
952 'cmdline' => $default_client_args,
953 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
954 "$fwknopdCmd -c $cf{'def'} -a $cf{'multi_src_access'} " .
955 "-d $default_digest_file -p $default_pid_file $intf_str",
956 'fw_rule_created' => $NEW_RULE_REQUIRED,
957 'fw_rule_removed' => $NEW_RULE_REMOVED,
961 'category' => 'Rijndael SPA',
962 'subcategory' => 'client+server',
963 'detail' => 'multi access stanzas (tcp/22 ssh)',
964 'err_msg' => "could not complete SPA cycle",
965 'function' => \&spa_cycle,
966 'cmdline' => $default_client_args,
967 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
968 "$fwknopdCmd -c $cf{'def'} -a $cf{'multi_stanza_access'} " .
969 "-d $default_digest_file -p $default_pid_file $intf_str",
970 'fw_rule_created' => $NEW_RULE_REQUIRED,
971 'fw_rule_removed' => $NEW_RULE_REMOVED,
975 'category' => 'Rijndael SPA',
976 'subcategory' => 'client+server',
977 'detail' => 'bad/good key stanzas (tcp/22 ssh)',
978 'err_msg' => "could not complete SPA cycle",
979 'function' => \&spa_cycle,
980 'cmdline' => $default_client_args,
981 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
982 "$fwknopdCmd -c $cf{'def'} -a $cf{'broken_keys_access'} " .
983 "-d $default_digest_file -p $default_pid_file $intf_str",
984 'fw_rule_created' => $NEW_RULE_REQUIRED,
985 'fw_rule_removed' => $NEW_RULE_REMOVED,
990 'category' => 'Rijndael SPA',
991 'subcategory' => 'client+server',
992 'detail' => "non-enabled NAT (tcp/22 ssh)",
993 'err_msg' => "SPA packet not filtered",
994 'function' => \&spa_cycle,
995 'cmdline' => "$default_client_args -N $internal_nat_host:22",
996 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
997 "$fwknopdCmd $default_server_conf_args $intf_str",
998 'server_positive_output_matches' => [qr/requested\sNAT\saccess.*not\senabled/i],
999 'server_conf' => $cf{'nat'},
1000 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1004 'category' => 'Rijndael SPA',
1005 'subcategory' => 'client+server',
1006 'detail' => "NAT to $internal_nat_host (tcp/22 ssh)",
1007 'err_msg' => "could not complete NAT SPA cycle",
1008 'function' => \&spa_cycle,
1009 'cmdline' => "$default_client_args -N $internal_nat_host:22",
1010 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1011 "$fwknopdCmd -c $cf{'nat'} -a $cf{'open_ports_access'} " .
1012 "-d $default_digest_file -p $default_pid_file $intf_str",
1013 'server_positive_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1014 'fw_rule_created' => $NEW_RULE_REQUIRED,
1015 'fw_rule_removed' => $NEW_RULE_REMOVED,
1016 'server_conf' => $cf{'nat'},
1020 'category' => 'Rijndael SPA',
1021 'subcategory' => 'client+server',
1022 'detail' => "force NAT $force_nat_host (tcp/22 ssh)",
1023 'err_msg' => "could not complete NAT SPA cycle",
1024 'function' => \&spa_cycle,
1025 'cmdline' => $default_client_args,
1026 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1027 "$fwknopdCmd -c $cf{'nat'} -a $cf{'force_nat_access'} " .
1028 "-d $default_digest_file -p $default_pid_file $intf_str",
1029 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i],
1030 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1031 'fw_rule_created' => $NEW_RULE_REQUIRED,
1032 'fw_rule_removed' => $NEW_RULE_REMOVED,
1033 'server_conf' => $cf{'nat'},
1037 'category' => 'Rijndael SPA',
1038 'subcategory' => 'client+server',
1039 'detail' => "local NAT $force_nat_host (tcp/22 ssh)",
1040 'err_msg' => "could not complete NAT SPA cycle",
1041 'function' => \&spa_cycle,
1042 'cmdline' => "$default_client_args --nat-local",
1043 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1044 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'force_nat_access'} " .
1045 "-d $default_digest_file -p $default_pid_file $intf_str",
1046 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i,
1047 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1048 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1049 'fw_rule_created' => $NEW_RULE_REQUIRED,
1050 'fw_rule_removed' => $NEW_RULE_REMOVED,
1051 'server_conf' => $cf{'nat'},
1055 'category' => 'Rijndael SPA',
1056 'subcategory' => 'client+server',
1057 'detail' => "local NAT non-FORCE_NAT (tcp/22 ssh)",
1058 'err_msg' => "could not complete NAT SPA cycle",
1059 'function' => \&spa_cycle,
1060 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1061 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
1062 "$local_key_file --verbose --verbose --nat-local --nat-port 22",
1063 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1064 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'def_access'} " .
1065 "-d $default_digest_file -p $default_pid_file $intf_str",
1066 'server_positive_output_matches' => [qr/to\:$loopback_ip\:22/i,
1067 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1068 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1069 'fw_rule_created' => $NEW_RULE_REQUIRED,
1070 'fw_rule_removed' => $NEW_RULE_REMOVED,
1071 'server_conf' => $cf{'nat'},
1076 'category' => 'Rijndael SPA',
1077 'subcategory' => 'client+server',
1078 'detail' => 'complete cycle (tcp/23 telnet)',
1079 'err_msg' => 'could not complete SPA cycle',
1080 'function' => \&spa_cycle,
1081 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1082 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1083 "$local_key_file --verbose --verbose",
1084 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1085 "$fwknopdCmd $default_server_conf_args $intf_str",
1086 'fw_rule_created' => $NEW_RULE_REQUIRED,
1087 'fw_rule_removed' => $NEW_RULE_REMOVED,
1091 'category' => 'Rijndael SPA',
1092 'subcategory' => 'client+server',
1093 'detail' => 'complete cycle (tcp/9418 git)',
1094 'err_msg' => 'could not complete SPA cycle',
1095 'function' => \&spa_cycle,
1096 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1097 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1098 "$local_key_file --verbose --verbose",
1099 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1100 "$fwknopdCmd $default_server_conf_args $intf_str",
1101 'fw_rule_created' => $NEW_RULE_REQUIRED,
1102 'fw_rule_removed' => $NEW_RULE_REMOVED,
1106 'category' => 'Rijndael SPA',
1107 'subcategory' => 'client+server',
1108 'detail' => 'complete cycle (tcp/60001)',
1109 'err_msg' => 'could not complete SPA cycle',
1110 'function' => \&spa_cycle,
1111 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1112 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1113 "$local_key_file --verbose --verbose",
1114 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1115 "$fwknopdCmd $default_server_conf_args $intf_str",
1116 'fw_rule_created' => $NEW_RULE_REQUIRED,
1117 'fw_rule_removed' => $NEW_RULE_REMOVED,
1121 'category' => 'Rijndael SPA',
1122 'subcategory' => 'client+server',
1123 'detail' => 'multi port (tcp/60001,udp/60001)',
1124 'err_msg' => 'could not complete SPA cycle',
1125 'function' => \&spa_cycle,
1126 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1127 "$fwknopCmd -A tcp/60001,udp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1128 "$local_key_file --verbose --verbose",
1129 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1130 "$fwknopdCmd $default_server_conf_args $intf_str",
1131 'fw_rule_created' => $NEW_RULE_REQUIRED,
1132 'fw_rule_removed' => $NEW_RULE_REMOVED,
1136 'category' => 'Rijndael SPA',
1137 'subcategory' => 'client+server',
1138 'detail' => 'multi port (tcp/22,udp/53,tcp/1234)',
1139 'err_msg' => 'could not complete SPA cycle',
1140 'function' => \&spa_cycle,
1141 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1142 "$fwknopCmd -A tcp/22,udp/53,tcp/1234 -a $fake_ip -D $loopback_ip --get-key " .
1143 "$local_key_file --verbose --verbose",
1144 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1145 "$fwknopdCmd $default_server_conf_args $intf_str",
1146 'fw_rule_created' => $NEW_RULE_REQUIRED,
1147 'fw_rule_removed' => $NEW_RULE_REMOVED,
1152 'category' => 'Rijndael SPA',
1153 'subcategory' => 'client+server',
1154 'detail' => 'complete cycle (udp/53 dns)',
1155 'err_msg' => 'could not complete SPA cycle',
1156 'function' => \&spa_cycle,
1157 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1158 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1159 "$local_key_file --verbose --verbose",
1160 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1161 "$fwknopdCmd $default_server_conf_args $intf_str",
1162 'fw_rule_created' => $NEW_RULE_REQUIRED,
1163 'fw_rule_removed' => $NEW_RULE_REMOVED,
1167 'category' => 'Rijndael SPA',
1168 'subcategory' => 'client+server',
1169 'detail' => "-P bpf SPA over port $non_std_spa_port",
1170 'err_msg' => 'could not complete SPA cycle',
1171 'function' => \&spa_cycle,
1172 'cmdline' => "$default_client_args --server-port $non_std_spa_port",
1173 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1174 "$fwknopdCmd $default_server_conf_args $intf_str " .
1175 qq|-P "udp port $non_std_spa_port"|,
1176 'server_positive_output_matches' => [qr/PCAP\sfilter.*\s$non_std_spa_port/],
1177 'fw_rule_created' => $NEW_RULE_REQUIRED,
1178 'fw_rule_removed' => $NEW_RULE_REMOVED,
1183 'category' => 'Rijndael SPA',
1184 'subcategory' => 'client+server',
1185 'detail' => 'random SPA port (tcp/22 ssh)',
1186 'err_msg' => 'could not complete SPA cycle',
1187 'function' => \&spa_cycle,
1188 'cmdline' => "$default_client_args -r",
1189 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1190 "$fwknopdCmd $default_server_conf_args $intf_str " .
1192 'fw_rule_created' => $NEW_RULE_REQUIRED,
1193 'fw_rule_removed' => $NEW_RULE_REMOVED,
1198 'category' => 'Rijndael SPA',
1199 'subcategory' => 'client+server',
1200 'detail' => 'spoof username (tcp/22)',
1201 'err_msg' => 'could not spoof username',
1202 'function' => \&spoof_username,
1203 'cmdline' => "SPOOF_USER=$spoof_user LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1204 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
1205 "$local_key_file --verbose --verbose",
1206 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1207 "$fwknopdCmd $default_server_conf_args $intf_str",
1212 'category' => 'Rijndael SPA',
1213 'subcategory' => 'client+server',
1214 'detail' => 'replay attack detection',
1215 'err_msg' => 'could not detect replay attack',
1216 'function' => \&replay_detection,
1217 'cmdline' => $default_client_args,
1218 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1219 "$fwknopdCmd $default_server_conf_args $intf_str",
1220 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1224 'category' => 'Rijndael SPA',
1225 'subcategory' => 'client+server',
1226 'detail' => 'replay detection (Rijndael prefix)',
1227 'err_msg' => 'could not detect replay attack',
1228 'function' => \&replay_detection,
1229 'pkt_prefix' => 'U2FsdGVkX1',
1230 'cmdline' => $default_client_args,
1231 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1232 "$fwknopdCmd $default_server_conf_args $intf_str",
1233 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1239 'category' => 'Rijndael SPA',
1240 'subcategory' => 'FUZZING',
1241 'detail' => 'overly long port value',
1242 'err_msg' => 'server crashed or did not detect error condition',
1243 'function' => \&fuzzer,
1244 ### this packet was generated with a modified fwknop client via the
1245 ### following command line:
1247 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1248 # "tcp/`perl -e '{print "1"x"40"}'`" -a 127.0.0.2 -D 127.0.0.1 \
1249 # --get-key local_spa.key --verbose --verbose
1251 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1252 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1253 # authenticated clients.
1256 '+JzxeTGlc6lwwzbJSrYChKx8bonWBIPajwGfEtGOaoglcMLbTY/GGXo/nxqiN1LykFS' .
1257 'lDFXgrkyx2emJ7NGzYqQPUYZxLdZRocR9aRIptvXLLIPBcIpJASi/TUiJlw7CDFMcj0' .
1258 'ptSBJJUZi0tozpKHETp3AgqfzyOy5FNs38aZsV5/sDl3Pt+kF7fTZJ+YLbmYY4yCUz2' .
1259 'ZUYoCaJ7X78ULyJTi5eT7nug',
1260 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1261 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1262 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1263 "-d $default_digest_file -p $default_pid_file $intf_str",
1267 'category' => 'Rijndael SPA',
1268 'subcategory' => 'FUZZING',
1269 'detail' => 'overly long proto value',
1270 'err_msg' => 'server crashed or did not detect error condition',
1271 'function' => \&fuzzer,
1272 ### this packet was generated with a modified fwknop client via the
1273 ### following command line:
1275 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1276 # "tcp`perl -e '{print "A"x"28"}'`/1" -a 127.0.0.2 -D 127.0.0.1 \
1277 # --get-key local_spa.key --verbose --verbose
1279 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1280 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1281 # authenticated clients.
1284 '/im5MiJQmOdzqrdWXv+AjEtAm/HsLrdaTFcSw3ZskqpGOdDIrSCz3VXbFfv7qDkc5Y4' .
1285 'q/k1mRXl9SGzpug87U5dZSyCdAr30z7/2kUFEPTGOQBi/x+L1t1pvdkm4xg13t09ldm' .
1286 '5OD8KiV6qzqLOvN4ULJjvvJJWBZ9qvo/f2Q9Wf67g2KHiwS6EeCINAuMoUw/mNRQMa4' .
1287 'oGnOXu3/DeWHJAwtSeh7EAr4',
1288 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1289 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1290 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1291 "-d $default_digest_file -p $default_pid_file $intf_str",
1295 'category' => 'Rijndael SPA',
1296 'subcategory' => 'FUZZING',
1297 'detail' => 'overly long IP value',
1298 'err_msg' => 'server crashed or did not detect error condition',
1299 'function' => \&fuzzer,
1300 ### this packet was generated with a modified fwknop client via the
1301 ### following command line:
1303 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1304 # -a `perl -e '{print "1"x"136"}'`.0.0.1 -D 127.0.0.1 \
1305 # --get-key local_spa.key --verbose --verbose
1307 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1308 # a condition in which pre-2.0.3 fwknopd servers fail to properly validate
1309 # allow IP addresses from malicious authenticated clients.
1312 '93f2rhsXLmBoPicWvYTqrbp+6lNqvWDc8dzmX2s3settwjBGRAXm33TB9agibEphrBu' .
1313 '3d+7DEsivZLDS6Kz0JwdjX7t0J9c8es+DVNjlLnPtVNcxhs+2kUzimNrgysIXQRJ+GF' .
1314 'GbhdxiXCqdy1vWxWpdoaZmY/CeGIkpoFJFPbJhCRLLX25UMvMF2wXj02MpI4d3t1/6W' .
1315 'DM3taM3kZsiFv6HxFjAhIEuQ1oAg2OgRGXkDmT3jDNZMHUm0d4Ahm9LonG7RbOxq/B0' .
1316 'qUvY8lkymbwvjelVok7Lvlc06cRhN4zm32D4V05g0vQS3PlX9C+mgph9DeAPVX+D8iZ' .
1317 '8lGrxcPSfbCOW61k0MP+q1EhLZkc1qAm5g2+2cLNZcoBNEdh3yj8OTPZJyBVw',
1318 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1319 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1320 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1321 "-d $default_digest_file -p $default_pid_file $intf_str",
1325 'category' => 'Rijndael SPA',
1326 'subcategory' => 'FUZZING',
1327 'detail' => 'negative port value',
1328 'err_msg' => 'server crashed or did not detect error condition',
1329 'function' => \&fuzzer,
1330 ### this packet was generated with a modified fwknop client via the
1331 ### following command line:
1333 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1334 # tcp/-33 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1335 # --verbose --verbose
1338 '/weoc+pEuQknZo8ImWTQBB+/PwSJ2/TcrmFoSkxpRXX4+jlUxoJakHrioxh8rhLmAD9' .
1339 '8E4lMnq+EbM2XYdhs2alpZ5bovAFojMsYRWwr/BvRO4Um4Fmo9z9sY3DR477TXNYXBR' .
1340 'iGXWxSL4u+AWSSePK3qiiYoRQVw',
1341 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1342 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1343 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1344 "-d $default_digest_file -p $default_pid_file $intf_str",
1348 'category' => 'Rijndael SPA',
1349 'subcategory' => 'FUZZING',
1350 'detail' => 'null port value',
1351 'err_msg' => 'server crashed or did not detect error condition',
1352 'function' => \&fuzzer,
1353 ### this packet was generated with a modified fwknop client via the
1354 ### following command line:
1356 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/ \
1357 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1358 # --verbose --verbose
1361 '94nu7hvq6V/3A27GzjHwfPnPCQfs44ySlraIFYHOAqy5YqjkrBS67nH35tX55N1BrYZ' .
1362 '07zvcT03keUhLE1Uo7Wme1nE7BfTOG5stmIK1UQI85sL52//lDHu+xCqNcL7GUKbVRz' .
1363 'ekw+EUscVvUkrsRcVtSvOm+fCNo',
1364 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1365 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1366 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1367 "-d $default_digest_file -p $default_pid_file $intf_str",
1371 'category' => 'Rijndael SPA',
1372 'subcategory' => 'FUZZING',
1373 'detail' => 'long FKO protocol value (enc mode trigger)',
1374 'err_msg' => 'server crashed or did not detect error condition',
1375 'function' => \&fuzzer,
1376 ### this packet was generated with a modified fwknop client via the
1377 ### following command line:
1379 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1380 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1382 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1383 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1384 # encrypted SPA packet
1387 '/ewH/k1XsDX+VQ8NlNvCZ4P2QOl/4IpJYXkq4TtAe3899OtApXJiTtPCuYW70XPuxge' .
1388 'MtFjc4UfslK/r9v+FYfyd3fIIHCz0Q0M4+nM3agTLmJj8nOxk6ZeBj82SDQWhHAxGdJ' .
1389 'IQALPve0ug4cuGxS3b4M+2Q/Av9i2tU3Lzlogw3sY0tk6wGf4zZk4UsviVXYpINniGT' .
1390 'RhYSIQ1dfdkng7hKiHMDaObYY1GFp4nxEt/QjasAwvE+7/iFyoKN+IRpGG4v4hGEPh2' .
1391 'vTDqmvfRuIHtgFD7NxZjt+m/jjcu0gkdWEoD4fenwGU35FlvchyM2AiAEw7yRzSABfn' .
1392 'R9d3sYZGMtyASw2O1vSluwIxUUnDop3gxEIhJEj8h+01pA3K+klSpALeY9EZgHqYC7E' .
1393 'ETuPS6dZ3764nWohtCY67JvNUX7TtNDNc2qrhrapdRP17+PT2Vh4s9m38V3WwVWC3uH' .
1394 'X/klLZcHIt+aRDV+uekw9GOKSgwFL2ekPpr3gXxigc3zrxel5hcsqLOpVUa4CP/0HkG' .
1395 'F0NPQvOT3ZvpeIJnirKP1ZX9gDFinqhuzL7oqktW61e1iwe7KZEdrZV0k2KZwyb8qU5' .
1397 'server_positive_output_matches' => [qr/No\sstanza\sencryption\smode\smatch/],
1398 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1399 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1400 "-d $default_digest_file -p $default_pid_file $intf_str",
1404 'category' => 'Rijndael SPA',
1405 'subcategory' => 'FUZZING',
1406 'detail' => 'long FKO protocol value (Rijndael trigger)',
1407 'err_msg' => 'server crashed or did not detect error condition',
1408 'function' => \&fuzzer,
1409 ### this packet was generated with a modified fwknop client via the
1410 ### following command line:
1412 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1413 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1415 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1416 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1417 # encrypted SPA packet
1420 '+YQNu4BFgiNeu8HeiBiNKriqCFSseALt9vJaKzkzK/OF4pjkJcvhGEOi7fEVXqn3VIdlGR' .
1421 'DmBul2I7H3z18U9E97bWGgT9NexKgEPCuekL18ZEPf5xR3JleNsNWatqYgAOkgN8ZWE69Q' .
1422 'qQUYYhxTvJHS6R+5JqFKB3A44hMXoICdYNkn9MAktHxk3PbbpQ+nA+jESwVCra2doAiLiM' .
1423 'ucvGIZZiTv0Mc1blFYIE2zqZ/C7ct1V+ukwSkUv0r87eA7uJhmlpThRsL0dN6iekJ6i87B' .
1424 'tE8QyuOXzOMftI11SUn/LwqD4RMdR21rvLrzR6ZB5eUX2UBpODyzX6n+PJJkTWCuFVT4z1' .
1426 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1427 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1428 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1429 "-d $default_digest_file -p $default_pid_file $intf_str",
1434 'category' => 'Rijndael SPA',
1435 'subcategory' => 'FUZZING',
1436 'detail' => 'null proto value',
1437 'err_msg' => 'server crashed or did not detect error condition',
1438 'function' => \&fuzzer,
1439 ### this packet was generated with a modified fwknop client via the
1440 ### following command line:
1442 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A /22 \
1443 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1444 # --verbose --verbose
1447 '/JT14qxh9P4iy+CuUZahThaQjoEuL2zd46a+jL6sTrBZJSa6faUX4dH5fte/4ZJv+9f' .
1448 'd/diWYKAUvdQ4DydPGlR7mwQa2W+obKpqrsTBz7D4054z6ATAOGpCtifakEVl1XRc2+' .
1449 'hW04WpY8mdUNu9i+PrfPr7/KxqU',
1450 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1451 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1452 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1453 "-d $default_digest_file -p $default_pid_file $intf_str",
1457 'category' => 'FUZZING',
1458 'subcategory' => 'server',
1459 'detail' => 'invalid SOURCE access.conf',
1460 'err_msg' => 'server crashed or did not detect error condition',
1461 'function' => \&generic_exec,
1462 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1463 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'fuzz_source'} " .
1464 "-d $default_digest_file -p $default_pid_file $intf_str",
1465 'positive_output_matches' => [qr/Fatal\sinvalid/],
1470 'category' => 'FUZZING',
1471 'subcategory' => 'server',
1472 'detail' => 'invalid OPEN_PORTS access.conf',
1473 'err_msg' => 'server crashed or did not detect error condition',
1474 'function' => \&generic_exec,
1475 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1476 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'fuzz_open_ports'} " .
1477 "-d $default_digest_file -p $default_pid_file $intf_str",
1478 'positive_output_matches' => [qr/Fatal\sinvalid/],
1483 'category' => 'FUZZING',
1484 'subcategory' => 'server',
1485 'detail' => 'invalid RESTRICT_PORTS access.conf',
1486 'err_msg' => 'server crashed or did not detect error condition',
1487 'function' => \&generic_exec,
1488 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1489 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'fuzz_restrict_ports'} " .
1490 "-d $default_digest_file -p $default_pid_file $intf_str",
1491 'positive_output_matches' => [qr/Fatal\sinvalid/],
1496 ### command execution tests
1498 'category' => 'Rijndael SPA',
1499 'subcategory' => 'client+server',
1500 'detail' => 'command execution',
1501 'err_msg' => 'could not complete SPA cycle',
1502 'function' => \&spa_cmd_exec_cycle,
1503 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1504 qq|$fwknopCmd --server-cmd "echo fwknoptest > $cmd_exec_test_file" | .
1505 "-a $fake_ip -D $loopback_ip --get-key $local_key_file " .
1506 "--verbose --verbose",
1507 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1508 "$fwknopdCmd -c $cf{'def'} -a $cf{'cmd_access'} " .
1509 "-d $default_digest_file -p $default_pid_file $intf_str",
1510 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1515 'category' => 'Rijndael SPA',
1516 'subcategory' => 'server',
1517 'detail' => 'digest cache structure',
1518 'err_msg' => 'improper digest cache structure',
1519 'function' => \&digest_cache_structure,
1524 'category' => 'Rijndael SPA',
1525 'subcategory' => 'server',
1526 'detail' => 'ipfw active/expire sets not equal',
1527 'err_msg' => 'allowed active/expire sets to be the same',
1528 'function' => \&spa_cycle,
1529 'cmdline' => $default_client_args,
1530 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1531 "$fwknopdCmd -c $cf{'ipfw_active_expire'} -a $cf{'def_access'} " .
1532 "-d $default_digest_file -p $default_pid_file $intf_str",
1533 'server_positive_output_matches' => [qr/Cannot\sset\sidentical\sipfw\sactive\sand\sexpire\ssets/],
1534 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1539 'category' => 'Rijndael SPA',
1540 'subcategory' => 'client+server',
1541 'detail' => 'non-base64 altered SPA data',
1542 'err_msg' => 'allowed improper SPA data',
1543 'function' => \&altered_non_base64_spa_data,
1544 'cmdline' => $default_client_args,
1545 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1546 "$fwknopdCmd $default_server_conf_args $intf_str",
1550 'category' => 'Rijndael SPA',
1551 'subcategory' => 'client+server',
1552 'detail' => 'base64 altered SPA data',
1553 'err_msg' => 'allowed improper SPA data',
1554 'function' => \&altered_base64_spa_data,
1555 'cmdline' => $default_client_args,
1556 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1557 "$fwknopdCmd $default_server_conf_args $intf_str",
1561 'category' => 'Rijndael SPA',
1562 'subcategory' => 'client+server',
1563 'detail' => 'appended data to SPA pkt',
1564 'err_msg' => 'allowed improper SPA data',
1565 'function' => \&appended_spa_data,
1566 'cmdline' => $default_client_args,
1567 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1568 "$fwknopdCmd $default_server_conf_args $intf_str",
1572 'category' => 'Rijndael SPA',
1573 'subcategory' => 'client+server',
1574 'detail' => 'prepended data to SPA pkt',
1575 'err_msg' => 'allowed improper SPA data',
1576 'function' => \&prepended_spa_data,
1577 'cmdline' => $default_client_args,
1578 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1579 "$fwknopdCmd $default_server_conf_args $intf_str",
1584 'category' => 'GPG (no pw) SPA',
1585 'subcategory' => 'client+server',
1586 'detail' => 'complete cycle (tcp/22 ssh)',
1587 'err_msg' => 'could not complete SPA cycle',
1588 'function' => \&spa_cycle,
1589 'cmdline' => "$default_client_gpg_args_no_homedir "
1590 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1591 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1592 'fw_rule_created' => $NEW_RULE_REQUIRED,
1593 'fw_rule_removed' => $NEW_RULE_REMOVED,
1597 'category' => 'GPG (no pw) SPA',
1598 'subcategory' => 'client+server',
1599 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1600 'err_msg' => 'could not complete SPA cycle',
1601 'function' => \&spa_cycle,
1602 'cmdline' => "$default_client_gpg_args_no_homedir "
1603 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1604 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1605 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1606 "-a $cf{'multi_gpg_access'} $intf_str " .
1607 "-d $default_digest_file -p $default_pid_file",
1608 'fw_rule_created' => $NEW_RULE_REQUIRED,
1609 'fw_rule_removed' => $NEW_RULE_REMOVED,
1614 'category' => 'GPG (no pw) SPA',
1615 'subcategory' => 'client+server',
1616 'detail' => 'complete cycle (tcp/23 telnet)',
1617 'err_msg' => 'could not complete SPA cycle',
1618 'function' => \&spa_cycle,
1619 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1620 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1621 "$local_key_file --verbose --verbose " .
1622 "--gpg-recipient-key $gpg_server_key " .
1623 "--gpg-signer-key $gpg_client_key " .
1624 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1625 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1626 'fw_rule_created' => $NEW_RULE_REQUIRED,
1627 'fw_rule_removed' => $NEW_RULE_REMOVED,
1631 'category' => 'GPG (no pw) SPA',
1632 'subcategory' => 'client+server',
1633 'detail' => 'complete cycle (tcp/9418 git)',
1634 'err_msg' => 'could not complete SPA cycle',
1635 'function' => \&spa_cycle,
1636 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1637 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1638 "$local_key_file --verbose --verbose " .
1639 "--gpg-recipient-key $gpg_server_key " .
1640 "--gpg-signer-key $gpg_client_key " .
1641 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1642 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1643 'fw_rule_created' => $NEW_RULE_REQUIRED,
1644 'fw_rule_removed' => $NEW_RULE_REMOVED,
1648 'category' => 'GPG (no pw) SPA',
1649 'subcategory' => 'client+server',
1650 'detail' => 'complete cycle (tcp/60001)',
1651 'err_msg' => 'could not complete SPA cycle',
1652 'function' => \&spa_cycle,
1653 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1654 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1655 "$local_key_file --verbose --verbose " .
1656 "--gpg-recipient-key $gpg_server_key " .
1657 "--gpg-signer-key $gpg_client_key " .
1658 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1659 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1660 'fw_rule_created' => $NEW_RULE_REQUIRED,
1661 'fw_rule_removed' => $NEW_RULE_REMOVED,
1666 'category' => 'GPG (no pw) SPA',
1667 'subcategory' => 'client+server',
1668 'detail' => 'complete cycle (udp/53 dns)',
1669 'err_msg' => 'could not complete SPA cycle',
1670 'function' => \&spa_cycle,
1671 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1672 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1673 "$local_key_file --verbose --verbose " .
1674 "--gpg-recipient-key $gpg_server_key " .
1675 "--gpg-signer-key $gpg_client_key " .
1676 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1677 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1678 'fw_rule_created' => $NEW_RULE_REQUIRED,
1679 'fw_rule_removed' => $NEW_RULE_REMOVED,
1684 'category' => 'GPG (no pw) SPA',
1685 'subcategory' => 'client+server',
1686 'detail' => 'replay attack detection',
1687 'err_msg' => 'could not detect replay attack',
1688 'function' => \&replay_detection,
1689 'cmdline' => "$default_client_gpg_args_no_homedir "
1690 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1691 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1692 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1696 'category' => 'GPG (no pw) SPA',
1697 'subcategory' => 'client+server',
1698 'detail' => 'replay detection (GnuPG prefix)',
1699 'err_msg' => 'could not detect replay attack',
1700 'function' => \&replay_detection,
1701 'pkt_prefix' => 'hQ',
1702 'cmdline' => "$default_client_gpg_args_no_homedir "
1703 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1704 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1705 "$fwknopdCmd $default_server_conf_args $intf_str",
1706 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1711 'category' => 'GPG (no pw) SPA',
1712 'subcategory' => 'client+server',
1713 'detail' => 'non-base64 altered SPA data',
1714 'err_msg' => 'allowed improper SPA data',
1715 'function' => \&altered_non_base64_spa_data,
1716 'cmdline' => "$default_client_gpg_args_no_homedir "
1717 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1718 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1722 'category' => 'GPG (no pw) SPA',
1723 'subcategory' => 'client+server',
1724 'detail' => 'base64 altered SPA data',
1725 'err_msg' => 'allowed improper SPA data',
1726 'function' => \&altered_base64_spa_data,
1727 'cmdline' => "$default_client_gpg_args_no_homedir "
1728 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1729 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1733 'category' => 'GPG (no pw) SPA',
1734 'subcategory' => 'client+server',
1735 'detail' => 'appended data to SPA pkt',
1736 'err_msg' => 'allowed improper SPA data',
1737 'function' => \&appended_spa_data,
1738 'cmdline' => "$default_client_gpg_args_no_homedir "
1739 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1740 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1744 'category' => 'GPG (no pw) SPA',
1745 'subcategory' => 'client+server',
1746 'detail' => 'prepended data to SPA pkt',
1747 'err_msg' => 'allowed improper SPA data',
1748 'function' => \&prepended_spa_data,
1749 'cmdline' => "$default_client_gpg_args_no_homedir "
1750 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1751 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1755 'category' => 'GPG (no pw) SPA',
1756 'subcategory' => 'client+server',
1757 'detail' => 'spoof username (tcp/22 ssh)',
1758 'err_msg' => 'could not spoof username',
1759 'function' => \&spoof_username,
1760 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args_no_homedir "
1761 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1762 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1767 'category' => 'GnuPG (GPG) SPA',
1768 'subcategory' => 'client+server',
1769 'detail' => 'complete cycle (tcp/22 ssh)',
1770 'err_msg' => 'could not complete SPA cycle',
1771 'function' => \&spa_cycle,
1772 'cmdline' => $default_client_gpg_args,
1773 'fwknopd_cmdline' => $default_server_gpg_args,
1774 'fw_rule_created' => $NEW_RULE_REQUIRED,
1775 'fw_rule_removed' => $NEW_RULE_REMOVED,
1779 'category' => 'GnuPG (GPG) SPA',
1780 'subcategory' => 'client+server',
1781 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1782 'err_msg' => 'could not complete SPA cycle',
1783 'function' => \&spa_cycle,
1784 'cmdline' => $default_client_gpg_args,
1785 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1786 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1787 "-a $cf{'multi_gpg_access'} $intf_str " .
1788 "-d $default_digest_file -p $default_pid_file",
1789 'fw_rule_created' => $NEW_RULE_REQUIRED,
1790 'fw_rule_removed' => $NEW_RULE_REMOVED,
1795 'category' => 'GnuPG (GPG) SPA',
1796 'subcategory' => 'client+server',
1797 'detail' => 'complete cycle (tcp/23 telnet)',
1798 'err_msg' => 'could not complete SPA cycle',
1799 'function' => \&spa_cycle,
1800 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1801 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1802 "$local_key_file --verbose --verbose " .
1803 "--gpg-recipient-key $gpg_server_key " .
1804 "--gpg-signer-key $gpg_client_key " .
1805 "--gpg-home-dir $gpg_client_home_dir",
1806 'fwknopd_cmdline' => $default_server_gpg_args,
1807 'fw_rule_created' => $NEW_RULE_REQUIRED,
1808 'fw_rule_removed' => $NEW_RULE_REMOVED,
1812 'category' => 'GnuPG (GPG) SPA',
1813 'subcategory' => 'client+server',
1814 'detail' => 'complete cycle (tcp/9418 git)',
1815 'err_msg' => 'could not complete SPA cycle',
1816 'function' => \&spa_cycle,
1817 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1818 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1819 "$local_key_file --verbose --verbose " .
1820 "--gpg-recipient-key $gpg_server_key " .
1821 "--gpg-signer-key $gpg_client_key " .
1822 "--gpg-home-dir $gpg_client_home_dir",
1823 'fwknopd_cmdline' => $default_server_gpg_args,
1824 'fw_rule_created' => $NEW_RULE_REQUIRED,
1825 'fw_rule_removed' => $NEW_RULE_REMOVED,
1829 'category' => 'GnuPG (GPG) SPA',
1830 'subcategory' => 'client+server',
1831 'detail' => 'complete cycle (tcp/60001)',
1832 'err_msg' => 'could not complete SPA cycle',
1833 'function' => \&spa_cycle,
1834 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1835 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1836 "$local_key_file --verbose --verbose " .
1837 "--gpg-recipient-key $gpg_server_key " .
1838 "--gpg-signer-key $gpg_client_key " .
1839 "--gpg-home-dir $gpg_client_home_dir",
1840 'fwknopd_cmdline' => $default_server_gpg_args,
1841 'fw_rule_created' => $NEW_RULE_REQUIRED,
1842 'fw_rule_removed' => $NEW_RULE_REMOVED,
1847 'category' => 'GnuPG (GPG) SPA',
1848 'subcategory' => 'client+server',
1849 'detail' => 'complete cycle (udp/53 dns)',
1850 'err_msg' => 'could not complete SPA cycle',
1851 'function' => \&spa_cycle,
1852 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1853 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1854 "$local_key_file --verbose --verbose " .
1855 "--gpg-recipient-key $gpg_server_key " .
1856 "--gpg-signer-key $gpg_client_key " .
1857 "--gpg-home-dir $gpg_client_home_dir",
1858 'fwknopd_cmdline' => $default_server_gpg_args,
1859 'fw_rule_created' => $NEW_RULE_REQUIRED,
1860 'fw_rule_removed' => $NEW_RULE_REMOVED,
1865 'category' => 'GnuPG (GPG) SPA',
1866 'subcategory' => 'client+server',
1867 'detail' => 'replay attack detection',
1868 'err_msg' => 'could not detect replay attack',
1869 'function' => \&replay_detection,
1870 'cmdline' => $default_client_gpg_args,
1871 'fwknopd_cmdline' => $default_server_gpg_args,
1872 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1876 'category' => 'GnuPG (GPG) SPA',
1877 'subcategory' => 'client+server',
1878 'detail' => 'replay detection (GnuPG prefix)',
1879 'err_msg' => 'could not detect replay attack',
1880 'function' => \&replay_detection,
1881 'pkt_prefix' => 'hQ',
1882 'cmdline' => $default_client_gpg_args,
1883 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1884 "$fwknopdCmd $default_server_conf_args $intf_str",
1885 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1890 'category' => 'GnuPG (GPG) SPA',
1891 'subcategory' => 'client+server',
1892 'detail' => 'non-base64 altered SPA data',
1893 'err_msg' => 'allowed improper SPA data',
1894 'function' => \&altered_non_base64_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' => 'base64 altered SPA data',
1903 'err_msg' => 'allowed improper SPA data',
1904 'function' => \&altered_base64_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' => 'appended data to SPA pkt',
1913 'err_msg' => 'allowed improper SPA data',
1914 'function' => \&appended_spa_data,
1915 'cmdline' => $default_client_gpg_args,
1916 'fwknopd_cmdline' => $default_server_gpg_args,
1920 'category' => 'GnuPG (GPG) SPA',
1921 'subcategory' => 'client+server',
1922 'detail' => 'prepended data to SPA pkt',
1923 'err_msg' => 'allowed improper SPA data',
1924 'function' => \&prepended_spa_data,
1925 'cmdline' => $default_client_gpg_args,
1926 'fwknopd_cmdline' => $default_server_gpg_args,
1930 'category' => 'GnuPG (GPG) SPA',
1931 'subcategory' => 'client+server',
1932 'detail' => 'spoof username (tcp/22 ssh)',
1933 'err_msg' => 'could not spoof username',
1934 'function' => \&spoof_username,
1935 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args",
1936 'fwknopd_cmdline' => $default_server_gpg_args,
1940 'category' => 'GnuPG (GPG) SPA',
1941 'subcategory' => 'server',
1942 'detail' => 'digest cache structure',
1943 'err_msg' => 'improper digest cache structure',
1944 'function' => \&digest_cache_structure,
1949 if ($use_valgrind) {
1952 'category' => 'valgrind output',
1953 'subcategory' => 'flagged functions',
1955 'err_msg' => 'could not parse flagged functions',
1956 'function' => \&parse_valgrind_flagged_functions,
1962 'category' => $REQUIRED,
1963 'subcategory' => $OPTIONAL,
1964 'detail' => $REQUIRED,
1965 'function' => $REQUIRED,
1966 'binary' => $OPTIONAL,
1967 'cmdline' => $OPTIONAL,
1968 'fwknopd_cmdline' => $OPTIONAL,
1969 'fatal' => $OPTIONAL,
1970 'exec_err' => $OPTIONAL,
1971 'fw_rule_created' => $OPTIONAL,
1972 'fw_rule_removed' => $OPTIONAL,
1973 'server_conf' => $OPTIONAL,
1974 'pkt_prefix' => $OPTIONAL,
1975 'no_ip_check' => $OPTIONAL,
1976 'positive_output_matches' => $OPTIONAL,
1977 'negative_output_matches' => $OPTIONAL,
1978 'server_positive_output_matches' => $OPTIONAL,
1979 'server_negative_output_matches' => $OPTIONAL,
1980 'replay_positive_output_matches' => $OPTIONAL,
1981 'replay_negative_output_matches' => $OPTIONAL,
1985 &diff_test_results();
1989 ### make sure everything looks as expected before continuing
1992 &logr("\n[+] Starting the fwknop test suite...\n\n" .
1993 " args: @args_cp\n\n"
1996 ### save the results from any previous test suite run
1997 ### so that we can potentially compare them with --diff
1998 if ($saved_last_results) {
1999 &logr(" Saved results from previous run " .
2000 "to: ${output_dir}.last/\n\n");
2003 ### main loop through all of the tests
2004 for my $test_hr (@tests) {
2005 &run_test($test_hr);
2008 &logr("\n[+] passed/failed/executed: $passed/$failed/$executed tests\n\n");
2010 copy $logfile, "$output_dir/$logfile" or die $!;
2014 #===================== end main =======================
2017 my $test_hr = shift;
2019 my $msg = "[$test_hr->{'category'}]";
2020 $msg .= " [$test_hr->{'subcategory'}]" if $test_hr->{'subcategory'};
2021 $msg .= " $test_hr->{'detail'}";
2023 return unless &process_include_exclude($msg);
2033 $current_test_file = "$output_dir/$executed.test";
2034 $server_test_file = "$output_dir/${executed}_fwknopd.test";
2036 &write_test_file("[+] TEST: $msg\n", $current_test_file);
2037 $test_hr->{'msg'} = $msg;
2038 if (&{$test_hr->{'function'}}($test_hr)) {
2039 &logr("pass ($executed)\n");
2042 &logr("fail ($executed)\n");
2045 if ($test_hr->{'fatal'} eq $YES) {
2046 die "[*] required test failed, exiting.";
2053 sub process_include_exclude() {
2056 ### inclusions/exclusions
2057 if (@tests_to_include) {
2059 for my $test (@tests_to_include) {
2060 if ($msg =~ $test or ($use_valgrind
2061 and $msg =~ /valgrind\soutput/)) {
2066 return 0 unless $found;
2068 if (@tests_to_exclude) {
2070 for my $test (@tests_to_exclude) {
2071 if ($msg =~ $test) {
2081 sub diff_test_results() {
2083 $diff_dir1 = "${output_dir}.last" unless $diff_dir1;
2084 $diff_dir2 = $output_dir unless $diff_dir2;
2086 die "[*] Need results from a previous run before running --diff"
2087 unless -d $diff_dir2;
2088 die "[*] Current results set does not exist." unless -d $diff_dir1;
2090 my %current_tests = ();
2091 my %previous_tests = ();
2093 ### Only diff results for matching tests (parse the logfile to see which
2094 ### test numbers match across the two test cycles).
2095 &build_results_hash(\%current_tests, $diff_dir1);
2096 &build_results_hash(\%previous_tests, $diff_dir2);
2098 for my $test_msg (sort {$current_tests{$a}{'num'} <=> $current_tests{$b}{'num'}}
2099 keys %current_tests) {
2100 my $current_result = $current_tests{$test_msg}{'pass_fail'};
2101 my $current_num = $current_tests{$test_msg}{'num'};
2102 if (defined $previous_tests{$test_msg}) {
2103 print "[+] Checking: $test_msg\n";
2104 my $previous_result = $previous_tests{$test_msg}{'pass_fail'};
2105 my $previous_num = $previous_tests{$test_msg}{'num'};
2106 if ($current_result ne $previous_result) {
2107 print " DIFF: **$current_result** $test_msg\n";
2110 &diff_results($previous_num, $current_num);
2118 sub diff_results() {
2119 my ($previous_num, $current_num) = @_;
2121 ### edit out any valgrind "==354==" prefixes
2122 my $valgrind_search_re = qr/^==\d+==\s/;
2124 ### remove CMD timestamps
2125 my $cmd_search_re = qr/^\S+\s.*?\s\d{4}\sCMD\:/;
2127 for my $file ("$diff_dir1/${previous_num}.test",
2128 "$diff_dir1/${previous_num}_fwknopd.test",
2129 "$diff_dir2/${current_num}.test",
2130 "$diff_dir2/${current_num}_fwknopd.test",
2132 system qq{perl -p -i -e 's|$valgrind_search_re||' $file} if -e $file;
2133 system qq{perl -p -i -e 's|$cmd_search_re|CMD:|' $file} if -e $file;
2136 if (-e "$diff_dir1/${previous_num}.test"
2137 and -e "$diff_dir2/${current_num}.test") {
2138 system "diff -u $diff_dir1/${previous_num}.test " .
2139 "$diff_dir2/${current_num}.test";
2142 if (-e "$diff_dir1/${previous_num}_fwknopd.test"
2143 and -e "$diff_dir2/${current_num}_fwknopd.test") {
2144 system "diff -u $diff_dir1/${previous_num}_fwknopd.test " .
2145 "$diff_dir2/${current_num}_fwknopd.test";
2151 sub build_results_hash() {
2152 my ($hr, $dir) = @_;
2154 open F, "< $dir/$logfile" or die $!;
2156 if (/^(.*?)\.\.\..*(pass|fail)\s\((\d+)\)/) {
2157 $hr->{$1}{'pass_fail'} = $2;
2158 $hr->{$1}{'num'} = $3;
2164 sub compile_warnings() {
2166 ### 'make clean' as root
2167 return 0 unless &run_cmd('make -C .. clean',
2168 $cmd_out_tmp, $current_test_file);
2171 my $username = getpwuid((stat($configure_path))[4]);
2172 die "[*] Could not determine $configure_path owner"
2175 return 0 unless &run_cmd("$sudo_path -u $username make -C ..",
2176 $cmd_out_tmp, $current_test_file);
2180 return 0 unless &run_cmd('make -C ..',
2181 $cmd_out_tmp, $current_test_file);
2185 ### look for compilation warnings - something like:
2186 ### warning: ‘test’ is used uninitialized in this function
2187 return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
2188 $MATCH_ANY, $current_test_file);
2190 ### the new binaries should exist
2191 unless (-e $fwknopCmd and -x $fwknopCmd) {
2192 &write_test_file("[-] $fwknopCmd does not exist or not executable.\n",
2193 $current_test_file);
2195 unless (-e $fwknopdCmd and -x $fwknopdCmd) {
2196 &write_test_file("[-] $fwknopdCmd does not exist or not executable.\n",
2197 $current_test_file);
2203 sub make_distcheck() {
2205 ### 'make clean' as root
2206 return 0 unless &run_cmd('make -C .. distcheck',
2207 $cmd_out_tmp, $current_test_file);
2209 ### look for compilation warnings - something like:
2210 ### warning: ‘test’ is used uninitialized in this function
2211 return 1 if &file_find_regex([qr/archives\sready\sfor\sdistribution/],
2212 $MATCH_ALL, $current_test_file);
2218 sub binary_exists() {
2219 my $test_hr = shift;
2220 return 0 unless $test_hr->{'binary'};
2222 ### account for different libfko.so paths (e.g. libfko.so.0.3 with no
2223 ### libfko.so link on OpenBSD, and libfko.dylib path on Mac OS X)
2225 if ($test_hr->{'binary'} =~ /libfko/) {
2226 unless (-e $test_hr->{'binary'}) {
2227 my $file = "$lib_dir/libfko.dylib";
2229 $test_hr->{'binary'} = $file;
2230 $libfko_bin = $file;
2232 for my $f (glob("$lib_dir/libfko.so*")) {
2233 if (-e $f and -x $f) {
2234 $test_hr->{'binary'} = $f;
2243 return 0 unless -e $test_hr->{'binary'} and -x $test_hr->{'binary'};
2247 sub expected_code_version() {
2248 my $test_hr = shift;
2250 unless (-e '../VERSION') {
2251 &write_test_file("[-] ../VERSION file does not exist.\n",
2252 $current_test_file);
2256 open F, '< ../VERSION' or die $!;
2259 if ($line =~ /(\d.*\d)/) {
2261 return 0 unless &run_cmd($test_hr->{'cmdline'},
2262 $cmd_out_tmp, $current_test_file);
2263 return 1 if &file_find_regex([qr/$version/],
2264 $MATCH_ALL, $current_test_file);
2269 sub client_send_spa_packet() {
2270 my $test_hr = shift;
2272 &write_key('fwknoptest', $local_key_file);
2274 return 0 unless &run_cmd($test_hr->{'cmdline'},
2275 $cmd_out_tmp, $current_test_file);
2276 return 0 unless &file_find_regex([qr/final\spacked/i],
2277 $MATCH_ALL, $current_test_file);
2282 sub permissions_check() {
2283 my $test_hr = shift;
2286 chmod 0777, $cf{'def'} or die $!;
2287 chmod 0777, $cf{'def_access'} or die $!;
2289 $rv = &spa_cycle($test_hr);
2291 chmod 0600, $cf{'def'} or die $!;
2292 chmod 0600, $cf{'def_access'} or die $!;
2294 if ($test_hr->{'server_positive_output_matches'}) {
2295 $rv = 0 unless &file_find_regex(
2296 $test_hr->{'server_positive_output_matches'},
2297 $MATCH_ALL, $server_test_file);
2303 my $test_hr = shift;
2305 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2306 = &client_server_interaction($test_hr, [], $USE_CLIENT);
2308 if ($test_hr->{'fw_rule_created'} eq $NEW_RULE_REQUIRED) {
2309 $rv = 0 unless $fw_rule_created;
2310 } elsif ($test_hr->{'fw_rule_created'} eq $REQUIRE_NO_NEW_RULE) {
2311 $rv = 0 if $fw_rule_created;
2314 if ($test_hr->{'fw_rule_removed'} eq $NEW_RULE_REMOVED) {
2315 $rv = 0 unless $fw_rule_removed;
2316 } elsif ($test_hr->{'fw_rule_removed'} eq $REQUIRE_NO_NEW_REMOVED) {
2317 $rv = 0 if $fw_rule_removed;
2320 if ($test_hr->{'server_positive_output_matches'}) {
2321 $rv = 0 unless &file_find_regex(
2322 $test_hr->{'server_positive_output_matches'},
2323 $MATCH_ALL, $server_test_file);
2326 if ($test_hr->{'server_negative_output_matches'}) {
2327 $rv = 0 if &file_find_regex(
2328 $test_hr->{'server_negative_output_matches'},
2329 $MATCH_ANY, $server_test_file);
2335 sub spoof_username() {
2336 my $test_hr = shift;
2338 my $rv = &spa_cycle($test_hr);
2340 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2341 $MATCH_ALL, $current_test_file)) {
2345 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2346 $MATCH_ALL, $server_test_file)) {
2353 sub spa_cmd_exec_cycle() {
2354 my $test_hr = shift;
2356 my $rv = &spa_cycle($test_hr);
2358 if (-e $cmd_exec_test_file) {
2359 unlink $cmd_exec_test_file;
2367 sub replay_detection() {
2368 my $test_hr = shift;
2370 ### do a complete SPA cycle and then parse the SPA packet out of the
2371 ### current test file and re-send
2373 return 0 unless &spa_cycle($test_hr);
2375 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2378 &write_test_file("[-] could not get SPA packet " .
2379 "from file: $current_test_file\n",
2380 $current_test_file);
2384 if ($test_hr->{'pkt_prefix'}) {
2385 $spa_pkt = $test_hr->{'pkt_prefix'} . $spa_pkt;
2391 'port' => $default_spa_port,
2392 'dst_ip' => $loopback_ip,
2397 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2398 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2400 $rv = 0 unless $server_was_stopped;
2402 if ($test_hr->{'replay_positive_output_matches'}) {
2403 $rv = 0 unless &file_find_regex(
2404 $test_hr->{'replay_positive_output_matches'},
2405 $MATCH_ALL, $server_test_file);
2408 if ($test_hr->{'replay_negative_output_matches'}) {
2409 $rv = 0 if &file_find_regex(
2410 $test_hr->{'replay_negative_output_matches'},
2411 $MATCH_ANY, $server_test_file);
2417 sub digest_cache_structure() {
2418 my $test_hr = shift;
2421 &run_cmd("file $default_digest_file", $cmd_out_tmp, $current_test_file);
2423 if (&file_find_regex([qr/ASCII/i], $MATCH_ALL, $cmd_out_tmp)) {
2425 ### the format should be:
2426 ### <digest> <proto> <src_ip> <src_port> <dst_ip> <dst_port> <time>
2427 open F, "< $default_digest_file" or
2428 die "[*] could not open $default_digest_file: $!";
2432 unless (m|^\S+\s+\d+\s+$ip_re\s+\d+\s+$ip_re\s+\d+\s+\d+|) {
2433 &write_test_file("[-] invalid digest.cache line: $_",
2434 $current_test_file);
2440 } elsif (&file_find_regex([qr/dbm/i], $MATCH_ALL, $cmd_out_tmp)) {
2441 &write_test_file("[+] DBM digest file format, " .
2442 "assuming this is valid.\n", $current_test_file);
2444 ### don't know what kind of file the digest.cache is
2445 &write_test_file("[-] unrecognized file type for " .
2446 "$default_digest_file.\n", $current_test_file);
2451 &write_test_file("[+] valid digest.cache structure.\n",
2452 $current_test_file);
2458 sub server_bpf_ignore_packet() {
2459 my $test_hr = shift;
2462 my $server_was_stopped = 0;
2463 my $fw_rule_created = 0;
2464 my $fw_rule_removed = 0;
2466 unless (&client_send_spa_packet($test_hr)) {
2467 &write_test_file("[-] fwknop client execution error.\n",
2468 $current_test_file);
2472 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2475 &write_test_file("[-] could not get SPA packet " .
2476 "from file: $current_test_file\n", $current_test_file);
2483 'port' => $default_spa_port,
2484 'dst_ip' => $loopback_ip,
2489 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2490 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2492 unless (&file_find_regex([qr/PCAP\sfilter.*\s$non_std_spa_port/],
2493 $MATCH_ALL, $server_test_file)) {
2500 sub altered_non_base64_spa_data() {
2501 my $test_hr = shift;
2504 my $server_was_stopped = 0;
2505 my $fw_rule_created = 0;
2506 my $fw_rule_removed = 0;
2508 unless (&client_send_spa_packet($test_hr)) {
2509 &write_test_file("[-] fwknop client execution error.\n",
2510 $current_test_file);
2514 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2517 &write_test_file("[-] could not get SPA packet " .
2518 "from file: $current_test_file\n", $current_test_file);
2522 ### alter one byte (change to a ":")
2523 $spa_pkt =~ s|^(.{3}).|$1:|;
2528 'port' => $default_spa_port,
2529 'dst_ip' => $loopback_ip,
2534 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2535 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2537 $rv = 0 unless $server_was_stopped;
2543 my $test_hr = shift;
2546 my $server_was_stopped = 0;
2547 my $fw_rule_created = 0;
2548 my $fw_rule_removed = 0;
2553 'port' => $default_spa_port,
2554 'dst_ip' => $loopback_ip,
2555 'data' => $test_hr->{'fuzzing_pkt'},
2559 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2560 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2562 $rv = 0 unless $server_was_stopped;
2564 if ($fw_rule_created) {
2565 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2568 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2571 if ($test_hr->{'server_positive_output_matches'}) {
2572 $rv = 0 unless &file_find_regex(
2573 $test_hr->{'server_positive_output_matches'},
2574 $MATCH_ALL, $server_test_file);
2580 sub altered_base64_spa_data() {
2581 my $test_hr = shift;
2584 my $server_was_stopped = 0;
2585 my $fw_rule_created = 0;
2586 my $fw_rule_removed = 0;
2588 unless (&client_send_spa_packet($test_hr)) {
2589 &write_test_file("[-] fwknop client execution error.\n",
2590 $current_test_file);
2594 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2597 &write_test_file("[-] could not get SPA packet " .
2598 "from file: $current_test_file\n", $current_test_file);
2602 $spa_pkt =~ s|^(.{3}).|AAAA|;
2607 'port' => $default_spa_port,
2608 'dst_ip' => $loopback_ip,
2613 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2614 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2616 $rv = 0 unless $server_was_stopped;
2618 if ($fw_rule_created) {
2619 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2622 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2625 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2626 $MATCH_ALL, $server_test_file)) {
2633 sub appended_spa_data() {
2634 my $test_hr = shift;
2637 my $server_was_stopped = 0;
2638 my $fw_rule_created = 0;
2639 my $fw_rule_removed = 0;
2641 unless (&client_send_spa_packet($test_hr)) {
2642 &write_test_file("[-] fwknop client execution error.\n",
2643 $current_test_file);
2647 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2650 &write_test_file("[-] could not get SPA packet " .
2651 "from file: $current_test_file\n", $current_test_file);
2660 'port' => $default_spa_port,
2661 'dst_ip' => $loopback_ip,
2666 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2667 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2669 $rv = 0 unless $server_was_stopped;
2671 if ($fw_rule_created) {
2672 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2675 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2678 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2679 $MATCH_ALL, $server_test_file)) {
2686 sub prepended_spa_data() {
2687 my $test_hr = shift;
2690 my $server_was_stopped = 0;
2691 my $fw_rule_created = 0;
2692 my $fw_rule_removed = 0;
2694 unless (&client_send_spa_packet($test_hr)) {
2695 &write_test_file("[-] fwknop client execution error.\n",
2696 $current_test_file);
2700 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2703 &write_test_file("[-] could not get SPA packet " .
2704 "from file: $current_test_file\n", $current_test_file);
2708 $spa_pkt = 'AAAA' . $spa_pkt;
2713 'port' => $default_spa_port,
2714 'dst_ip' => $loopback_ip,
2719 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2720 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2722 $rv = 0 unless $server_was_stopped;
2724 if ($fw_rule_created) {
2725 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2728 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2731 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2732 $MATCH_ALL, $server_test_file)) {
2739 sub server_start() {
2740 my $test_hr = shift;
2742 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2743 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2745 unless (&file_find_regex([qr/Starting\sfwknopd\smain\sevent\sloop/],
2746 $MATCH_ALL, $server_test_file)) {
2750 $rv = 0 unless $server_was_stopped;
2756 my $test_hr = shift;
2758 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2759 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2761 $rv = 0 unless $server_was_stopped;
2766 sub server_packet_limit() {
2767 my $test_hr = shift;
2772 'port' => $default_spa_port,
2773 'dst_ip' => $loopback_ip,
2778 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2779 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2781 if (&is_fwknopd_running()) {
2786 unless (&file_find_regex([qr/count\slimit\sof\s1\sreached/],
2787 $MATCH_ALL, $server_test_file)) {
2791 unless (&file_find_regex([qr/Shutting\sDown\sfwknopd/i],
2792 $MATCH_ALL, $server_test_file)) {
2799 sub server_ignore_small_packets() {
2800 my $test_hr = shift;
2805 'port' => $default_spa_port,
2806 'dst_ip' => $loopback_ip,
2807 'data' => 'A'x120, ### < MIN_SPA_DATA_SIZE
2811 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2812 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2816 if (&is_fwknopd_running()) {
2824 sub client_server_interaction() {
2825 my ($test_hr, $pkts_hr, $spa_client_flag) = @_;
2828 my $server_was_stopped = 1;
2829 my $fw_rule_created = 1;
2830 my $fw_rule_removed = 0;
2832 ### start fwknopd to monitor for the SPA packet over the loopback interface
2833 my $fwknopd_parent_pid = &start_fwknopd($test_hr);
2835 ### give fwknopd a chance to parse its config and start sniffing
2836 ### on the loopback interface
2837 if ($use_valgrind) {
2843 ### send the SPA packet(s) to the server either manually using IO::Socket or
2844 ### with the fwknopd client
2845 if ($spa_client_flag == $USE_CLIENT) {
2846 unless (&client_send_spa_packet($test_hr)) {
2847 &write_test_file("[-] fwknop client execution error.\n",
2848 $current_test_file);
2852 &send_packets($pkts_hr);
2855 ### check to see if the SPA packet resulted in a new fw access rule
2857 while (not &is_fw_rule_active($test_hr)) {
2858 &write_test_file("[-] new fw rule does not exist.\n",
2859 $current_test_file);
2865 $fw_rule_created = 0;
2866 $fw_rule_removed = 0;
2869 &time_for_valgrind() if $use_valgrind;
2871 if ($fw_rule_created) {
2872 sleep 3; ### allow time for rule time out.
2873 if (&is_fw_rule_active($test_hr)) {
2874 &write_test_file("[-] new fw rule not timed out.\n",
2875 $current_test_file);
2878 &write_test_file("[+] new fw rule timed out.\n",
2879 $current_test_file);
2880 $fw_rule_removed = 1;
2884 if (&is_fwknopd_running()) {
2886 unless (&file_find_regex([qr/Got\sSIGTERM/],
2887 $MATCH_ALL, $server_test_file)) {
2888 $server_was_stopped = 0;
2891 &write_test_file("[-] server is not running.\n",
2892 $current_test_file);
2893 $server_was_stopped = 0;
2896 return ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed);
2899 sub get_spa_packet_from_file() {
2904 my $found_trigger_line = 0;
2905 open F, "< $file" or die "[*] Could not open file $file: $!";
2907 if (/final\spacked/i) {
2908 $found_trigger_line = 1;
2911 next unless $found_trigger_line;
2913 ### the next line with non whitespace is the SPA packet
2924 sub send_packets() {
2925 my $pkts_ar = shift;
2927 open F, ">> $current_test_file" or die $!;
2928 print F "[+] send_packets(): Sending the following packets...\n";
2929 print F Dumper $pkts_ar;
2932 for my $pkt_hr (@$pkts_ar) {
2933 if ($pkt_hr->{'proto'} eq 'tcp' or $pkt_hr->{'proto'} eq 'udp') {
2934 my $socket = IO::Socket::INET->new(
2935 PeerAddr => $pkt_hr->{'dst_ip'},
2936 PeerPort => $pkt_hr->{'port'},
2937 Proto => $pkt_hr->{'proto'},
2939 ) or die "[*] Could not acquire $pkt_hr->{'proto'}/$pkt_hr->{'port'} " .
2940 "socket to $pkt_hr->{'dst_ip'}: $!";
2942 $socket->send($pkt_hr->{'data'});
2945 } elsif ($pkt_hr->{'proto'} eq 'http') {
2947 } elsif ($pkt_hr->{'proto'} eq 'icmp') {
2951 sleep $pkt_hr->{'delay'} if defined $pkt_hr->{'delay'};
2956 sub generic_exec() {
2957 my $test_hr = shift;
2961 my $exec_rv = &run_cmd($test_hr->{'cmdline'},
2962 $cmd_out_tmp, $current_test_file);
2964 if ($test_hr->{'exec_err'} eq $YES) {
2965 $rv = 0 if $exec_rv;
2967 $rv = 0 unless $exec_rv;
2970 if ($test_hr->{'positive_output_matches'}) {
2971 $rv = 0 unless &file_find_regex(
2972 $test_hr->{'positive_output_matches'},
2973 $MATCH_ALL, $current_test_file);
2976 if ($test_hr->{'negative_output_matches'}) {
2977 $rv = 0 if &file_find_regex(
2978 $test_hr->{'negative_output_matches'},
2979 $MATCH_ANY, $current_test_file);
2987 my $test_hr = shift;
2988 return 0 unless $test_hr->{'binary'};
2989 &run_cmd("./hardening-check $test_hr->{'binary'}",
2990 $cmd_out_tmp, $current_test_file);
2991 return 0 if &file_find_regex([qr/Position\sIndependent.*:\sno/i],
2992 $MATCH_ALL, $current_test_file);
2996 ### check for stack protection
2997 sub stack_protected_binary() {
2998 my $test_hr = shift;
2999 return 0 unless $test_hr->{'binary'};
3000 &run_cmd("./hardening-check $test_hr->{'binary'}",
3001 $cmd_out_tmp, $current_test_file);
3002 return 0 if &file_find_regex([qr/Stack\sprotected.*:\sno/i],
3003 $MATCH_ALL, $current_test_file);
3007 ### check for fortified source functions
3008 sub fortify_source_functions() {
3009 my $test_hr = shift;
3010 return 0 unless $test_hr->{'binary'};
3011 &run_cmd("./hardening-check $test_hr->{'binary'}",
3012 $cmd_out_tmp, $current_test_file);
3013 return 0 if &file_find_regex([qr/Fortify\sSource\sfunctions:\sno/i],
3014 $MATCH_ALL, $current_test_file);
3018 ### check for read-only relocations
3019 sub read_only_relocations() {
3020 my $test_hr = shift;
3021 return 0 unless $test_hr->{'binary'};
3022 &run_cmd("./hardening-check $test_hr->{'binary'}",
3023 $cmd_out_tmp, $current_test_file);
3024 return 0 if &file_find_regex([qr/Read.only\srelocations:\sno/i],
3025 $MATCH_ALL, $current_test_file);
3029 ### check for immediate binding
3030 sub immediate_binding() {
3031 my $test_hr = shift;
3032 return 0 unless $test_hr->{'binary'};
3033 &run_cmd("./hardening-check $test_hr->{'binary'}",
3034 $cmd_out_tmp, $current_test_file);
3035 return 0 if &file_find_regex([qr/Immediate\sbinding:\sno/i],
3036 $MATCH_ALL, $current_test_file);
3042 &run_cmd("LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd " .
3043 "$default_server_conf_args --fw-list-all",
3044 $cmd_out_tmp, $current_test_file);
3052 'ls -l /etc', 'if [ -e /etc/issue ]; then cat /etc/issue; fi',
3053 'if [ `which iptables` ]; then iptables -V; fi',
3054 'if [ -e /proc/cpuinfo ]; then cat /proc/cpuinfo; fi',
3055 'if [ -e /proc/config.gz ]; then zcat /proc/config.gz; fi',
3056 'if [ `which gpg` ]; then gpg --version; fi',
3057 'if [ `which tcpdump` ]; then ldd `which tcpdump`; fi',
3061 'ls -l /usr/lib/*pcap*',
3062 'ls -l /usr/local/lib/*pcap*',
3063 'ls -l /usr/lib/*fko*',
3064 'ls -l /usr/local/lib/*fko*',
3066 &run_cmd($cmd, $cmd_out_tmp, $current_test_file);
3068 if ($cmd =~ /^ldd/) {
3069 $have_gpgme++ if &file_find_regex([qr/gpgme/],
3070 $MATCH_ALL, $cmd_out_tmp);
3074 ### all three of fwknop/fwknopd/libfko must link against gpgme in order
3075 ### to enable gpg tests
3076 unless ($have_gpgme == 3) {
3077 push @tests_to_exclude, qr/GPG/;
3083 sub time_for_valgrind() {
3085 while (&run_cmd("ps axuww | grep LD_LIBRARY_PATH | " .
3086 "grep valgrind |grep -v perl | grep -v grep",
3087 $cmd_out_tmp, $current_test_file)) {
3095 sub anonymize_results() {
3097 die "[*] $output_dir does not exist" unless -d $output_dir;
3098 die "[*] $logfile does not exist, has $0 been executed?"
3101 unlink $tarfile or die "[*] Could not unlink $tarfile: $!";
3104 ### remove non-loopback IP addresses
3105 my $search_re = qr/\b127\.0\.0\.1\b/;
3106 system "perl -p -i -e 's|$search_re|00MY1271STR00|g' $output_dir/*.test";
3107 $search_re = qr/\b127\.0\.0\.2\b/;
3108 system "perl -p -i -e 's|$search_re|00MY1272STR00|g' $output_dir/*.test";
3109 $search_re = qr/\b0\.0\.0\.0\b/;
3110 system "perl -p -i -e 's|$search_re|00MY0000STR00|g' $output_dir/*.test";
3111 $search_re = qr/\b(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}\b/;
3112 system "perl -p -i -e 's|$search_re|N.N.N.N|g' $output_dir/*.test";
3113 system "perl -p -i -e 's|00MY1271STR00|127.0.0.1|g' $output_dir/*.test";
3114 system "perl -p -i -e 's|00MY1272STR00|127.0.0.2|g' $output_dir/*.test";
3115 system "perl -p -i -e 's|00MY0000STR00|0.0.0.0|g' $output_dir/*.test";
3117 ### remove hostname from any uname output
3118 $search_re = qr/\suname\s+\-a\s*\n\s*(\S+)\s+\S+/;
3119 system "perl -p -i -e 'undef \$/; s|$search_re" .
3120 "| uname -a\n\$1 (removed)|s' $output_dir/*.test";
3122 $search_re = qr/uname=\x27(\S+)\s+\S+/;
3123 system "perl -p -i -e 's|$search_re|uname= \$1 (removed)|' $output_dir/*.test";
3126 system "tar cvfz $tarfile $logfile $output_dir";
3127 print "[+] Anonymized test results file: $tarfile\n";
3136 my $test_hr = shift;
3138 open F, "> $default_pid_file" or die $!;
3142 &server_start($test_hr);
3144 open F, "< $default_pid_file" or die $!;
3156 sub start_fwknopd() {
3157 my $test_hr = shift;
3159 &write_test_file("[+] TEST: $test_hr->{'msg'}\n", $server_test_file);
3162 die "[*] Could not fork: $!" unless defined $pid;
3166 ### we are the child, so start fwknopd
3167 exit &run_cmd($test_hr->{'fwknopd_cmdline'},
3168 $server_cmd_tmp, $server_test_file);
3174 my ($key, $file) = @_;
3176 open K, "> $file" or die "[*] Could not open $file: $!";
3177 print K "$loopback_ip: $key\n";
3178 print K "localhost: $key\n";
3179 print K "some.host.through.proxy.com: $key\n";
3185 open C, ">> $current_test_file"
3186 or die "[*] Could not open $current_test_file: $!";
3187 print C "\n" . localtime() . " [+] PID dump:\n";
3189 &run_cmd("ps auxww | grep knop |grep -v grep",
3190 $cmd_out_tmp, $current_test_file);
3195 my ($cmd, $cmd_out, $file) = @_;
3199 or die "[*] Could not open $file: $!";
3200 print F localtime() . " CMD: $cmd\n";
3204 or die "[*] Could not open $file: $!";
3205 print F localtime() . " CMD: $cmd\n";
3209 ### copy original file descriptors (credit: Perl Cookbook)
3210 open OLDOUT, ">&STDOUT";
3211 open OLDERR, ">&STDERR";
3213 ### redirect command output
3214 open STDOUT, "> $cmd_out" or die "[*] Could not redirect stdout: $!";
3215 open STDERR, ">&STDOUT" or die "[*] Could not dup stdout: $!";
3217 my $rv = ((system $cmd) >> 8);
3219 close STDOUT or die "[*] Could not close STDOUT: $!";
3220 close STDERR or die "[*] Could not close STDERR: $!";
3222 ### restore original filehandles
3223 open STDERR, ">&OLDERR" or die "[*] Could not restore stderr: $!";
3224 open STDOUT, ">&OLDOUT" or die "[*] Could not restore stdout: $!";
3226 ### close the old copies
3227 close OLDOUT or die "[*] Could not close OLDOUT: $!";
3228 close OLDERR or die "[*] Could not close OLDERR: $!";
3230 open C, "< $cmd_out" or die "[*] Could not open $cmd_out: $!";
3231 my @cmd_lines = <C>;
3234 open F, ">> $file" or die "[*] Could not open $file: $!";
3235 print F $_ for @cmd_lines;
3248 for (my $i=length($msg); $i < $PRINT_LEN; $i++) {
3257 $|++; ### turn off buffering
3259 $< == 0 && $> == 0 or
3260 die "[*] $0: You must be root (or equivalent ",
3261 "UID 0 account) to effectively test fwknop";
3263 ### validate test hashes
3265 for my $test_hr (@tests) {
3266 for my $key (keys %test_keys) {
3267 if ($test_keys{$key} == $REQUIRED) {
3268 die "[*] Missing '$key' element in hash: $hash_num"
3269 unless defined $test_hr->{$key};
3271 $test_hr->{$key} = '' unless defined $test_hr->{$key};
3277 if ($use_valgrind) {
3278 die "[*] $valgrindCmd exec problem, use --valgrind-path"
3279 unless -e $valgrindCmd and -x $valgrindCmd;
3282 die "[*] $conf_dir directory does not exist." unless -d $conf_dir;
3283 die "[*] $lib_dir directory does not exist." unless -d $lib_dir;
3285 unlink $cmd_exec_test_file if -e $cmd_exec_test_file;
3286 for my $name (keys %cf) {
3287 die "[*] $cf{$name} does not exist" unless -e $cf{$name};
3288 chmod 0600, $cf{$name} or die "[*] Could not chmod 0600 $cf{$name}";
3291 if (-d $output_dir) {
3292 if (-d "${output_dir}.last") {
3293 rmtree "${output_dir}.last"
3294 or die "[*] rmtree ${output_dir}.last $!";
3296 mkdir "${output_dir}.last"
3297 or die "[*] ${output_dir}.last: $!";
3298 for my $file (glob("$output_dir/*.test")) {
3299 if ($file =~ m|.*/(.*)|) {
3300 copy $file, "${output_dir}.last/$1" or die $!;
3303 if (-e "$output_dir/init") {
3304 copy "$output_dir/init", "${output_dir}.last/init";
3307 copy $logfile, "${output_dir}.last/$logfile" or die $!;
3309 $saved_last_results = 1;
3311 mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!";
3315 rmtree $run_dir or die $!;
3317 mkdir $run_dir or die "[*] Could not mkdir $run_dir: $!";
3319 for my $file (glob("$output_dir/*.test")) {
3320 unlink $file or die "[*] Could not unlink($file)";
3322 if (-e "$output_dir/init") {
3323 unlink "$output_dir/init" or die $!;
3327 unlink $logfile or die $!;
3330 if ($test_include) {
3331 for my $re (split /\s*,\s*/, $test_include) {
3332 push @tests_to_include, qr/$re/;
3335 if ($test_exclude) {
3336 for my $re (split /\s*,\s*/, $test_exclude) {
3337 push @tests_to_exclude, qr/$re/;
3341 ### make sure no fwknopd instance is currently running
3342 die "[*] Please stop the running fwknopd instance."
3343 if &is_fwknopd_running();
3345 unless ($enable_recompilation_warnings_check) {
3346 push @tests_to_exclude, qr/recompilation/;
3349 unless ($enable_make_distcheck) {
3350 push @tests_to_exclude, qr/distcheck/;
3353 unless ($enable_client_ip_resolve_test) {
3354 push @tests_to_exclude, qr/IP resolve/;
3357 $sudo_path = &find_command('sudo');
3359 unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
3360 ### disable compilation checks
3361 push @tests_to_exclude, qr/recompilation/;
3364 open UNAME, "uname |" or die "[*] Could not execute uname: $!";
3369 } elsif (/freebsd/i) {
3370 $platform = $FREEBSD;
3376 unless ($platform eq $LINUX) {
3377 push @tests_to_exclude, qr/NAT/;
3379 unless ($platform eq $FREEBSD or $platform eq $MACOSX) {
3380 push @tests_to_exclude, qr|active/expire sets|;
3383 if (-e $default_digest_file) {
3384 unlink $default_digest_file;
3390 sub identify_loopback_intf() {
3391 return if $loopback_intf;
3395 ### lo Link encap:Local Loopback
3396 ### inet addr:127.0.0.1 Mask:255.0.0.0
3397 ### inet6 addr: ::1/128 Scope:Host
3398 ### UP LOOPBACK RUNNING MTU:16436 Metric:1
3399 ### RX packets:534709 errors:0 dropped:0 overruns:0 frame:0
3400 ### TX packets:534709 errors:0 dropped:0 overruns:0 carrier:0
3401 ### collisions:0 txqueuelen:0
3402 ### RX bytes:101110617 (101.1 MB) TX byt