[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
This commit is contained in:
Michael Rash
2012-08-10 22:20:30 -04:00
parent 0af3bd0ee1
commit 27ccfe35d3
12 changed files with 229 additions and 4 deletions
+23
View File
@@ -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
+9 -3
View File
@@ -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 \
+13
View File
@@ -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);
+1 -1
View File
@@ -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;
Binary file not shown.
Binary file not shown.
Binary file not shown.
+7
View File
@@ -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;
Binary file not shown.
Binary file not shown.
Binary file not shown.
+176
View File
@@ -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;
@@ -1183,6 +1194,171 @@ my @tests = (
'fatal' => $NO
},
{
'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',