7 use Getopt::Long 'GetOptions';
10 #==================== config =====================
11 my $logfile = 'test.log';
12 my $local_key_file = 'local_spa.key';
13 my $output_dir = 'output';
14 my $lib_dir = '../lib/.libs';
15 my $conf_dir = 'conf';
17 my $configure_path = '../configure';
18 my $cmd_out_tmp = 'cmd.out';
19 my $server_cmd_tmp = 'server_cmd.out';
20 my $gpg_client_home_dir = "$conf_dir/client-gpg";
21 my $gpg_client_home_dir_no_pw = "$conf_dir/client-gpg-no-pw";
24 'nat' => "$conf_dir/nat_fwknopd.conf",
25 'def' => "$conf_dir/default_fwknopd.conf",
26 'def_access' => "$conf_dir/default_access.conf",
27 'exp_access' => "$conf_dir/expired_stanza_access.conf",
28 'future_exp_access' => "$conf_dir/future_expired_stanza_access.conf",
29 'exp_epoch_access' => "$conf_dir/expired_epoch_stanza_access.conf",
30 'invalid_exp_access' => "$conf_dir/invalid_expire_access.conf",
31 'force_nat_access' => "$conf_dir/force_nat_access.conf",
32 'local_nat' => "$conf_dir/local_nat_fwknopd.conf",
33 'ipfw_active_expire' => "$conf_dir/ipfw_active_expire_equal_fwknopd.conf",
34 'dual_key_access' => "$conf_dir/dual_key_usage_access.conf",
35 'gpg_access' => "$conf_dir/gpg_access.conf",
36 'gpg_no_pw_access' => "$conf_dir/gpg_no_pw_access.conf",
37 'open_ports_access' => "$conf_dir/open_ports_access.conf",
38 'multi_gpg_access' => "$conf_dir/multi_gpg_access.conf",
39 'multi_stanza_access' => "$conf_dir/multi_stanzas_access.conf",
40 'broken_keys_access' => "$conf_dir/multi_stanzas_with_broken_keys.conf",
41 'open_ports_mismatch' => "$conf_dir/mismatch_open_ports_access.conf",
42 'require_user_access' => "$conf_dir/require_user_access.conf",
43 'user_mismatch_access' => "$conf_dir/mismatch_user_access.conf",
44 'require_src_access' => "$conf_dir/require_src_access.conf",
45 'no_src_match' => "$conf_dir/no_source_match_access.conf",
46 'no_subnet_match' => "$conf_dir/no_subnet_source_match_access.conf",
47 'no_multi_src' => "$conf_dir/no_multi_source_match_access.conf",
48 'multi_src_access' => "$conf_dir/multi_source_match_access.conf",
49 'ip_src_match' => "$conf_dir/ip_source_match_access.conf",
50 'subnet_src_match' => "$conf_dir/ip_source_match_access.conf",
51 'disable_aging' => "$conf_dir/disable_aging_fwknopd.conf",
54 my $default_digest_file = "$run_dir/digest.cache";
55 my $default_pid_file = "$run_dir/fwknopd.pid";
57 my $fwknopCmd = '../client/.libs/fwknop';
58 my $fwknopdCmd = '../server/.libs/fwknopd';
59 my $libfko_bin = "$lib_dir/libfko.so"; ### this is usually a link
60 my $valgrindCmd = '/usr/bin/valgrind';
62 my $gpg_server_key = '361BBAD4';
63 my $gpg_client_key = '6A3FAD56';
65 my $loopback_ip = '127.0.0.1';
66 my $fake_ip = '127.0.0.2';
67 my $internal_nat_host = '192.168.1.2';
68 my $force_nat_host = '192.168.1.123';
69 my $default_spa_port = 62201;
70 my $non_std_spa_port = 12345;
72 my $spoof_user = 'testuser';
73 #================== end config ===================
78 my $test_include = '';
79 my @tests_to_include = ();
80 my $test_exclude = '';
81 my @tests_to_exclude = ();
82 my %valgrind_flagged_fcns = ();
83 my %valgrind_flagged_fcns_unique = ();
87 my $loopback_intf = '';
88 my $anonymize_results = 0;
89 my $current_test_file = "$output_dir/init";
90 my $tarfile = 'test_fwknop.tar.gz';
91 my $server_test_file = '';
93 my $valgrind_str = '';
94 my $enable_client_ip_resolve_test = 0;
95 my $saved_last_results = 0;
97 my $enable_recompilation_warnings_check = 0;
98 my $enable_make_distcheck = 0;
105 my $USE_PREDEF_PKTS = 1;
109 my $NEW_RULE_REQUIRED = 1;
110 my $REQUIRE_NO_NEW_RULE = 2;
111 my $NEW_RULE_REMOVED = 1;
112 my $REQUIRE_NO_NEW_REMOVED = 2;
120 my $ip_re = qr|(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}|; ### IPv4
124 exit 1 unless GetOptions(
125 'Anonymize-results' => \$anonymize_results,
126 'fwknop-path=s' => \$fwknopCmd,
127 'fwknopd-path=s' => \$fwknopdCmd,
128 'libfko-path=s' => \$libfko_bin,
129 'loopback-intf=s' => \$loopback_intf,
130 'test-include=s' => \$test_include,
131 'include=s' => \$test_include, ### synonym
132 'test-exclude=s' => \$test_exclude,
133 'exclude=s' => \$test_exclude, ### synonym
134 'enable-recompile-check' => \$enable_recompilation_warnings_check,
135 'enable-ip-resolve' => \$enable_client_ip_resolve_test,
136 'enable-distcheck' => \$enable_make_distcheck,
137 'List-mode' => \$list_mode,
138 'enable-valgrind' => \$use_valgrind,
139 'valgrind-path=s' => \$valgrindCmd,
140 'output-dir=s' => \$output_dir,
141 'diff' => \$diff_mode,
142 'diff-dir1=s' => \$diff_dir1,
143 'diff-dir2=s' => \$diff_dir2,
149 ### create an anonymized tar file of test suite results that can be
150 ### emailed around to assist in debugging fwknop communications
151 exit &anonymize_results() if $anonymize_results;
153 &identify_loopback_intf();
155 $valgrind_str = "$valgrindCmd --leak-check=full " .
156 "--show-reachable=yes --track-origins=yes" if $use_valgrind;
158 my $intf_str = "-i $loopback_intf --foreground --verbose --verbose";
160 my $default_client_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
161 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
162 "$local_key_file --verbose --verbose";
164 my $client_ip_resolve_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
165 "$fwknopCmd -A tcp/22 -R -D $loopback_ip --get-key " .
166 "$local_key_file --verbose --verbose";
168 my $default_client_gpg_args = "$default_client_args " .
169 "--gpg-recipient-key $gpg_server_key " .
170 "--gpg-signer-key $gpg_client_key " .
171 "--gpg-home-dir $gpg_client_home_dir";
173 my $default_client_gpg_args_no_homedir = "$default_client_args " .
174 "--gpg-recipient-key $gpg_server_key " .
175 "--gpg-signer-key $gpg_client_key ";
177 my $default_server_conf_args = "-c $cf{'def'} -a $cf{'def_access'} " .
178 "-d $default_digest_file -p $default_pid_file";
180 my $default_server_gpg_args = "LD_LIBRARY_PATH=$lib_dir " .
181 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
182 "-a $cf{'gpg_access'} $intf_str " .
183 "-d $default_digest_file -p $default_pid_file";
185 my $default_server_gpg_args_no_pw = "LD_LIBRARY_PATH=$lib_dir " .
186 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
187 "-a $cf{'gpg_no_pw_access'} $intf_str " .
188 "-d $default_digest_file -p $default_pid_file";
190 ### point the compiled binaries at the local libary path
191 ### instead of any installed libfko instance
192 $ENV{'LD_LIBRARY_PATH'} = $lib_dir;
194 ### main array that defines the tests we will run
197 'category' => 'recompilation',
198 'detail' => 'recompile and look for compilation warnings',
199 'err_msg' => 'compile warnings exist',
200 'function' => \&compile_warnings,
204 'category' => 'make distcheck',
205 'detail' => 'ensure proper distribution creation',
206 'err_msg' => 'could not create proper tarball',
207 'function' => \&make_distcheck,
211 'category' => 'build',
212 'subcategory' => 'client',
213 'detail' => 'binary exists',
214 'err_msg' => 'binary not found',
215 'function' => \&binary_exists,
216 'binary' => $fwknopCmd,
220 'category' => 'build security',
221 'subcategory' => 'client',
222 'detail' => 'Position Independent Executable (PIE)',
223 'err_msg' => 'non PIE binary (fwknop client)',
224 'function' => \&pie_binary,
225 'binary' => $fwknopCmd,
229 'category' => 'build security',
230 'subcategory' => 'client',
231 'detail' => 'stack protected binary',
232 'err_msg' => 'non stack protected binary (fwknop client)',
233 'function' => \&stack_protected_binary,
234 'binary' => $fwknopCmd,
238 'category' => 'build security',
239 'subcategory' => 'client',
240 'detail' => 'fortify source functions',
241 'err_msg' => 'source functions not fortified (fwknop client)',
242 'function' => \&fortify_source_functions,
243 'binary' => $fwknopCmd,
247 'category' => 'build security',
248 'subcategory' => 'client',
249 'detail' => 'read-only relocations',
250 'err_msg' => 'no read-only relocations (fwknop client)',
251 'function' => \&read_only_relocations,
252 'binary' => $fwknopCmd,
256 'category' => 'build security',
257 'subcategory' => 'client',
258 'detail' => 'immediate binding',
259 'err_msg' => 'no immediate binding (fwknop client)',
260 'function' => \&immediate_binding,
261 'binary' => $fwknopCmd,
266 'category' => 'build',
267 'subcategory' => 'server',
268 'detail' => 'binary exists',
269 'err_msg' => 'binary not found',
270 'function' => \&binary_exists,
271 'binary' => $fwknopdCmd,
276 'category' => 'build security',
277 'subcategory' => 'server',
278 'detail' => 'Position Independent Executable (PIE)',
279 'err_msg' => 'non PIE binary (fwknopd server)',
280 'function' => \&pie_binary,
281 'binary' => $fwknopdCmd,
285 'category' => 'build security',
286 'subcategory' => 'server',
287 'detail' => 'stack protected binary',
288 'err_msg' => 'non stack protected binary (fwknopd server)',
289 'function' => \&stack_protected_binary,
290 'binary' => $fwknopdCmd,
294 'category' => 'build security',
295 'subcategory' => 'server',
296 'detail' => 'fortify source functions',
297 'err_msg' => 'source functions not fortified (fwknopd server)',
298 'function' => \&fortify_source_functions,
299 'binary' => $fwknopdCmd,
303 'category' => 'build security',
304 'subcategory' => 'server',
305 'detail' => 'read-only relocations',
306 'err_msg' => 'no read-only relocations (fwknopd server)',
307 'function' => \&read_only_relocations,
308 'binary' => $fwknopdCmd,
312 'category' => 'build security',
313 'subcategory' => 'server',
314 'detail' => 'immediate binding',
315 'err_msg' => 'no immediate binding (fwknopd server)',
316 'function' => \&immediate_binding,
317 'binary' => $fwknopdCmd,
322 'category' => 'build',
323 'subcategory' => 'libfko',
324 'detail' => 'binary exists',
325 'err_msg' => 'binary not found',
326 'function' => \&binary_exists,
327 'binary' => $libfko_bin,
331 'category' => 'build security',
332 'subcategory' => 'libfko',
333 'detail' => 'stack protected binary',
334 'err_msg' => 'non stack protected binary (libfko)',
335 'function' => \&stack_protected_binary,
336 'binary' => $libfko_bin,
340 'category' => 'build security',
341 'subcategory' => 'libfko',
342 'detail' => 'fortify source functions',
343 'err_msg' => 'source functions not fortified (libfko)',
344 'function' => \&fortify_source_functions,
345 'binary' => $libfko_bin,
349 'category' => 'build security',
350 'subcategory' => 'libfko',
351 'detail' => 'read-only relocations',
352 'err_msg' => 'no read-only relocations (libfko)',
353 'function' => \&read_only_relocations,
354 'binary' => $libfko_bin,
358 'category' => 'build security',
359 'subcategory' => 'libfko',
360 'detail' => 'immediate binding',
361 'err_msg' => 'no immediate binding (libfko)',
362 'function' => \&immediate_binding,
363 'binary' => $libfko_bin,
368 'category' => 'preliminaries',
369 'subcategory' => 'client',
370 'detail' => 'usage info',
371 'err_msg' => 'could not get usage info',
372 'function' => \&generic_exec,
373 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd -h",
377 'category' => 'preliminaries',
378 'subcategory' => 'client',
379 'detail' => 'getopt() no such argument',
380 'err_msg' => 'getopt() allowed non-existant argument',
381 'function' => \&generic_exec,
382 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd --no-such-arg",
387 'category' => 'preliminaries',
388 'subcategory' => 'client',
389 'detail' => '--test mode, packet not sent',
390 'err_msg' => '--test mode, packet sent?',
391 'function' => \&generic_exec,
392 'positive_output_matches' => [qr/test\smode\senabled/],
393 'cmdline' => "$default_client_args --test",
398 'category' => 'preliminaries',
399 'subcategory' => 'client',
400 'detail' => 'expected code version',
401 'err_msg' => 'code version mis-match',
402 'function' => \&expected_code_version,
403 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopCmd --version",
408 'category' => 'preliminaries',
409 'subcategory' => 'server',
410 'detail' => 'usage info',
411 'err_msg' => 'could not get usage info',
412 'function' => \&generic_exec,
413 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd -h",
417 'category' => 'preliminaries',
418 'subcategory' => 'server',
419 'detail' => 'getopt() no such argument',
420 'err_msg' => 'getopt() allowed non-existant argument',
421 'function' => \&generic_exec,
422 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd --no-such-arg",
428 'category' => 'preliminaries',
429 'subcategory' => 'server',
430 'detail' => 'expected code version',
431 'err_msg' => 'code version mis-match',
432 'function' => \&expected_code_version,
433 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
434 "$fwknopdCmd -c $cf{'def'} -a " .
435 "$cf{'def_access'} --version",
439 'category' => 'preliminaries',
440 'detail' => 'collecting system specifics',
441 'err_msg' => 'could not get complete system specs',
442 'function' => \&specs,
443 'binary' => $fwknopdCmd,
448 'category' => 'basic operations',
449 'detail' => 'dump config',
450 'err_msg' => 'could not dump configuration',
451 'function' => \&generic_exec,
452 'positive_output_matches' => [qr/SYSLOG_IDENTITY/],
454 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
455 "$fwknopdCmd -c $cf{'def'} " .
456 "-a $cf{'def_access'} --dump-config",
460 'category' => 'basic operations',
461 'detail' => 'override config',
462 'err_msg' => 'could not override configuration',
463 'function' => \&generic_exec,
464 'positive_output_matches' => [qr/ENABLE_PCAP_PROMISC.*\'Y\'/],
466 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
467 "$fwknopdCmd $default_server_conf_args " .
468 "-O $conf_dir/override_fwknopd.conf --dump-config",
473 'category' => 'basic operations',
474 'subcategory' => 'client',
475 'detail' => '--get-key path validation',
476 'err_msg' => 'accepted improper --get-key path',
477 'function' => \&generic_exec,
478 'positive_output_matches' => [qr/could\snot\sopen/i],
480 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
481 "$fwknopCmd -A tcp/22 -s $fake_ip " .
482 "-D $loopback_ip --get-key not/there",
486 'category' => 'basic operations',
487 'subcategory' => 'client',
488 'detail' => 'require [-s|-R|-a]',
489 'err_msg' => 'allowed null allow IP',
490 'function' => \&generic_exec,
491 'positive_output_matches' => [qr/must\suse\sone\sof/i],
493 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
494 "$fwknopCmd -D $loopback_ip",
498 'category' => 'basic operations',
499 'subcategory' => 'client',
500 'detail' => '--allow-ip <IP> valid IP',
501 'err_msg' => 'permitted invalid --allow-ip arg',
502 'function' => \&generic_exec,
503 'positive_output_matches' => [qr/Invalid\sallow\sIP\saddress/i],
505 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
506 "$fwknopCmd -A tcp/22 -a invalidIP -D $loopback_ip",
510 'category' => 'basic operations',
511 'subcategory' => 'client',
512 'detail' => '-A <proto>/<port> specification (proto)',
513 'err_msg' => 'permitted invalid -A <proto>/<port>',
514 'function' => \&generic_exec,
515 'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
517 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
518 "$fwknopCmd -A invalid/22 -a $fake_ip -D $loopback_ip",
522 'category' => 'basic operations',
523 'subcategory' => 'client',
524 'detail' => '-A <proto>/<port> specification (port)',
525 'err_msg' => 'permitted invalid -A <proto>/<port>',
526 'function' => \&generic_exec,
527 'positive_output_matches' => [qr/Invalid\sSPA\saccess\smessage/i],
529 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
530 "$fwknopCmd -A tcp/600001 -a $fake_ip -D $loopback_ip",
535 'category' => 'basic operations',
536 'subcategory' => 'client',
537 'detail' => 'generate SPA packet',
538 'err_msg' => 'could not generate SPA packet',
539 'function' => \&client_send_spa_packet,
540 'cmdline' => $default_client_args,
545 'category' => 'basic operations',
546 'subcategory' => 'server',
547 'detail' => 'list current fwknopd fw rules',
548 'err_msg' => 'could not list current fwknopd fw rules',
549 'function' => \&generic_exec,
550 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
551 "$fwknopdCmd $default_server_conf_args --fw-list",
555 'category' => 'basic operations',
556 'subcategory' => 'server',
557 'detail' => 'list all current fw rules',
558 'err_msg' => 'could not list all current fw rules',
559 'function' => \&generic_exec,
560 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
561 "$fwknopdCmd $default_server_conf_args --fw-list-all",
565 'category' => 'basic operations',
566 'subcategory' => 'server',
567 'detail' => 'flush current firewall rules',
568 'err_msg' => 'could not flush current fw rules',
569 'function' => \&generic_exec,
570 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
571 "$fwknopdCmd $default_server_conf_args --fw-flush",
576 'category' => 'basic operations',
577 'subcategory' => 'server',
579 'err_msg' => 'start error',
580 'function' => \&server_start,
581 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
582 "$fwknopdCmd $default_server_conf_args $intf_str",
586 'category' => 'basic operations',
587 'subcategory' => 'server',
589 'err_msg' => 'stop error',
590 'function' => \&server_stop,
591 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
592 "$fwknopdCmd $default_server_conf_args $intf_str",
596 'category' => 'basic operations',
597 'subcategory' => 'server',
598 'detail' => 'write PID',
599 'err_msg' => 'did not write PID',
600 'function' => \&write_pid,
601 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
602 "$fwknopdCmd $default_server_conf_args $intf_str",
607 'category' => 'basic operations',
608 'subcategory' => 'server',
609 'detail' => '--packet-limit 1 exit',
610 'err_msg' => 'did not exit after one packet',
611 'function' => \&server_packet_limit,
612 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
613 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
617 'category' => 'basic operations',
618 'subcategory' => 'server',
619 'detail' => 'ignore packets < min SPA len (140)',
620 'err_msg' => 'did not ignore small packets',
621 'function' => \&server_ignore_small_packets,
622 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
623 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str",
627 'category' => 'basic operations',
628 'subcategory' => 'server',
629 'detail' => '-P bpf filter ignore packet',
630 'err_msg' => 'filter did not ignore packet',
631 'function' => \&server_bpf_ignore_packet,
632 'cmdline' => $default_client_args,
633 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
634 "$fwknopdCmd $default_server_conf_args --packet-limit 1 $intf_str " .
635 qq|-P "udp port $non_std_spa_port"|,
640 'category' => 'Rijndael SPA',
641 'subcategory' => 'client+server',
642 'detail' => 'complete cycle (tcp/22 ssh)',
643 'err_msg' => 'could not complete SPA cycle',
644 'function' => \&spa_cycle,
645 'cmdline' => $default_client_args,
646 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
647 "$fwknopdCmd $default_server_conf_args $intf_str",
648 'fw_rule_created' => $NEW_RULE_REQUIRED,
649 'fw_rule_removed' => $NEW_RULE_REMOVED,
653 'category' => 'Rijndael SPA',
654 'subcategory' => 'client+server',
655 'detail' => 'client IP resolve (tcp/22 ssh)',
656 'err_msg' => 'could not complete SPA cycle',
657 'function' => \&spa_cycle,
658 'cmdline' => $client_ip_resolve_args,
660 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
661 "$fwknopdCmd $default_server_conf_args $intf_str",
662 'fw_rule_created' => $NEW_RULE_REQUIRED,
663 'fw_rule_removed' => $NEW_RULE_REMOVED,
668 'category' => 'Rijndael SPA',
669 'subcategory' => 'client+server',
670 'detail' => 'dual usage access key (tcp/80 http)',
671 'err_msg' => 'could not complete SPA cycle',
672 'function' => \&spa_cycle,
673 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
674 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
675 "$local_key_file --verbose --verbose",
676 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
677 "$fwknopdCmd -c $cf{'def'} -a $cf{'dual_key_access'} " .
678 "-d $default_digest_file -p $default_pid_file $intf_str",
679 ### check for the first stanza that does not allow tcp/80 - the
680 ### second stanza allows this
681 'server_positive_output_matches' => [qr/stanza #1\)\sOne\sor\smore\srequested\sprotocol\/ports\swas\sdenied/],
682 'fw_rule_created' => $NEW_RULE_REQUIRED,
683 'fw_rule_removed' => $NEW_RULE_REMOVED,
687 'category' => 'Rijndael SPA',
688 'subcategory' => 'client+server',
689 'detail' => 'packet aging (past) (tcp/22 ssh)',
690 'err_msg' => 'old SPA packet accepted',
691 'function' => \&spa_cycle,
692 'cmdline' => "$default_client_args --time-offset-minus 300s",
693 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
694 "$fwknopdCmd $default_server_conf_args $intf_str",
695 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
696 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
700 'category' => 'Rijndael SPA',
701 'subcategory' => 'client+server',
702 'detail' => 'packet aging (future) (tcp/22 ssh)',
703 'err_msg' => 'future SPA packet accepted',
704 'function' => \&spa_cycle,
705 'cmdline' => "$default_client_args --time-offset-plus 300s",
706 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
707 "$fwknopdCmd $default_server_conf_args $intf_str",
708 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
709 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
713 'category' => 'Rijndael SPA',
714 'subcategory' => 'client+server',
715 'detail' => 'expired stanza (tcp/22 ssh)',
716 'err_msg' => 'SPA packet accepted',
717 'function' => \&spa_cycle,
718 'cmdline' => $default_client_args,
719 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
720 "$fwknopdCmd -c $cf{'def'} -a $cf{'exp_access'} " .
721 "-d $default_digest_file -p $default_pid_file $intf_str",
722 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
723 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
727 'category' => 'Rijndael SPA',
728 'subcategory' => 'client+server',
729 'detail' => 'invalid expire date (tcp/22 ssh)',
730 'err_msg' => 'SPA packet accepted',
731 'function' => \&spa_cycle,
732 'cmdline' => $default_client_args,
733 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
734 "$fwknopdCmd -c $cf{'def'} -a $cf{'invalid_exp_access'} " .
735 "-d $default_digest_file -p $default_pid_file $intf_str",
736 'server_positive_output_matches' => [qr/invalid\sdate\svalue/],
737 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
741 'category' => 'Rijndael SPA',
742 'subcategory' => 'client+server',
743 'detail' => 'expired epoch stanza (tcp/22 ssh)',
744 'err_msg' => 'SPA packet accepted',
745 'function' => \&spa_cycle,
746 'cmdline' => $default_client_args,
747 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
748 "$fwknopdCmd -c $cf{'def'} -a $cf{'exp_epoch_access'} " .
749 "-d $default_digest_file -p $default_pid_file $intf_str",
750 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
751 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
755 'category' => 'Rijndael SPA',
756 'subcategory' => 'client+server',
757 'detail' => 'future expired stanza (tcp/22 ssh)',
758 'err_msg' => 'SPA packet not accepted',
759 'function' => \&spa_cycle,
760 'cmdline' => $default_client_args,
761 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
762 "$fwknopdCmd -c $cf{'def'} -a $cf{'future_exp_access'} " .
763 "-d $default_digest_file -p $default_pid_file $intf_str",
764 'fw_rule_created' => $NEW_RULE_REQUIRED,
765 'fw_rule_removed' => $NEW_RULE_REMOVED,
770 'category' => 'Rijndael SPA',
771 'subcategory' => 'client+server',
772 'detail' => 'OPEN_PORTS (tcp/22 ssh)',
773 'err_msg' => "improper OPEN_PORTS result",
774 'function' => \&spa_cycle,
775 'cmdline' => $default_client_args,
776 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
777 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_access'} " .
778 "-d $default_digest_file -p $default_pid_file $intf_str",
779 'fw_rule_created' => $NEW_RULE_REQUIRED,
780 'fw_rule_removed' => $NEW_RULE_REMOVED,
784 'category' => 'Rijndael SPA',
785 'subcategory' => 'client+server',
786 'detail' => 'OPEN_PORTS mismatch',
787 'err_msg' => "SPA packet accepted",
788 'function' => \&spa_cycle,
789 'cmdline' => $default_client_args,
790 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
791 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_mismatch'} " .
792 "-d $default_digest_file -p $default_pid_file $intf_str",
793 'server_positive_output_matches' => [qr/One\s+or\s+more\s+requested/],
794 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
798 'category' => 'Rijndael SPA',
799 'subcategory' => 'client+server',
800 'detail' => 'require user (tcp/22 ssh)',
801 'err_msg' => "missed require user criteria",
802 'function' => \&spa_cycle,
803 'cmdline' => "SPOOF_USER=$spoof_user $default_client_args",
804 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
805 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_user_access'} " .
806 "-d $default_digest_file -p $default_pid_file $intf_str",
807 'fw_rule_created' => $NEW_RULE_REQUIRED,
808 'fw_rule_removed' => $NEW_RULE_REMOVED,
812 'category' => 'Rijndael SPA',
813 'subcategory' => 'client+server',
814 'detail' => 'user mismatch (tcp/22 ssh)',
815 'err_msg' => "improper user accepted for access",
816 'function' => \&user_mismatch,
817 'function' => \&spa_cycle,
818 'cmdline' => $default_client_args,
819 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
820 "$fwknopdCmd -c $cf{'def'} -a $cf{'user_mismatch_access'} " .
821 "-d $default_digest_file -p $default_pid_file $intf_str",
822 'server_positive_output_matches' => [qr/Username\s+in\s+SPA\s+data/],
823 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
827 'category' => 'Rijndael SPA',
828 'subcategory' => 'client+server',
829 'detail' => 'require src (tcp/22 ssh)',
830 'err_msg' => "fw rule not created",
831 'function' => \&spa_cycle,
832 'cmdline' => $default_client_args,
833 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
834 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
835 "-d $default_digest_file -p $default_pid_file $intf_str",
836 'fw_rule_created' => $NEW_RULE_REQUIRED,
837 'fw_rule_removed' => $NEW_RULE_REMOVED,
841 'category' => 'Rijndael SPA',
842 'subcategory' => 'client+server',
843 'detail' => 'mismatch require src (tcp/22 ssh)',
844 'err_msg' => "fw rule created",
845 'function' => \&spa_cycle,
846 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
847 "$fwknopCmd -A tcp/22 -s -D $loopback_ip --get-key " .
848 "$local_key_file --verbose --verbose",
849 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
850 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
851 "-d $default_digest_file -p $default_pid_file $intf_str",
852 'server_positive_output_matches' => [qr/Got\s0.0.0.0\swhen\svalid\ssource\sIP/],
853 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
858 'category' => 'Rijndael SPA',
859 'subcategory' => 'client+server',
860 'detail' => 'IP filtering (tcp/22 ssh)',
861 'err_msg' => "did not filter $loopback_ip",
862 'function' => \&spa_cycle,
863 'cmdline' => $default_client_args,
864 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
865 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_src_match'} " .
866 "-d $default_digest_file -p $default_pid_file $intf_str",
867 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
868 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
872 'category' => 'Rijndael SPA',
873 'subcategory' => 'client+server',
874 'detail' => 'subnet filtering (tcp/22 ssh)',
875 'err_msg' => "did not filter $loopback_ip",
876 'function' => \&spa_cycle,
877 'cmdline' => $default_client_args,
878 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
879 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_subnet_match'} " .
880 "-d $default_digest_file -p $default_pid_file $intf_str",
881 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
882 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
886 'category' => 'Rijndael SPA',
887 'subcategory' => 'client+server',
888 'detail' => 'IP+subnet filtering (tcp/22 ssh)',
889 'err_msg' => "did not filter $loopback_ip",
890 'function' => \&spa_cycle,
891 'cmdline' => $default_client_args,
892 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
893 "$fwknopdCmd -c $cf{'def'} -a $cf{'no_multi_src'} " .
894 "-d $default_digest_file -p $default_pid_file $intf_str",
895 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
896 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
900 'category' => 'Rijndael SPA',
901 'subcategory' => 'client+server',
902 'detail' => 'IP match (tcp/22 ssh)',
903 'err_msg' => "did not filter $loopback_ip",
904 'function' => \&spa_cycle,
905 'cmdline' => $default_client_args,
906 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
907 "$fwknopdCmd -c $cf{'def'} -a $cf{'ip_src_match'} " .
908 "-d $default_digest_file -p $default_pid_file $intf_str",
909 'fw_rule_created' => $NEW_RULE_REQUIRED,
910 'fw_rule_removed' => $NEW_RULE_REMOVED,
914 'category' => 'Rijndael SPA',
915 'subcategory' => 'client+server',
916 'detail' => 'subnet match (tcp/22 ssh)',
917 'err_msg' => "did not filter $loopback_ip",
918 'function' => \&spa_cycle,
919 'cmdline' => $default_client_args,
920 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
921 "$fwknopdCmd -c $cf{'def'} -a $cf{'subnet_src_match'} " .
922 "-d $default_digest_file -p $default_pid_file $intf_str",
923 'fw_rule_created' => $NEW_RULE_REQUIRED,
924 'fw_rule_removed' => $NEW_RULE_REMOVED,
928 'category' => 'Rijndael SPA',
929 'subcategory' => 'client+server',
930 'detail' => 'multi IP/net match (tcp/22 ssh)',
931 'err_msg' => "did not filter $loopback_ip",
932 'function' => \&spa_cycle,
933 'cmdline' => $default_client_args,
934 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
935 "$fwknopdCmd -c $cf{'def'} -a $cf{'multi_src_access'} " .
936 "-d $default_digest_file -p $default_pid_file $intf_str",
937 'fw_rule_created' => $NEW_RULE_REQUIRED,
938 'fw_rule_removed' => $NEW_RULE_REMOVED,
942 'category' => 'Rijndael SPA',
943 'subcategory' => 'client+server',
944 'detail' => 'multi access stanzas (tcp/22 ssh)',
945 'err_msg' => "could not complete SPA cycle",
946 'function' => \&spa_cycle,
947 'cmdline' => $default_client_args,
948 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
949 "$fwknopdCmd -c $cf{'def'} -a $cf{'multi_stanza_access'} " .
950 "-d $default_digest_file -p $default_pid_file $intf_str",
951 'fw_rule_created' => $NEW_RULE_REQUIRED,
952 'fw_rule_removed' => $NEW_RULE_REMOVED,
956 'category' => 'Rijndael SPA',
957 'subcategory' => 'client+server',
958 'detail' => 'bad/good key stanzas (tcp/22 ssh)',
959 'err_msg' => "could not complete SPA cycle",
960 'function' => \&spa_cycle,
961 'cmdline' => $default_client_args,
962 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
963 "$fwknopdCmd -c $cf{'def'} -a $cf{'broken_keys_access'} " .
964 "-d $default_digest_file -p $default_pid_file $intf_str",
965 'fw_rule_created' => $NEW_RULE_REQUIRED,
966 'fw_rule_removed' => $NEW_RULE_REMOVED,
971 'category' => 'Rijndael SPA',
972 'subcategory' => 'client+server',
973 'detail' => "non-enabled NAT (tcp/22 ssh)",
974 'err_msg' => "SPA packet not filtered",
975 'function' => \&spa_cycle,
976 'cmdline' => "$default_client_args -N $internal_nat_host:22",
977 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
978 "$fwknopdCmd $default_server_conf_args $intf_str",
979 'server_positive_output_matches' => [qr/requested\sNAT\saccess.*not\senabled/i],
980 'server_conf' => $cf{'nat'},
981 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
985 'category' => 'Rijndael SPA',
986 'subcategory' => 'client+server',
987 'detail' => "NAT to $internal_nat_host (tcp/22 ssh)",
988 'err_msg' => "could not complete NAT SPA cycle",
989 'function' => \&spa_cycle,
990 'cmdline' => "$default_client_args -N $internal_nat_host:22",
991 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
992 "$fwknopdCmd -c $cf{'nat'} -a $cf{'open_ports_access'} " .
993 "-d $default_digest_file -p $default_pid_file $intf_str",
994 'server_positive_output_matches' => [qr/to\:$internal_nat_host\:22/i],
995 'fw_rule_created' => $NEW_RULE_REQUIRED,
996 'fw_rule_removed' => $NEW_RULE_REMOVED,
997 'server_conf' => $cf{'nat'},
1001 'category' => 'Rijndael SPA',
1002 'subcategory' => 'client+server',
1003 'detail' => "force NAT $force_nat_host (tcp/22 ssh)",
1004 'err_msg' => "could not complete NAT SPA cycle",
1005 'function' => \&spa_cycle,
1006 'cmdline' => $default_client_args,
1007 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1008 "$fwknopdCmd -c $cf{'nat'} -a $cf{'force_nat_access'} " .
1009 "-d $default_digest_file -p $default_pid_file $intf_str",
1010 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i],
1011 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1012 'fw_rule_created' => $NEW_RULE_REQUIRED,
1013 'fw_rule_removed' => $NEW_RULE_REMOVED,
1014 'server_conf' => $cf{'nat'},
1018 'category' => 'Rijndael SPA',
1019 'subcategory' => 'client+server',
1020 'detail' => "local NAT $force_nat_host (tcp/22 ssh)",
1021 'err_msg' => "could not complete NAT SPA cycle",
1022 'function' => \&spa_cycle,
1023 'cmdline' => "$default_client_args --nat-local",
1024 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1025 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'force_nat_access'} " .
1026 "-d $default_digest_file -p $default_pid_file $intf_str",
1027 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i,
1028 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1029 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1030 'fw_rule_created' => $NEW_RULE_REQUIRED,
1031 'fw_rule_removed' => $NEW_RULE_REMOVED,
1032 'server_conf' => $cf{'nat'},
1036 'category' => 'Rijndael SPA',
1037 'subcategory' => 'client+server',
1038 'detail' => "local NAT non-FORCE_NAT (tcp/22 ssh)",
1039 'err_msg' => "could not complete NAT SPA cycle",
1040 'function' => \&spa_cycle,
1041 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1042 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
1043 "$local_key_file --verbose --verbose --nat-local --nat-port 22",
1044 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1045 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'def_access'} " .
1046 "-d $default_digest_file -p $default_pid_file $intf_str",
1047 'server_positive_output_matches' => [qr/to\:$loopback_ip\:22/i,
1048 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1049 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1050 'fw_rule_created' => $NEW_RULE_REQUIRED,
1051 'fw_rule_removed' => $NEW_RULE_REMOVED,
1052 'server_conf' => $cf{'nat'},
1057 'category' => 'Rijndael SPA',
1058 'subcategory' => 'client+server',
1059 'detail' => 'complete cycle (tcp/23 telnet)',
1060 'err_msg' => 'could not complete SPA cycle',
1061 'function' => \&spa_cycle,
1062 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1063 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1064 "$local_key_file --verbose --verbose",
1065 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1066 "$fwknopdCmd $default_server_conf_args $intf_str",
1067 'fw_rule_created' => $NEW_RULE_REQUIRED,
1068 'fw_rule_removed' => $NEW_RULE_REMOVED,
1072 'category' => 'Rijndael SPA',
1073 'subcategory' => 'client+server',
1074 'detail' => 'complete cycle (tcp/9418 git)',
1075 'err_msg' => 'could not complete SPA cycle',
1076 'function' => \&spa_cycle,
1077 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1078 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1079 "$local_key_file --verbose --verbose",
1080 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1081 "$fwknopdCmd $default_server_conf_args $intf_str",
1082 'fw_rule_created' => $NEW_RULE_REQUIRED,
1083 'fw_rule_removed' => $NEW_RULE_REMOVED,
1087 'category' => 'Rijndael SPA',
1088 'subcategory' => 'client+server',
1089 'detail' => 'complete cycle (tcp/60001)',
1090 'err_msg' => 'could not complete SPA cycle',
1091 'function' => \&spa_cycle,
1092 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1093 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1094 "$local_key_file --verbose --verbose",
1095 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1096 "$fwknopdCmd $default_server_conf_args $intf_str",
1097 'fw_rule_created' => $NEW_RULE_REQUIRED,
1098 'fw_rule_removed' => $NEW_RULE_REMOVED,
1102 'category' => 'Rijndael SPA',
1103 'subcategory' => 'client+server',
1104 'detail' => 'multi port (tcp/60001,udp/60001)',
1105 'err_msg' => 'could not complete SPA cycle',
1106 'function' => \&spa_cycle,
1107 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1108 "$fwknopCmd -A tcp/60001,udp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1109 "$local_key_file --verbose --verbose",
1110 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1111 "$fwknopdCmd $default_server_conf_args $intf_str",
1112 'fw_rule_created' => $NEW_RULE_REQUIRED,
1113 'fw_rule_removed' => $NEW_RULE_REMOVED,
1117 'category' => 'Rijndael SPA',
1118 'subcategory' => 'client+server',
1119 'detail' => 'multi port (tcp/22,udp/53,tcp/1234)',
1120 'err_msg' => 'could not complete SPA cycle',
1121 'function' => \&spa_cycle,
1122 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1123 "$fwknopCmd -A tcp/22,udp/53,tcp/1234 -a $fake_ip -D $loopback_ip --get-key " .
1124 "$local_key_file --verbose --verbose",
1125 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1126 "$fwknopdCmd $default_server_conf_args $intf_str",
1127 'fw_rule_created' => $NEW_RULE_REQUIRED,
1128 'fw_rule_removed' => $NEW_RULE_REMOVED,
1133 'category' => 'Rijndael SPA',
1134 'subcategory' => 'client+server',
1135 'detail' => 'complete cycle (udp/53 dns)',
1136 'err_msg' => 'could not complete SPA cycle',
1137 'function' => \&spa_cycle,
1138 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1139 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1140 "$local_key_file --verbose --verbose",
1141 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1142 "$fwknopdCmd $default_server_conf_args $intf_str",
1143 'fw_rule_created' => $NEW_RULE_REQUIRED,
1144 'fw_rule_removed' => $NEW_RULE_REMOVED,
1148 'category' => 'Rijndael SPA',
1149 'subcategory' => 'client+server',
1150 'detail' => "-P bpf SPA over port $non_std_spa_port",
1151 'err_msg' => 'could not complete SPA cycle',
1152 'function' => \&spa_cycle,
1153 'cmdline' => "$default_client_args --server-port $non_std_spa_port",
1154 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1155 "$fwknopdCmd $default_server_conf_args $intf_str " .
1156 qq|-P "udp port $non_std_spa_port"|,
1157 'server_positive_output_matches' => [qr/PCAP\sfilter.*\s$non_std_spa_port/],
1158 'fw_rule_created' => $NEW_RULE_REQUIRED,
1159 'fw_rule_removed' => $NEW_RULE_REMOVED,
1164 'category' => 'Rijndael SPA',
1165 'subcategory' => 'client+server',
1166 'detail' => 'random SPA port (tcp/22 ssh)',
1167 'err_msg' => 'could not complete SPA cycle',
1168 'function' => \&spa_cycle,
1169 'cmdline' => "$default_client_args -r",
1170 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1171 "$fwknopdCmd $default_server_conf_args $intf_str " .
1173 'fw_rule_created' => $NEW_RULE_REQUIRED,
1174 'fw_rule_removed' => $NEW_RULE_REMOVED,
1179 'category' => 'Rijndael SPA',
1180 'subcategory' => 'client+server',
1181 'detail' => 'spoof username (tcp/22)',
1182 'err_msg' => 'could not spoof username',
1183 'function' => \&spoof_username,
1184 'cmdline' => "SPOOF_USER=$spoof_user LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1185 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
1186 "$local_key_file --verbose --verbose",
1187 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1188 "$fwknopdCmd $default_server_conf_args $intf_str",
1193 'category' => 'Rijndael SPA',
1194 'subcategory' => 'client+server',
1195 'detail' => 'replay attack detection',
1196 'err_msg' => 'could not detect replay attack',
1197 'function' => \&replay_detection,
1198 'cmdline' => $default_client_args,
1199 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1200 "$fwknopdCmd $default_server_conf_args $intf_str",
1201 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1205 'category' => 'Rijndael SPA',
1206 'subcategory' => 'client+server',
1207 'detail' => 'replay detection (Rijndael prefix)',
1208 'err_msg' => 'could not detect replay attack',
1209 'function' => \&replay_detection,
1210 'pkt_prefix' => 'U2FsdGVkX1',
1211 'cmdline' => $default_client_args,
1212 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1213 "$fwknopdCmd $default_server_conf_args $intf_str",
1214 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1220 'category' => 'Rijndael SPA',
1221 'subcategory' => 'FUZZING',
1222 'detail' => 'overly long port value',
1223 'err_msg' => 'server crashed or did not detect error condition',
1224 'function' => \&fuzzer,
1225 ### this packet was generated with a modified fwknop client via the
1226 ### following command line:
1228 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1229 # "tcp/`perl -e '{print "1"x"40"}'`" -a 127.0.0.2 -D 127.0.0.1 \
1230 # --get-key local_spa.key --verbose --verbose
1232 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1233 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1234 # authenticated clients.
1237 '+JzxeTGlc6lwwzbJSrYChKx8bonWBIPajwGfEtGOaoglcMLbTY/GGXo/nxqiN1LykFS' .
1238 'lDFXgrkyx2emJ7NGzYqQPUYZxLdZRocR9aRIptvXLLIPBcIpJASi/TUiJlw7CDFMcj0' .
1239 'ptSBJJUZi0tozpKHETp3AgqfzyOy5FNs38aZsV5/sDl3Pt+kF7fTZJ+YLbmYY4yCUz2' .
1240 'ZUYoCaJ7X78ULyJTi5eT7nug',
1241 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1242 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1243 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1244 "-d $default_digest_file -p $default_pid_file $intf_str",
1248 'category' => 'Rijndael SPA',
1249 'subcategory' => 'FUZZING',
1250 'detail' => 'overly long proto value',
1251 'err_msg' => 'server crashed or did not detect error condition',
1252 'function' => \&fuzzer,
1253 ### this packet was generated with a modified fwknop client via the
1254 ### following command line:
1256 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1257 # "tcp`perl -e '{print "A"x"28"}'`/1" -a 127.0.0.2 -D 127.0.0.1 \
1258 # --get-key local_spa.key --verbose --verbose
1260 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1261 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1262 # authenticated clients.
1265 '/im5MiJQmOdzqrdWXv+AjEtAm/HsLrdaTFcSw3ZskqpGOdDIrSCz3VXbFfv7qDkc5Y4' .
1266 'q/k1mRXl9SGzpug87U5dZSyCdAr30z7/2kUFEPTGOQBi/x+L1t1pvdkm4xg13t09ldm' .
1267 '5OD8KiV6qzqLOvN4ULJjvvJJWBZ9qvo/f2Q9Wf67g2KHiwS6EeCINAuMoUw/mNRQMa4' .
1268 'oGnOXu3/DeWHJAwtSeh7EAr4',
1269 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1270 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1271 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1272 "-d $default_digest_file -p $default_pid_file $intf_str",
1276 'category' => 'Rijndael SPA',
1277 'subcategory' => 'FUZZING',
1278 'detail' => 'overly long IP value',
1279 'err_msg' => 'server crashed or did not detect error condition',
1280 'function' => \&fuzzer,
1281 ### this packet was generated with a modified fwknop client via the
1282 ### following command line:
1284 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1285 # -a `perl -e '{print "1"x"136"}'`.0.0.1 -D 127.0.0.1 \
1286 # --get-key local_spa.key --verbose --verbose
1288 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1289 # a condition in which pre-2.0.3 fwknopd servers fail to properly validate
1290 # allow IP addresses from malicious authenticated clients.
1293 '93f2rhsXLmBoPicWvYTqrbp+6lNqvWDc8dzmX2s3settwjBGRAXm33TB9agibEphrBu' .
1294 '3d+7DEsivZLDS6Kz0JwdjX7t0J9c8es+DVNjlLnPtVNcxhs+2kUzimNrgysIXQRJ+GF' .
1295 'GbhdxiXCqdy1vWxWpdoaZmY/CeGIkpoFJFPbJhCRLLX25UMvMF2wXj02MpI4d3t1/6W' .
1296 'DM3taM3kZsiFv6HxFjAhIEuQ1oAg2OgRGXkDmT3jDNZMHUm0d4Ahm9LonG7RbOxq/B0' .
1297 'qUvY8lkymbwvjelVok7Lvlc06cRhN4zm32D4V05g0vQS3PlX9C+mgph9DeAPVX+D8iZ' .
1298 '8lGrxcPSfbCOW61k0MP+q1EhLZkc1qAm5g2+2cLNZcoBNEdh3yj8OTPZJyBVw',
1299 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1300 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1301 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1302 "-d $default_digest_file -p $default_pid_file $intf_str",
1306 'category' => 'Rijndael SPA',
1307 'subcategory' => 'FUZZING',
1308 'detail' => 'negative port value',
1309 'err_msg' => 'server crashed or did not detect error condition',
1310 'function' => \&fuzzer,
1311 ### this packet was generated with a modified fwknop client via the
1312 ### following command line:
1314 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1315 # tcp/-33 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1316 # --verbose --verbose
1319 '/weoc+pEuQknZo8ImWTQBB+/PwSJ2/TcrmFoSkxpRXX4+jlUxoJakHrioxh8rhLmAD9' .
1320 '8E4lMnq+EbM2XYdhs2alpZ5bovAFojMsYRWwr/BvRO4Um4Fmo9z9sY3DR477TXNYXBR' .
1321 'iGXWxSL4u+AWSSePK3qiiYoRQVw',
1322 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1323 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1324 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1325 "-d $default_digest_file -p $default_pid_file $intf_str",
1329 'category' => 'Rijndael SPA',
1330 'subcategory' => 'FUZZING',
1331 'detail' => 'null port value',
1332 'err_msg' => 'server crashed or did not detect error condition',
1333 'function' => \&fuzzer,
1334 ### this packet was generated with a modified fwknop client via the
1335 ### following command line:
1337 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/ \
1338 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1339 # --verbose --verbose
1342 '94nu7hvq6V/3A27GzjHwfPnPCQfs44ySlraIFYHOAqy5YqjkrBS67nH35tX55N1BrYZ' .
1343 '07zvcT03keUhLE1Uo7Wme1nE7BfTOG5stmIK1UQI85sL52//lDHu+xCqNcL7GUKbVRz' .
1344 'ekw+EUscVvUkrsRcVtSvOm+fCNo',
1345 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1346 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1347 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1348 "-d $default_digest_file -p $default_pid_file $intf_str",
1352 'category' => 'Rijndael SPA',
1353 'subcategory' => 'FUZZING',
1354 'detail' => 'long FKO protocol value (enc mode trigger)',
1355 'err_msg' => 'server crashed or did not detect error condition',
1356 'function' => \&fuzzer,
1357 ### this packet was generated with a modified fwknop client via the
1358 ### following command line:
1360 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1361 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1363 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1364 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1365 # encrypted SPA packet
1368 '/ewH/k1XsDX+VQ8NlNvCZ4P2QOl/4IpJYXkq4TtAe3899OtApXJiTtPCuYW70XPuxge' .
1369 'MtFjc4UfslK/r9v+FYfyd3fIIHCz0Q0M4+nM3agTLmJj8nOxk6ZeBj82SDQWhHAxGdJ' .
1370 'IQALPve0ug4cuGxS3b4M+2Q/Av9i2tU3Lzlogw3sY0tk6wGf4zZk4UsviVXYpINniGT' .
1371 'RhYSIQ1dfdkng7hKiHMDaObYY1GFp4nxEt/QjasAwvE+7/iFyoKN+IRpGG4v4hGEPh2' .
1372 'vTDqmvfRuIHtgFD7NxZjt+m/jjcu0gkdWEoD4fenwGU35FlvchyM2AiAEw7yRzSABfn' .
1373 'R9d3sYZGMtyASw2O1vSluwIxUUnDop3gxEIhJEj8h+01pA3K+klSpALeY9EZgHqYC7E' .
1374 'ETuPS6dZ3764nWohtCY67JvNUX7TtNDNc2qrhrapdRP17+PT2Vh4s9m38V3WwVWC3uH' .
1375 'X/klLZcHIt+aRDV+uekw9GOKSgwFL2ekPpr3gXxigc3zrxel5hcsqLOpVUa4CP/0HkG' .
1376 'F0NPQvOT3ZvpeIJnirKP1ZX9gDFinqhuzL7oqktW61e1iwe7KZEdrZV0k2KZwyb8qU5' .
1378 'server_positive_output_matches' => [qr/No\sstanza\sencryption\smode\smatch/],
1379 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1380 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1381 "-d $default_digest_file -p $default_pid_file $intf_str",
1385 'category' => 'Rijndael SPA',
1386 'subcategory' => 'FUZZING',
1387 'detail' => 'long FKO protocol value (Rijndael trigger)',
1388 'err_msg' => 'server crashed or did not detect error condition',
1389 'function' => \&fuzzer,
1390 ### this packet was generated with a modified fwknop client via the
1391 ### following command line:
1393 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1394 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1396 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1397 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1398 # encrypted SPA packet
1401 '+YQNu4BFgiNeu8HeiBiNKriqCFSseALt9vJaKzkzK/OF4pjkJcvhGEOi7fEVXqn3VIdlGR' .
1402 'DmBul2I7H3z18U9E97bWGgT9NexKgEPCuekL18ZEPf5xR3JleNsNWatqYgAOkgN8ZWE69Q' .
1403 'qQUYYhxTvJHS6R+5JqFKB3A44hMXoICdYNkn9MAktHxk3PbbpQ+nA+jESwVCra2doAiLiM' .
1404 'ucvGIZZiTv0Mc1blFYIE2zqZ/C7ct1V+ukwSkUv0r87eA7uJhmlpThRsL0dN6iekJ6i87B' .
1405 'tE8QyuOXzOMftI11SUn/LwqD4RMdR21rvLrzR6ZB5eUX2UBpODyzX6n+PJJkTWCuFVT4z1' .
1407 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1408 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1409 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1410 "-d $default_digest_file -p $default_pid_file $intf_str",
1415 'category' => 'Rijndael SPA',
1416 'subcategory' => 'FUZZING',
1417 'detail' => 'null proto value',
1418 'err_msg' => 'server crashed or did not detect error condition',
1419 'function' => \&fuzzer,
1420 ### this packet was generated with a modified fwknop client via the
1421 ### following command line:
1423 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A /22 \
1424 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1425 # --verbose --verbose
1428 '/JT14qxh9P4iy+CuUZahThaQjoEuL2zd46a+jL6sTrBZJSa6faUX4dH5fte/4ZJv+9f' .
1429 'd/diWYKAUvdQ4DydPGlR7mwQa2W+obKpqrsTBz7D4054z6ATAOGpCtifakEVl1XRc2+' .
1430 'hW04WpY8mdUNu9i+PrfPr7/KxqU',
1431 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1432 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1433 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1434 "-d $default_digest_file -p $default_pid_file $intf_str",
1439 'category' => 'Rijndael SPA',
1440 'subcategory' => 'server',
1441 'detail' => 'digest cache structure',
1442 'err_msg' => 'improper digest cache structure',
1443 'function' => \&digest_cache_structure,
1448 'category' => 'Rijndael SPA',
1449 'subcategory' => 'server',
1450 'detail' => 'ipfw active/expire sets not equal',
1451 'err_msg' => 'allowed active/expire sets to be the same',
1452 'function' => \&spa_cycle,
1453 'cmdline' => $default_client_args,
1454 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1455 "$fwknopdCmd -c $cf{'ipfw_active_expire'} -a $cf{'def_access'} " .
1456 "-d $default_digest_file -p $default_pid_file $intf_str",
1457 'server_positive_output_matches' => [qr/Cannot\sset\sidentical\sipfw\sactive\sand\sexpire\ssets/],
1458 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1463 'category' => 'Rijndael SPA',
1464 'subcategory' => 'client+server',
1465 'detail' => 'non-base64 altered SPA data',
1466 'err_msg' => 'allowed improper SPA data',
1467 'function' => \&altered_non_base64_spa_data,
1468 'cmdline' => $default_client_args,
1469 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1470 "$fwknopdCmd $default_server_conf_args $intf_str",
1474 'category' => 'Rijndael SPA',
1475 'subcategory' => 'client+server',
1476 'detail' => 'base64 altered SPA data',
1477 'err_msg' => 'allowed improper SPA data',
1478 'function' => \&altered_base64_spa_data,
1479 'cmdline' => $default_client_args,
1480 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1481 "$fwknopdCmd $default_server_conf_args $intf_str",
1485 'category' => 'Rijndael SPA',
1486 'subcategory' => 'client+server',
1487 'detail' => 'appended data to SPA pkt',
1488 'err_msg' => 'allowed improper SPA data',
1489 'function' => \&appended_spa_data,
1490 'cmdline' => $default_client_args,
1491 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1492 "$fwknopdCmd $default_server_conf_args $intf_str",
1496 'category' => 'Rijndael SPA',
1497 'subcategory' => 'client+server',
1498 'detail' => 'prepended data to SPA pkt',
1499 'err_msg' => 'allowed improper SPA data',
1500 'function' => \&prepended_spa_data,
1501 'cmdline' => $default_client_args,
1502 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1503 "$fwknopdCmd $default_server_conf_args $intf_str",
1508 'category' => 'GPG (no pw) SPA',
1509 'subcategory' => 'client+server',
1510 'detail' => 'complete cycle (tcp/22 ssh)',
1511 'err_msg' => 'could not complete SPA cycle',
1512 'function' => \&spa_cycle,
1513 'cmdline' => "$default_client_gpg_args_no_homedir "
1514 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1515 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1516 'fw_rule_created' => $NEW_RULE_REQUIRED,
1517 'fw_rule_removed' => $NEW_RULE_REMOVED,
1521 'category' => 'GPG (no pw) SPA',
1522 'subcategory' => 'client+server',
1523 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1524 'err_msg' => 'could not complete SPA cycle',
1525 'function' => \&spa_cycle,
1526 'cmdline' => "$default_client_gpg_args_no_homedir "
1527 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1528 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1529 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1530 "-a $cf{'multi_gpg_access'} $intf_str " .
1531 "-d $default_digest_file -p $default_pid_file",
1532 'fw_rule_created' => $NEW_RULE_REQUIRED,
1533 'fw_rule_removed' => $NEW_RULE_REMOVED,
1538 'category' => 'GPG (no pw) SPA',
1539 'subcategory' => 'client+server',
1540 'detail' => 'complete cycle (tcp/23 telnet)',
1541 'err_msg' => 'could not complete SPA cycle',
1542 'function' => \&spa_cycle,
1543 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1544 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1545 "$local_key_file --verbose --verbose " .
1546 "--gpg-recipient-key $gpg_server_key " .
1547 "--gpg-signer-key $gpg_client_key " .
1548 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1549 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1550 'fw_rule_created' => $NEW_RULE_REQUIRED,
1551 'fw_rule_removed' => $NEW_RULE_REMOVED,
1555 'category' => 'GPG (no pw) SPA',
1556 'subcategory' => 'client+server',
1557 'detail' => 'complete cycle (tcp/9418 git)',
1558 'err_msg' => 'could not complete SPA cycle',
1559 'function' => \&spa_cycle,
1560 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1561 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1562 "$local_key_file --verbose --verbose " .
1563 "--gpg-recipient-key $gpg_server_key " .
1564 "--gpg-signer-key $gpg_client_key " .
1565 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1566 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1567 'fw_rule_created' => $NEW_RULE_REQUIRED,
1568 'fw_rule_removed' => $NEW_RULE_REMOVED,
1572 'category' => 'GPG (no pw) SPA',
1573 'subcategory' => 'client+server',
1574 'detail' => 'complete cycle (tcp/60001)',
1575 'err_msg' => 'could not complete SPA cycle',
1576 'function' => \&spa_cycle,
1577 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1578 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1579 "$local_key_file --verbose --verbose " .
1580 "--gpg-recipient-key $gpg_server_key " .
1581 "--gpg-signer-key $gpg_client_key " .
1582 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1583 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1584 'fw_rule_created' => $NEW_RULE_REQUIRED,
1585 'fw_rule_removed' => $NEW_RULE_REMOVED,
1590 'category' => 'GPG (no pw) SPA',
1591 'subcategory' => 'client+server',
1592 'detail' => 'complete cycle (udp/53 dns)',
1593 'err_msg' => 'could not complete SPA cycle',
1594 'function' => \&spa_cycle,
1595 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1596 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1597 "$local_key_file --verbose --verbose " .
1598 "--gpg-recipient-key $gpg_server_key " .
1599 "--gpg-signer-key $gpg_client_key " .
1600 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1601 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1602 'fw_rule_created' => $NEW_RULE_REQUIRED,
1603 'fw_rule_removed' => $NEW_RULE_REMOVED,
1608 'category' => 'GPG (no pw) SPA',
1609 'subcategory' => 'client+server',
1610 'detail' => 'replay attack detection',
1611 'err_msg' => 'could not detect replay attack',
1612 'function' => \&replay_detection,
1613 'cmdline' => "$default_client_gpg_args_no_homedir "
1614 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1615 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1616 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1620 'category' => 'GPG (no pw) SPA',
1621 'subcategory' => 'client+server',
1622 'detail' => 'replay detection (GnuPG prefix)',
1623 'err_msg' => 'could not detect replay attack',
1624 'function' => \&replay_detection,
1625 'pkt_prefix' => 'hQ',
1626 'cmdline' => "$default_client_gpg_args_no_homedir "
1627 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1628 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1629 "$fwknopdCmd $default_server_conf_args $intf_str",
1630 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1635 'category' => 'GPG (no pw) SPA',
1636 'subcategory' => 'client+server',
1637 'detail' => 'non-base64 altered SPA data',
1638 'err_msg' => 'allowed improper SPA data',
1639 'function' => \&altered_non_base64_spa_data,
1640 'cmdline' => "$default_client_gpg_args_no_homedir "
1641 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1642 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1646 'category' => 'GPG (no pw) SPA',
1647 'subcategory' => 'client+server',
1648 'detail' => 'base64 altered SPA data',
1649 'err_msg' => 'allowed improper SPA data',
1650 'function' => \&altered_base64_spa_data,
1651 'cmdline' => "$default_client_gpg_args_no_homedir "
1652 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1653 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1657 'category' => 'GPG (no pw) SPA',
1658 'subcategory' => 'client+server',
1659 'detail' => 'appended data to SPA pkt',
1660 'err_msg' => 'allowed improper SPA data',
1661 'function' => \&appended_spa_data,
1662 'cmdline' => "$default_client_gpg_args_no_homedir "
1663 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1664 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1668 'category' => 'GPG (no pw) SPA',
1669 'subcategory' => 'client+server',
1670 'detail' => 'prepended data to SPA pkt',
1671 'err_msg' => 'allowed improper SPA data',
1672 'function' => \&prepended_spa_data,
1673 'cmdline' => "$default_client_gpg_args_no_homedir "
1674 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1675 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1679 'category' => 'GPG (no pw) SPA',
1680 'subcategory' => 'client+server',
1681 'detail' => 'spoof username (tcp/22 ssh)',
1682 'err_msg' => 'could not spoof username',
1683 'function' => \&spoof_username,
1684 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args_no_homedir "
1685 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1686 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1691 'category' => 'GnuPG (GPG) SPA',
1692 'subcategory' => 'client+server',
1693 'detail' => 'complete cycle (tcp/22 ssh)',
1694 'err_msg' => 'could not complete SPA cycle',
1695 'function' => \&spa_cycle,
1696 'cmdline' => $default_client_gpg_args,
1697 'fwknopd_cmdline' => $default_server_gpg_args,
1698 'fw_rule_created' => $NEW_RULE_REQUIRED,
1699 'fw_rule_removed' => $NEW_RULE_REMOVED,
1703 'category' => 'GnuPG (GPG) SPA',
1704 'subcategory' => 'client+server',
1705 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1706 'err_msg' => 'could not complete SPA cycle',
1707 'function' => \&spa_cycle,
1708 'cmdline' => $default_client_gpg_args,
1709 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1710 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1711 "-a $cf{'multi_gpg_access'} $intf_str " .
1712 "-d $default_digest_file -p $default_pid_file",
1713 'fw_rule_created' => $NEW_RULE_REQUIRED,
1714 'fw_rule_removed' => $NEW_RULE_REMOVED,
1719 'category' => 'GnuPG (GPG) SPA',
1720 'subcategory' => 'client+server',
1721 'detail' => 'complete cycle (tcp/23 telnet)',
1722 'err_msg' => 'could not complete SPA cycle',
1723 'function' => \&spa_cycle,
1724 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1725 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1726 "$local_key_file --verbose --verbose " .
1727 "--gpg-recipient-key $gpg_server_key " .
1728 "--gpg-signer-key $gpg_client_key " .
1729 "--gpg-home-dir $gpg_client_home_dir",
1730 'fwknopd_cmdline' => $default_server_gpg_args,
1731 'fw_rule_created' => $NEW_RULE_REQUIRED,
1732 'fw_rule_removed' => $NEW_RULE_REMOVED,
1736 'category' => 'GnuPG (GPG) SPA',
1737 'subcategory' => 'client+server',
1738 'detail' => 'complete cycle (tcp/9418 git)',
1739 'err_msg' => 'could not complete SPA cycle',
1740 'function' => \&spa_cycle,
1741 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1742 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1743 "$local_key_file --verbose --verbose " .
1744 "--gpg-recipient-key $gpg_server_key " .
1745 "--gpg-signer-key $gpg_client_key " .
1746 "--gpg-home-dir $gpg_client_home_dir",
1747 'fwknopd_cmdline' => $default_server_gpg_args,
1748 'fw_rule_created' => $NEW_RULE_REQUIRED,
1749 'fw_rule_removed' => $NEW_RULE_REMOVED,
1753 'category' => 'GnuPG (GPG) SPA',
1754 'subcategory' => 'client+server',
1755 'detail' => 'complete cycle (tcp/60001)',
1756 'err_msg' => 'could not complete SPA cycle',
1757 'function' => \&spa_cycle,
1758 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1759 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1760 "$local_key_file --verbose --verbose " .
1761 "--gpg-recipient-key $gpg_server_key " .
1762 "--gpg-signer-key $gpg_client_key " .
1763 "--gpg-home-dir $gpg_client_home_dir",
1764 'fwknopd_cmdline' => $default_server_gpg_args,
1765 'fw_rule_created' => $NEW_RULE_REQUIRED,
1766 'fw_rule_removed' => $NEW_RULE_REMOVED,
1771 'category' => 'GnuPG (GPG) SPA',
1772 'subcategory' => 'client+server',
1773 'detail' => 'complete cycle (udp/53 dns)',
1774 'err_msg' => 'could not complete SPA cycle',
1775 'function' => \&spa_cycle,
1776 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1777 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1778 "$local_key_file --verbose --verbose " .
1779 "--gpg-recipient-key $gpg_server_key " .
1780 "--gpg-signer-key $gpg_client_key " .
1781 "--gpg-home-dir $gpg_client_home_dir",
1782 'fwknopd_cmdline' => $default_server_gpg_args,
1783 'fw_rule_created' => $NEW_RULE_REQUIRED,
1784 'fw_rule_removed' => $NEW_RULE_REMOVED,
1789 'category' => 'GnuPG (GPG) SPA',
1790 'subcategory' => 'client+server',
1791 'detail' => 'replay attack detection',
1792 'err_msg' => 'could not detect replay attack',
1793 'function' => \&replay_detection,
1794 'cmdline' => $default_client_gpg_args,
1795 'fwknopd_cmdline' => $default_server_gpg_args,
1796 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1800 'category' => 'GnuPG (GPG) SPA',
1801 'subcategory' => 'client+server',
1802 'detail' => 'replay detection (GnuPG prefix)',
1803 'err_msg' => 'could not detect replay attack',
1804 'function' => \&replay_detection,
1805 'pkt_prefix' => 'hQ',
1806 'cmdline' => $default_client_gpg_args,
1807 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1808 "$fwknopdCmd $default_server_conf_args $intf_str",
1809 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1814 'category' => 'GnuPG (GPG) SPA',
1815 'subcategory' => 'client+server',
1816 'detail' => 'non-base64 altered SPA data',
1817 'err_msg' => 'allowed improper SPA data',
1818 'function' => \&altered_non_base64_spa_data,
1819 'cmdline' => $default_client_gpg_args,
1820 'fwknopd_cmdline' => $default_server_gpg_args,
1824 'category' => 'GnuPG (GPG) SPA',
1825 'subcategory' => 'client+server',
1826 'detail' => 'base64 altered SPA data',
1827 'err_msg' => 'allowed improper SPA data',
1828 'function' => \&altered_base64_spa_data,
1829 'cmdline' => $default_client_gpg_args,
1830 'fwknopd_cmdline' => $default_server_gpg_args,
1834 'category' => 'GnuPG (GPG) SPA',
1835 'subcategory' => 'client+server',
1836 'detail' => 'appended data to SPA pkt',
1837 'err_msg' => 'allowed improper SPA data',
1838 'function' => \&appended_spa_data,
1839 'cmdline' => $default_client_gpg_args,
1840 'fwknopd_cmdline' => $default_server_gpg_args,
1844 'category' => 'GnuPG (GPG) SPA',
1845 'subcategory' => 'client+server',
1846 'detail' => 'prepended data to SPA pkt',
1847 'err_msg' => 'allowed improper SPA data',
1848 'function' => \&prepended_spa_data,
1849 'cmdline' => $default_client_gpg_args,
1850 'fwknopd_cmdline' => $default_server_gpg_args,
1854 'category' => 'GnuPG (GPG) SPA',
1855 'subcategory' => 'client+server',
1856 'detail' => 'spoof username (tcp/22 ssh)',
1857 'err_msg' => 'could not spoof username',
1858 'function' => \&spoof_username,
1859 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args",
1860 'fwknopd_cmdline' => $default_server_gpg_args,
1864 'category' => 'GnuPG (GPG) SPA',
1865 'subcategory' => 'server',
1866 'detail' => 'digest cache structure',
1867 'err_msg' => 'improper digest cache structure',
1868 'function' => \&digest_cache_structure,
1873 if ($use_valgrind) {
1876 'category' => 'valgrind output',
1877 'subcategory' => 'flagged functions',
1879 'err_msg' => 'could not parse flagged functions',
1880 'function' => \&parse_valgrind_flagged_functions,
1886 'category' => $REQUIRED,
1887 'subcategory' => $OPTIONAL,
1888 'detail' => $REQUIRED,
1889 'function' => $REQUIRED,
1890 'binary' => $OPTIONAL,
1891 'cmdline' => $OPTIONAL,
1892 'fwknopd_cmdline' => $OPTIONAL,
1893 'fatal' => $OPTIONAL,
1894 'exec_err' => $OPTIONAL,
1895 'fw_rule_created' => $OPTIONAL,
1896 'fw_rule_removed' => $OPTIONAL,
1897 'server_conf' => $OPTIONAL,
1898 'pkt_prefix' => $OPTIONAL,
1899 'no_ip_check' => $OPTIONAL,
1900 'positive_output_matches' => $OPTIONAL,
1901 'negative_output_matches' => $OPTIONAL,
1902 'server_positive_output_matches' => $OPTIONAL,
1903 'server_negative_output_matches' => $OPTIONAL,
1904 'replay_positive_output_matches' => $OPTIONAL,
1905 'replay_negative_output_matches' => $OPTIONAL,
1909 &diff_test_results();
1913 ### make sure everything looks as expected before continuing
1916 &logr("\n[+] Starting the fwknop test suite...\n\n" .
1917 " args: @args_cp\n\n"
1920 ### save the results from any previous test suite run
1921 ### so that we can potentially compare them with --diff
1922 if ($saved_last_results) {
1923 &logr(" Saved results from previous run " .
1924 "to: ${output_dir}.last/\n\n");
1927 ### main loop through all of the tests
1928 for my $test_hr (@tests) {
1929 &run_test($test_hr);
1932 &logr("\n[+] passed/failed/executed: $passed/$failed/$executed tests\n\n");
1934 copy $logfile, "$output_dir/$logfile" or die $!;
1938 #===================== end main =======================
1941 my $test_hr = shift;
1943 my $msg = "[$test_hr->{'category'}]";
1944 $msg .= " [$test_hr->{'subcategory'}]" if $test_hr->{'subcategory'};
1945 $msg .= " $test_hr->{'detail'}";
1947 return unless &process_include_exclude($msg);
1957 $current_test_file = "$output_dir/$executed.test";
1958 $server_test_file = "$output_dir/${executed}_fwknopd.test";
1960 &write_test_file("[+] TEST: $msg\n", $current_test_file);
1961 $test_hr->{'msg'} = $msg;
1962 if (&{$test_hr->{'function'}}($test_hr)) {
1963 &logr("pass ($executed)\n");
1966 &logr("fail ($executed)\n");
1969 if ($test_hr->{'fatal'} eq $YES) {
1970 die "[*] required test failed, exiting.";
1977 sub process_include_exclude() {
1980 ### inclusions/exclusions
1981 if (@tests_to_include) {
1983 for my $test (@tests_to_include) {
1984 if ($msg =~ $test or ($use_valgrind
1985 and $msg =~ /valgrind\soutput/)) {
1990 return 0 unless $found;
1992 if (@tests_to_exclude) {
1994 for my $test (@tests_to_exclude) {
1995 if ($msg =~ $test) {
2005 sub diff_test_results() {
2007 $diff_dir1 = "${output_dir}.last" unless $diff_dir1;
2008 $diff_dir2 = $output_dir unless $diff_dir2;
2010 die "[*] Need results from a previous run before running --diff"
2011 unless -d $diff_dir2;
2012 die "[*] Current results set does not exist." unless -d $diff_dir1;
2014 my %current_tests = ();
2015 my %previous_tests = ();
2017 ### Only diff results for matching tests (parse the logfile to see which
2018 ### test numbers match across the two test cycles).
2019 &build_results_hash(\%current_tests, $diff_dir1);
2020 &build_results_hash(\%previous_tests, $diff_dir2);
2022 for my $test_msg (sort {$current_tests{$a}{'num'} <=> $current_tests{$b}{'num'}}
2023 keys %current_tests) {
2024 my $current_result = $current_tests{$test_msg}{'pass_fail'};
2025 my $current_num = $current_tests{$test_msg}{'num'};
2026 if (defined $previous_tests{$test_msg}) {
2027 print "[+] Checking: $test_msg\n";
2028 my $previous_result = $previous_tests{$test_msg}{'pass_fail'};
2029 my $previous_num = $previous_tests{$test_msg}{'num'};
2030 if ($current_result ne $previous_result) {
2031 print " DIFF: **$current_result** $test_msg\n";
2034 &diff_results($previous_num, $current_num);
2042 sub diff_results() {
2043 my ($previous_num, $current_num) = @_;
2045 ### edit out any valgrind "==354==" prefixes
2046 my $valgrind_search_re = qr/^==\d+==\s/;
2048 ### remove CMD timestamps
2049 my $cmd_search_re = qr/^\S+\s.*?\s\d{4}\sCMD\:/;
2051 for my $file ("$diff_dir1/${previous_num}.test",
2052 "$diff_dir1/${previous_num}_fwknopd.test",
2053 "$diff_dir2/${current_num}.test",
2054 "$diff_dir2/${current_num}_fwknopd.test",
2056 system qq{perl -p -i -e 's|$valgrind_search_re||' $file} if -e $file;
2057 system qq{perl -p -i -e 's|$cmd_search_re|CMD:|' $file} if -e $file;
2060 if (-e "$diff_dir1/${previous_num}.test"
2061 and -e "$diff_dir2/${current_num}.test") {
2062 system "diff -u $diff_dir1/${previous_num}.test " .
2063 "$diff_dir2/${current_num}.test";
2066 if (-e "$diff_dir1/${previous_num}_fwknopd.test"
2067 and -e "$diff_dir2/${current_num}_fwknopd.test") {
2068 system "diff -u $diff_dir1/${previous_num}_fwknopd.test " .
2069 "$diff_dir2/${current_num}_fwknopd.test";
2075 sub build_results_hash() {
2076 my ($hr, $dir) = @_;
2078 open F, "< $dir/$logfile" or die $!;
2080 if (/^(.*?)\.\.\..*(pass|fail)\s\((\d+)\)/) {
2081 $hr->{$1}{'pass_fail'} = $2;
2082 $hr->{$1}{'num'} = $3;
2088 sub compile_warnings() {
2090 ### 'make clean' as root
2091 return 0 unless &run_cmd('make -C .. clean',
2092 $cmd_out_tmp, $current_test_file);
2095 my $username = getpwuid((stat($configure_path))[4]);
2096 die "[*] Could not determine $configure_path owner"
2099 return 0 unless &run_cmd("$sudo_path -u $username make -C ..",
2100 $cmd_out_tmp, $current_test_file);
2104 return 0 unless &run_cmd('make -C ..',
2105 $cmd_out_tmp, $current_test_file);
2109 ### look for compilation warnings - something like:
2110 ### warning: ‘test’ is used uninitialized in this function
2111 return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
2112 $MATCH_ANY, $current_test_file);
2114 ### the new binaries should exist
2115 unless (-e $fwknopCmd and -x $fwknopCmd) {
2116 &write_test_file("[-] $fwknopCmd does not exist or not executable.\n",
2117 $current_test_file);
2119 unless (-e $fwknopdCmd and -x $fwknopdCmd) {
2120 &write_test_file("[-] $fwknopdCmd does not exist or not executable.\n",
2121 $current_test_file);
2127 sub make_distcheck() {
2129 ### 'make clean' as root
2130 return 0 unless &run_cmd('make -C .. distcheck',
2131 $cmd_out_tmp, $current_test_file);
2133 ### look for compilation warnings - something like:
2134 ### warning: ‘test’ is used uninitialized in this function
2135 return 1 if &file_find_regex([qr/archives\sready\sfor\sdistribution/],
2136 $MATCH_ALL, $current_test_file);
2142 sub binary_exists() {
2143 my $test_hr = shift;
2144 return 0 unless $test_hr->{'binary'};
2146 ### account for different libfko.so paths (e.g. libfko.so.0.3 with no
2147 ### libfko.so link on OpenBSD, and libfko.dylib path on Mac OS X)
2149 if ($test_hr->{'binary'} =~ /libfko/) {
2150 unless (-e $test_hr->{'binary'}) {
2151 my $file = "$lib_dir/libfko.dylib";
2153 $test_hr->{'binary'} = $file;
2154 $libfko_bin = $file;
2156 for my $f (glob("$lib_dir/libfko.so*")) {
2157 if (-e $f and -x $f) {
2158 $test_hr->{'binary'} = $f;
2167 return 0 unless -e $test_hr->{'binary'} and -x $test_hr->{'binary'};
2171 sub expected_code_version() {
2172 my $test_hr = shift;
2174 unless (-e '../VERSION') {
2175 &write_test_file("[-] ../VERSION file does not exist.\n",
2176 $current_test_file);
2180 open F, '< ../VERSION' or die $!;
2183 if ($line =~ /(\d.*\d)/) {
2185 return 0 unless &run_cmd($test_hr->{'cmdline'},
2186 $cmd_out_tmp, $current_test_file);
2187 return 1 if &file_find_regex([qr/$version/],
2188 $MATCH_ALL, $current_test_file);
2193 sub client_send_spa_packet() {
2194 my $test_hr = shift;
2196 &write_key('fwknoptest', $local_key_file);
2198 return 0 unless &run_cmd($test_hr->{'cmdline'},
2199 $cmd_out_tmp, $current_test_file);
2200 return 0 unless &file_find_regex([qr/final\spacked/i],
2201 $MATCH_ALL, $current_test_file);
2207 my $test_hr = shift;
2209 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2210 = &client_server_interaction($test_hr, [], $USE_CLIENT);
2212 if ($test_hr->{'fw_rule_created'} eq $NEW_RULE_REQUIRED) {
2213 $rv = 0 unless $fw_rule_created;
2214 } elsif ($test_hr->{'fw_rule_created'} eq $REQUIRE_NO_NEW_RULE) {
2215 $rv = 0 if $fw_rule_created;
2218 if ($test_hr->{'fw_rule_removed'} eq $NEW_RULE_REMOVED) {
2219 $rv = 0 unless $fw_rule_removed;
2220 } elsif ($test_hr->{'fw_rule_removed'} eq $REQUIRE_NO_NEW_REMOVED) {
2221 $rv = 0 if $fw_rule_removed;
2224 if ($test_hr->{'server_positive_output_matches'}) {
2225 $rv = 0 unless &file_find_regex(
2226 $test_hr->{'server_positive_output_matches'},
2227 $MATCH_ALL, $server_test_file);
2230 if ($test_hr->{'server_negative_output_matches'}) {
2231 $rv = 0 if &file_find_regex(
2232 $test_hr->{'server_negative_output_matches'},
2233 $MATCH_ANY, $server_test_file);
2239 sub spoof_username() {
2240 my $test_hr = shift;
2242 my $rv = &spa_cycle($test_hr);
2244 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2245 $MATCH_ALL, $current_test_file)) {
2249 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2250 $MATCH_ALL, $server_test_file)) {
2257 sub replay_detection() {
2258 my $test_hr = shift;
2260 ### do a complete SPA cycle and then parse the SPA packet out of the
2261 ### current test file and re-send
2263 return 0 unless &spa_cycle($test_hr);
2265 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2268 &write_test_file("[-] could not get SPA packet " .
2269 "from file: $current_test_file\n",
2270 $current_test_file);
2274 if ($test_hr->{'pkt_prefix'}) {
2275 $spa_pkt = $test_hr->{'pkt_prefix'} . $spa_pkt;
2281 'port' => $default_spa_port,
2282 'dst_ip' => $loopback_ip,
2287 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2288 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2290 $rv = 0 unless $server_was_stopped;
2292 if ($test_hr->{'replay_positive_output_matches'}) {
2293 $rv = 0 unless &file_find_regex(
2294 $test_hr->{'replay_positive_output_matches'},
2295 $MATCH_ALL, $server_test_file);
2298 if ($test_hr->{'replay_negative_output_matches'}) {
2299 $rv = 0 if &file_find_regex(
2300 $test_hr->{'replay_negative_output_matches'},
2301 $MATCH_ANY, $server_test_file);
2307 sub digest_cache_structure() {
2308 my $test_hr = shift;
2311 &run_cmd("file $default_digest_file", $cmd_out_tmp, $current_test_file);
2313 if (&file_find_regex([qr/ASCII/i], $MATCH_ALL, $cmd_out_tmp)) {
2315 ### the format should be:
2316 ### <digest> <proto> <src_ip> <src_port> <dst_ip> <dst_port> <time>
2317 open F, "< $default_digest_file" or
2318 die "[*] could not open $default_digest_file: $!";
2322 unless (m|^\S+\s+\d+\s+$ip_re\s+\d+\s+$ip_re\s+\d+\s+\d+|) {
2323 &write_test_file("[-] invalid digest.cache line: $_",
2324 $current_test_file);
2330 } elsif (&file_find_regex([qr/dbm/i], $MATCH_ALL, $cmd_out_tmp)) {
2331 &write_test_file("[+] DBM digest file format, " .
2332 "assuming this is valid.\n", $current_test_file);
2334 ### don't know what kind of file the digest.cache is
2335 &write_test_file("[-] unrecognized file type for " .
2336 "$default_digest_file.\n", $current_test_file);
2341 &write_test_file("[+] valid digest.cache structure.\n",
2342 $current_test_file);
2348 sub server_bpf_ignore_packet() {
2349 my $test_hr = shift;
2352 my $server_was_stopped = 0;
2353 my $fw_rule_created = 0;
2354 my $fw_rule_removed = 0;
2356 unless (&client_send_spa_packet($test_hr)) {
2357 &write_test_file("[-] fwknop client execution error.\n",
2358 $current_test_file);
2362 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2365 &write_test_file("[-] could not get SPA packet " .
2366 "from file: $current_test_file\n", $current_test_file);
2373 'port' => $default_spa_port,
2374 'dst_ip' => $loopback_ip,
2379 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2380 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2382 unless (&file_find_regex([qr/PCAP\sfilter.*\s$non_std_spa_port/],
2383 $MATCH_ALL, $server_test_file)) {
2390 sub altered_non_base64_spa_data() {
2391 my $test_hr = shift;
2394 my $server_was_stopped = 0;
2395 my $fw_rule_created = 0;
2396 my $fw_rule_removed = 0;
2398 unless (&client_send_spa_packet($test_hr)) {
2399 &write_test_file("[-] fwknop client execution error.\n",
2400 $current_test_file);
2404 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2407 &write_test_file("[-] could not get SPA packet " .
2408 "from file: $current_test_file\n", $current_test_file);
2412 ### alter one byte (change to a ":")
2413 $spa_pkt =~ s|^(.{3}).|$1:|;
2418 'port' => $default_spa_port,
2419 'dst_ip' => $loopback_ip,
2424 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2425 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2427 $rv = 0 unless $server_was_stopped;
2433 my $test_hr = shift;
2436 my $server_was_stopped = 0;
2437 my $fw_rule_created = 0;
2438 my $fw_rule_removed = 0;
2443 'port' => $default_spa_port,
2444 'dst_ip' => $loopback_ip,
2445 'data' => $test_hr->{'fuzzing_pkt'},
2449 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2450 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2452 $rv = 0 unless $server_was_stopped;
2454 if ($fw_rule_created) {
2455 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2458 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2461 if ($test_hr->{'server_positive_output_matches'}) {
2462 $rv = 0 unless &file_find_regex(
2463 $test_hr->{'server_positive_output_matches'},
2464 $MATCH_ALL, $server_test_file);
2470 sub altered_base64_spa_data() {
2471 my $test_hr = shift;
2474 my $server_was_stopped = 0;
2475 my $fw_rule_created = 0;
2476 my $fw_rule_removed = 0;
2478 unless (&client_send_spa_packet($test_hr)) {
2479 &write_test_file("[-] fwknop client execution error.\n",
2480 $current_test_file);
2484 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2487 &write_test_file("[-] could not get SPA packet " .
2488 "from file: $current_test_file\n", $current_test_file);
2492 $spa_pkt =~ s|^(.{3}).|AAAA|;
2497 'port' => $default_spa_port,
2498 'dst_ip' => $loopback_ip,
2503 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2504 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2506 $rv = 0 unless $server_was_stopped;
2508 if ($fw_rule_created) {
2509 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2512 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2515 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2516 $MATCH_ALL, $server_test_file)) {
2523 sub appended_spa_data() {
2524 my $test_hr = shift;
2527 my $server_was_stopped = 0;
2528 my $fw_rule_created = 0;
2529 my $fw_rule_removed = 0;
2531 unless (&client_send_spa_packet($test_hr)) {
2532 &write_test_file("[-] fwknop client execution error.\n",
2533 $current_test_file);
2537 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2540 &write_test_file("[-] could not get SPA packet " .
2541 "from file: $current_test_file\n", $current_test_file);
2550 'port' => $default_spa_port,
2551 'dst_ip' => $loopback_ip,
2556 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2557 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2559 $rv = 0 unless $server_was_stopped;
2561 if ($fw_rule_created) {
2562 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2565 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2568 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2569 $MATCH_ALL, $server_test_file)) {
2576 sub prepended_spa_data() {
2577 my $test_hr = shift;
2580 my $server_was_stopped = 0;
2581 my $fw_rule_created = 0;
2582 my $fw_rule_removed = 0;
2584 unless (&client_send_spa_packet($test_hr)) {
2585 &write_test_file("[-] fwknop client execution error.\n",
2586 $current_test_file);
2590 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2593 &write_test_file("[-] could not get SPA packet " .
2594 "from file: $current_test_file\n", $current_test_file);
2598 $spa_pkt = 'AAAA' . $spa_pkt;
2603 'port' => $default_spa_port,
2604 'dst_ip' => $loopback_ip,
2609 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2610 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2612 $rv = 0 unless $server_was_stopped;
2614 if ($fw_rule_created) {
2615 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2618 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2621 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2622 $MATCH_ALL, $server_test_file)) {
2629 sub server_start() {
2630 my $test_hr = shift;
2632 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2633 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2635 unless (&file_find_regex([qr/Starting\sfwknopd\smain\sevent\sloop/],
2636 $MATCH_ALL, $server_test_file)) {
2640 $rv = 0 unless $server_was_stopped;
2646 my $test_hr = shift;
2648 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2649 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2651 $rv = 0 unless $server_was_stopped;
2656 sub server_packet_limit() {
2657 my $test_hr = shift;
2662 'port' => $default_spa_port,
2663 'dst_ip' => $loopback_ip,
2668 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2669 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2671 if (&is_fwknopd_running()) {
2676 unless (&file_find_regex([qr/count\slimit\sof\s1\sreached/],
2677 $MATCH_ALL, $server_test_file)) {
2681 unless (&file_find_regex([qr/Shutting\sDown\sfwknopd/i],
2682 $MATCH_ALL, $server_test_file)) {
2689 sub server_ignore_small_packets() {
2690 my $test_hr = shift;
2695 'port' => $default_spa_port,
2696 'dst_ip' => $loopback_ip,
2697 'data' => 'A'x120, ### < MIN_SPA_DATA_SIZE
2701 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2702 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2706 if (&is_fwknopd_running()) {
2714 sub client_server_interaction() {
2715 my ($test_hr, $pkts_hr, $spa_client_flag) = @_;
2718 my $server_was_stopped = 1;
2719 my $fw_rule_created = 1;
2720 my $fw_rule_removed = 0;
2722 ### start fwknopd to monitor for the SPA packet over the loopback interface
2723 my $fwknopd_parent_pid = &start_fwknopd($test_hr);
2725 ### give fwknopd a chance to parse its config and start sniffing
2726 ### on the loopback interface
2727 if ($use_valgrind) {
2733 ### send the SPA packet(s) to the server either manually using IO::Socket or
2734 ### with the fwknopd client
2735 if ($spa_client_flag == $USE_CLIENT) {
2736 unless (&client_send_spa_packet($test_hr)) {
2737 &write_test_file("[-] fwknop client execution error.\n",
2738 $current_test_file);
2742 &send_packets($pkts_hr);
2745 ### check to see if the SPA packet resulted in a new fw access rule
2747 while (not &is_fw_rule_active($test_hr)) {
2748 &write_test_file("[-] new fw rule does not exist.\n",
2749 $current_test_file);
2755 $fw_rule_created = 0;
2756 $fw_rule_removed = 0;
2759 &time_for_valgrind() if $use_valgrind;
2761 if ($fw_rule_created) {
2762 sleep 3; ### allow time for rule time out.
2763 if (&is_fw_rule_active($test_hr)) {
2764 &write_test_file("[-] new fw rule not timed out.\n",
2765 $current_test_file);
2768 &write_test_file("[+] new fw rule timed out.\n",
2769 $current_test_file);
2770 $fw_rule_removed = 1;
2774 if (&is_fwknopd_running()) {
2776 unless (&file_find_regex([qr/Got\sSIGTERM/],
2777 $MATCH_ALL, $server_test_file)) {
2778 $server_was_stopped = 0;
2781 &write_test_file("[-] server is not running.\n",
2782 $current_test_file);
2783 $server_was_stopped = 0;
2786 return ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed);
2789 sub get_spa_packet_from_file() {
2794 my $found_trigger_line = 0;
2795 open F, "< $file" or die "[*] Could not open file $file: $!";
2797 if (/final\spacked/i) {
2798 $found_trigger_line = 1;
2801 next unless $found_trigger_line;
2803 ### the next line with non whitespace is the SPA packet
2814 sub send_packets() {
2815 my $pkts_ar = shift;
2817 open F, ">> $current_test_file" or die $!;
2818 print F "[+] send_packets(): Sending the following packets...\n";
2819 print F Dumper $pkts_ar;
2822 for my $pkt_hr (@$pkts_ar) {
2823 if ($pkt_hr->{'proto'} eq 'tcp' or $pkt_hr->{'proto'} eq 'udp') {
2824 my $socket = IO::Socket::INET->new(
2825 PeerAddr => $pkt_hr->{'dst_ip'},
2826 PeerPort => $pkt_hr->{'port'},
2827 Proto => $pkt_hr->{'proto'},
2829 ) or die "[*] Could not acquire $pkt_hr->{'proto'}/$pkt_hr->{'port'} " .
2830 "socket to $pkt_hr->{'dst_ip'}: $!";
2832 $socket->send($pkt_hr->{'data'});
2835 } elsif ($pkt_hr->{'proto'} eq 'http') {
2837 } elsif ($pkt_hr->{'proto'} eq 'icmp') {
2841 sleep $pkt_hr->{'delay'} if defined $pkt_hr->{'delay'};
2846 sub generic_exec() {
2847 my $test_hr = shift;
2851 my $exec_rv = &run_cmd($test_hr->{'cmdline'},
2852 $cmd_out_tmp, $current_test_file);
2854 if ($test_hr->{'exec_err'} eq $YES) {
2855 $rv = 0 if $exec_rv;
2857 $rv = 0 unless $exec_rv;
2860 if ($test_hr->{'positive_output_matches'}) {
2861 $rv = 0 unless &file_find_regex(
2862 $test_hr->{'positive_output_matches'},
2863 $MATCH_ALL, $current_test_file);
2866 if ($test_hr->{'negative_output_matches'}) {
2867 $rv = 0 if &file_find_regex(
2868 $test_hr->{'negative_output_matches'},
2869 $MATCH_ANY, $current_test_file);
2877 my $test_hr = shift;
2878 return 0 unless $test_hr->{'binary'};
2879 &run_cmd("./hardening-check $test_hr->{'binary'}",
2880 $cmd_out_tmp, $current_test_file);
2881 return 0 if &file_find_regex([qr/Position\sIndependent.*:\sno/i],
2882 $MATCH_ALL, $current_test_file);
2886 ### check for stack protection
2887 sub stack_protected_binary() {
2888 my $test_hr = shift;
2889 return 0 unless $test_hr->{'binary'};
2890 &run_cmd("./hardening-check $test_hr->{'binary'}",
2891 $cmd_out_tmp, $current_test_file);
2892 return 0 if &file_find_regex([qr/Stack\sprotected.*:\sno/i],
2893 $MATCH_ALL, $current_test_file);
2897 ### check for fortified source functions
2898 sub fortify_source_functions() {
2899 my $test_hr = shift;
2900 return 0 unless $test_hr->{'binary'};
2901 &run_cmd("./hardening-check $test_hr->{'binary'}",
2902 $cmd_out_tmp, $current_test_file);
2903 return 0 if &file_find_regex([qr/Fortify\sSource\sfunctions:\sno/i],
2904 $MATCH_ALL, $current_test_file);
2908 ### check for read-only relocations
2909 sub read_only_relocations() {
2910 my $test_hr = shift;
2911 return 0 unless $test_hr->{'binary'};
2912 &run_cmd("./hardening-check $test_hr->{'binary'}",
2913 $cmd_out_tmp, $current_test_file);
2914 return 0 if &file_find_regex([qr/Read.only\srelocations:\sno/i],
2915 $MATCH_ALL, $current_test_file);
2919 ### check for immediate binding
2920 sub immediate_binding() {
2921 my $test_hr = shift;
2922 return 0 unless $test_hr->{'binary'};
2923 &run_cmd("./hardening-check $test_hr->{'binary'}",
2924 $cmd_out_tmp, $current_test_file);
2925 return 0 if &file_find_regex([qr/Immediate\sbinding:\sno/i],
2926 $MATCH_ALL, $current_test_file);
2932 &run_cmd("LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd " .
2933 "$default_server_conf_args --fw-list-all",
2934 $cmd_out_tmp, $current_test_file);
2942 'ls -l /etc', 'if [ -e /etc/issue ]; then cat /etc/issue; fi',
2943 'if [ `which iptables` ]; then iptables -V; fi',
2944 'if [ -e /proc/cpuinfo ]; then cat /proc/cpuinfo; fi',
2945 'if [ -e /proc/config.gz ]; then zcat /proc/config.gz; fi',
2946 'if [ `which gpg` ]; then gpg --version; fi',
2947 'if [ `which tcpdump` ]; then ldd `which tcpdump`; fi',
2951 'ls -l /usr/lib/*pcap*',
2952 'ls -l /usr/local/lib/*pcap*',
2953 'ls -l /usr/lib/*fko*',
2954 'ls -l /usr/local/lib/*fko*',
2956 &run_cmd($cmd, $cmd_out_tmp, $current_test_file);
2958 if ($cmd =~ /^ldd/) {
2959 $have_gpgme++ if &file_find_regex([qr/gpgme/],
2960 $MATCH_ALL, $cmd_out_tmp);
2964 ### all three of fwknop/fwknopd/libfko must link against gpgme in order
2965 ### to enable gpg tests
2966 unless ($have_gpgme == 3) {
2967 push @tests_to_exclude, qr/GPG/;
2973 sub time_for_valgrind() {
2975 while (&run_cmd("ps axuww | grep LD_LIBRARY_PATH | " .
2976 "grep valgrind |grep -v perl | grep -v grep",
2977 $cmd_out_tmp, $current_test_file)) {
2985 sub anonymize_results() {
2987 die "[*] $output_dir does not exist" unless -d $output_dir;
2988 die "[*] $logfile does not exist, has $0 been executed?"
2991 unlink $tarfile or die "[*] Could not unlink $tarfile: $!";
2994 ### remove non-loopback IP addresses
2995 my $search_re = qr/\b127\.0\.0\.1\b/;
2996 system "perl -p -i -e 's|$search_re|00MY1271STR00|g' $output_dir/*.test";
2997 $search_re = qr/\b127\.0\.0\.2\b/;
2998 system "perl -p -i -e 's|$search_re|00MY1272STR00|g' $output_dir/*.test";
2999 $search_re = qr/\b0\.0\.0\.0\b/;
3000 system "perl -p -i -e 's|$search_re|00MY0000STR00|g' $output_dir/*.test";
3001 $search_re = qr/\b(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}\b/;
3002 system "perl -p -i -e 's|$search_re|N.N.N.N|g' $output_dir/*.test";
3003 system "perl -p -i -e 's|00MY1271STR00|127.0.0.1|g' $output_dir/*.test";
3004 system "perl -p -i -e 's|00MY1272STR00|127.0.0.2|g' $output_dir/*.test";
3005 system "perl -p -i -e 's|00MY0000STR00|0.0.0.0|g' $output_dir/*.test";
3007 ### remove hostname from any uname output
3008 $search_re = qr/\suname\s+\-a\s*\n\s*(\S+)\s+\S+/;
3009 system "perl -p -i -e 'undef \$/; s|$search_re" .
3010 "| uname -a\n\$1 (removed)|s' $output_dir/*.test";
3012 $search_re = qr/uname=\x27(\S+)\s+\S+/;
3013 system "perl -p -i -e 's|$search_re|uname= \$1 (removed)|' $output_dir/*.test";
3016 system "tar cvfz $tarfile $logfile $output_dir";
3017 print "[+] Anonymized test results file: $tarfile\n";
3026 my $test_hr = shift;
3028 open F, "> $default_pid_file" or die $!;
3032 &server_start($test_hr);
3034 open F, "< $default_pid_file" or die $!;
3046 sub start_fwknopd() {
3047 my $test_hr = shift;
3049 &write_test_file("[+] TEST: $test_hr->{'msg'}\n", $server_test_file);
3052 die "[*] Could not fork: $!" unless defined $pid;
3056 ### we are the child, so start fwknopd
3057 exit &run_cmd($test_hr->{'fwknopd_cmdline'},
3058 $server_cmd_tmp, $server_test_file);
3064 my ($key, $file) = @_;
3066 open K, "> $file" or die "[*] Could not open $file: $!";
3067 print K "$loopback_ip: $key\n";
3068 print K "localhost: $key\n";
3069 print K "some.host.through.proxy.com: $key\n";
3075 open C, ">> $current_test_file"
3076 or die "[*] Could not open $current_test_file: $!";
3077 print C "\n" . localtime() . " [+] PID dump:\n";
3079 &run_cmd("ps auxww | grep knop |grep -v grep",
3080 $cmd_out_tmp, $current_test_file);
3085 my ($cmd, $cmd_out, $file) = @_;
3089 or die "[*] Could not open $file: $!";
3090 print F localtime() . " CMD: $cmd\n";
3094 or die "[*] Could not open $file: $!";
3095 print F localtime() . " CMD: $cmd\n";
3099 my $rv = ((system "$cmd > $cmd_out 2>&1") >> 8);
3101 open C, "< $cmd_out" or die "[*] Could not open $cmd_out: $!";
3102 my @cmd_lines = <C>;
3105 open F, ">> $file" or die "[*] Could not open $file: $!";
3106 print F $_ for @cmd_lines;
3119 for (my $i=length($msg); $i < $PRINT_LEN; $i++) {
3128 $|++; ### turn off buffering
3130 $< == 0 && $> == 0 or
3131 die "[*] $0: You must be root (or equivalent ",
3132 "UID 0 account) to effectively test fwknop";
3134 ### validate test hashes
3136 for my $test_hr (@tests) {
3137 for my $key (keys %test_keys) {
3138 if ($test_keys{$key} == $REQUIRED) {
3139 die "[*] Missing '$key' element in hash: $hash_num"
3140 unless defined $test_hr->{$key};
3142 $test_hr->{$key} = '' unless defined $test_hr->{$key};
3148 if ($use_valgrind) {
3149 die "[*] $valgrindCmd exec problem, use --valgrind-path"
3150 unless -e $valgrindCmd and -x $valgrindCmd;
3153 die "[*] $conf_dir directory does not exist." unless -d $conf_dir;
3154 die "[*] $lib_dir directory does not exist." unless -d $lib_dir;
3156 for my $name (keys %cf) {
3157 die "[*] $cf{$name} does not exist" unless -e $cf{$name};
3160 if (-d $output_dir) {
3161 if (-d "${output_dir}.last") {
3162 rmtree "${output_dir}.last"
3163 or die "[*] rmtree ${output_dir}.last $!";
3165 mkdir "${output_dir}.last"
3166 or die "[*] ${output_dir}.last: $!";
3167 for my $file (glob("$output_dir/*.test")) {
3168 if ($file =~ m|.*/(.*)|) {
3169 copy $file, "${output_dir}.last/$1" or die $!;
3172 if (-e "$output_dir/init") {
3173 copy "$output_dir/init", "${output_dir}.last/init";
3176 copy $logfile, "${output_dir}.last/$logfile" or die $!;
3178 $saved_last_results = 1;
3180 mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!";
3182 unless (-d $run_dir) {
3183 mkdir $run_dir or die "[*] Could not mkdir $run_dir: $!";
3186 for my $file (glob("$output_dir/*.test")) {
3187 unlink $file or die "[*] Could not unlink($file)";
3189 if (-e "$output_dir/init") {
3190 unlink "$output_dir/init" or die $!;
3194 unlink $logfile or die $!;
3197 if ($test_include) {
3198 for my $re (split /\s*,\s*/, $test_include) {
3199 push @tests_to_include, qr/$re/;
3202 if ($test_exclude) {
3203 for my $re (split /\s*,\s*/, $test_exclude) {
3204 push @tests_to_exclude, qr/$re/;
3208 ### make sure no fwknopd instance is currently running
3209 die "[*] Please stop the running fwknopd instance."
3210 if &is_fwknopd_running();
3212 unless ($enable_recompilation_warnings_check) {
3213 push @tests_to_exclude, qr/recompilation/;
3216 unless ($enable_make_distcheck) {
3217 push @tests_to_exclude, qr/distcheck/;
3220 unless ($enable_client_ip_resolve_test) {
3221 push @tests_to_exclude, qr/IP resolve/;
3224 $sudo_path = &find_command('sudo');
3226 unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
3227 ### disable compilation checks
3228 push @tests_to_exclude, qr/recompilation/;
3231 open UNAME, "uname |" or die "[*] Could not execute uname: $!";
3236 } elsif (/freebsd/i) {
3237 $platform = $FREEBSD;
3243 unless ($platform eq $LINUX) {
3244 push @tests_to_exclude, qr/NAT/;
3246 unless ($platform eq $FREEBSD or $platform eq $MACOSX) {
3247 push @tests_to_exclude, qr|active/expire sets|;
3250 if (-e $default_digest_file) {
3251 unlink $default_digest_file;
3257 sub identify_loopback_intf() {
3258 return if $loopback_intf;
3262 ### lo Link encap:Local Loopback
3263 ### inet addr:127.0.0.1 Mask:255.0.0.0
3264 ### inet6 addr: ::1/128 Scope:Host
3265 ### UP LOOPBACK RUNNING MTU:16436 Metric:1
3266 ### RX packets:534709 errors:0 dropped:0 overruns:0 frame:0
3267 ### TX packets:534709 errors:0 dropped:0 overruns:0 carrier:0
3268 ### collisions:0 txqueuelen:0
3269 ### RX bytes:101110617 (101.1 MB) TX bytes:101110617 (101.1 MB)
3273 ### lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
3274 ### options=3<RXCSUM,TXCSUM>
3275 ### inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
3276 ### inet6 ::1 prefixlen 128
3277 ### inet 127.0.0.1 netmask 0xff000000
3278 ### nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
3281 my $found_loopback_intf = 0;
3283 my $cmd = 'ifconfig -a';
3284 open C, "$cmd |" or die "[*] (use --loopback <name>) $cmd: $!";
3286 if (/^(\S+?):?\s+.*loopback/i) {
3290 if (/^\S/ and $intf and not $found_loopback_intf) {
3291 ### should not happen
3294 if ($intf and /\b127\.0\.0\.1\b/) {
3295 $found_loopback_intf = 1;
3301 die "[*] could not determine loopback interface, use --loopback <name>"
3302 unless $found_loopback_intf;
3304 $loopback_intf = $intf;
3309 sub parse_valgrind_flagged_functions() {
3310 for my $file (glob("$output_dir/*.test")) {
3311 my $type = 'server';
3312 $type = 'client' if $file =~ /\d\.test/;
3313 open F, "< $file" or die $!;
3315 ### ==30969== by 0x4E3983A: fko_set_username (fko_user.c:65)
3316 if (/^==.*\sby\s\S+\:\s(\S+)\s(.*)/) {
3317 $valgrind_flagged_fcns{$type}{"$1 $2"}++;
3318 $valgrind_flagged_fcns_unique{$type}{$1}++;
3324 open F, ">> $current_test_file" or die $!;
3325 for my $type ('client', 'server') {
3326 print F "\n[+] fwknop $type functions (unique view):\n";
3327 next unless defined $valgrind_flagged_fcns_unique{$type};
3328 for my $fcn (sort {$valgrind_flagged_fcns_unique{$type}{$b}
3329 <=> $valgrind_flagged_fcns_unique{$type}{$a}}
3330 keys %{$valgrind_flagged_fcns_unique{$type}}) {
3331 printf F " %5d : %s\n", $valgrind_flagged_fcns_unique{$type}{$fcn}, $fcn;
3333 print F "\n[+] fwknop $type functions (with call line numbers):\n";
3334 for my $fcn (sort {$valgrind_flagged_fcns{$type}{$b}
3335 <=> $valgrind_flagged_fcns{$type}{$a}} keys %{$valgrind_flagged_fcns{$type}}) {
3336 printf F " %5d : %s\n", $valgrind_flagged_fcns{$type}{$fcn}, $fcn;
3338 next unless defined $valgrind_flagged_fcns{$type};
3345 sub is_fw_rule_active() {
3346 my $test_hr = shift;
3348 my $conf_args = $default_server_conf_args;
3350 if ($test_hr->{'server_conf'}) {
3351 $conf_args = "-c $test_hr->{'server_conf'} -a $cf{'def_access'} " .
3352 "-d $default_digest_file -p $default_pid_file";
3355 if ($test_hr->{'no_ip_check'}) {
3356 return 1 if &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd " .
3357 qq{$conf_args --fw-list | grep -v "# DISABLED" |grep _exp_},
3358 $cmd_out_tmp, $current_test_file);
3360 return 1 if &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd " .
3361 qq{$conf_args --fw-list | grep -v "# DISABLED" |grep $fake_ip |grep _exp_},
3362 $cmd_out_tmp, $current_test_file);
3368 sub is_fwknopd_running() {
3370 sleep 2 if $use_valgrind;
3372 &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd $default_server_conf_args " .
3373 "--status", $cmd_out_tmp, $current_test_file);
3375 return 1 if &file_find_regex([qr/Detected\sfwknopd\sis\srunning/i],
3376 $MATCH_ALL, $cmd_out_tmp);
3381 sub stop_fwknopd() {
3383 &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd " .
3384 "$default_server_conf_args -K", $cmd_out_tmp, $current_test_file);
3386 if ($use_valgrind) {
3387 &time_for_valgrind();
3395 sub file_find_regex() {
3396 my ($re_ar, $match_style, $file) = @_;
3398 my $found_all_regexs = 1;
3399 my $found_single_match = 0;
3400 my @write_lines = ();
3401 my @file_lines = ();
3403 open F, "< $file" or die "[*] Could not open $file: $!";
3405 push @file_lines, $_;
3409 for my $re (@$re_ar) {
3411 for my $line (@file_lines) {
3413 push @write_lines, "[.] file_find_regex() " .
3414 "Matched '$re' with line: $line";
3416 $found_single_match = 1;
3420 push @write_lines, "[.] file_find_regex() " .
3421 "Did not match regex '$re' from regexs: '@$re_ar' " .
3422 "within file: $file\n";
3423 $found_all_regexs = 0;
3427 for my $line (@write_lines) {
3428 &write_test_file($line, $file);
3431 if ($match_style == $MATCH_ANY) {
3432 return $found_single_match;
3435 return $found_all_regexs;
3438 sub find_command() {
3442 open C, "which $cmd |" or die "[*] Could not execute: which $cmd: $!";
3444 if (m|^(/.*$cmd)$|) {
3453 sub write_test_file() {
3454 my ($msg, $file) = @_;
3458 or die "[*] Could not open $file: $!";
3463 or die "[*] Could not open $file: $!";
3473 open F, ">> $logfile" or die $!;
3484 -A --Anonymize-results - Prepare anonymized results at:
3486 --diff - Compare the results of one test run to
3487 another. By default this compares output
3488 in ${output_dir}.last to $output_dir
3489 --diff-dir1=<path> - Left hand side of diff directory path,
3490 default is: ${output_dir}.last
3491 --diff-dir2=<path> - Right hand side of diff directory path,
3492 default is: $output_dir
3493 --include=<regex> - Specify a regex to be used over test
3494 names that must match.
3495 --exclude=<regex> - Specify a regex to be used over test
3496 names that must not match.
3497 --enable-recompile - Recompile fwknop sources and look for
3498 compilation warnings.
3499 --enable-valgrind - Run every test underneath valgrind.
3500 --List - List test names.
3501 --loopback-intf=<intf> - Specify loopback interface name (default
3502 depends on the OS where the test suite
3504 --output-dir=<path> - Path to output directory, default is:
3506 --fwknop-path=<path> - Path to fwknop binary, default is:
3508 --fwknopd-path=<path> - Path to fwknopd binary, default is:
3510 --libfko-path=<path> - Path to libfko, default is:
3512 --valgrind-path=<path> - Path to valgrind, default is:
3514 -h --help - Display usage on STDOUT and exit.