From 89b2e8f477245bf6fdf1d2746c829f9ba26faf15 Mon Sep 17 00:00:00 2001 From: Michael Rash Date: Sat, 18 Jul 2015 13:11:25 -0700 Subject: [PATCH] [server] interface goes down will cause fwknopd to exit By default, fwknopd will now exit if the interface that it is sniffing goes down (patch contributed by Github user 'sgh7'). If this happens, it is expected that the native process monitoring feature in things like systemd or upstart will restart fwknopd. However, if fwknopd is not being monitored by systemd, upstart, or anything else, this behavior can be disabled with the EXIT_AT_INTF_DOWN variable in the fwknopd.conf file. If disabled, fwknopd will try to recover when a downed interface comes back up. --- CREDITS | 6 ++++ ChangeLog | 8 +++++ Makefile.am | 1 + doc/fwknopd.man.asciidoc | 9 +++++ server/cmd_opts.h | 1 + server/config_init.c | 7 ++++ server/fwknopd_common.h | 2 ++ server/pcap_capture.c | 3 +- test/conf/no_exit_down_intf_fwknopd.conf | 1 + test/test-fwknop.pl | 46 ++++++++++++++++++++---- test/tests/basic_operations.pl | 20 +++++++++++ 11 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 test/conf/no_exit_down_intf_fwknopd.conf diff --git a/CREDITS b/CREDITS index 5dc3fa2b..b9ebecd6 100644 --- a/CREDITS +++ b/CREDITS @@ -224,3 +224,9 @@ Dan Brooks - Contributed a patch for the Android client app to add the definition of custom server udp port. This is similiar to the --server-port argument offered by the main fwknop client. + +Github user 'sgh7': + - Contributed a patch to have fwknopd exit if the interface it is sniffing + on goes down. If this happens, it is expected that the native process + monitoring feature in things like systemd or upstart will restart + fwknopd. diff --git a/ChangeLog b/ChangeLog index 141b9d15..360dfce8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,14 @@ fwknop-2.6.7 (05//2015): Jonathan Bennett, and will help with ease of use efforts. The first platform to take advantage of this will likely be OpenWRT thanks to Jonathan. + - [server] By default, fwknopd will now exit if the interface that it is + sniffing goes down (patch contributed by Github user 'sgh7'). If this + happens, it is expected that the native process monitoring feature in + things like systemd or upstart will restart fwknopd. However, if fwknopd + is not being monitored by systemd, upstart, or anything else, this + behavior can be disabled with the EXIT_AT_INTF_DOWN variable in the + fwknopd.conf file. If disabled, fwknopd will try to recover when a + downed interface comes back up. - [extras] Added a script from Jonathan Bennett at extras/console-qr/console-qr.sh to generate QR codes from fwknopd access.conf keys. diff --git a/Makefile.am b/Makefile.am index 9b3781cd..306e3b09 100644 --- a/Makefile.am +++ b/Makefile.am @@ -151,6 +151,7 @@ EXTRA_DIST = \ test/conf/expired_epoch_stanza_access.conf \ test/conf/expired_stanza_access.conf \ test/conf/force_nat_access.conf \ + test/conf/no_exit_down_intf_fwknopd.conf \ test/conf/future_expired_stanza_access.conf \ test/conf/fuzzing_open_ports_access.conf \ test/conf/fuzzing_restrict_ports_access.conf \ diff --git a/doc/fwknopd.man.asciidoc b/doc/fwknopd.man.asciidoc index b56f9085..faa7d459 100644 --- a/doc/fwknopd.man.asciidoc +++ b/doc/fwknopd.man.asciidoc @@ -335,6 +335,15 @@ corresponding details. Flush all existing rules in the fwknop chains when *fwknopd* is stopped or otherwise exits cleanly. The default is ``Y''. +*EXIT_AT_INTF_DOWN* '':: + When *fwknopd* is sniffing an interface, if the interface is + administratively downed or unplugged, fwknopd will cleanly exit and an + assumption is made that any process monitoring infrastructure like systemd + or upstart will restart it. However, if fwknopd is not being monitored by + systemd, upstart, or anything else, this behavior can be disabled with the + ``EXIT_AT_INTF_DOWN'' variable. If disabled, fwknopd will try to recover + when a downed interface comes back up. + *GPG_HOME_DIR* '':: If GPG keys are used instead of a Rijndael symmetric key, this is the default GPG keys directory. Note that each access stanza in diff --git a/server/cmd_opts.h b/server/cmd_opts.h index 561a0198..cd39a7c1 100644 --- a/server/cmd_opts.h +++ b/server/cmd_opts.h @@ -48,6 +48,7 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = { "PCAP_DISPATCH_COUNT", "PCAP_LOOP_SLEEP", "ENABLE_PCAP_ANY_DIRECTION", + "EXIT_AT_INTF_DOWN", "MAX_SNIFF_BYTES", "ENABLE_SPA_PACKET_AGING", "MAX_SPA_PACKET_AGE", diff --git a/server/config_init.c b/server/config_init.c index a1312549..d1456820 100644 --- a/server/config_init.c +++ b/server/config_init.c @@ -459,6 +459,13 @@ validate_options(fko_srv_options_t *opts) set_config_entry(opts, CONF_PCAP_LOOP_SLEEP, DEF_PCAP_LOOP_SLEEP); + /* Control whether to exit if the interface where we're sniffing + * goes down. + */ + if(opts->config[CONF_EXIT_AT_INTF_DOWN] == NULL) + set_config_entry(opts, CONF_EXIT_AT_INTF_DOWN, + DEF_EXIT_AT_INTF_DOWN); + /* PCAP Filter. */ if(opts->config[CONF_PCAP_FILTER] == NULL) diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index 505b341c..2fdc2ae2 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -88,6 +88,7 @@ #define DEF_PCAP_DISPATCH_COUNT "100" #define DEF_PCAP_LOOP_SLEEP "100000" /* a tenth of a second (in microseconds) */ #define DEF_ENABLE_PCAP_ANY_DIRECTION "N" +#define DEF_EXIT_AT_INTF_DOWN "Y" #define DEF_ENABLE_SPA_PACKET_AGING "Y" #define DEF_MAX_SPA_PACKET_AGE "120" #define DEF_ENABLE_DIGEST_PERSISTENCE "Y" @@ -233,6 +234,7 @@ enum { CONF_PCAP_DISPATCH_COUNT, CONF_PCAP_LOOP_SLEEP, CONF_ENABLE_PCAP_ANY_DIRECTION, + CONF_EXIT_AT_INTF_DOWN, CONF_MAX_SNIFF_BYTES, CONF_ENABLE_SPA_PACKET_AGING, CONF_MAX_SPA_PACKET_AGE, diff --git a/server/pcap_capture.c b/server/pcap_capture.c index aff9d314..38d91e3d 100644 --- a/server/pcap_capture.c +++ b/server/pcap_capture.c @@ -299,7 +299,8 @@ pcap_capture(fko_srv_options_t *opts) */ else if(res == -1) { - if(errno == ENETDOWN) + if((strncasecmp(opts->config[CONF_EXIT_AT_INTF_DOWN], "Y", 1) == 0) + && errno == ENETDOWN) { log_msg(LOG_ERR, "[*] Fatal error from pcap_dispatch: %s", pcap_geterr(pcap) diff --git a/test/conf/no_exit_down_intf_fwknopd.conf b/test/conf/no_exit_down_intf_fwknopd.conf new file mode 100644 index 00000000..cac6a28d --- /dev/null +++ b/test/conf/no_exit_down_intf_fwknopd.conf @@ -0,0 +1 @@ +EXIT_AT_INTF_DOWN N; diff --git a/test/test-fwknop.pl b/test/test-fwknop.pl index 3e53e3b0..323d0286 100755 --- a/test/test-fwknop.pl +++ b/test/test-fwknop.pl @@ -276,6 +276,7 @@ our $openssl_path = ''; our $base64_path = ''; our $pinentry_fail = 0; our $perl_path = ''; +our $ifconfig_path = ''; our $platform = ''; our $help = 0; our $YES = 1; @@ -463,6 +464,7 @@ our %cf = ( 'dual_key_access' => "$conf_dir/dual_key_usage_access.conf", 'dual_key_legacy_iv_access' => "$conf_dir/dual_key_legacy_iv_access.conf", 'hmac_dual_key_access' => "$conf_dir/hmac_dual_key_usage_access.conf", + 'no_exit_down_intf' => "$conf_dir/no_exit_down_intf_fwknopd.conf", 'gpg_access' => "$conf_dir/gpg_access.conf", 'gpg_hmac_access' => "$conf_dir/gpg_hmac_access.conf", 'gpg_invalid_exe_access' => "$conf_dir/gpg_invalid_exe_access.conf", @@ -603,6 +605,7 @@ exit &diff_test_results() if $diff_mode; ### run an fwknop command under gdb from a previous test run exit &gdb_test_cmd() if $gdb_test_file; +$ifconfig_path = &find_command('ifconfig') unless $ifconfig_path; &identify_loopback_intf() unless $list_mode or $client_only_mode; ### make sure everything looks as expected before continuing @@ -901,6 +904,7 @@ my %test_keys = ( 'cmd_exec_file_owner' => $OPTIONAL, 'rm_rule_mid_cycle' => $OPTIONAL, 'server_receive_re' => $OPTIONAL, + 'no_exit_intf_down' => $OPTIONAL, 'positive_output_matches' => $OPTIONAL, 'negative_output_matches' => $OPTIONAL, 'client_and_server_mode' => $OPTIONAL_NUMERIC, @@ -5438,6 +5442,27 @@ sub server_ignore_small_packets() { return $rv; } +sub down_interface() { + my $test_hr = shift; + + my $rv = 1; + + &start_fwknopd($test_hr); + + &run_cmd("$ifconfig_path lo down", $cmd_out_tmp, $curr_test_file); + sleep 1; + &run_cmd("$ifconfig_path lo up", $cmd_out_tmp, $curr_test_file); + + if (&is_fwknopd_running()) { + $rv = 0 unless $test_hr->{'no_exit_intf_down'} eq $YES; + &stop_fwknopd(); + } + + $rv = 0 unless &process_output_matches($test_hr); + + return $rv; +} + sub client_server_interaction() { my ($test_hr, $pkts_hr, $spa_client_flag) = @_; @@ -6911,12 +6936,12 @@ sub init() { push @tests_to_exclude, qr/perl FKO module.*FUZZING/; } - $sudo_path = &find_command('sudo') unless $sudo_path; - $killall_path = &find_command('killall') unless $killall_path; - $pgrep_path = &find_command('pgrep') unless $pgrep_path; - $lib_view_cmd = &find_command('ldd') unless $lib_view_cmd; - $git_path = &find_command('git') unless $git_path; - $perl_path = &find_command('perl') unless $perl_path; + $sudo_path = &find_command('sudo') unless $sudo_path; + $killall_path = &find_command('killall') unless $killall_path; + $pgrep_path = &find_command('pgrep') unless $pgrep_path; + $lib_view_cmd = &find_command('ldd') unless $lib_view_cmd; + $git_path = &find_command('git') unless $git_path; + $perl_path = &find_command('perl') unless $perl_path; if ($sudo_path) { $username = (getpwuid((stat($test_suite_path))[4]))[0]; @@ -6949,6 +6974,10 @@ sub init() { $lcov_path = &find_command('lcov') unless $lcov_path; $genhtml_path = &find_command('genhtml') unless $genhtml_path; + unless ($ifconfig_path) { + push @tests_to_exclude, qr/down interface/; + } + ### see if we're compiled with ASAN support if (&file_find_regex([qr/enable\-asan\-support/], $MATCH_ALL, $NO_APPEND_RESULTS, $config_log)) { @@ -7154,6 +7183,9 @@ sub openssl_hmac_style_check() { sub identify_loopback_intf() { return if $loopback_intf; + die "[*] ifconfig command not found, use --loopback " + unless $ifconfig_path; + ### Linux: ### lo Link encap:Local Loopback @@ -7177,7 +7209,7 @@ sub identify_loopback_intf() { my $intf = ''; my $found_loopback_intf = 0; - my $cmd = 'ifconfig -a'; + my $cmd = "$ifconfig_path -a"; open C, "$cmd |" or die "[*] (use --loopback ) $cmd: $!"; while () { if (/^(\S+?):?\s+.*loopback/i) { diff --git a/test/tests/basic_operations.pl b/test/tests/basic_operations.pl index a2246581..0a1f8415 100644 --- a/test/tests/basic_operations.pl +++ b/test/tests/basic_operations.pl @@ -62,6 +62,26 @@ 'detail' => 'start restart stop cycle', 'function' => \&server_start_stop_cycle, }, + { + 'category' => 'basic operations', + 'subcategory' => 'server', + 'detail' => 'exit upon down interface', + 'function' => \&down_interface, + 'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " . + "-d $default_digest_file -p $default_pid_file $intf_str", + 'server_positive_output_matches' => [qr/Fatal error from pcap_dispatch\b/], + }, + { + 'category' => 'basic operations', + 'subcategory' => 'server', + 'detail' => 'no exit upon down interface', + 'function' => \&down_interface, + 'fwknopd_cmdline' => "$fwknopdCmd -c $cf{'no_exit_down_intf'} " . + "-a $cf{'hmac_access'} -d $default_digest_file -p " . + "$default_pid_file $intf_str", + 'server_positive_output_matches' => [qr/Error from pcap_dispatch\b/], + 'no_exit_intf_down' => $YES + }, { 'category' => 'basic operations',