From: Michael Rash Date: Sat, 11 Aug 2012 01:52:09 +0000 (-0400) Subject: [server] Added GPG_ALLOW_NO_PW variable and associated test suite support X-Git-Tag: fwknop-2.0.2-pre2~2 X-Git-Url: http://www.cipherdyne.com/cgi-bin/gitweb.cgi?p=fwknop.git;a=commitdiff_plain;h=27ccfe35d36c7ba1d94734fb21a46c77aaf30719 [server] Added GPG_ALLOW_NO_PW variable and associated test suite support For GPG mode, added a new access.conf variable "GPG_ALLOW_NO_PW" to make it possible to leverage a server-side GPG key pair that has no associated password. This comes in handy when a system requires the user to leverage gpg-agent / pinentry which can present a problem in automated environments as required by the fwknopd server. Now, it might seem like a problem to remove the passphrase from a GPG key pair, but it's important to note that simply doing this is little worse than storing the passphrase in the clear on disk anyway in the access.conf file. Further, this link help provides additional detail: http://www.gnupg.org/faq/GnuPG-FAQ.html#how-can-i-use-gnupg-in-an-automated-environment --- diff --git a/ChangeLog b/ChangeLog index 17c531c..dc0027e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,16 @@ fwknop-2.0.2 (08//2012): + - [server] For GPG mode, added a new access.conf variable + "GPG_ALLOW_NO_PW" to make it possible to leverage a server-side GPG key + pair that has no associated password. This comes in handy when a system + requires the user to leverage gpg-agent / pinentry which can present a + problem in automated environments as required by the fwknopd server. + Now, it might seem like a problem to remove the passphrase from a GPG + key pair, but it's important to note that simply doing this is little + worse than storing the passphrase in the clear on disk anyway in the + access.conf file. Further, this link helps provide additional detail: + + http://www.gnupg.org/faq/GnuPG-FAQ.html#how-can-i-use-gnupg-in-an-automated-environment + - [client] In IP resolution mode (-R) changed HTTP connection type to 'close' since there is no need for connection persistence, and indeed the client expects to just get the IP and the connection to be closed. @@ -7,6 +19,14 @@ fwknop-2.0.2 (08//2012): remote webserver IP resolution mode (-R). Previously IP resolution could fail if HTTP headers were transferred separately from the data (for whatever reason). Jonathan Schulz submitted a patch for this. + - [server] Bug fix to implement FLUSH_IPT_AT_INIT and FLUSH_IPT_AT_EXIT + functionality. These are enabled by default, and now iptables rules + added by fwknopd can be made persistant by setting these variables to + "N" in the fwknopd.conf file (this is not a recommended setting + however). + [server] Added FLUSH_IPFW_AT_INIT and FLUSH_IPFW_AT_EXIT for ipfw + firewalls to emulate the corresponding functionality that is implemented + for iptables firewalls. This was suggested by Jonathan Schulz. - [server] Replay attack bug fix to ensure that an attacker cannot force a replay attack by intercepting an SPA packet and the replaying it with the base64 version of "Salted__" (for Rindael) or the "hQ" prefix (for @@ -36,6 +56,9 @@ fwknop-2.0.2 (08//2012): by 0x10DABF: pcap_capture (pcap_capture.c:226) by 0x10A798: main (fwknopd.c:299) + - [test suite] Added GPG tests for keyrings that have no associated + passphrases. + fwknop-2.0.1 (07/23/2012): - [server] Bug fix where the same encryption key used for two stanzas in the access.conf file would result in access requests that matched the diff --git a/Makefile.am b/Makefile.am index b682fa3..16dfecb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -109,6 +109,15 @@ EXTRA_DIST = \ test/conf/client-gpg/pubring.gpg \ test/conf/client-gpg/secring.gpg \ test/conf/client-gpg/trustdb.gpg \ + test/conf/client-gpg-no-pw/pubring.gpg \ + test/conf/client-gpg-no-pw/secring.gpg \ + test/conf/client-gpg-no-pw/trustdb.gpg \ + test/conf/server-gpg/pubring.gpg \ + test/conf/server-gpg/secring.gpg \ + test/conf/server-gpg/trustdb.gpg \ + test/conf/server-gpg-no-pw/pubring.gpg \ + test/conf/server-gpg-no-pw/secring.gpg \ + test/conf/server-gpg-no-pw/trustdb.gpg \ test/conf/default_access.conf \ test/conf/default_fwknopd.conf \ test/conf/dual_key_usage_access.conf \ @@ -133,9 +142,6 @@ EXTRA_DIST = \ test/conf/override_fwknopd.conf \ test/conf/require_src_access.conf \ test/conf/require_user_access.conf \ - test/conf/server-gpg/pubring.gpg \ - test/conf/server-gpg/secring.gpg \ - test/conf/server-gpg/trustdb.gpg \ test/conf/subnet_source_match_access.conf \ test/conf/local_nat_fwknopd.conf \ test/hardening-check \ diff --git a/server/access.c b/server/access.c index 15057d3..c81fb93 100644 --- a/server/access.c +++ b/server/access.c @@ -46,6 +46,9 @@ static void add_acc_string(char **var, const char *val) { + if(*var != NULL) + free(*var); + if((*var = strdup(val)) == NULL) { log_msg(LOG_ERR, @@ -396,6 +399,9 @@ add_string_list_ent(acc_string_list_t **stlist, const char *str_str) last_stlist->next = new_stlist; } + if(new_stlist->str != NULL) + free(new_stlist->str); + new_stlist->str = strdup(str_str); if(new_stlist->str == NULL) @@ -930,6 +936,13 @@ parse_access_file(fko_srv_options_t *opts) } add_acc_string(&(curr_acc->gpg_decrypt_pw), val); } + else if(CONF_VAR_IS(var, "GPG_ALLOW_NO_PW")) + { + if(curr_acc->gpg_decrypt_pw != NULL && curr_acc->gpg_decrypt_pw[0] != '\0') + free(curr_acc->gpg_decrypt_pw); + + add_acc_string(&(curr_acc->gpg_decrypt_pw), ""); + } else if(CONF_VAR_IS(var, "GPG_REQUIRE_SIG")) { add_acc_bool(&(curr_acc->gpg_require_sig), val); diff --git a/server/incoming_spa.c b/server/incoming_spa.c index 7f27248..2703a77 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -436,7 +436,7 @@ incoming_spa(fko_srv_options_t *opts) else { log_msg(LOG_ERR, - "(stanza #%d) No GPG_DECRYPT_PW for GPG encrypted messages", + "(stanza #%d) No GPG_DECRYPT_PW for GPG encrypted messages, set GPG_ALLOW_NO_PW", stanza_num ); acc = acc->next; diff --git a/test/conf/client-gpg-no-pw/pubring.gpg b/test/conf/client-gpg-no-pw/pubring.gpg new file mode 100644 index 0000000..615e12f Binary files /dev/null and b/test/conf/client-gpg-no-pw/pubring.gpg differ diff --git a/test/conf/client-gpg-no-pw/secring.gpg b/test/conf/client-gpg-no-pw/secring.gpg new file mode 100644 index 0000000..e84fd95 Binary files /dev/null and b/test/conf/client-gpg-no-pw/secring.gpg differ diff --git a/test/conf/client-gpg-no-pw/trustdb.gpg b/test/conf/client-gpg-no-pw/trustdb.gpg new file mode 100644 index 0000000..58ec2d6 Binary files /dev/null and b/test/conf/client-gpg-no-pw/trustdb.gpg differ diff --git a/test/conf/gpg_no_pw_access.conf b/test/conf/gpg_no_pw_access.conf new file mode 100644 index 0000000..2f6e810 --- /dev/null +++ b/test/conf/gpg_no_pw_access.conf @@ -0,0 +1,7 @@ +SOURCE: ANY; +KEY: fwknoptest; +FW_ACCESS_TIMEOUT: 3; +GPG_HOME_DIR: conf/server-gpg-no-pw; +GPG_DECRYPT_ID: 361BBAD4; +GPG_ALLOW_NO_PW: Y; +GPG_REMOTE_ID: 6A3FAD56; diff --git a/test/conf/server-gpg-no-pw/pubring.gpg b/test/conf/server-gpg-no-pw/pubring.gpg new file mode 100644 index 0000000..b0aa06e Binary files /dev/null and b/test/conf/server-gpg-no-pw/pubring.gpg differ diff --git a/test/conf/server-gpg-no-pw/secring.gpg b/test/conf/server-gpg-no-pw/secring.gpg new file mode 100644 index 0000000..c3a465a Binary files /dev/null and b/test/conf/server-gpg-no-pw/secring.gpg differ diff --git a/test/conf/server-gpg-no-pw/trustdb.gpg b/test/conf/server-gpg-no-pw/trustdb.gpg new file mode 100644 index 0000000..d5b5b60 Binary files /dev/null and b/test/conf/server-gpg-no-pw/trustdb.gpg differ diff --git a/test/test-fwknop.pl b/test/test-fwknop.pl index e2e580b..324f8cb 100755 --- a/test/test-fwknop.pl +++ b/test/test-fwknop.pl @@ -18,6 +18,7 @@ my $configure_path = '../configure'; my $cmd_out_tmp = 'cmd.out'; my $server_cmd_tmp = 'server_cmd.out'; my $gpg_client_home_dir = "$conf_dir/client-gpg"; +my $gpg_client_home_dir_no_pw = "$conf_dir/client-gpg-no-pw"; my %cf = ( 'nat' => "$conf_dir/nat_fwknopd.conf", @@ -31,6 +32,7 @@ my %cf = ( 'local_nat' => "$conf_dir/local_nat_fwknopd.conf", 'dual_key_access' => "$conf_dir/dual_key_usage_access.conf", 'gpg_access' => "$conf_dir/gpg_access.conf", + 'gpg_no_pw_access' => "$conf_dir/gpg_no_pw_access.conf", 'open_ports_access' => "$conf_dir/open_ports_access.conf", 'multi_gpg_access' => "$conf_dir/multi_gpg_access.conf", 'multi_stanza_access' => "$conf_dir/multi_stanzas_access.conf", @@ -160,6 +162,10 @@ my $default_client_gpg_args = "$default_client_args " . "--gpg-signer-key $gpg_client_key " . "--gpg-home-dir $gpg_client_home_dir"; +my $default_client_gpg_args_no_homedir = "$default_client_args " . + "--gpg-recipient-key $gpg_server_key " . + "--gpg-signer-key $gpg_client_key "; + my $default_server_conf_args = "-c $cf{'def'} -a $cf{'def_access'} " . "-d $default_digest_file -p $default_pid_file"; @@ -168,6 +174,11 @@ my $default_server_gpg_args = "LD_LIBRARY_PATH=$lib_dir " . "-a $cf{'gpg_access'} $intf_str " . "-d $default_digest_file -p $default_pid_file"; +my $default_server_gpg_args_no_pw = "LD_LIBRARY_PATH=$lib_dir " . + "$valgrind_str $fwknopdCmd -c $cf{'def'} " . + "-a $cf{'gpg_no_pw_access'} $intf_str " . + "-d $default_digest_file -p $default_pid_file"; + ### point the compiled binaries at the local libary path ### instead of any installed libfko instance $ENV{'LD_LIBRARY_PATH'} = $lib_dir; @@ -1184,6 +1195,171 @@ my @tests = ( }, { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'complete cycle (tcp/22 ssh)', + 'err_msg' => 'could not complete SPA cycle', + 'function' => \&spa_cycle, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'multi gpg-IDs (tcp/22 ssh)', + 'err_msg' => 'could not complete SPA cycle', + 'function' => \&spa_cycle, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir " . + "$valgrind_str $fwknopdCmd -c $cf{'def'} " . + "-a $cf{'multi_gpg_access'} $intf_str " . + "-d $default_digest_file -p $default_pid_file", + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'fatal' => $NO + }, + + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'complete cycle (tcp/23 telnet)', + 'err_msg' => 'could not complete SPA cycle', + 'function' => \&spa_cycle, + 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " . + "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --get-key " . + "$local_key_file --verbose --verbose " . + "--gpg-recipient-key $gpg_server_key " . + "--gpg-signer-key $gpg_client_key " . + "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'complete cycle (tcp/9418 git)', + 'err_msg' => 'could not complete SPA cycle', + 'function' => \&spa_cycle, + 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " . + "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --get-key " . + "$local_key_file --verbose --verbose " . + "--gpg-recipient-key $gpg_server_key " . + "--gpg-signer-key $gpg_client_key " . + "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'complete cycle (udp/53 dns)', + 'err_msg' => 'could not complete SPA cycle', + 'function' => \&spa_cycle, + 'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " . + "$fwknopCmd -A udp/53 -a $fake_ip -D $loopback_ip --get-key " . + "$local_key_file --verbose --verbose " . + "--gpg-recipient-key $gpg_server_key " . + "--gpg-signer-key $gpg_client_key " . + "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'fatal' => $NO + }, + + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'replay attack detection', + 'err_msg' => 'could not detect replay attack', + 'function' => \&replay_detection, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'replay_positive_output_matches' => [qr/Replay\sdetected\sfrom\ssource\sIP/], + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'replay detection (GnuPG prefix)', + 'err_msg' => 'could not detect replay attack', + 'function' => \&replay_detection, + 'pkt_prefix' => 'hQ', + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " . + "$fwknopdCmd $default_server_conf_args $intf_str", + 'replay_positive_output_matches' => [qr/Data\sis\snot\sa\svalid\sSPA\smessage\sformat/], + 'fatal' => $NO + }, + + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'non-base64 altered SPA data', + 'err_msg' => 'allowed improper SPA data', + 'function' => \&altered_non_base64_spa_data, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'base64 altered SPA data', + 'err_msg' => 'allowed improper SPA data', + 'function' => \&altered_base64_spa_data, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'appended data to SPA pkt', + 'err_msg' => 'allowed improper SPA data', + 'function' => \&appended_spa_data, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'prepended data to SPA pkt', + 'err_msg' => 'allowed improper SPA data', + 'function' => \&prepended_spa_data, + 'cmdline' => "$default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fatal' => $NO + }, + { + 'category' => 'GPG (no pw) SPA', + 'subcategory' => 'client+server', + 'detail' => 'spoof username (tcp/22 ssh)', + 'err_msg' => 'could not spoof username', + 'function' => \&spoof_username, + 'cmdline' => "SPOOF_USER=$spoof_user $default_client_gpg_args_no_homedir " + . "--gpg-home-dir $gpg_client_home_dir_no_pw", + 'fwknopd_cmdline' => $default_server_gpg_args_no_pw, + 'fatal' => $NO + }, + + { 'category' => 'GnuPG (GPG) SPA', 'subcategory' => 'client+server', 'detail' => 'complete cycle (tcp/22 ssh)',