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' => 'permissions check cycle (tcp/22)',
656 'err_msg' => 'could not complete SPA cycle',
657 'function' => \&permissions_check,
658 'cmdline' => $default_client_args,
659 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
660 "$fwknopdCmd $default_server_conf_args $intf_str",
661 'server_positive_output_matches' => [qr/permissions\sshould\sonly\sbe\suser/],
662 'fw_rule_created' => $NEW_RULE_REQUIRED,
663 'fw_rule_removed' => $NEW_RULE_REMOVED,
667 'category' => 'Rijndael SPA',
668 'subcategory' => 'client+server',
669 'detail' => 'client IP resolve (tcp/22 ssh)',
670 'err_msg' => 'could not complete SPA cycle',
671 'function' => \&spa_cycle,
672 'cmdline' => $client_ip_resolve_args,
674 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
675 "$fwknopdCmd $default_server_conf_args $intf_str",
676 'fw_rule_created' => $NEW_RULE_REQUIRED,
677 'fw_rule_removed' => $NEW_RULE_REMOVED,
682 'category' => 'Rijndael SPA',
683 'subcategory' => 'client+server',
684 'detail' => 'dual usage access key (tcp/80 http)',
685 'err_msg' => 'could not complete SPA cycle',
686 'function' => \&spa_cycle,
687 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
688 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
689 "$local_key_file --verbose --verbose",
690 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
691 "$fwknopdCmd -c $cf{'def'} -a $cf{'dual_key_access'} " .
692 "-d $default_digest_file -p $default_pid_file $intf_str",
693 ### check for the first stanza that does not allow tcp/80 - the
694 ### second stanza allows this
695 'server_positive_output_matches' => [qr/stanza #1\)\sOne\sor\smore\srequested\sprotocol\/ports\swas\sdenied/],
696 'fw_rule_created' => $NEW_RULE_REQUIRED,
697 'fw_rule_removed' => $NEW_RULE_REMOVED,
701 'category' => 'Rijndael SPA',
702 'subcategory' => 'client+server',
703 'detail' => 'packet aging (past) (tcp/22 ssh)',
704 'err_msg' => 'old SPA packet accepted',
705 'function' => \&spa_cycle,
706 'cmdline' => "$default_client_args --time-offset-minus 300s",
707 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
708 "$fwknopdCmd $default_server_conf_args $intf_str",
709 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
710 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
714 'category' => 'Rijndael SPA',
715 'subcategory' => 'client+server',
716 'detail' => 'packet aging (future) (tcp/22 ssh)',
717 'err_msg' => 'future SPA packet accepted',
718 'function' => \&spa_cycle,
719 'cmdline' => "$default_client_args --time-offset-plus 300s",
720 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
721 "$fwknopdCmd $default_server_conf_args $intf_str",
722 'server_positive_output_matches' => [qr/SPA\sdata\stime\sdifference/],
723 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
727 'category' => 'Rijndael SPA',
728 'subcategory' => 'client+server',
729 'detail' => 'expired stanza (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{'exp_access'} " .
735 "-d $default_digest_file -p $default_pid_file $intf_str",
736 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
737 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
741 'category' => 'Rijndael SPA',
742 'subcategory' => 'client+server',
743 'detail' => 'invalid expire date (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{'invalid_exp_access'} " .
749 "-d $default_digest_file -p $default_pid_file $intf_str",
750 'server_positive_output_matches' => [qr/invalid\sdate\svalue/],
751 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
755 'category' => 'Rijndael SPA',
756 'subcategory' => 'client+server',
757 'detail' => 'expired epoch stanza (tcp/22 ssh)',
758 'err_msg' => 'SPA packet 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{'exp_epoch_access'} " .
763 "-d $default_digest_file -p $default_pid_file $intf_str",
764 'server_positive_output_matches' => [qr/Access\sstanza\shas\sexpired/],
765 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
769 'category' => 'Rijndael SPA',
770 'subcategory' => 'client+server',
771 'detail' => 'future expired stanza (tcp/22 ssh)',
772 'err_msg' => 'SPA packet not accepted',
773 'function' => \&spa_cycle,
774 'cmdline' => $default_client_args,
775 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
776 "$fwknopdCmd -c $cf{'def'} -a $cf{'future_exp_access'} " .
777 "-d $default_digest_file -p $default_pid_file $intf_str",
778 'fw_rule_created' => $NEW_RULE_REQUIRED,
779 'fw_rule_removed' => $NEW_RULE_REMOVED,
784 'category' => 'Rijndael SPA',
785 'subcategory' => 'client+server',
786 'detail' => 'OPEN_PORTS (tcp/22 ssh)',
787 'err_msg' => "improper OPEN_PORTS result",
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_access'} " .
792 "-d $default_digest_file -p $default_pid_file $intf_str",
793 'fw_rule_created' => $NEW_RULE_REQUIRED,
794 'fw_rule_removed' => $NEW_RULE_REMOVED,
798 'category' => 'Rijndael SPA',
799 'subcategory' => 'client+server',
800 'detail' => 'OPEN_PORTS mismatch',
801 'err_msg' => "SPA packet accepted",
802 'function' => \&spa_cycle,
803 'cmdline' => $default_client_args,
804 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
805 "$fwknopdCmd -c $cf{'def'} -a $cf{'open_ports_mismatch'} " .
806 "-d $default_digest_file -p $default_pid_file $intf_str",
807 'server_positive_output_matches' => [qr/One\s+or\s+more\s+requested/],
808 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
812 'category' => 'Rijndael SPA',
813 'subcategory' => 'client+server',
814 'detail' => 'require user (tcp/22 ssh)',
815 'err_msg' => "missed require user criteria",
816 'function' => \&spa_cycle,
817 'cmdline' => "SPOOF_USER=$spoof_user $default_client_args",
818 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
819 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_user_access'} " .
820 "-d $default_digest_file -p $default_pid_file $intf_str",
821 'fw_rule_created' => $NEW_RULE_REQUIRED,
822 'fw_rule_removed' => $NEW_RULE_REMOVED,
826 'category' => 'Rijndael SPA',
827 'subcategory' => 'client+server',
828 'detail' => 'user mismatch (tcp/22 ssh)',
829 'err_msg' => "improper user accepted for access",
830 'function' => \&user_mismatch,
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{'user_mismatch_access'} " .
835 "-d $default_digest_file -p $default_pid_file $intf_str",
836 'server_positive_output_matches' => [qr/Username\s+in\s+SPA\s+data/],
837 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
841 'category' => 'Rijndael SPA',
842 'subcategory' => 'client+server',
843 'detail' => 'require src (tcp/22 ssh)',
844 'err_msg' => "fw rule not created",
845 'function' => \&spa_cycle,
846 'cmdline' => $default_client_args,
847 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
848 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
849 "-d $default_digest_file -p $default_pid_file $intf_str",
850 'fw_rule_created' => $NEW_RULE_REQUIRED,
851 'fw_rule_removed' => $NEW_RULE_REMOVED,
855 'category' => 'Rijndael SPA',
856 'subcategory' => 'client+server',
857 'detail' => 'mismatch require src (tcp/22 ssh)',
858 'err_msg' => "fw rule created",
859 'function' => \&spa_cycle,
860 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
861 "$fwknopCmd -A tcp/22 -s -D $loopback_ip --get-key " .
862 "$local_key_file --verbose --verbose",
863 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
864 "$fwknopdCmd -c $cf{'def'} -a $cf{'require_src_access'} " .
865 "-d $default_digest_file -p $default_pid_file $intf_str",
866 'server_positive_output_matches' => [qr/Got\s0.0.0.0\swhen\svalid\ssource\sIP/],
867 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
872 'category' => 'Rijndael SPA',
873 'subcategory' => 'client+server',
874 'detail' => 'IP 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_src_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' => '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_subnet_match'} " .
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+subnet filtering (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{'no_multi_src'} " .
908 "-d $default_digest_file -p $default_pid_file $intf_str",
909 'server_positive_output_matches' => [qr/No\saccess\sdata\sfound/],
910 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
914 'category' => 'Rijndael SPA',
915 'subcategory' => 'client+server',
916 'detail' => 'IP 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{'ip_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' => 'subnet 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{'subnet_src_match'} " .
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 IP/net match (tcp/22 ssh)',
945 'err_msg' => "did not filter $loopback_ip",
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_src_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' => 'multi access 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{'multi_stanza_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,
970 'category' => 'Rijndael SPA',
971 'subcategory' => 'client+server',
972 'detail' => 'bad/good key stanzas (tcp/22 ssh)',
973 'err_msg' => "could not complete SPA cycle",
974 'function' => \&spa_cycle,
975 'cmdline' => $default_client_args,
976 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
977 "$fwknopdCmd -c $cf{'def'} -a $cf{'broken_keys_access'} " .
978 "-d $default_digest_file -p $default_pid_file $intf_str",
979 'fw_rule_created' => $NEW_RULE_REQUIRED,
980 'fw_rule_removed' => $NEW_RULE_REMOVED,
985 'category' => 'Rijndael SPA',
986 'subcategory' => 'client+server',
987 'detail' => "non-enabled NAT (tcp/22 ssh)",
988 'err_msg' => "SPA packet not filtered",
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 $default_server_conf_args $intf_str",
993 'server_positive_output_matches' => [qr/requested\sNAT\saccess.*not\senabled/i],
994 'server_conf' => $cf{'nat'},
995 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
999 'category' => 'Rijndael SPA',
1000 'subcategory' => 'client+server',
1001 'detail' => "NAT to $internal_nat_host (tcp/22 ssh)",
1002 'err_msg' => "could not complete NAT SPA cycle",
1003 'function' => \&spa_cycle,
1004 'cmdline' => "$default_client_args -N $internal_nat_host:22",
1005 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1006 "$fwknopdCmd -c $cf{'nat'} -a $cf{'open_ports_access'} " .
1007 "-d $default_digest_file -p $default_pid_file $intf_str",
1008 'server_positive_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1009 'fw_rule_created' => $NEW_RULE_REQUIRED,
1010 'fw_rule_removed' => $NEW_RULE_REMOVED,
1011 'server_conf' => $cf{'nat'},
1015 'category' => 'Rijndael SPA',
1016 'subcategory' => 'client+server',
1017 'detail' => "force NAT $force_nat_host (tcp/22 ssh)",
1018 'err_msg' => "could not complete NAT SPA cycle",
1019 'function' => \&spa_cycle,
1020 'cmdline' => $default_client_args,
1021 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1022 "$fwknopdCmd -c $cf{'nat'} -a $cf{'force_nat_access'} " .
1023 "-d $default_digest_file -p $default_pid_file $intf_str",
1024 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i],
1025 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1026 'fw_rule_created' => $NEW_RULE_REQUIRED,
1027 'fw_rule_removed' => $NEW_RULE_REMOVED,
1028 'server_conf' => $cf{'nat'},
1032 'category' => 'Rijndael SPA',
1033 'subcategory' => 'client+server',
1034 'detail' => "local NAT $force_nat_host (tcp/22 ssh)",
1035 'err_msg' => "could not complete NAT SPA cycle",
1036 'function' => \&spa_cycle,
1037 'cmdline' => "$default_client_args --nat-local",
1038 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1039 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'force_nat_access'} " .
1040 "-d $default_digest_file -p $default_pid_file $intf_str",
1041 'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i,
1042 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1043 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1044 'fw_rule_created' => $NEW_RULE_REQUIRED,
1045 'fw_rule_removed' => $NEW_RULE_REMOVED,
1046 'server_conf' => $cf{'nat'},
1050 'category' => 'Rijndael SPA',
1051 'subcategory' => 'client+server',
1052 'detail' => "local NAT non-FORCE_NAT (tcp/22 ssh)",
1053 'err_msg' => "could not complete NAT SPA cycle",
1054 'function' => \&spa_cycle,
1055 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1056 "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
1057 "$local_key_file --verbose --verbose --nat-local --nat-port 22",
1058 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1059 "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'def_access'} " .
1060 "-d $default_digest_file -p $default_pid_file $intf_str",
1061 'server_positive_output_matches' => [qr/to\:$loopback_ip\:22/i,
1062 qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
1063 'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
1064 'fw_rule_created' => $NEW_RULE_REQUIRED,
1065 'fw_rule_removed' => $NEW_RULE_REMOVED,
1066 'server_conf' => $cf{'nat'},
1071 'category' => 'Rijndael SPA',
1072 'subcategory' => 'client+server',
1073 'detail' => 'complete cycle (tcp/23 telnet)',
1074 'err_msg' => 'could not complete SPA cycle',
1075 'function' => \&spa_cycle,
1076 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1077 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1078 "$local_key_file --verbose --verbose",
1079 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1080 "$fwknopdCmd $default_server_conf_args $intf_str",
1081 'fw_rule_created' => $NEW_RULE_REQUIRED,
1082 'fw_rule_removed' => $NEW_RULE_REMOVED,
1086 'category' => 'Rijndael SPA',
1087 'subcategory' => 'client+server',
1088 'detail' => 'complete cycle (tcp/9418 git)',
1089 'err_msg' => 'could not complete SPA cycle',
1090 'function' => \&spa_cycle,
1091 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1092 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1093 "$local_key_file --verbose --verbose",
1094 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1095 "$fwknopdCmd $default_server_conf_args $intf_str",
1096 'fw_rule_created' => $NEW_RULE_REQUIRED,
1097 'fw_rule_removed' => $NEW_RULE_REMOVED,
1101 'category' => 'Rijndael SPA',
1102 'subcategory' => 'client+server',
1103 'detail' => 'complete cycle (tcp/60001)',
1104 'err_msg' => 'could not complete SPA cycle',
1105 'function' => \&spa_cycle,
1106 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1107 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1108 "$local_key_file --verbose --verbose",
1109 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1110 "$fwknopdCmd $default_server_conf_args $intf_str",
1111 'fw_rule_created' => $NEW_RULE_REQUIRED,
1112 'fw_rule_removed' => $NEW_RULE_REMOVED,
1116 'category' => 'Rijndael SPA',
1117 'subcategory' => 'client+server',
1118 'detail' => 'multi port (tcp/60001,udp/60001)',
1119 'err_msg' => 'could not complete SPA cycle',
1120 'function' => \&spa_cycle,
1121 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1122 "$fwknopCmd -A tcp/60001,udp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1123 "$local_key_file --verbose --verbose",
1124 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1125 "$fwknopdCmd $default_server_conf_args $intf_str",
1126 'fw_rule_created' => $NEW_RULE_REQUIRED,
1127 'fw_rule_removed' => $NEW_RULE_REMOVED,
1131 'category' => 'Rijndael SPA',
1132 'subcategory' => 'client+server',
1133 'detail' => 'multi port (tcp/22,udp/53,tcp/1234)',
1134 'err_msg' => 'could not complete SPA cycle',
1135 'function' => \&spa_cycle,
1136 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1137 "$fwknopCmd -A tcp/22,udp/53,tcp/1234 -a $fake_ip -D $loopback_ip --get-key " .
1138 "$local_key_file --verbose --verbose",
1139 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1140 "$fwknopdCmd $default_server_conf_args $intf_str",
1141 'fw_rule_created' => $NEW_RULE_REQUIRED,
1142 'fw_rule_removed' => $NEW_RULE_REMOVED,
1147 'category' => 'Rijndael SPA',
1148 'subcategory' => 'client+server',
1149 'detail' => 'complete cycle (udp/53 dns)',
1150 'err_msg' => 'could not complete SPA cycle',
1151 'function' => \&spa_cycle,
1152 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1153 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1154 "$local_key_file --verbose --verbose",
1155 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1156 "$fwknopdCmd $default_server_conf_args $intf_str",
1157 'fw_rule_created' => $NEW_RULE_REQUIRED,
1158 'fw_rule_removed' => $NEW_RULE_REMOVED,
1162 'category' => 'Rijndael SPA',
1163 'subcategory' => 'client+server',
1164 'detail' => "-P bpf SPA over port $non_std_spa_port",
1165 'err_msg' => 'could not complete SPA cycle',
1166 'function' => \&spa_cycle,
1167 'cmdline' => "$default_client_args --server-port $non_std_spa_port",
1168 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1169 "$fwknopdCmd $default_server_conf_args $intf_str " .
1170 qq|-P "udp port $non_std_spa_port"|,
1171 'server_positive_output_matches' => [qr/PCAP\sfilter.*\s$non_std_spa_port/],
1172 'fw_rule_created' => $NEW_RULE_REQUIRED,
1173 'fw_rule_removed' => $NEW_RULE_REMOVED,
1178 'category' => 'Rijndael SPA',
1179 'subcategory' => 'client+server',
1180 'detail' => 'random SPA port (tcp/22 ssh)',
1181 'err_msg' => 'could not complete SPA cycle',
1182 'function' => \&spa_cycle,
1183 'cmdline' => "$default_client_args -r",
1184 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1185 "$fwknopdCmd $default_server_conf_args $intf_str " .
1187 'fw_rule_created' => $NEW_RULE_REQUIRED,
1188 'fw_rule_removed' => $NEW_RULE_REMOVED,
1193 'category' => 'Rijndael SPA',
1194 'subcategory' => 'client+server',
1195 'detail' => 'spoof username (tcp/22)',
1196 'err_msg' => 'could not spoof username',
1197 'function' => \&spoof_username,
1198 'cmdline' => "SPOOF_USER=$spoof_user LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1199 "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
1200 "$local_key_file --verbose --verbose",
1201 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1202 "$fwknopdCmd $default_server_conf_args $intf_str",
1207 'category' => 'Rijndael SPA',
1208 'subcategory' => 'client+server',
1209 'detail' => 'replay attack detection',
1210 'err_msg' => 'could not detect replay attack',
1211 'function' => \&replay_detection,
1212 'cmdline' => $default_client_args,
1213 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1214 "$fwknopdCmd $default_server_conf_args $intf_str",
1215 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1219 'category' => 'Rijndael SPA',
1220 'subcategory' => 'client+server',
1221 'detail' => 'replay detection (Rijndael prefix)',
1222 'err_msg' => 'could not detect replay attack',
1223 'function' => \&replay_detection,
1224 'pkt_prefix' => 'U2FsdGVkX1',
1225 'cmdline' => $default_client_args,
1226 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1227 "$fwknopdCmd $default_server_conf_args $intf_str",
1228 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1234 'category' => 'Rijndael SPA',
1235 'subcategory' => 'FUZZING',
1236 'detail' => 'overly long port value',
1237 'err_msg' => 'server crashed or did not detect error condition',
1238 'function' => \&fuzzer,
1239 ### this packet was generated with a modified fwknop client via the
1240 ### following command line:
1242 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1243 # "tcp/`perl -e '{print "1"x"40"}'`" -a 127.0.0.2 -D 127.0.0.1 \
1244 # --get-key local_spa.key --verbose --verbose
1246 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1247 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1248 # authenticated clients.
1251 '+JzxeTGlc6lwwzbJSrYChKx8bonWBIPajwGfEtGOaoglcMLbTY/GGXo/nxqiN1LykFS' .
1252 'lDFXgrkyx2emJ7NGzYqQPUYZxLdZRocR9aRIptvXLLIPBcIpJASi/TUiJlw7CDFMcj0' .
1253 'ptSBJJUZi0tozpKHETp3AgqfzyOy5FNs38aZsV5/sDl3Pt+kF7fTZJ+YLbmYY4yCUz2' .
1254 'ZUYoCaJ7X78ULyJTi5eT7nug',
1255 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1256 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1257 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1258 "-d $default_digest_file -p $default_pid_file $intf_str",
1262 'category' => 'Rijndael SPA',
1263 'subcategory' => 'FUZZING',
1264 'detail' => 'overly long proto value',
1265 'err_msg' => 'server crashed or did not detect error condition',
1266 'function' => \&fuzzer,
1267 ### this packet was generated with a modified fwknop client via the
1268 ### following command line:
1270 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1271 # "tcp`perl -e '{print "A"x"28"}'`/1" -a 127.0.0.2 -D 127.0.0.1 \
1272 # --get-key local_spa.key --verbose --verbose
1274 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1275 # a buffer overflow in the fwknopd servers prior to 2.0.3 from
1276 # authenticated clients.
1279 '/im5MiJQmOdzqrdWXv+AjEtAm/HsLrdaTFcSw3ZskqpGOdDIrSCz3VXbFfv7qDkc5Y4' .
1280 'q/k1mRXl9SGzpug87U5dZSyCdAr30z7/2kUFEPTGOQBi/x+L1t1pvdkm4xg13t09ldm' .
1281 '5OD8KiV6qzqLOvN4ULJjvvJJWBZ9qvo/f2Q9Wf67g2KHiwS6EeCINAuMoUw/mNRQMa4' .
1282 'oGnOXu3/DeWHJAwtSeh7EAr4',
1283 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1284 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1285 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1286 "-d $default_digest_file -p $default_pid_file $intf_str",
1290 'category' => 'Rijndael SPA',
1291 'subcategory' => 'FUZZING',
1292 'detail' => 'overly long IP value',
1293 'err_msg' => 'server crashed or did not detect error condition',
1294 'function' => \&fuzzer,
1295 ### this packet was generated with a modified fwknop client via the
1296 ### following command line:
1298 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1299 # -a `perl -e '{print "1"x"136"}'`.0.0.1 -D 127.0.0.1 \
1300 # --get-key local_spa.key --verbose --verbose
1302 # This problem was found by Fernando Arnaboldi of IOActive and exploits
1303 # a condition in which pre-2.0.3 fwknopd servers fail to properly validate
1304 # allow IP addresses from malicious authenticated clients.
1307 '93f2rhsXLmBoPicWvYTqrbp+6lNqvWDc8dzmX2s3settwjBGRAXm33TB9agibEphrBu' .
1308 '3d+7DEsivZLDS6Kz0JwdjX7t0J9c8es+DVNjlLnPtVNcxhs+2kUzimNrgysIXQRJ+GF' .
1309 'GbhdxiXCqdy1vWxWpdoaZmY/CeGIkpoFJFPbJhCRLLX25UMvMF2wXj02MpI4d3t1/6W' .
1310 'DM3taM3kZsiFv6HxFjAhIEuQ1oAg2OgRGXkDmT3jDNZMHUm0d4Ahm9LonG7RbOxq/B0' .
1311 'qUvY8lkymbwvjelVok7Lvlc06cRhN4zm32D4V05g0vQS3PlX9C+mgph9DeAPVX+D8iZ' .
1312 '8lGrxcPSfbCOW61k0MP+q1EhLZkc1qAm5g2+2cLNZcoBNEdh3yj8OTPZJyBVw',
1313 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1314 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1315 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1316 "-d $default_digest_file -p $default_pid_file $intf_str",
1320 'category' => 'Rijndael SPA',
1321 'subcategory' => 'FUZZING',
1322 'detail' => 'negative port value',
1323 'err_msg' => 'server crashed or did not detect error condition',
1324 'function' => \&fuzzer,
1325 ### this packet was generated with a modified fwknop client via the
1326 ### following command line:
1328 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A \
1329 # tcp/-33 -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1330 # --verbose --verbose
1333 '/weoc+pEuQknZo8ImWTQBB+/PwSJ2/TcrmFoSkxpRXX4+jlUxoJakHrioxh8rhLmAD9' .
1334 '8E4lMnq+EbM2XYdhs2alpZ5bovAFojMsYRWwr/BvRO4Um4Fmo9z9sY3DR477TXNYXBR' .
1335 'iGXWxSL4u+AWSSePK3qiiYoRQVw',
1336 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1337 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1338 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1339 "-d $default_digest_file -p $default_pid_file $intf_str",
1343 'category' => 'Rijndael SPA',
1344 'subcategory' => 'FUZZING',
1345 'detail' => 'null port value',
1346 'err_msg' => 'server crashed or did not detect error condition',
1347 'function' => \&fuzzer,
1348 ### this packet was generated with a modified fwknop client via the
1349 ### following command line:
1351 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/ \
1352 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1353 # --verbose --verbose
1356 '94nu7hvq6V/3A27GzjHwfPnPCQfs44ySlraIFYHOAqy5YqjkrBS67nH35tX55N1BrYZ' .
1357 '07zvcT03keUhLE1Uo7Wme1nE7BfTOG5stmIK1UQI85sL52//lDHu+xCqNcL7GUKbVRz' .
1358 'ekw+EUscVvUkrsRcVtSvOm+fCNo',
1359 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1360 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1361 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1362 "-d $default_digest_file -p $default_pid_file $intf_str",
1366 'category' => 'Rijndael SPA',
1367 'subcategory' => 'FUZZING',
1368 'detail' => 'long FKO protocol value (enc mode trigger)',
1369 'err_msg' => 'server crashed or did not detect error condition',
1370 'function' => \&fuzzer,
1371 ### this packet was generated with a modified fwknop client via the
1372 ### following command line:
1374 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1375 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1377 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1378 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1379 # encrypted SPA packet
1382 '/ewH/k1XsDX+VQ8NlNvCZ4P2QOl/4IpJYXkq4TtAe3899OtApXJiTtPCuYW70XPuxge' .
1383 'MtFjc4UfslK/r9v+FYfyd3fIIHCz0Q0M4+nM3agTLmJj8nOxk6ZeBj82SDQWhHAxGdJ' .
1384 'IQALPve0ug4cuGxS3b4M+2Q/Av9i2tU3Lzlogw3sY0tk6wGf4zZk4UsviVXYpINniGT' .
1385 'RhYSIQ1dfdkng7hKiHMDaObYY1GFp4nxEt/QjasAwvE+7/iFyoKN+IRpGG4v4hGEPh2' .
1386 'vTDqmvfRuIHtgFD7NxZjt+m/jjcu0gkdWEoD4fenwGU35FlvchyM2AiAEw7yRzSABfn' .
1387 'R9d3sYZGMtyASw2O1vSluwIxUUnDop3gxEIhJEj8h+01pA3K+klSpALeY9EZgHqYC7E' .
1388 'ETuPS6dZ3764nWohtCY67JvNUX7TtNDNc2qrhrapdRP17+PT2Vh4s9m38V3WwVWC3uH' .
1389 'X/klLZcHIt+aRDV+uekw9GOKSgwFL2ekPpr3gXxigc3zrxel5hcsqLOpVUa4CP/0HkG' .
1390 'F0NPQvOT3ZvpeIJnirKP1ZX9gDFinqhuzL7oqktW61e1iwe7KZEdrZV0k2KZwyb8qU5' .
1392 'server_positive_output_matches' => [qr/No\sstanza\sencryption\smode\smatch/],
1393 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1394 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1395 "-d $default_digest_file -p $default_pid_file $intf_str",
1399 'category' => 'Rijndael SPA',
1400 'subcategory' => 'FUZZING',
1401 'detail' => 'long FKO protocol value (Rijndael trigger)',
1402 'err_msg' => 'server crashed or did not detect error condition',
1403 'function' => \&fuzzer,
1404 ### this packet was generated with a modified fwknop client via the
1405 ### following command line:
1407 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A tcp/22 \
1408 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key --verbose --verbose
1410 # This problem was found by Fernando Arnaboldi of IOActive and is designed
1411 # to have fwknopd look for a mode decryption mode for a long Rijndael-
1412 # encrypted SPA packet
1415 '+YQNu4BFgiNeu8HeiBiNKriqCFSseALt9vJaKzkzK/OF4pjkJcvhGEOi7fEVXqn3VIdlGR' .
1416 'DmBul2I7H3z18U9E97bWGgT9NexKgEPCuekL18ZEPf5xR3JleNsNWatqYgAOkgN8ZWE69Q' .
1417 'qQUYYhxTvJHS6R+5JqFKB3A44hMXoICdYNkn9MAktHxk3PbbpQ+nA+jESwVCra2doAiLiM' .
1418 'ucvGIZZiTv0Mc1blFYIE2zqZ/C7ct1V+ukwSkUv0r87eA7uJhmlpThRsL0dN6iekJ6i87B' .
1419 'tE8QyuOXzOMftI11SUn/LwqD4RMdR21rvLrzR6ZB5eUX2UBpODyzX6n+PJJkTWCuFVT4z1' .
1421 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1422 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1423 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1424 "-d $default_digest_file -p $default_pid_file $intf_str",
1429 'category' => 'Rijndael SPA',
1430 'subcategory' => 'FUZZING',
1431 'detail' => 'null proto value',
1432 'err_msg' => 'server crashed or did not detect error condition',
1433 'function' => \&fuzzer,
1434 ### this packet was generated with a modified fwknop client via the
1435 ### following command line:
1437 # LD_LIBRARY_PATH=../lib/.libs ../client/.libs/fwknop -A /22 \
1438 # -a 127.0.0.2 -D 127.0.0.1 --get-key local_spa.key \
1439 # --verbose --verbose
1442 '/JT14qxh9P4iy+CuUZahThaQjoEuL2zd46a+jL6sTrBZJSa6faUX4dH5fte/4ZJv+9f' .
1443 'd/diWYKAUvdQ4DydPGlR7mwQa2W+obKpqrsTBz7D4054z6ATAOGpCtifakEVl1XRc2+' .
1444 'hW04WpY8mdUNu9i+PrfPr7/KxqU',
1445 'server_positive_output_matches' => [qr/Args\scontain\sinvalid\sdata/],
1446 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1447 "$fwknopdCmd -c $cf{'disable_aging'} -a $cf{'def_access'} " .
1448 "-d $default_digest_file -p $default_pid_file $intf_str",
1453 'category' => 'Rijndael SPA',
1454 'subcategory' => 'server',
1455 'detail' => 'digest cache structure',
1456 'err_msg' => 'improper digest cache structure',
1457 'function' => \&digest_cache_structure,
1462 'category' => 'Rijndael SPA',
1463 'subcategory' => 'server',
1464 'detail' => 'ipfw active/expire sets not equal',
1465 'err_msg' => 'allowed active/expire sets to be the same',
1466 'function' => \&spa_cycle,
1467 'cmdline' => $default_client_args,
1468 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1469 "$fwknopdCmd -c $cf{'ipfw_active_expire'} -a $cf{'def_access'} " .
1470 "-d $default_digest_file -p $default_pid_file $intf_str",
1471 'server_positive_output_matches' => [qr/Cannot\sset\sidentical\sipfw\sactive\sand\sexpire\ssets/],
1472 'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
1477 'category' => 'Rijndael SPA',
1478 'subcategory' => 'client+server',
1479 'detail' => 'non-base64 altered SPA data',
1480 'err_msg' => 'allowed improper SPA data',
1481 'function' => \&altered_non_base64_spa_data,
1482 'cmdline' => $default_client_args,
1483 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1484 "$fwknopdCmd $default_server_conf_args $intf_str",
1488 'category' => 'Rijndael SPA',
1489 'subcategory' => 'client+server',
1490 'detail' => 'base64 altered SPA data',
1491 'err_msg' => 'allowed improper SPA data',
1492 'function' => \&altered_base64_spa_data,
1493 'cmdline' => $default_client_args,
1494 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1495 "$fwknopdCmd $default_server_conf_args $intf_str",
1499 'category' => 'Rijndael SPA',
1500 'subcategory' => 'client+server',
1501 'detail' => 'appended data to SPA pkt',
1502 'err_msg' => 'allowed improper SPA data',
1503 'function' => \&appended_spa_data,
1504 'cmdline' => $default_client_args,
1505 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1506 "$fwknopdCmd $default_server_conf_args $intf_str",
1510 'category' => 'Rijndael SPA',
1511 'subcategory' => 'client+server',
1512 'detail' => 'prepended data to SPA pkt',
1513 'err_msg' => 'allowed improper SPA data',
1514 'function' => \&prepended_spa_data,
1515 'cmdline' => $default_client_args,
1516 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1517 "$fwknopdCmd $default_server_conf_args $intf_str",
1522 'category' => 'GPG (no pw) SPA',
1523 'subcategory' => 'client+server',
1524 'detail' => 'complete cycle (tcp/22 ssh)',
1525 'err_msg' => 'could not complete SPA cycle',
1526 'function' => \&spa_cycle,
1527 'cmdline' => "$default_client_gpg_args_no_homedir "
1528 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1529 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1530 'fw_rule_created' => $NEW_RULE_REQUIRED,
1531 'fw_rule_removed' => $NEW_RULE_REMOVED,
1535 'category' => 'GPG (no pw) SPA',
1536 'subcategory' => 'client+server',
1537 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1538 'err_msg' => 'could not complete SPA cycle',
1539 'function' => \&spa_cycle,
1540 'cmdline' => "$default_client_gpg_args_no_homedir "
1541 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1542 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1543 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1544 "-a $cf{'multi_gpg_access'} $intf_str " .
1545 "-d $default_digest_file -p $default_pid_file",
1546 'fw_rule_created' => $NEW_RULE_REQUIRED,
1547 'fw_rule_removed' => $NEW_RULE_REMOVED,
1552 'category' => 'GPG (no pw) SPA',
1553 'subcategory' => 'client+server',
1554 'detail' => 'complete cycle (tcp/23 telnet)',
1555 'err_msg' => 'could not complete SPA cycle',
1556 'function' => \&spa_cycle,
1557 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1558 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1559 "$local_key_file --verbose --verbose " .
1560 "--gpg-recipient-key $gpg_server_key " .
1561 "--gpg-signer-key $gpg_client_key " .
1562 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1563 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1564 'fw_rule_created' => $NEW_RULE_REQUIRED,
1565 'fw_rule_removed' => $NEW_RULE_REMOVED,
1569 'category' => 'GPG (no pw) SPA',
1570 'subcategory' => 'client+server',
1571 'detail' => 'complete cycle (tcp/9418 git)',
1572 'err_msg' => 'could not complete SPA cycle',
1573 'function' => \&spa_cycle,
1574 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1575 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1576 "$local_key_file --verbose --verbose " .
1577 "--gpg-recipient-key $gpg_server_key " .
1578 "--gpg-signer-key $gpg_client_key " .
1579 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1580 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1581 'fw_rule_created' => $NEW_RULE_REQUIRED,
1582 'fw_rule_removed' => $NEW_RULE_REMOVED,
1586 'category' => 'GPG (no pw) SPA',
1587 'subcategory' => 'client+server',
1588 'detail' => 'complete cycle (tcp/60001)',
1589 'err_msg' => 'could not complete SPA cycle',
1590 'function' => \&spa_cycle,
1591 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1592 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1593 "$local_key_file --verbose --verbose " .
1594 "--gpg-recipient-key $gpg_server_key " .
1595 "--gpg-signer-key $gpg_client_key " .
1596 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1597 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1598 'fw_rule_created' => $NEW_RULE_REQUIRED,
1599 'fw_rule_removed' => $NEW_RULE_REMOVED,
1604 'category' => 'GPG (no pw) SPA',
1605 'subcategory' => 'client+server',
1606 'detail' => 'complete cycle (udp/53 dns)',
1607 'err_msg' => 'could not complete SPA cycle',
1608 'function' => \&spa_cycle,
1609 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1610 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1611 "$local_key_file --verbose --verbose " .
1612 "--gpg-recipient-key $gpg_server_key " .
1613 "--gpg-signer-key $gpg_client_key " .
1614 "--gpg-home-dir $gpg_client_home_dir_no_pw",
1615 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1616 'fw_rule_created' => $NEW_RULE_REQUIRED,
1617 'fw_rule_removed' => $NEW_RULE_REMOVED,
1622 'category' => 'GPG (no pw) SPA',
1623 'subcategory' => 'client+server',
1624 'detail' => 'replay attack detection',
1625 'err_msg' => 'could not detect replay attack',
1626 'function' => \&replay_detection,
1627 'cmdline' => "$default_client_gpg_args_no_homedir "
1628 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1629 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1630 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1634 'category' => 'GPG (no pw) SPA',
1635 'subcategory' => 'client+server',
1636 'detail' => 'replay detection (GnuPG prefix)',
1637 'err_msg' => 'could not detect replay attack',
1638 'function' => \&replay_detection,
1639 'pkt_prefix' => 'hQ',
1640 'cmdline' => "$default_client_gpg_args_no_homedir "
1641 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1642 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1643 "$fwknopdCmd $default_server_conf_args $intf_str",
1644 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1649 'category' => 'GPG (no pw) SPA',
1650 'subcategory' => 'client+server',
1651 'detail' => 'non-base64 altered SPA data',
1652 'err_msg' => 'allowed improper SPA data',
1653 'function' => \&altered_non_base64_spa_data,
1654 'cmdline' => "$default_client_gpg_args_no_homedir "
1655 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1656 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1660 'category' => 'GPG (no pw) SPA',
1661 'subcategory' => 'client+server',
1662 'detail' => 'base64 altered SPA data',
1663 'err_msg' => 'allowed improper SPA data',
1664 'function' => \&altered_base64_spa_data,
1665 'cmdline' => "$default_client_gpg_args_no_homedir "
1666 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1667 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1671 'category' => 'GPG (no pw) SPA',
1672 'subcategory' => 'client+server',
1673 'detail' => 'appended data to SPA pkt',
1674 'err_msg' => 'allowed improper SPA data',
1675 'function' => \&appended_spa_data,
1676 'cmdline' => "$default_client_gpg_args_no_homedir "
1677 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1678 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1682 'category' => 'GPG (no pw) SPA',
1683 'subcategory' => 'client+server',
1684 'detail' => 'prepended data to SPA pkt',
1685 'err_msg' => 'allowed improper SPA data',
1686 'function' => \&prepended_spa_data,
1687 'cmdline' => "$default_client_gpg_args_no_homedir "
1688 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1689 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1693 'category' => 'GPG (no pw) SPA',
1694 'subcategory' => 'client+server',
1695 'detail' => 'spoof username (tcp/22 ssh)',
1696 'err_msg' => 'could not spoof username',
1697 'function' => \&spoof_username,
1698 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args_no_homedir "
1699 . "--gpg-home-dir $gpg_client_home_dir_no_pw",
1700 'fwknopd_cmdline' => $default_server_gpg_args_no_pw,
1705 'category' => 'GnuPG (GPG) SPA',
1706 'subcategory' => 'client+server',
1707 'detail' => 'complete cycle (tcp/22 ssh)',
1708 'err_msg' => 'could not complete SPA cycle',
1709 'function' => \&spa_cycle,
1710 'cmdline' => $default_client_gpg_args,
1711 'fwknopd_cmdline' => $default_server_gpg_args,
1712 'fw_rule_created' => $NEW_RULE_REQUIRED,
1713 'fw_rule_removed' => $NEW_RULE_REMOVED,
1717 'category' => 'GnuPG (GPG) SPA',
1718 'subcategory' => 'client+server',
1719 'detail' => 'multi gpg-IDs (tcp/22 ssh)',
1720 'err_msg' => 'could not complete SPA cycle',
1721 'function' => \&spa_cycle,
1722 'cmdline' => $default_client_gpg_args,
1723 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
1724 "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
1725 "-a $cf{'multi_gpg_access'} $intf_str " .
1726 "-d $default_digest_file -p $default_pid_file",
1727 'fw_rule_created' => $NEW_RULE_REQUIRED,
1728 'fw_rule_removed' => $NEW_RULE_REMOVED,
1733 'category' => 'GnuPG (GPG) SPA',
1734 'subcategory' => 'client+server',
1735 'detail' => 'complete cycle (tcp/23 telnet)',
1736 'err_msg' => 'could not complete SPA cycle',
1737 'function' => \&spa_cycle,
1738 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1739 "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " .
1740 "$local_key_file --verbose --verbose " .
1741 "--gpg-recipient-key $gpg_server_key " .
1742 "--gpg-signer-key $gpg_client_key " .
1743 "--gpg-home-dir $gpg_client_home_dir",
1744 'fwknopd_cmdline' => $default_server_gpg_args,
1745 'fw_rule_created' => $NEW_RULE_REQUIRED,
1746 'fw_rule_removed' => $NEW_RULE_REMOVED,
1750 'category' => 'GnuPG (GPG) SPA',
1751 'subcategory' => 'client+server',
1752 'detail' => 'complete cycle (tcp/9418 git)',
1753 'err_msg' => 'could not complete SPA cycle',
1754 'function' => \&spa_cycle,
1755 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1756 "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " .
1757 "$local_key_file --verbose --verbose " .
1758 "--gpg-recipient-key $gpg_server_key " .
1759 "--gpg-signer-key $gpg_client_key " .
1760 "--gpg-home-dir $gpg_client_home_dir",
1761 'fwknopd_cmdline' => $default_server_gpg_args,
1762 'fw_rule_created' => $NEW_RULE_REQUIRED,
1763 'fw_rule_removed' => $NEW_RULE_REMOVED,
1767 'category' => 'GnuPG (GPG) SPA',
1768 'subcategory' => 'client+server',
1769 'detail' => 'complete cycle (tcp/60001)',
1770 'err_msg' => 'could not complete SPA cycle',
1771 'function' => \&spa_cycle,
1772 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1773 "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --get-key " .
1774 "$local_key_file --verbose --verbose " .
1775 "--gpg-recipient-key $gpg_server_key " .
1776 "--gpg-signer-key $gpg_client_key " .
1777 "--gpg-home-dir $gpg_client_home_dir",
1778 'fwknopd_cmdline' => $default_server_gpg_args,
1779 'fw_rule_created' => $NEW_RULE_REQUIRED,
1780 'fw_rule_removed' => $NEW_RULE_REMOVED,
1785 'category' => 'GnuPG (GPG) SPA',
1786 'subcategory' => 'client+server',
1787 'detail' => 'complete cycle (udp/53 dns)',
1788 'err_msg' => 'could not complete SPA cycle',
1789 'function' => \&spa_cycle,
1790 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1791 "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " .
1792 "$local_key_file --verbose --verbose " .
1793 "--gpg-recipient-key $gpg_server_key " .
1794 "--gpg-signer-key $gpg_client_key " .
1795 "--gpg-home-dir $gpg_client_home_dir",
1796 'fwknopd_cmdline' => $default_server_gpg_args,
1797 'fw_rule_created' => $NEW_RULE_REQUIRED,
1798 'fw_rule_removed' => $NEW_RULE_REMOVED,
1803 'category' => 'GnuPG (GPG) SPA',
1804 'subcategory' => 'client+server',
1805 'detail' => 'replay attack detection',
1806 'err_msg' => 'could not detect replay attack',
1807 'function' => \&replay_detection,
1808 'cmdline' => $default_client_gpg_args,
1809 'fwknopd_cmdline' => $default_server_gpg_args,
1810 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/],
1814 'category' => 'GnuPG (GPG) SPA',
1815 'subcategory' => 'client+server',
1816 'detail' => 'replay detection (GnuPG prefix)',
1817 'err_msg' => 'could not detect replay attack',
1818 'function' => \&replay_detection,
1819 'pkt_prefix' => 'hQ',
1820 'cmdline' => $default_client_gpg_args,
1821 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
1822 "$fwknopdCmd $default_server_conf_args $intf_str",
1823 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/],
1828 'category' => 'GnuPG (GPG) SPA',
1829 'subcategory' => 'client+server',
1830 'detail' => 'non-base64 altered SPA data',
1831 'err_msg' => 'allowed improper SPA data',
1832 'function' => \&altered_non_base64_spa_data,
1833 'cmdline' => $default_client_gpg_args,
1834 'fwknopd_cmdline' => $default_server_gpg_args,
1838 'category' => 'GnuPG (GPG) SPA',
1839 'subcategory' => 'client+server',
1840 'detail' => 'base64 altered SPA data',
1841 'err_msg' => 'allowed improper SPA data',
1842 'function' => \&altered_base64_spa_data,
1843 'cmdline' => $default_client_gpg_args,
1844 'fwknopd_cmdline' => $default_server_gpg_args,
1848 'category' => 'GnuPG (GPG) SPA',
1849 'subcategory' => 'client+server',
1850 'detail' => 'appended data to SPA pkt',
1851 'err_msg' => 'allowed improper SPA data',
1852 'function' => \&appended_spa_data,
1853 'cmdline' => $default_client_gpg_args,
1854 'fwknopd_cmdline' => $default_server_gpg_args,
1858 'category' => 'GnuPG (GPG) SPA',
1859 'subcategory' => 'client+server',
1860 'detail' => 'prepended data to SPA pkt',
1861 'err_msg' => 'allowed improper SPA data',
1862 'function' => \&prepended_spa_data,
1863 'cmdline' => $default_client_gpg_args,
1864 'fwknopd_cmdline' => $default_server_gpg_args,
1868 'category' => 'GnuPG (GPG) SPA',
1869 'subcategory' => 'client+server',
1870 'detail' => 'spoof username (tcp/22 ssh)',
1871 'err_msg' => 'could not spoof username',
1872 'function' => \&spoof_username,
1873 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args",
1874 'fwknopd_cmdline' => $default_server_gpg_args,
1878 'category' => 'GnuPG (GPG) SPA',
1879 'subcategory' => 'server',
1880 'detail' => 'digest cache structure',
1881 'err_msg' => 'improper digest cache structure',
1882 'function' => \&digest_cache_structure,
1887 if ($use_valgrind) {
1890 'category' => 'valgrind output',
1891 'subcategory' => 'flagged functions',
1893 'err_msg' => 'could not parse flagged functions',
1894 'function' => \&parse_valgrind_flagged_functions,
1900 'category' => $REQUIRED,
1901 'subcategory' => $OPTIONAL,
1902 'detail' => $REQUIRED,
1903 'function' => $REQUIRED,
1904 'binary' => $OPTIONAL,
1905 'cmdline' => $OPTIONAL,
1906 'fwknopd_cmdline' => $OPTIONAL,
1907 'fatal' => $OPTIONAL,
1908 'exec_err' => $OPTIONAL,
1909 'fw_rule_created' => $OPTIONAL,
1910 'fw_rule_removed' => $OPTIONAL,
1911 'server_conf' => $OPTIONAL,
1912 'pkt_prefix' => $OPTIONAL,
1913 'no_ip_check' => $OPTIONAL,
1914 'positive_output_matches' => $OPTIONAL,
1915 'negative_output_matches' => $OPTIONAL,
1916 'server_positive_output_matches' => $OPTIONAL,
1917 'server_negative_output_matches' => $OPTIONAL,
1918 'replay_positive_output_matches' => $OPTIONAL,
1919 'replay_negative_output_matches' => $OPTIONAL,
1923 &diff_test_results();
1927 ### make sure everything looks as expected before continuing
1930 &logr("\n[+] Starting the fwknop test suite...\n\n" .
1931 " args: @args_cp\n\n"
1934 ### save the results from any previous test suite run
1935 ### so that we can potentially compare them with --diff
1936 if ($saved_last_results) {
1937 &logr(" Saved results from previous run " .
1938 "to: ${output_dir}.last/\n\n");
1941 ### main loop through all of the tests
1942 for my $test_hr (@tests) {
1943 &run_test($test_hr);
1946 &logr("\n[+] passed/failed/executed: $passed/$failed/$executed tests\n\n");
1948 copy $logfile, "$output_dir/$logfile" or die $!;
1952 #===================== end main =======================
1955 my $test_hr = shift;
1957 my $msg = "[$test_hr->{'category'}]";
1958 $msg .= " [$test_hr->{'subcategory'}]" if $test_hr->{'subcategory'};
1959 $msg .= " $test_hr->{'detail'}";
1961 return unless &process_include_exclude($msg);
1971 $current_test_file = "$output_dir/$executed.test";
1972 $server_test_file = "$output_dir/${executed}_fwknopd.test";
1974 &write_test_file("[+] TEST: $msg\n", $current_test_file);
1975 $test_hr->{'msg'} = $msg;
1976 if (&{$test_hr->{'function'}}($test_hr)) {
1977 &logr("pass ($executed)\n");
1980 &logr("fail ($executed)\n");
1983 if ($test_hr->{'fatal'} eq $YES) {
1984 die "[*] required test failed, exiting.";
1991 sub process_include_exclude() {
1994 ### inclusions/exclusions
1995 if (@tests_to_include) {
1997 for my $test (@tests_to_include) {
1998 if ($msg =~ $test or ($use_valgrind
1999 and $msg =~ /valgrind\soutput/)) {
2004 return 0 unless $found;
2006 if (@tests_to_exclude) {
2008 for my $test (@tests_to_exclude) {
2009 if ($msg =~ $test) {
2019 sub diff_test_results() {
2021 $diff_dir1 = "${output_dir}.last" unless $diff_dir1;
2022 $diff_dir2 = $output_dir unless $diff_dir2;
2024 die "[*] Need results from a previous run before running --diff"
2025 unless -d $diff_dir2;
2026 die "[*] Current results set does not exist." unless -d $diff_dir1;
2028 my %current_tests = ();
2029 my %previous_tests = ();
2031 ### Only diff results for matching tests (parse the logfile to see which
2032 ### test numbers match across the two test cycles).
2033 &build_results_hash(\%current_tests, $diff_dir1);
2034 &build_results_hash(\%previous_tests, $diff_dir2);
2036 for my $test_msg (sort {$current_tests{$a}{'num'} <=> $current_tests{$b}{'num'}}
2037 keys %current_tests) {
2038 my $current_result = $current_tests{$test_msg}{'pass_fail'};
2039 my $current_num = $current_tests{$test_msg}{'num'};
2040 if (defined $previous_tests{$test_msg}) {
2041 print "[+] Checking: $test_msg\n";
2042 my $previous_result = $previous_tests{$test_msg}{'pass_fail'};
2043 my $previous_num = $previous_tests{$test_msg}{'num'};
2044 if ($current_result ne $previous_result) {
2045 print " DIFF: **$current_result** $test_msg\n";
2048 &diff_results($previous_num, $current_num);
2056 sub diff_results() {
2057 my ($previous_num, $current_num) = @_;
2059 ### edit out any valgrind "==354==" prefixes
2060 my $valgrind_search_re = qr/^==\d+==\s/;
2062 ### remove CMD timestamps
2063 my $cmd_search_re = qr/^\S+\s.*?\s\d{4}\sCMD\:/;
2065 for my $file ("$diff_dir1/${previous_num}.test",
2066 "$diff_dir1/${previous_num}_fwknopd.test",
2067 "$diff_dir2/${current_num}.test",
2068 "$diff_dir2/${current_num}_fwknopd.test",
2070 system qq{perl -p -i -e 's|$valgrind_search_re||' $file} if -e $file;
2071 system qq{perl -p -i -e 's|$cmd_search_re|CMD:|' $file} if -e $file;
2074 if (-e "$diff_dir1/${previous_num}.test"
2075 and -e "$diff_dir2/${current_num}.test") {
2076 system "diff -u $diff_dir1/${previous_num}.test " .
2077 "$diff_dir2/${current_num}.test";
2080 if (-e "$diff_dir1/${previous_num}_fwknopd.test"
2081 and -e "$diff_dir2/${current_num}_fwknopd.test") {
2082 system "diff -u $diff_dir1/${previous_num}_fwknopd.test " .
2083 "$diff_dir2/${current_num}_fwknopd.test";
2089 sub build_results_hash() {
2090 my ($hr, $dir) = @_;
2092 open F, "< $dir/$logfile" or die $!;
2094 if (/^(.*?)\.\.\..*(pass|fail)\s\((\d+)\)/) {
2095 $hr->{$1}{'pass_fail'} = $2;
2096 $hr->{$1}{'num'} = $3;
2102 sub compile_warnings() {
2104 ### 'make clean' as root
2105 return 0 unless &run_cmd('make -C .. clean',
2106 $cmd_out_tmp, $current_test_file);
2109 my $username = getpwuid((stat($configure_path))[4]);
2110 die "[*] Could not determine $configure_path owner"
2113 return 0 unless &run_cmd("$sudo_path -u $username make -C ..",
2114 $cmd_out_tmp, $current_test_file);
2118 return 0 unless &run_cmd('make -C ..',
2119 $cmd_out_tmp, $current_test_file);
2123 ### look for compilation warnings - something like:
2124 ### warning: ‘test’ is used uninitialized in this function
2125 return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
2126 $MATCH_ANY, $current_test_file);
2128 ### the new binaries should exist
2129 unless (-e $fwknopCmd and -x $fwknopCmd) {
2130 &write_test_file("[-] $fwknopCmd does not exist or not executable.\n",
2131 $current_test_file);
2133 unless (-e $fwknopdCmd and -x $fwknopdCmd) {
2134 &write_test_file("[-] $fwknopdCmd does not exist or not executable.\n",
2135 $current_test_file);
2141 sub make_distcheck() {
2143 ### 'make clean' as root
2144 return 0 unless &run_cmd('make -C .. distcheck',
2145 $cmd_out_tmp, $current_test_file);
2147 ### look for compilation warnings - something like:
2148 ### warning: ‘test’ is used uninitialized in this function
2149 return 1 if &file_find_regex([qr/archives\sready\sfor\sdistribution/],
2150 $MATCH_ALL, $current_test_file);
2156 sub binary_exists() {
2157 my $test_hr = shift;
2158 return 0 unless $test_hr->{'binary'};
2160 ### account for different libfko.so paths (e.g. libfko.so.0.3 with no
2161 ### libfko.so link on OpenBSD, and libfko.dylib path on Mac OS X)
2163 if ($test_hr->{'binary'} =~ /libfko/) {
2164 unless (-e $test_hr->{'binary'}) {
2165 my $file = "$lib_dir/libfko.dylib";
2167 $test_hr->{'binary'} = $file;
2168 $libfko_bin = $file;
2170 for my $f (glob("$lib_dir/libfko.so*")) {
2171 if (-e $f and -x $f) {
2172 $test_hr->{'binary'} = $f;
2181 return 0 unless -e $test_hr->{'binary'} and -x $test_hr->{'binary'};
2185 sub expected_code_version() {
2186 my $test_hr = shift;
2188 unless (-e '../VERSION') {
2189 &write_test_file("[-] ../VERSION file does not exist.\n",
2190 $current_test_file);
2194 open F, '< ../VERSION' or die $!;
2197 if ($line =~ /(\d.*\d)/) {
2199 return 0 unless &run_cmd($test_hr->{'cmdline'},
2200 $cmd_out_tmp, $current_test_file);
2201 return 1 if &file_find_regex([qr/$version/],
2202 $MATCH_ALL, $current_test_file);
2207 sub client_send_spa_packet() {
2208 my $test_hr = shift;
2210 &write_key('fwknoptest', $local_key_file);
2212 return 0 unless &run_cmd($test_hr->{'cmdline'},
2213 $cmd_out_tmp, $current_test_file);
2214 return 0 unless &file_find_regex([qr/final\spacked/i],
2215 $MATCH_ALL, $current_test_file);
2220 sub permissions_check() {
2221 my $test_hr = shift;
2224 chmod 0777, $cf{'def'} or die $!;
2225 chmod 0777, $cf{'def_access'} or die $!;
2227 $rv = &spa_cycle($test_hr);
2229 chmod 0600, $cf{'def'} or die $!;
2230 chmod 0600, $cf{'def_access'} or die $!;
2232 if ($test_hr->{'server_positive_output_matches'}) {
2233 $rv = 0 unless &file_find_regex(
2234 $test_hr->{'server_positive_output_matches'},
2235 $MATCH_ALL, $server_test_file);
2241 my $test_hr = shift;
2243 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2244 = &client_server_interaction($test_hr, [], $USE_CLIENT);
2246 if ($test_hr->{'fw_rule_created'} eq $NEW_RULE_REQUIRED) {
2247 $rv = 0 unless $fw_rule_created;
2248 } elsif ($test_hr->{'fw_rule_created'} eq $REQUIRE_NO_NEW_RULE) {
2249 $rv = 0 if $fw_rule_created;
2252 if ($test_hr->{'fw_rule_removed'} eq $NEW_RULE_REMOVED) {
2253 $rv = 0 unless $fw_rule_removed;
2254 } elsif ($test_hr->{'fw_rule_removed'} eq $REQUIRE_NO_NEW_REMOVED) {
2255 $rv = 0 if $fw_rule_removed;
2258 if ($test_hr->{'server_positive_output_matches'}) {
2259 $rv = 0 unless &file_find_regex(
2260 $test_hr->{'server_positive_output_matches'},
2261 $MATCH_ALL, $server_test_file);
2264 if ($test_hr->{'server_negative_output_matches'}) {
2265 $rv = 0 if &file_find_regex(
2266 $test_hr->{'server_negative_output_matches'},
2267 $MATCH_ANY, $server_test_file);
2273 sub spoof_username() {
2274 my $test_hr = shift;
2276 my $rv = &spa_cycle($test_hr);
2278 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2279 $MATCH_ALL, $current_test_file)) {
2283 unless (&file_find_regex([qr/Username:\s*$spoof_user/],
2284 $MATCH_ALL, $server_test_file)) {
2291 sub replay_detection() {
2292 my $test_hr = shift;
2294 ### do a complete SPA cycle and then parse the SPA packet out of the
2295 ### current test file and re-send
2297 return 0 unless &spa_cycle($test_hr);
2299 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2302 &write_test_file("[-] could not get SPA packet " .
2303 "from file: $current_test_file\n",
2304 $current_test_file);
2308 if ($test_hr->{'pkt_prefix'}) {
2309 $spa_pkt = $test_hr->{'pkt_prefix'} . $spa_pkt;
2315 'port' => $default_spa_port,
2316 'dst_ip' => $loopback_ip,
2321 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2322 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2324 $rv = 0 unless $server_was_stopped;
2326 if ($test_hr->{'replay_positive_output_matches'}) {
2327 $rv = 0 unless &file_find_regex(
2328 $test_hr->{'replay_positive_output_matches'},
2329 $MATCH_ALL, $server_test_file);
2332 if ($test_hr->{'replay_negative_output_matches'}) {
2333 $rv = 0 if &file_find_regex(
2334 $test_hr->{'replay_negative_output_matches'},
2335 $MATCH_ANY, $server_test_file);
2341 sub digest_cache_structure() {
2342 my $test_hr = shift;
2345 &run_cmd("file $default_digest_file", $cmd_out_tmp, $current_test_file);
2347 if (&file_find_regex([qr/ASCII/i], $MATCH_ALL, $cmd_out_tmp)) {
2349 ### the format should be:
2350 ### <digest> <proto> <src_ip> <src_port> <dst_ip> <dst_port> <time>
2351 open F, "< $default_digest_file" or
2352 die "[*] could not open $default_digest_file: $!";
2356 unless (m|^\S+\s+\d+\s+$ip_re\s+\d+\s+$ip_re\s+\d+\s+\d+|) {
2357 &write_test_file("[-] invalid digest.cache line: $_",
2358 $current_test_file);
2364 } elsif (&file_find_regex([qr/dbm/i], $MATCH_ALL, $cmd_out_tmp)) {
2365 &write_test_file("[+] DBM digest file format, " .
2366 "assuming this is valid.\n", $current_test_file);
2368 ### don't know what kind of file the digest.cache is
2369 &write_test_file("[-] unrecognized file type for " .
2370 "$default_digest_file.\n", $current_test_file);
2375 &write_test_file("[+] valid digest.cache structure.\n",
2376 $current_test_file);
2382 sub server_bpf_ignore_packet() {
2383 my $test_hr = shift;
2386 my $server_was_stopped = 0;
2387 my $fw_rule_created = 0;
2388 my $fw_rule_removed = 0;
2390 unless (&client_send_spa_packet($test_hr)) {
2391 &write_test_file("[-] fwknop client execution error.\n",
2392 $current_test_file);
2396 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2399 &write_test_file("[-] could not get SPA packet " .
2400 "from file: $current_test_file\n", $current_test_file);
2407 'port' => $default_spa_port,
2408 'dst_ip' => $loopback_ip,
2413 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2414 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2416 unless (&file_find_regex([qr/PCAP\sfilter.*\s$non_std_spa_port/],
2417 $MATCH_ALL, $server_test_file)) {
2424 sub altered_non_base64_spa_data() {
2425 my $test_hr = shift;
2428 my $server_was_stopped = 0;
2429 my $fw_rule_created = 0;
2430 my $fw_rule_removed = 0;
2432 unless (&client_send_spa_packet($test_hr)) {
2433 &write_test_file("[-] fwknop client execution error.\n",
2434 $current_test_file);
2438 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2441 &write_test_file("[-] could not get SPA packet " .
2442 "from file: $current_test_file\n", $current_test_file);
2446 ### alter one byte (change to a ":")
2447 $spa_pkt =~ s|^(.{3}).|$1:|;
2452 'port' => $default_spa_port,
2453 'dst_ip' => $loopback_ip,
2458 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2459 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2461 $rv = 0 unless $server_was_stopped;
2467 my $test_hr = shift;
2470 my $server_was_stopped = 0;
2471 my $fw_rule_created = 0;
2472 my $fw_rule_removed = 0;
2477 'port' => $default_spa_port,
2478 'dst_ip' => $loopback_ip,
2479 'data' => $test_hr->{'fuzzing_pkt'},
2483 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2484 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2486 $rv = 0 unless $server_was_stopped;
2488 if ($fw_rule_created) {
2489 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2492 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2495 if ($test_hr->{'server_positive_output_matches'}) {
2496 $rv = 0 unless &file_find_regex(
2497 $test_hr->{'server_positive_output_matches'},
2498 $MATCH_ALL, $server_test_file);
2504 sub altered_base64_spa_data() {
2505 my $test_hr = shift;
2508 my $server_was_stopped = 0;
2509 my $fw_rule_created = 0;
2510 my $fw_rule_removed = 0;
2512 unless (&client_send_spa_packet($test_hr)) {
2513 &write_test_file("[-] fwknop client execution error.\n",
2514 $current_test_file);
2518 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2521 &write_test_file("[-] could not get SPA packet " .
2522 "from file: $current_test_file\n", $current_test_file);
2526 $spa_pkt =~ s|^(.{3}).|AAAA|;
2531 'port' => $default_spa_port,
2532 'dst_ip' => $loopback_ip,
2537 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2538 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2540 $rv = 0 unless $server_was_stopped;
2542 if ($fw_rule_created) {
2543 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2546 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2549 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2550 $MATCH_ALL, $server_test_file)) {
2557 sub appended_spa_data() {
2558 my $test_hr = shift;
2561 my $server_was_stopped = 0;
2562 my $fw_rule_created = 0;
2563 my $fw_rule_removed = 0;
2565 unless (&client_send_spa_packet($test_hr)) {
2566 &write_test_file("[-] fwknop client execution error.\n",
2567 $current_test_file);
2571 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2574 &write_test_file("[-] could not get SPA packet " .
2575 "from file: $current_test_file\n", $current_test_file);
2584 'port' => $default_spa_port,
2585 'dst_ip' => $loopback_ip,
2590 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2591 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2593 $rv = 0 unless $server_was_stopped;
2595 if ($fw_rule_created) {
2596 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2599 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2602 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2603 $MATCH_ALL, $server_test_file)) {
2610 sub prepended_spa_data() {
2611 my $test_hr = shift;
2614 my $server_was_stopped = 0;
2615 my $fw_rule_created = 0;
2616 my $fw_rule_removed = 0;
2618 unless (&client_send_spa_packet($test_hr)) {
2619 &write_test_file("[-] fwknop client execution error.\n",
2620 $current_test_file);
2624 my $spa_pkt = &get_spa_packet_from_file($current_test_file);
2627 &write_test_file("[-] could not get SPA packet " .
2628 "from file: $current_test_file\n", $current_test_file);
2632 $spa_pkt = 'AAAA' . $spa_pkt;
2637 'port' => $default_spa_port,
2638 'dst_ip' => $loopback_ip,
2643 ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2644 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2646 $rv = 0 unless $server_was_stopped;
2648 if ($fw_rule_created) {
2649 &write_test_file("[-] new fw rule created.\n", $current_test_file);
2652 &write_test_file("[+] new fw rule not created.\n", $current_test_file);
2655 unless (&file_find_regex([qr/Error\screating\sfko\scontext/],
2656 $MATCH_ALL, $server_test_file)) {
2663 sub server_start() {
2664 my $test_hr = shift;
2666 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2667 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2669 unless (&file_find_regex([qr/Starting\sfwknopd\smain\sevent\sloop/],
2670 $MATCH_ALL, $server_test_file)) {
2674 $rv = 0 unless $server_was_stopped;
2680 my $test_hr = shift;
2682 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2683 = &client_server_interaction($test_hr, [], $USE_PREDEF_PKTS);
2685 $rv = 0 unless $server_was_stopped;
2690 sub server_packet_limit() {
2691 my $test_hr = shift;
2696 'port' => $default_spa_port,
2697 'dst_ip' => $loopback_ip,
2702 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2703 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2705 if (&is_fwknopd_running()) {
2710 unless (&file_find_regex([qr/count\slimit\sof\s1\sreached/],
2711 $MATCH_ALL, $server_test_file)) {
2715 unless (&file_find_regex([qr/Shutting\sDown\sfwknopd/i],
2716 $MATCH_ALL, $server_test_file)) {
2723 sub server_ignore_small_packets() {
2724 my $test_hr = shift;
2729 'port' => $default_spa_port,
2730 'dst_ip' => $loopback_ip,
2731 'data' => 'A'x120, ### < MIN_SPA_DATA_SIZE
2735 my ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed)
2736 = &client_server_interaction($test_hr, \@packets, $USE_PREDEF_PKTS);
2740 if (&is_fwknopd_running()) {
2748 sub client_server_interaction() {
2749 my ($test_hr, $pkts_hr, $spa_client_flag) = @_;
2752 my $server_was_stopped = 1;
2753 my $fw_rule_created = 1;
2754 my $fw_rule_removed = 0;
2756 ### start fwknopd to monitor for the SPA packet over the loopback interface
2757 my $fwknopd_parent_pid = &start_fwknopd($test_hr);
2759 ### give fwknopd a chance to parse its config and start sniffing
2760 ### on the loopback interface
2761 if ($use_valgrind) {
2767 ### send the SPA packet(s) to the server either manually using IO::Socket or
2768 ### with the fwknopd client
2769 if ($spa_client_flag == $USE_CLIENT) {
2770 unless (&client_send_spa_packet($test_hr)) {
2771 &write_test_file("[-] fwknop client execution error.\n",
2772 $current_test_file);
2776 &send_packets($pkts_hr);
2779 ### check to see if the SPA packet resulted in a new fw access rule
2781 while (not &is_fw_rule_active($test_hr)) {
2782 &write_test_file("[-] new fw rule does not exist.\n",
2783 $current_test_file);
2789 $fw_rule_created = 0;
2790 $fw_rule_removed = 0;
2793 &time_for_valgrind() if $use_valgrind;
2795 if ($fw_rule_created) {
2796 sleep 3; ### allow time for rule time out.
2797 if (&is_fw_rule_active($test_hr)) {
2798 &write_test_file("[-] new fw rule not timed out.\n",
2799 $current_test_file);
2802 &write_test_file("[+] new fw rule timed out.\n",
2803 $current_test_file);
2804 $fw_rule_removed = 1;
2808 if (&is_fwknopd_running()) {
2810 unless (&file_find_regex([qr/Got\sSIGTERM/],
2811 $MATCH_ALL, $server_test_file)) {
2812 $server_was_stopped = 0;
2815 &write_test_file("[-] server is not running.\n",
2816 $current_test_file);
2817 $server_was_stopped = 0;
2820 return ($rv, $server_was_stopped, $fw_rule_created, $fw_rule_removed);
2823 sub get_spa_packet_from_file() {
2828 my $found_trigger_line = 0;
2829 open F, "< $file" or die "[*] Could not open file $file: $!";
2831 if (/final\spacked/i) {
2832 $found_trigger_line = 1;
2835 next unless $found_trigger_line;
2837 ### the next line with non whitespace is the SPA packet
2848 sub send_packets() {
2849 my $pkts_ar = shift;
2851 open F, ">> $current_test_file" or die $!;
2852 print F "[+] send_packets(): Sending the following packets...\n";
2853 print F Dumper $pkts_ar;
2856 for my $pkt_hr (@$pkts_ar) {
2857 if ($pkt_hr->{'proto'} eq 'tcp' or $pkt_hr->{'proto'} eq 'udp') {
2858 my $socket = IO::Socket::INET->new(
2859 PeerAddr => $pkt_hr->{'dst_ip'},
2860 PeerPort => $pkt_hr->{'port'},
2861 Proto => $pkt_hr->{'proto'},
2863 ) or die "[*] Could not acquire $pkt_hr->{'proto'}/$pkt_hr->{'port'} " .
2864 "socket to $pkt_hr->{'dst_ip'}: $!";
2866 $socket->send($pkt_hr->{'data'});
2869 } elsif ($pkt_hr->{'proto'} eq 'http') {
2871 } elsif ($pkt_hr->{'proto'} eq 'icmp') {
2875 sleep $pkt_hr->{'delay'} if defined $pkt_hr->{'delay'};
2880 sub generic_exec() {
2881 my $test_hr = shift;
2885 my $exec_rv = &run_cmd($test_hr->{'cmdline'},
2886 $cmd_out_tmp, $current_test_file);
2888 if ($test_hr->{'exec_err'} eq $YES) {
2889 $rv = 0 if $exec_rv;
2891 $rv = 0 unless $exec_rv;
2894 if ($test_hr->{'positive_output_matches'}) {
2895 $rv = 0 unless &file_find_regex(
2896 $test_hr->{'positive_output_matches'},
2897 $MATCH_ALL, $current_test_file);
2900 if ($test_hr->{'negative_output_matches'}) {
2901 $rv = 0 if &file_find_regex(
2902 $test_hr->{'negative_output_matches'},
2903 $MATCH_ANY, $current_test_file);
2911 my $test_hr = shift;
2912 return 0 unless $test_hr->{'binary'};
2913 &run_cmd("./hardening-check $test_hr->{'binary'}",
2914 $cmd_out_tmp, $current_test_file);
2915 return 0 if &file_find_regex([qr/Position\sIndependent.*:\sno/i],
2916 $MATCH_ALL, $current_test_file);
2920 ### check for stack protection
2921 sub stack_protected_binary() {
2922 my $test_hr = shift;
2923 return 0 unless $test_hr->{'binary'};
2924 &run_cmd("./hardening-check $test_hr->{'binary'}",
2925 $cmd_out_tmp, $current_test_file);
2926 return 0 if &file_find_regex([qr/Stack\sprotected.*:\sno/i],
2927 $MATCH_ALL, $current_test_file);
2931 ### check for fortified source functions
2932 sub fortify_source_functions() {
2933 my $test_hr = shift;
2934 return 0 unless $test_hr->{'binary'};
2935 &run_cmd("./hardening-check $test_hr->{'binary'}",
2936 $cmd_out_tmp, $current_test_file);
2937 return 0 if &file_find_regex([qr/Fortify\sSource\sfunctions:\sno/i],
2938 $MATCH_ALL, $current_test_file);
2942 ### check for read-only relocations
2943 sub read_only_relocations() {
2944 my $test_hr = shift;
2945 return 0 unless $test_hr->{'binary'};
2946 &run_cmd("./hardening-check $test_hr->{'binary'}",
2947 $cmd_out_tmp, $current_test_file);
2948 return 0 if &file_find_regex([qr/Read.only\srelocations:\sno/i],
2949 $MATCH_ALL, $current_test_file);
2953 ### check for immediate binding
2954 sub immediate_binding() {
2955 my $test_hr = shift;
2956 return 0 unless $test_hr->{'binary'};
2957 &run_cmd("./hardening-check $test_hr->{'binary'}",
2958 $cmd_out_tmp, $current_test_file);
2959 return 0 if &file_find_regex([qr/Immediate\sbinding:\sno/i],
2960 $MATCH_ALL, $current_test_file);
2966 &run_cmd("LD_LIBRARY_PATH=$lib_dir $valgrind_str $fwknopdCmd " .
2967 "$default_server_conf_args --fw-list-all",
2968 $cmd_out_tmp, $current_test_file);
2976 'ls -l /etc', 'if [ -e /etc/issue ]; then cat /etc/issue; fi',
2977 'if [ `which iptables` ]; then iptables -V; fi',
2978 'if [ -e /proc/cpuinfo ]; then cat /proc/cpuinfo; fi',
2979 'if [ -e /proc/config.gz ]; then zcat /proc/config.gz; fi',
2980 'if [ `which gpg` ]; then gpg --version; fi',
2981 'if [ `which tcpdump` ]; then ldd `which tcpdump`; fi',
2985 'ls -l /usr/lib/*pcap*',
2986 'ls -l /usr/local/lib/*pcap*',
2987 'ls -l /usr/lib/*fko*',
2988 'ls -l /usr/local/lib/*fko*',
2990 &run_cmd($cmd, $cmd_out_tmp, $current_test_file);
2992 if ($cmd =~ /^ldd/) {
2993 $have_gpgme++ if &file_find_regex([qr/gpgme/],
2994 $MATCH_ALL, $cmd_out_tmp);
2998 ### all three of fwknop/fwknopd/libfko must link against gpgme in order
2999 ### to enable gpg tests
3000 unless ($have_gpgme == 3) {
3001 push @tests_to_exclude, qr/GPG/;
3007 sub time_for_valgrind() {
3009 while (&run_cmd("ps axuww | grep LD_LIBRARY_PATH | " .
3010 "grep valgrind |grep -v perl | grep -v grep",
3011 $cmd_out_tmp, $current_test_file)) {
3019 sub anonymize_results() {
3021 die "[*] $output_dir does not exist" unless -d $output_dir;
3022 die "[*] $logfile does not exist, has $0 been executed?"
3025 unlink $tarfile or die "[*] Could not unlink $tarfile: $!";
3028 ### remove non-loopback IP addresses
3029 my $search_re = qr/\b127\.0\.0\.1\b/;
3030 system "perl -p -i -e 's|$search_re|00MY1271STR00|g' $output_dir/*.test";
3031 $search_re = qr/\b127\.0\.0\.2\b/;
3032 system "perl -p -i -e 's|$search_re|00MY1272STR00|g' $output_dir/*.test";
3033 $search_re = qr/\b0\.0\.0\.0\b/;
3034 system "perl -p -i -e 's|$search_re|00MY0000STR00|g' $output_dir/*.test";
3035 $search_re = qr/\b(?:[0-2]?\d{1,2}\.){3}[0-2]?\d{1,2}\b/;
3036 system "perl -p -i -e 's|$search_re|N.N.N.N|g' $output_dir/*.test";
3037 system "perl -p -i -e 's|00MY1271STR00|127.0.0.1|g' $output_dir/*.test";
3038 system "perl -p -i -e 's|00MY1272STR00|127.0.0.2|g' $output_dir/*.test";
3039 system "perl -p -i -e 's|00MY0000STR00|0.0.0.0|g' $output_dir/*.test";
3041 ### remove hostname from any uname output
3042 $search_re = qr/\suname\s+\-a\s*\n\s*(\S+)\s+\S+/;
3043 system "perl -p -i -e 'undef \$/; s|$search_re" .
3044 "| uname -a\n\$1 (removed)|s' $output_dir/*.test";
3046 $search_re = qr/uname=\x27(\S+)\s+\S+/;
3047 system "perl -p -i -e 's|$search_re|uname= \$1 (removed)|' $output_dir/*.test";
3050 system "tar cvfz $tarfile $logfile $output_dir";
3051 print "[+] Anonymized test results file: $tarfile\n";
3060 my $test_hr = shift;
3062 open F, "> $default_pid_file" or die $!;
3066 &server_start($test_hr);
3068 open F, "< $default_pid_file" or die $!;
3080 sub start_fwknopd() {
3081 my $test_hr = shift;
3083 &write_test_file("[+] TEST: $test_hr->{'msg'}\n", $server_test_file);
3086 die "[*] Could not fork: $!" unless defined $pid;
3090 ### we are the child, so start fwknopd
3091 exit &run_cmd($test_hr->{'fwknopd_cmdline'},
3092 $server_cmd_tmp, $server_test_file);
3098 my ($key, $file) = @_;
3100 open K, "> $file" or die "[*] Could not open $file: $!";
3101 print K "$loopback_ip: $key\n";
3102 print K "localhost: $key\n";
3103 print K "some.host.through.proxy.com: $key\n";
3109 open C, ">> $current_test_file"
3110 or die "[*] Could not open $current_test_file: $!";
3111 print C "\n" . localtime() . " [+] PID dump:\n";
3113 &run_cmd("ps auxww | grep knop |grep -v grep",
3114 $cmd_out_tmp, $current_test_file);
3119 my ($cmd, $cmd_out, $file) = @_;
3123 or die "[*] Could not open $file: $!";
3124 print F localtime() . " CMD: $cmd\n";
3128 or die "[*] Could not open $file: $!";
3129 print F localtime() . " CMD: $cmd\n";
3133 ### copy original file descriptors (credit: Perl Cookbook)
3134 open OLDOUT, ">&STDOUT";
3135 open OLDERR, ">&STDERR";
3137 ### redirect command output
3138 open STDOUT, "> $cmd_out" or die "[*] Could not redirect stdout: $!";
3139 open STDERR, ">&STDOUT" or die "[*] Could not dup stdout: $!";
3141 my $rv = ((system $cmd) >> 8);
3143 close STDOUT or die "[*] Could not close STDOUT: $!";
3144 close STDERR or die "[*] Could not close STDERR: $!";
3146 ### restore original filehandles
3147 open STDERR, ">&OLDERR" or die "[*] Could not restore stderr: $!";
3148 open STDOUT, ">&OLDOUT" or die "[*] Could not restore stdout: $!";
3150 ### close the old copies
3151 close OLDOUT or die "[*] Could not close OLDOUT: $!";
3152 close OLDERR or die "[*] Could not close OLDERR: $!";
3154 open C, "< $cmd_out" or die "[*] Could not open $cmd_out: $!";
3155 my @cmd_lines = <C>;
3158 open F, ">> $file" or die "[*] Could not open $file: $!";
3159 print F $_ for @cmd_lines;
3172 for (my $i=length($msg); $i < $PRINT_LEN; $i++) {
3181 $|++; ### turn off buffering
3183 $< == 0 && $> == 0 or
3184 die "[*] $0: You must be root (or equivalent ",
3185 "UID 0 account) to effectively test fwknop";
3187 ### validate test hashes
3189 for my $test_hr (@tests) {
3190 for my $key (keys %test_keys) {
3191 if ($test_keys{$key} == $REQUIRED) {
3192 die "[*] Missing '$key' element in hash: $hash_num"
3193 unless defined $test_hr->{$key};
3195 $test_hr->{$key} = '' unless defined $test_hr->{$key};
3201 if ($use_valgrind) {
3202 die "[*] $valgrindCmd exec problem, use --valgrind-path"
3203 unless -e $valgrindCmd and -x $valgrindCmd;
3206 die "[*] $conf_dir directory does not exist." unless -d $conf_dir;
3207 die "[*] $lib_dir directory does not exist." unless -d $lib_dir;
3209 for my $name (keys %cf) {
3210 die "[*] $cf{$name} does not exist" unless -e $cf{$name};
3211 chmod 0600, $cf{$name} or die "[*] Could not chmod 0600 $cf{$name}";
3214 if (-d $output_dir) {
3215 if (-d "${output_dir}.last") {
3216 rmtree "${output_dir}.last"
3217 or die "[*] rmtree ${output_dir}.last $!";
3219 mkdir "${output_dir}.last"
3220 or die "[*] ${output_dir}.last: $!";
3221 for my $file (glob("$output_dir/*.test")) {
3222 if ($file =~ m|.*/(.*)|) {
3223 copy $file, "${output_dir}.last/$1" or die $!;
3226 if (-e "$output_dir/init") {
3227 copy "$output_dir/init", "${output_dir}.last/init";
3230 copy $logfile, "${output_dir}.last/$logfile" or die $!;
3232 $saved_last_results = 1;
3234 mkdir $output_dir or die "[*] Could not mkdir $output_dir: $!";
3238 rmtree $run_dir or die $!;
3240 mkdir $run_dir or die "[*] Could not mkdir $run_dir: $!";
3242 for my $file (glob("$output_dir/*.test")) {
3243 unlink $file or die "[*] Could not unlink($file)";
3245 if (-e "$output_dir/init") {
3246 unlink "$output_dir/init" or die $!;
3250 unlink $logfile or die $!;
3253 if ($test_include) {
3254 for my $re (split /\s*,\s*/, $test_include) {
3255 push @tests_to_include, qr/$re/;
3258 if ($test_exclude) {
3259 for my $re (split /\s*,\s*/, $test_exclude) {
3260 push @tests_to_exclude, qr/$re/;
3264 ### make sure no fwknopd instance is currently running
3265 die "[*] Please stop the running fwknopd instance."
3266 if &is_fwknopd_running();
3268 unless ($enable_recompilation_warnings_check) {
3269 push @tests_to_exclude, qr/recompilation/;
3272 unless ($enable_make_distcheck) {
3273 push @tests_to_exclude, qr/distcheck/;
3276 unless ($enable_client_ip_resolve_test) {
3277 push @tests_to_exclude, qr/IP resolve/;
3280 $sudo_path = &find_command('sudo');
3282 unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
3283 ### disable compilation checks
3284 push @tests_to_exclude, qr/recompilation/;
3287 open UNAME, "uname |" or die "[*] Could not execute uname: $!";
3292 } elsif (/freebsd/i) {
3293 $platform = $FREEBSD;
3299 unless ($platform eq $LINUX) {
3300 push @tests_to_exclude, qr/NAT/;
3302 unless ($platform eq $FREEBSD or $platform eq $MACOSX) {
3303 push @tests_to_exclude, qr|active/expire sets|;
3306 if (-e $default_digest_file) {
3307 unlink $default_digest_file;
3313 sub identify_loopback_intf() {
3314 return if $loopback_intf;
3318 ### lo Link encap:Local Loopback
3319 ### inet addr:127.0.0.1 Mask:255.0.0.0
3320 ### inet6 addr: ::1/128 Scope:Host
3321 ### UP LOOPBACK RUNNING MTU:16436 Metric:1
3322 ### RX packets:534709 errors:0 dropped:0 overruns:0 frame:0
3323 ### TX packets:534709 errors:0 dropped:0 overruns:0 carrier:0
3324 ### collisions:0 txqueuelen:0
3325 ### RX bytes:101110617 (101.1 MB) TX bytes:101110617 (101.1 MB)
3329 ### lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
3330 ### options=3<RXCSUM,TXCSUM>
3331 ### inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
3332 ### inet6 ::1 prefixlen 128
3333 ### inet 127.0.0.1 netmask 0xff000000
3334 ### nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
3337 my $found_loopback_intf = 0;
3339 my $cmd = 'ifconfig -a';
3340 open C, "$cmd |" or die "[*] (use --loopback <name>) $cmd: $!";
3342 if (/^(\S+?):?\s+.*loopback/i) {
3346 if (/^\S/ and $intf and not $found_loopback_intf) {
3347 ### should not happen
3350 if ($intf and /\b127\.0\.0\.1\b/) {
3351 $found_loopback_intf = 1;
3357 die "[*] could not determine loopback interface, use --loopback <name>"
3358 unless $found_loopback_intf;
3360 $loopback_intf = $intf;
3365 sub parse_valgrind_flagged_functions() {
3366 for my $file (glob("$output_dir/*.test")) {
3367 my $type = 'server';
3368 $type = 'client' if $file =~ /\d\.test/;
3369 open F, "< $file" or die $!;
3371 ### ==30969== by 0x4E3983A: fko_set_username (fko_user.c:65)
3372 if (/^==.*\sby\s\S+\:\s(\S+)\s(.*)/) {
3373 $valgrind_flagged_fcns{$type}{"$1 $2"}++;
3374 $valgrind_flagged_fcns_unique{$type}{$1}++;
3380 open F, ">> $current_test_file" or die $!;
3381 for my $type ('client', 'server') {
3382 print F "\n[+] fwknop $type functions (unique view):\n";
3383 next unless defined $valgrind_flagged_fcns_unique{$type};
3384 for my $fcn (sort {$valgrind_flagged_fcns_unique{$type}{$b}
3385 <=> $valgrind_flagged_fcns_unique{$type}{$a}}
3386 keys %{$valgrind_flagged_fcns_unique{$type}}) {
3387 printf F " %5d : %s\n", $valgrind_flagged_fcns_unique{$type}{$fcn}, $fcn;
3389 print F "\n[+] fwknop $type functions (with call line numbers):\n";
3390 for my $fcn (sort {$valgrind_flagged_fcns{$type}{$b}
3391 <=> $valgrind_flagged_fcns{$type}{$a}} keys %{$valgrind_flagged_fcns{$type}}) {
3392 printf F " %5d : %s\n", $valgrind_flagged_fcns{$type}{$fcn}, $fcn;
3394 next unless defined $valgrind_flagged_fcns{$type};
3401 sub is_fw_rule_active() {
3402 my $test_hr = shift;
3404 my $conf_args = $default_server_conf_args;
3406 if ($test_hr->{'server_conf'}) {
3407 $conf_args = "-c $test_hr->{'server_conf'} -a $cf{'def_access'} " .
3408 "-d $default_digest_file -p $default_pid_file";
3411 if ($test_hr->{'no_ip_check'}) {
3412 return 1 if &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd " .
3413 qq{$conf_args --fw-list | grep -v "# DISABLED" |grep _exp_},
3414 $cmd_out_tmp, $current_test_file);
3416 return 1 if &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd " .
3417 qq{$conf_args --fw-list | grep -v "# DISABLED" |grep $fake_ip |grep _exp_},
3418 $cmd_out_tmp, $current_test_file);
3424 sub is_fwknopd_running() {
3426 sleep 2 if $use_valgrind;
3428 &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd $default_server_conf_args " .
3429 "--status", $cmd_out_tmp, $current_test_file);
3431 return 1 if &file_find_regex([qr/Detected\sfwknopd\sis\srunning/i],
3432 $MATCH_ALL, $cmd_out_tmp);
3437 sub stop_fwknopd() {
3439 &run_cmd("LD_LIBRARY_PATH=$lib_dir $fwknopdCmd " .
3440 "$default_server_conf_args -K", $cmd_out_tmp, $current_test_file);
3442 if ($use_valgrind) {
3443 &time_for_valgrind();
3451 sub file_find_regex() {
3452 my ($re_ar, $match_style, $file) = @_;
3454 my $found_all_regexs = 1;
3455 my $found_single_match = 0;
3456 my @write_lines = ();
3457 my @file_lines = ();
3459 open F, "< $file" or die "[*] Could not open $file: $!";
3461 push @file_lines, $_;
3465 for my $re (@$re_ar) {
3467 for my $line (@file_lines) {
3469 push @write_lines, "[.] file_find_regex() " .
3470 "Matched '$re' with line: $line";
3472 $found_single_match = 1;
3476 push @write_lines, "[.] file_find_regex() " .
3477 "Did not match regex '$re' from regexs: '@$re_ar' " .
3478 "within file: $file\n";
3479 $found_all_regexs = 0;
3483 for my $line (@write_lines) {
3484 &write_test_file($line, $file);
3487 if ($match_style == $MATCH_ANY) {
3488 return $found_single_match;
3491 return $found_all_regexs;
3494 sub find_command() {
3498 open C, "which $cmd |" or die "[*] Could not execute: which $cmd: $!";
3500 if (m|^(/.*$cmd)$|) {
3509 sub write_test_file() {
3510 my ($msg, $file) = @_;
3514 or die "[*] Could not open $file: $!";
3519 or die "[*] Could not open $file: $!";
3529 open F, ">> $logfile" or die $!;
3540 -A --Anonymize-results - Prepare anonymized results at:
3542 --diff - Compare the results of one test run to
3543 another. By default this compares output
3544 in ${output_dir}.last to $output_dir
3545 --diff-dir1=<path> - Left hand side of diff directory path,
3546 default is: ${output_dir}.last
3547 --diff-dir2=<path> - Right hand side of diff directory path,
3548 default is: $output_dir
3549 --include=<regex> - Specify a regex to be used over test
3550 names that must match.
3551 --exclude=<regex> - Specify a regex to be used over test
3552 names that must not match.
3553 --enable-recompile - Recompile fwknop sources and look for
3554 compilation warnings.
3555 --enable-valgrind - Run every test underneath valgrind.
3556 --List - List test names.
3557 --loopback-intf=<intf> - Specify loopback interface name (default
3558 depends on the OS where the test suite
3560 --output-dir=<path> - Path to output directory, default is:
3562 --fwknop-path=<path> - Path to fwknop binary, default is:
3564 --fwknopd-path=<path> - Path to fwknopd binary, default is:
3566 --libfko-path=<path> - Path to libfko, default is:
3568 --valgrind-path=<path> - Path to valgrind, default is:
3570 -h --help - Display usage on STDOUT and exit.