[client+server] verify GnuPG signatures by default

- [server] When GnuPG is used, the default now is to require that
incoming SPA packets are signed by a key listed in GPG_REMOTE_ID for each
access.conf stanza. In other words, the usage of GPG_REQUIRE_SIG
is no longer necessary in order to authenticate SPA packets via the
GnuPG signature. Verification of GnuPG signatures can be disabled with a
new access.conf variable GPG_DISABLE_SIG, but this is NOT a
recommended configuration.
- [client+server] Add --gpg-exe command line argument and GPG_EXE
config variable to ~/.fwknoprc and the access.conf file so that the path
to GnuPG can be changed from the default /usr/bin/gpg path.
This commit is contained in:
Michael Rash 2014-03-19 23:12:01 -04:00
parent a52aa8d54a
commit 73bc473563
19 changed files with 267 additions and 15 deletions

View File

@ -3,6 +3,16 @@ fwknop-2.6.1 (//2014):
header which references both the AUTHORS and CREDITS files. The header which references both the AUTHORS and CREDITS files. The
specific language in this header was created by the Debian legal team at specific language in this header was created by the Debian legal team at
the request of Franck Joncourt. the request of Franck Joncourt.
- [server] When GnuPG is used, the default now is to require that incoming
SPA packets are signed by a key listed in GPG_REMOTE_ID for each
access.conf stanza. In other words, the usage of GPG_REQUIRE_SIG is no
longer necessary in order to authenticate SPA packets via the GnuPG
signature. Verification of GnuPG signatures can be disabled with a new
access.conf variable GPG_DISABLE_SIG, but this is NOT a recommended
configuration.
- [client+server] Add --gpg-exe command line argument and GPG_EXE config
variable to ~/.fwknoprc and the access.conf file so that the path to
GnuPG can be changed from the default /usr/bin/gpg path.
- [libfko] Allow usernames that are compatible with Microsoft guidelines as - [libfko] Allow usernames that are compatible with Microsoft guidelines as
defined here: http://technet.microsoft.com/en-us/library/bb726984.aspx defined here: http://technet.microsoft.com/en-us/library/bb726984.aspx
This allows for greater compatibility between fwknop clients on Windows This allows for greater compatibility between fwknop clients on Windows

View File

@ -141,6 +141,7 @@ EXTRA_DIST = \
test/conf/portrange_fwknopd.conf \ test/conf/portrange_fwknopd.conf \
test/conf/custom_input_chain_fwknopd.conf \ test/conf/custom_input_chain_fwknopd.conf \
test/conf/custom_nat_chain_fwknopd.conf \ test/conf/custom_nat_chain_fwknopd.conf \
test/conf/gpg_invalid_exe_access.conf \
test/conf/disable_aging_fwknopd.conf \ test/conf/disable_aging_fwknopd.conf \
test/conf/disable_aging_nat_fwknopd.conf \ test/conf/disable_aging_nat_fwknopd.conf \
test/conf/dual_key_usage_access.conf \ test/conf/dual_key_usage_access.conf \
@ -157,6 +158,7 @@ EXTRA_DIST = \
test/conf/gpg_hmac_access.conf \ test/conf/gpg_hmac_access.conf \
test/conf/gpg_no_pw_access.conf \ test/conf/gpg_no_pw_access.conf \
test/conf/gpg_no_pw_hmac_access.conf \ test/conf/gpg_no_pw_hmac_access.conf \
test/conf/fwknoprc_gpg_invalid_exe \
test/conf/fwknoprc_gpg_hmac_sha512_key \ test/conf/fwknoprc_gpg_hmac_sha512_key \
test/conf/gpg_hmac_sha512_access.conf \ test/conf/gpg_hmac_sha512_access.conf \
test/conf/fwknoprc_hmac_sha512_base64_key \ test/conf/fwknoprc_hmac_sha512_base64_key \

View File

@ -66,6 +66,7 @@ enum {
GPG_RECIP_KEY, GPG_RECIP_KEY,
GPG_SIGNER_KEY, GPG_SIGNER_KEY,
GPG_HOME_DIR, GPG_HOME_DIR,
GPG_EXE_PATH,
GPG_AGENT, GPG_AGENT,
GPG_ALLOW_NO_SIGNING_PW, GPG_ALLOW_NO_SIGNING_PW,
NOOP /* Just to be a marker for the end */ NOOP /* Just to be a marker for the end */
@ -99,6 +100,7 @@ static struct option cmd_opts[] =
{"gpg-recipient-key", 1, NULL, GPG_RECIP_KEY }, {"gpg-recipient-key", 1, NULL, GPG_RECIP_KEY },
{"gpg-signer-key", 1, NULL, GPG_SIGNER_KEY }, {"gpg-signer-key", 1, NULL, GPG_SIGNER_KEY },
{"gpg-home-dir", 1, NULL, GPG_HOME_DIR }, {"gpg-home-dir", 1, NULL, GPG_HOME_DIR },
{"gpg-exe", 1, NULL, GPG_EXE_PATH },
{"gpg-agent", 0, NULL, GPG_AGENT }, {"gpg-agent", 0, NULL, GPG_AGENT },
{"gpg-no-signing-pw", 0, NULL, GPG_ALLOW_NO_SIGNING_PW }, {"gpg-no-signing-pw", 0, NULL, GPG_ALLOW_NO_SIGNING_PW },
{"get-key", 1, NULL, 'G'}, {"get-key", 1, NULL, 'G'},

View File

@ -99,6 +99,7 @@ enum
FWKNOP_CLI_ARG_GPG_RECIPIENT, FWKNOP_CLI_ARG_GPG_RECIPIENT,
FWKNOP_CLI_ARG_GPG_SIGNER, FWKNOP_CLI_ARG_GPG_SIGNER,
FWKNOP_CLI_ARG_GPG_HOMEDIR, FWKNOP_CLI_ARG_GPG_HOMEDIR,
FWKNOP_CLI_ARG_GPG_EXE_PATH,
FWKNOP_CLI_ARG_SPOOF_USER, FWKNOP_CLI_ARG_SPOOF_USER,
FWKNOP_CLI_ARG_SPOOF_SOURCE_IP, FWKNOP_CLI_ARG_SPOOF_SOURCE_IP,
FWKNOP_CLI_ARG_ACCESS, FWKNOP_CLI_ARG_ACCESS,
@ -140,6 +141,7 @@ static fko_var_t fko_var_array[FWKNOP_CLI_LAST_ARG] =
{ "GPG_RECIPIENT", FWKNOP_CLI_ARG_GPG_RECIPIENT }, { "GPG_RECIPIENT", FWKNOP_CLI_ARG_GPG_RECIPIENT },
{ "GPG_SIGNER", FWKNOP_CLI_ARG_GPG_SIGNER }, { "GPG_SIGNER", FWKNOP_CLI_ARG_GPG_SIGNER },
{ "GPG_HOMEDIR", FWKNOP_CLI_ARG_GPG_HOMEDIR }, { "GPG_HOMEDIR", FWKNOP_CLI_ARG_GPG_HOMEDIR },
{ "GPG_EXE", FWKNOP_CLI_ARG_GPG_EXE_PATH },
{ "GPG_SIGNING_PW", FWKNOP_CLI_ARG_GPG_SIGNING_PW }, { "GPG_SIGNING_PW", FWKNOP_CLI_ARG_GPG_SIGNING_PW },
{ "GPG_SIGNING_PW_BASE64", FWKNOP_CLI_ARG_GPG_SIGNING_PW_BASE64 }, { "GPG_SIGNING_PW_BASE64", FWKNOP_CLI_ARG_GPG_SIGNING_PW_BASE64 },
{ "GPG_NO_SIGNING_PW", FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW }, { "GPG_NO_SIGNING_PW", FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW },
@ -198,7 +200,7 @@ generate_keys(fko_cli_options_t *options)
memset(&(options->key_base64), 0x00, sizeof(options->key_base64)); memset(&(options->key_base64), 0x00, sizeof(options->key_base64));
memset(&(options->hmac_key_base64), 0x00, sizeof(options->hmac_key_base64)); memset(&(options->hmac_key_base64), 0x00, sizeof(options->hmac_key_base64));
/* Generate the key with through libfko */ /* Generate the key through libfko */
res = fko_key_gen(options->key_base64, options->key_len, res = fko_key_gen(options->key_base64, options->key_len,
options->hmac_key_base64, options->hmac_key_len, options->hmac_key_base64, options->hmac_key_len,
options->hmac_type); options->hmac_type);
@ -849,6 +851,7 @@ create_fwknoprc(const char *rcfile)
"#TIME_OFFSET 0\n" "#TIME_OFFSET 0\n"
"#USE_GPG N\n" "#USE_GPG N\n"
"#GPG_HOMEDIR /path/to/.gnupg\n" "#GPG_HOMEDIR /path/to/.gnupg\n"
"#GPG_EXE /path/to/gpg\n"
"#GPG_SIGNER <signer ID>\n" "#GPG_SIGNER <signer ID>\n"
"#GPG_RECIPIENT <recipient ID>\n" "#GPG_RECIPIENT <recipient ID>\n"
"\n" "\n"
@ -1016,6 +1019,11 @@ parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val)
{ {
strlcpy(options->gpg_home_dir, val, sizeof(options->gpg_home_dir)); strlcpy(options->gpg_home_dir, val, sizeof(options->gpg_home_dir));
} }
/* GPG path */
else if (var->pos == FWKNOP_CLI_ARG_GPG_EXE_PATH)
{
strlcpy(options->gpg_exe, val, sizeof(options->gpg_exe));
}
/* Spoof User */ /* Spoof User */
else if (var->pos == FWKNOP_CLI_ARG_SPOOF_USER) else if (var->pos == FWKNOP_CLI_ARG_SPOOF_USER)
{ {
@ -1286,6 +1294,9 @@ add_single_var_to_rc(FILE* fhandle, short var_pos, fko_cli_options_t *options)
case FWKNOP_CLI_ARG_GPG_HOMEDIR : case FWKNOP_CLI_ARG_GPG_HOMEDIR :
strlcpy(val, options->gpg_home_dir, sizeof(val)); strlcpy(val, options->gpg_home_dir, sizeof(val));
break; break;
case FWKNOP_CLI_ARG_GPG_EXE_PATH :
strlcpy(val, options->gpg_exe, sizeof(val));
break;
case FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW : case FWKNOP_CLI_ARG_GPG_NO_SIGNING_PW :
bool_to_yesno(options->gpg_no_signing_pw, val, sizeof(val)); bool_to_yesno(options->gpg_no_signing_pw, val, sizeof(val));
break; break;
@ -2191,6 +2202,12 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask); add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_HOMEDIR, &var_bitmask); add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_HOMEDIR, &var_bitmask);
break; break;
case GPG_EXE_PATH:
options->use_gpg = 1;
strlcpy(options->gpg_exe, optarg, sizeof(options->gpg_exe));
add_var_to_bitmask(FWKNOP_CLI_ARG_USE_GPG, &var_bitmask);
add_var_to_bitmask(FWKNOP_CLI_ARG_GPG_EXE_PATH, &var_bitmask);
break;
case GPG_AGENT: case GPG_AGENT:
options->use_gpg = 1; options->use_gpg = 1;
options->use_gpg_agent = 1; options->use_gpg_agent = 1;
@ -2388,6 +2405,7 @@ usage(void)
" --gpg-signer-key Specify the signer's GPG key name or ID.\n" " --gpg-signer-key Specify the signer's GPG key name or ID.\n"
" --gpg-home-dir Specify the GPG home directory.\n" " --gpg-home-dir Specify the GPG home directory.\n"
" --gpg-agent Use GPG agent if available.\n" " --gpg-agent Use GPG agent if available.\n"
" --gpg-exe Set path to GPG binary.\n"
" --no-save-args Do not save fwknop command line args to the\n" " --no-save-args Do not save fwknop command line args to the\n"
" $HOME/fwknop.run file\n" " $HOME/fwknop.run file\n"
" --rc-file Specify path to the fwknop rc file (default\n" " --rc-file Specify path to the fwknop rc file (default\n"

View File

@ -329,6 +329,19 @@ main(int argc, char **argv)
hmac_key, &hmac_key_len, EXIT_FAILURE); hmac_key, &hmac_key_len, EXIT_FAILURE);
} }
/* Set gpg path if necessary
*/
if(strlen(options.gpg_exe) > 0)
{
res = fko_set_gpg_exe(ctx, options.gpg_exe);
if(res != FKO_SUCCESS)
{
errmsg("fko_set_gpg_exe", res);
clean_exit(ctx, &options, key, &key_len,
hmac_key, &hmac_key_len, EXIT_FAILURE);
}
}
/* If a GPG home dir was specified, set it here. Note: Setting /* If a GPG home dir was specified, set it here. Note: Setting
* this has to occur before calling any of the other GPG-related * this has to occur before calling any of the other GPG-related
* functions. * functions.

View File

@ -101,6 +101,7 @@ typedef struct fko_cli_options
char gpg_recipient_key[MAX_GPG_KEY_ID]; char gpg_recipient_key[MAX_GPG_KEY_ID];
char gpg_signer_key[MAX_GPG_KEY_ID]; char gpg_signer_key[MAX_GPG_KEY_ID];
char gpg_home_dir[MAX_PATH_LEN]; char gpg_home_dir[MAX_PATH_LEN];
char gpg_exe[MAX_PATH_LEN];
/* Encryption keys read from a .fwknoprc stanza /* Encryption keys read from a .fwknoprc stanza
*/ */

View File

@ -692,6 +692,9 @@ description and its matching command-line option(s):
*GPG_HOMEDIR* '<dir>':: *GPG_HOMEDIR* '<dir>'::
Specify the GPG home directory ('--gpg-home-dir'). Defaults to '~/.gnupg'. Specify the GPG home directory ('--gpg-home-dir'). Defaults to '~/.gnupg'.
*GPG_EXE* '<path>'::
Specify the path to GPG ('--gpg-exe'). Defaults to '/usr/bin/gpg'.
*SPOOF_USER* '<user>':: *SPOOF_USER* '<user>'::
Set the username in the SPA data to the specified value ('-U, Set the username in the SPA data to the specified value ('-U,
--spoof-user'). --spoof-user').

View File

@ -267,12 +267,15 @@ See the '@sysconfdir@/fwknop/fwknopd.conf'' file for the full list and correspon
*GPG_HOME_DIR* '<path>':: *GPG_HOME_DIR* '<path>'::
If GPG keys are used instead of a Rijndael symmetric key, this is If GPG keys are used instead of a Rijndael symmetric key, this is
the default GPG keys directory. Note that each access block in the default GPG keys directory. Note that each access stanza in
'@sysconfdir@/fwknop/access.conf' can specify its own GPG directory to override '@sysconfdir@/fwknop/access.conf' can specify its own GPG directory to override
this default. If not set here or in an 'access.conf' stanza, then this default. If not set here or in an 'access.conf' stanza, then
the '$HOME/.gnupg' directory of the user running *fwknopd* (most the '$HOME/.gnupg' directory of the user running *fwknopd* (most
likely root). likely root).
GPG_EXE* '<path>'::
Specify the path to GPG, and defaults to '/usr/bin/gpg' if not set.
*LOCALE* '<locale>':: *LOCALE* '<locale>'::
Set the locale (via the LC_ALL variable). This can be set to override Set the locale (via the LC_ALL variable). This can be set to override
the default system locale. the default system locale.
@ -458,13 +461,6 @@ directive starts a new stanza.
necessary to also specify an IP address for SNAT rules because the necessary to also specify an IP address for SNAT rules because the
MASQUERADE target is used instead. MASQUERADE target is used instead.
*GPG_HOME_DIR* '<path>'::
Define the path to the GnuPG directory to be used by the *fwknopd*
server. If this keyword is not specified within '@sysconfdir@/fwknop/access.conf'
then *fwknopd* will default to using the '/root/.gnupg' directory for the
server key(s) for incoming SPA packets handled by the matching
'access.conf' stanza.
*GPG_DECRYPT_ID* '<keyID>':: *GPG_DECRYPT_ID* '<keyID>'::
Define a GnuPG key ID to use for decrypting SPA messages that Define a GnuPG key ID to use for decrypting SPA messages that
have been encrypted by an *fwknop* client. This keyword is have been encrypted by an *fwknop* client. This keyword is
@ -515,6 +511,17 @@ directive starts a new stanza.
This setting only applies if the ``GPG_REQUIRE_SIG'' is set to 'Y'. This setting only applies if the ``GPG_REQUIRE_SIG'' is set to 'Y'.
Separate multiple entries with a comma. Separate multiple entries with a comma.
*GPG_HOME_DIR* '<path>'::
Define the path to the GnuPG directory to be used by the *fwknopd*
server. If this keyword is not specified within '@sysconfdir@/fwknop/access.conf'
then *fwknopd* will default to using the '/root/.gnupg' directory for the
server key(s) for incoming SPA packets handled by the matching
'access.conf' stanza.
*GPG_EXE* '<path>'::
Define the path to the GnuPG executable. If this keyword is not specified
within '@sysconfdir@/fwknop/access.conf' then *fwknopd* will default to
using '/usr/bin/gpg'.
FILES FILES
----- -----
@ -532,7 +539,7 @@ binary distributions, and is a dedicated library developed by the fwknop
project. project.
For packet sniffing, *fwknopd* currently requires libpcap, but future versions For packet sniffing, *fwknopd* currently requires libpcap, but future versions
still remove this as a dependency. will (optionally) remove this as a dependency.
For GPG functionality, GnuPG must also be correctly installed and configured For GPG functionality, GnuPG must also be correctly installed and configured
along with the libgpgme library. along with the libgpgme library.

View File

@ -628,6 +628,17 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
char *enc_data = NULL; char *enc_data = NULL;
char *hmac_data = NULL; char *hmac_data = NULL;
char *spa_digest = NULL; char *spa_digest = NULL;
#if HAVE_LIBGPGME
char *gpg_signer = NULL;
char *gpg_recip = NULL;
char *gpg_sig_id = NULL;
unsigned char gpg_sig_verify = 0;
unsigned char gpg_ignore_verify = 0;
char *gpg_sig_fpr = NULL;
char *gpg_home_dir = NULL;
char *gpg_exe = NULL;
int gpg_sigsum = -1;
#endif
char *spa_data = NULL; char *spa_data = NULL;
char digest_str[24] = {0}; char digest_str[24] = {0};
char hmac_str[24] = {0}; char hmac_str[24] = {0};
@ -669,6 +680,26 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
RETURN_ON_FKO_ERROR(err, fko_get_spa_digest(ctx, &spa_digest)); RETURN_ON_FKO_ERROR(err, fko_get_spa_digest(ctx, &spa_digest));
RETURN_ON_FKO_ERROR(err, fko_get_spa_data(ctx, &spa_data)); RETURN_ON_FKO_ERROR(err, fko_get_spa_data(ctx, &spa_data));
#if HAVE_LIBGPGME
if(encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
{
/* Populate GPG variables
*/
RETURN_ON_FKO_ERROR(err, fko_get_gpg_signer(ctx, &gpg_signer));
RETURN_ON_FKO_ERROR(err, fko_get_gpg_recipient(ctx, &gpg_recip));
RETURN_ON_FKO_ERROR(err, fko_get_gpg_signature_verify(ctx, &gpg_sig_verify));
RETURN_ON_FKO_ERROR(err, fko_get_gpg_ignore_verify_error(ctx, &gpg_ignore_verify));
RETURN_ON_FKO_ERROR(err, fko_get_gpg_home_dir(ctx, &gpg_home_dir));
RETURN_ON_FKO_ERROR(err, fko_get_gpg_exe(ctx, &gpg_exe));
if(fko_get_gpg_signature_id(ctx, &gpg_sig_id) != FKO_SUCCESS)
gpg_sig_id = NULL;
if(fko_get_gpg_signature_summary(ctx, &gpg_sigsum) != FKO_SUCCESS)
gpg_sigsum = -1;
if(fko_get_gpg_signature_fpr(ctx, &gpg_sig_fpr) != FKO_SUCCESS)
gpg_sig_fpr = NULL;
}
#endif
/* Convert the digest integer to a string */ /* Convert the digest integer to a string */
if (digest_inttostr(digest_type, digest_str, sizeof(digest_str)) != 0) if (digest_inttostr(digest_type, digest_str, sizeof(digest_str)) != 0)
return (FKO_ERROR_INVALID_DIGEST_TYPE); return (FKO_ERROR_INVALID_DIGEST_TYPE);
@ -699,6 +730,20 @@ dump_ctx_to_buffer(fko_ctx_t ctx, char *dump_buf, size_t dump_buf_len)
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " HMAC Type: %u (%s)\n", hmac_type, hmac_type == 0 ? "None" : hmac_str); cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " HMAC Type: %u (%s)\n", hmac_type, hmac_type == 0 ? "None" : hmac_str);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "Encryption Type: %d (%s)\n", encryption_type, enc_type_inttostr(encryption_type)); cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "Encryption Type: %d (%s)\n", encryption_type, enc_type_inttostr(encryption_type));
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "Encryption Mode: %d (%s)\n", encryption_mode, enc_mode_str); cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "Encryption Mode: %d (%s)\n", encryption_mode, enc_mode_str);
#if HAVE_LIBGPGME
if(encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
{
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG signer: %s\n", gpg_signer == NULL ? NULL_STRING : gpg_signer);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG recipient: %s\n", gpg_recip == NULL ? NULL_STRING : gpg_recip);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG sig verify: %s\n", gpg_sig_verify == 0 ? "No" : "Yes");
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG ignore sig: %s\n", gpg_ignore_verify == 0 ? "No" : "Yes");
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG sig ID: %s\n", gpg_sig_id == NULL ? NULL_STRING : gpg_sig_id);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG sig fpr: %s\n", gpg_sig_fpr == NULL ? NULL_STRING : gpg_sig_fpr);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "GPG sig summary: %d\n", gpg_sigsum);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG home dir: %s\n", gpg_home_dir == NULL ? NULL_STRING : gpg_home_dir);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " GPG exe: %s\n", gpg_exe == NULL ? GPG_EXE : gpg_exe);
}
#endif
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Encoded Data: %s\n", enc_data == NULL ? NULL_STRING : enc_data); cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " Encoded Data: %s\n", enc_data == NULL ? NULL_STRING : enc_data);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "SPA Data Digest: %s\n", spa_digest == NULL ? NULL_STRING : spa_digest); cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, "SPA Data Digest: %s\n", spa_digest == NULL ? NULL_STRING : spa_digest);
cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " HMAC: %s\n", hmac_data == NULL ? NULL_STRING : hmac_data); cp += append_msg_to_buf(dump_buf+cp, dump_buf_len-cp, " HMAC: %s\n", hmac_data == NULL ? NULL_STRING : hmac_data);

View File

@ -741,6 +741,9 @@ free_acc_stanza_data(acc_stanza_t *acc)
if(acc->gpg_home_dir != NULL) if(acc->gpg_home_dir != NULL)
free(acc->gpg_home_dir); free(acc->gpg_home_dir);
if(acc->gpg_exe != NULL)
free(acc->gpg_exe);
if(acc->gpg_decrypt_id != NULL) if(acc->gpg_decrypt_id != NULL)
free(acc->gpg_decrypt_id); free(acc->gpg_decrypt_id);
@ -875,13 +878,14 @@ acc_stanza_add(fko_srv_options_t *opts)
return(new_acc); return(new_acc);
} }
/* Scan the access options for entries that have not bees set, but need /* Scan the access options for entries that have not been set, but need
* a default value. * a default value.
*/ */
static void static void
set_acc_defaults(fko_srv_options_t *opts) set_acc_defaults(fko_srv_options_t *opts)
{ {
acc_stanza_t *acc = opts->acc_stanzas; acc_stanza_t *acc = opts->acc_stanzas;
int i=1;
if(!acc) if(!acc)
return; return;
@ -899,6 +903,33 @@ set_acc_defaults(fko_srv_options_t *opts)
{ {
if(acc->gpg_home_dir == NULL) if(acc->gpg_home_dir == NULL)
add_acc_string(&(acc->gpg_home_dir), opts->config[CONF_GPG_HOME_DIR]); add_acc_string(&(acc->gpg_home_dir), opts->config[CONF_GPG_HOME_DIR]);
if(! acc->gpg_require_sig)
{
if (acc->gpg_disable_sig)
{
log_msg(LOG_INFO,
"Warning: GPG_REQUIRE_SIG should really be enabled for stanza source: '%s' (#%d)",
acc->source, i
);
}
else
{
/* Make this the default unless explicitly disabled
*/
acc->gpg_require_sig = 1;
}
}
else
{
if (acc->gpg_disable_sig)
{
log_msg(LOG_INFO,
"Warning: GPG_REQUIRE_SIG and GPG_DISABLE_SIG are both set, will check sigs (stanza source: '%s' #%d)",
acc->source, i
);
}
}
} }
if(acc->encryption_mode == FKO_ENC_MODE_UNKNOWN) if(acc->encryption_mode == FKO_ENC_MODE_UNKNOWN)
@ -915,6 +946,7 @@ set_acc_defaults(fko_srv_options_t *opts)
} }
acc = acc->next; acc = acc->next;
i++;
} }
} }
@ -1314,6 +1346,10 @@ parse_access_file(fko_srv_options_t *opts)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE); clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
} }
} }
else if(CONF_VAR_IS(var, "GPG_EXE"))
{
add_acc_string(&(curr_acc->gpg_exe), val);
}
else if(CONF_VAR_IS(var, "GPG_DECRYPT_ID")) else if(CONF_VAR_IS(var, "GPG_DECRYPT_ID"))
{ {
add_acc_string(&(curr_acc->gpg_decrypt_id), val); add_acc_string(&(curr_acc->gpg_decrypt_id), val);
@ -1344,6 +1380,10 @@ parse_access_file(fko_srv_options_t *opts)
{ {
add_acc_bool(&(curr_acc->gpg_require_sig), val); add_acc_bool(&(curr_acc->gpg_require_sig), val);
} }
else if(CONF_VAR_IS(var, "GPG_DISABLE_SIG"))
{
add_acc_bool(&(curr_acc->gpg_disable_sig), val);
}
else if(CONF_VAR_IS(var, "GPG_IGNORE_SIG_VERIFY_ERROR")) else if(CONF_VAR_IS(var, "GPG_IGNORE_SIG_VERIFY_ERROR"))
{ {
add_acc_bool(&(curr_acc->gpg_ignore_sig_error), val); add_acc_bool(&(curr_acc->gpg_ignore_sig_error), val);
@ -1661,6 +1701,7 @@ dump_access_list(const fko_srv_options_t *opts)
" FORCE_MASQUERADE: %s\n" " FORCE_MASQUERADE: %s\n"
" ACCESS_EXPIRE: %s" /* asctime() adds a newline */ " ACCESS_EXPIRE: %s" /* asctime() adds a newline */
" GPG_HOME_DIR: %s\n" " GPG_HOME_DIR: %s\n"
" GPG_EXE: %s\n"
" GPG_DECRYPT_ID: %s\n" " GPG_DECRYPT_ID: %s\n"
" GPG_DECRYPT_PW: %s\n" " GPG_DECRYPT_PW: %s\n"
" GPG_REQUIRE_SIG: %s\n" " GPG_REQUIRE_SIG: %s\n"
@ -1689,6 +1730,7 @@ dump_access_list(const fko_srv_options_t *opts)
acc->force_masquerade ? "Yes" : "No", acc->force_masquerade ? "Yes" : "No",
(acc->access_expire_time > 0) ? asctime(localtime(&acc->access_expire_time)) : "<not set>\n", (acc->access_expire_time > 0) ? asctime(localtime(&acc->access_expire_time)) : "<not set>\n",
(acc->gpg_home_dir == NULL) ? "<not set>" : acc->gpg_home_dir, (acc->gpg_home_dir == NULL) ? "<not set>" : acc->gpg_home_dir,
(acc->gpg_exe == NULL) ? "<not set>" : acc->gpg_exe,
(acc->gpg_decrypt_id == NULL) ? "<not set>" : acc->gpg_decrypt_id, (acc->gpg_decrypt_id == NULL) ? "<not set>" : acc->gpg_decrypt_id,
(acc->gpg_decrypt_pw == NULL) ? "<not set>" : "<see the access.conf file>", (acc->gpg_decrypt_pw == NULL) ? "<not set>" : "<see the access.conf file>",
acc->gpg_require_sig ? "Yes" : "No", acc->gpg_require_sig ? "Yes" : "No",

View File

@ -106,6 +106,7 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
"DIGEST_DB_FILE", "DIGEST_DB_FILE",
#endif #endif
"GPG_HOME_DIR", "GPG_HOME_DIR",
"GPG_EXE",
"FIREWALL_EXE", "FIREWALL_EXE",
"VERBOSE" "VERBOSE"
}; };
@ -118,6 +119,7 @@ enum {
FW_LIST_ALL, FW_LIST_ALL,
FW_FLUSH, FW_FLUSH,
GPG_HOME_DIR, GPG_HOME_DIR,
GPG_EXE_PATH,
PCAP_FILE, PCAP_FILE,
ENABLE_PCAP_ANY_DIRECTION, ENABLE_PCAP_ANY_DIRECTION,
ROTATE_DIGEST_CACHE, ROTATE_DIGEST_CACHE,
@ -147,6 +149,7 @@ static struct option cmd_opts[] =
{"fw-list", 0, NULL, FW_LIST }, {"fw-list", 0, NULL, FW_LIST },
{"fw-list-all", 0, NULL, FW_LIST_ALL }, {"fw-list-all", 0, NULL, FW_LIST_ALL },
{"gpg-home-dir", 1, NULL, GPG_HOME_DIR }, {"gpg-home-dir", 1, NULL, GPG_HOME_DIR },
{"gpg-exe", 1, NULL, GPG_EXE_PATH },
{"locale", 1, NULL, 'l' }, {"locale", 1, NULL, 'l' },
{"rotate-digest-cache", 0, NULL, ROTATE_DIGEST_CACHE }, {"rotate-digest-cache", 0, NULL, ROTATE_DIGEST_CACHE },
{"override-config", 1, NULL, 'O' }, {"override-config", 1, NULL, 'O' },

View File

@ -639,6 +639,11 @@ validate_options(fko_srv_options_t *opts)
if(opts->config[CONF_GPG_HOME_DIR] == NULL) if(opts->config[CONF_GPG_HOME_DIR] == NULL)
set_config_entry(opts, CONF_GPG_HOME_DIR, DEF_GPG_HOME_DIR); set_config_entry(opts, CONF_GPG_HOME_DIR, DEF_GPG_HOME_DIR);
/* GPG executable
*/
if(opts->config[CONF_GPG_EXE] == NULL)
set_config_entry(opts, CONF_GPG_EXE, DEF_GPG_EXE);
/* Enable SPA over HTTP. /* Enable SPA over HTTP.
*/ */
if(opts->config[CONF_ENABLE_SPA_OVER_HTTP] == NULL) if(opts->config[CONF_ENABLE_SPA_OVER_HTTP] == NULL)

View File

@ -91,12 +91,17 @@
#MAX_SNIFF_BYTES 1500; #MAX_SNIFF_BYTES 1500;
# If GPG keys are used instead of a Rijndael symmetric key, this is # If GPG keys are used instead of a Rijndael symmetric key, this is
# the default GPG keys directory. Note that each access block in # the default GPG keys directory. Note that each access stanza in
# fwknop access.conf can specify its own GPG directory to override # fwknop access.conf can specify its own GPG directory to override
# this default. # this default.
# #
#GPG_HOME_DIR /root/.gnupg; #GPG_HOME_DIR /root/.gnupg;
# Set the default GPG path when GPG is used for SPA encryption and
# authentication.
#
#GPG_EXE /usr/bin/gpg;
# Allow fwknopd to acquire SPA data from HTTP requests (generated with the # Allow fwknopd to acquire SPA data from HTTP requests (generated with the
# fwknop client in --HTTP mode). Note that the PCAP_FILTER variable would # fwknop client in --HTTP mode). Note that the PCAP_FILTER variable would
# need to be updated when this is enabled to sniff traffic over TCP/80 # need to be updated when this is enabled to sniff traffic over TCP/80

View File

@ -93,6 +93,11 @@
#define DEF_ENABLE_DIGEST_PERSISTENCE "Y" #define DEF_ENABLE_DIGEST_PERSISTENCE "Y"
#define DEF_MAX_SNIFF_BYTES "1500" #define DEF_MAX_SNIFF_BYTES "1500"
#define DEF_GPG_HOME_DIR "/root/.gnupg" #define DEF_GPG_HOME_DIR "/root/.gnupg"
#ifdef GPG_EXE
#define DEF_GPG_EXE GPG_EXE
#else
#define DEF_GPG_EXE "/usr/bin/gpg"
#endif
#define DEF_ENABLE_SPA_OVER_HTTP "N" #define DEF_ENABLE_SPA_OVER_HTTP "N"
#define DEF_ENABLE_TCP_SERVER "N" #define DEF_ENABLE_TCP_SERVER "N"
#define DEF_TCPSERV_PORT "62201" #define DEF_TCPSERV_PORT "62201"
@ -250,6 +255,7 @@ enum {
CONF_DIGEST_DB_FILE, CONF_DIGEST_DB_FILE,
#endif #endif
CONF_GPG_HOME_DIR, CONF_GPG_HOME_DIR,
CONF_GPG_EXE,
CONF_FIREWALL_EXE, CONF_FIREWALL_EXE,
CONF_VERBOSE, CONF_VERBOSE,
@ -310,9 +316,11 @@ typedef struct acc_stanza
char *require_username; char *require_username;
unsigned char require_source_address; unsigned char require_source_address;
char *gpg_home_dir; char *gpg_home_dir;
char *gpg_exe;
char *gpg_decrypt_id; char *gpg_decrypt_id;
char *gpg_decrypt_pw; char *gpg_decrypt_pw;
unsigned char gpg_require_sig; unsigned char gpg_require_sig;
unsigned char gpg_disable_sig;
unsigned char gpg_ignore_sig_error; unsigned char gpg_ignore_sig_error;
unsigned char use_gpg; unsigned char use_gpg;
unsigned char gpg_allow_no_pw; unsigned char gpg_allow_no_pw;

View File

@ -462,6 +462,21 @@ incoming_spa(fko_srv_options_t *opts)
/* Set whatever GPG parameters we have. /* Set whatever GPG parameters we have.
*/ */
if(acc->gpg_exe != NULL)
{
res = fko_set_gpg_exe(ctx, acc->gpg_exe);
if(res != FKO_SUCCESS)
{
log_msg(LOG_WARNING,
"[%s] (stanza #%d) Error setting GPG path %s: %s",
spadat.pkt_source_ip, stanza_num, acc->gpg_exe,
fko_errstr(res)
);
acc = acc->next;
continue;
}
}
if(acc->gpg_home_dir != NULL) if(acc->gpg_home_dir != NULL)
{ {
res = fko_set_gpg_home_dir(ctx, acc->gpg_home_dir); res = fko_set_gpg_home_dir(ctx, acc->gpg_home_dir);
@ -469,7 +484,8 @@ incoming_spa(fko_srv_options_t *opts)
{ {
log_msg(LOG_WARNING, log_msg(LOG_WARNING,
"[%s] (stanza #%d) Error setting GPG keyring path to %s: %s", "[%s] (stanza #%d) Error setting GPG keyring path to %s: %s",
spadat.pkt_source_ip, stanza_num, acc->gpg_home_dir, fko_errstr(res) spadat.pkt_source_ip, stanza_num, acc->gpg_home_dir,
fko_errstr(res)
); );
acc = acc->next; acc = acc->next;
continue; continue;

View File

@ -0,0 +1,4 @@
[default]
HMAC_DIGEST_TYPE sha256
HMAC_KEY_BASE64 Yh+xizBnl6FotC5ec7FanVGClRMlsOAPh2u6eovnerfBVKwaVKzjGoblFMHMc593TNyi0dWn4opLoTIV9q/ttg==
GPG_EXE /invalid/gpg/path

View File

@ -0,0 +1,9 @@
SOURCE ANY
FW_ACCESS_TIMEOUT 3
HMAC_DIGEST_TYPE sha256
HMAC_KEY_BASE64 Yh+xizBnl6FotC5ec7FanVGClRMlsOAPh2u6eovnerfBVKwaVKzjGoblFMHMc593TNyi0dWn4opLoTIV9q/ttg==
GPG_HOME_DIR conf/server-gpg
GPG_DECRYPT_ID 361BBAD4
GPG_DECRYPT_PW fwknoptest
GPG_REMOTE_ID 6A3FAD56
GPG_EXE /invalid/path/gpg

View File

@ -98,6 +98,7 @@ our %cf = (
'hmac_dual_key_access' => "$conf_dir/hmac_dual_key_usage_access.conf", 'hmac_dual_key_access' => "$conf_dir/hmac_dual_key_usage_access.conf",
'gpg_access' => "$conf_dir/gpg_access.conf", 'gpg_access' => "$conf_dir/gpg_access.conf",
'gpg_hmac_access' => "$conf_dir/gpg_hmac_access.conf", 'gpg_hmac_access' => "$conf_dir/gpg_hmac_access.conf",
'gpg_invalid_exe_access' => "$conf_dir/gpg_invalid_exe_access.conf",
'gpg_hmac_sha512_access' => "$conf_dir/gpg_hmac_sha512_access.conf", 'gpg_hmac_sha512_access' => "$conf_dir/gpg_hmac_sha512_access.conf",
'legacy_iv_access' => "$conf_dir/legacy_iv_access.conf", 'legacy_iv_access' => "$conf_dir/legacy_iv_access.conf",
'legacy_iv_long_key_access' => "$conf_dir/legacy_iv_long_key_access.conf", 'legacy_iv_long_key_access' => "$conf_dir/legacy_iv_long_key_access.conf",
@ -143,6 +144,7 @@ our %cf = (
'rc_gpg_signing_pw' => "$conf_dir/fwknoprc_gpg_signing_pw", 'rc_gpg_signing_pw' => "$conf_dir/fwknoprc_gpg_signing_pw",
'rc_gpg_named_signing_pw' => "$conf_dir/fwknoprc_named_gpg_signing_pw", 'rc_gpg_named_signing_pw' => "$conf_dir/fwknoprc_named_gpg_signing_pw",
'rc_gpg_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_hmac_key", 'rc_gpg_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_hmac_key",
'rc_gpg_invalid_gpg_exe' => "$conf_dir/fwknoprc_gpg_invalid_exe",
'rc_gpg_hmac_sha512_b64_key' => "$conf_dir/fwknoprc_gpg_hmac_sha512_key", 'rc_gpg_hmac_sha512_b64_key' => "$conf_dir/fwknoprc_gpg_hmac_sha512_key",
'rc_gpg_args_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_args_hmac_key", 'rc_gpg_args_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_args_hmac_key",
'rc_gpg_args_no_pw_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_args_no_pw_hmac_key", 'rc_gpg_args_no_pw_hmac_b64_key' => "$conf_dir/fwknoprc_gpg_args_no_pw_hmac_key",
@ -534,6 +536,11 @@ our $default_server_gpg_args_hmac = "$lib_view_str " .
"-a $cf{'gpg_hmac_access'} $intf_str " . "-a $cf{'gpg_hmac_access'} $intf_str " .
"-d $default_digest_file -p $default_pid_file"; "-d $default_digest_file -p $default_pid_file";
our $invalid_gpg_exe_server_args = "$lib_view_str " .
"$valgrind_str $fwknopdCmd -c $cf{'def'} " .
"-a $cf{'gpg_invalid_exe_access'} $intf_str " .
"-d $default_digest_file -p $default_pid_file";
our $default_server_gpg_args_no_pw_hmac = "$lib_view_str " . our $default_server_gpg_args_no_pw_hmac = "$lib_view_str " .
"$valgrind_str $fwknopdCmd -c $cf{'def'} " . "$valgrind_str $fwknopdCmd -c $cf{'def'} " .
"-a $cf{'gpg_no_pw_hmac_access'} $intf_str " . "-a $cf{'gpg_no_pw_hmac_access'} $intf_str " .
@ -628,6 +635,7 @@ my %test_keys = (
'set_legacy_iv' => $OPTIONAL, 'set_legacy_iv' => $OPTIONAL,
'write_rc_file' => $OPTIONAL, 'write_rc_file' => $OPTIONAL,
'save_rc_stanza' => $OPTIONAL, 'save_rc_stanza' => $OPTIONAL,
'client_pkt_tries' => $OPTIONAL_NUMERIC,
'disable_valgrind' => $OPTIONAL, 'disable_valgrind' => $OPTIONAL,
'positive_output_matches' => $OPTIONAL, 'positive_output_matches' => $OPTIONAL,
'negative_output_matches' => $OPTIONAL, 'negative_output_matches' => $OPTIONAL,
@ -1673,7 +1681,11 @@ sub client_send_spa_packet() {
last if $server_receive_check == $NO_SERVER_RECEIVE_CHECK; last if $server_receive_check == $NO_SERVER_RECEIVE_CHECK;
$tries++; $tries++;
last if $tries == 10; ### should be plenty of time if ($test_hr->{'client_pkt_tries'} > 0) {
last if $tries == $test_hr->{'client_pkt_tries'};
} else {
last if $tries == 10;
}
sleep 1; sleep 1;
} }
} else { } else {

View File

@ -22,6 +22,53 @@
'fw_rule_removed' => $NEW_RULE_REMOVED, 'fw_rule_removed' => $NEW_RULE_REMOVED,
'key_file' => $cf{'rc_gpg_hmac_b64_key'}, 'key_file' => $cf{'rc_gpg_hmac_b64_key'},
}, },
{
'category' => 'GPG+HMAC',
'subcategory' => 'client+server',
'detail' => '--gpg-exe invalid path',
'function' => \&generic_exec,
'cmdline' => $default_client_gpg_args
. " --rc-file $cf{'rc_gpg_hmac_b64_key'} --gpg-exe /invalid/bin/gpg",
'positive_output_matches' => [qr/Unable\sto\sstat/i],
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'key_file' => $cf{'rc_gpg_hmac_b64_key'},
},
{
'category' => 'GPG+HMAC',
'subcategory' => 'client',
'detail' => '--gpg-exe invalid rc path',
'function' => \&generic_exec,
'cmdline' => $default_client_gpg_args
. " --rc-file $cf{'rc_gpg_invalid_gpg_exe'}",
'positive_output_matches' => [qr/Unable\sto\sstat/i],
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'key_file' => $cf{'rc_gpg_invalid_gpg_exe'},
},
{
'category' => 'GPG+HMAC',
'subcategory' => 'client+server',
'detail' => 'complete cycle invalid gpg path',
'function' => \&spa_cycle,
'cmdline' => $default_client_gpg_args
. " --rc-file $cf{'rc_gpg_hmac_b64_key'} --gpg-exe /usr/bin/gpg",
'fwknopd_cmdline' => $invalid_gpg_exe_server_args,
'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
'key_file' => $cf{'rc_gpg_hmac_b64_key'},
'client_pkt_tries' => 1,
},
{
'category' => 'GPG+HMAC',
'subcategory' => 'client+server',
'detail' => 'complete cycle --gpg-exe path',
'function' => \&spa_cycle,
'cmdline' => $default_client_gpg_args
. " --rc-file $cf{'rc_gpg_hmac_b64_key'} --gpg-exe /usr/bin/gpg",
'fwknopd_cmdline' => $default_server_gpg_args_hmac,
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'key_file' => $cf{'rc_gpg_hmac_b64_key'},
},
{ {
'category' => 'GPG+HMAC', 'category' => 'GPG+HMAC',
'subcategory' => 'client+server', 'subcategory' => 'client+server',