Added key generation support with --key-gen

Added --key-gen to allow KEY_BASE64 and HMAC_KEY_BASE64 keys to be created from
reading random data from /dev/random.  These keys can be placed within server
access.conf files and corresponding client .fwknoprc files for SPA
communications.  The HMAC key is not used yet with this commit, but that is
coming.
This commit is contained in:
Michael Rash
2012-06-27 23:06:17 -04:00
parent 20e3e3b6e5
commit 3095f0ee43
22 changed files with 631 additions and 44 deletions
+5 -1
View File
@@ -43,6 +43,7 @@ enum {
TIME_OFFSET_PLUS,
NO_SAVE_ARGS,
SHOW_LAST_ARGS,
RC_FILE_PATH,
RESOLVE_URL,
/* Put GPG-related items below the following line */
GPG_ENCRYPTION = 0x200,
@@ -56,7 +57,7 @@ enum {
/* Our getopt_long options string.
*/
#define GETOPTS_OPTION_STRING "a:A:bB:C:D:f:gG:hH:lm:M:n:N:p:P:Q:rRsS:Tu:U:vV"
#define GETOPTS_OPTION_STRING "a:A:bB:C:D:f:gG:hH:kK:lm:M:n:N:p:P:Q:rRsS:Tu:U:vV"
/* Our program command-line options...
*/
@@ -80,6 +81,8 @@ static struct option cmd_opts[] =
{"get-key", 1, NULL, 'G'},
{"help", 0, NULL, 'h'},
{"http-proxy", 1, NULL, 'H'},
{"key-gen", 0, NULL, 'k'},
{"key-gen-file", 1, NULL, 'K'},
{"last-cmd", 0, NULL, 'l'},
{"nat-access", 1, NULL, 'N'},
{"named-config", 1, NULL, 'n'},
@@ -89,6 +92,7 @@ static struct option cmd_opts[] =
{"server-port", 1, NULL, 'p'},
{"server-proto", 1, NULL, 'P'},
{"spoof-src", 1, NULL, 'Q'},
{"rc-file", 1, NULL, RC_FILE_PATH},
{"rand-port", 0, NULL, 'r'},
{"resolve-ip-http", 0, NULL, 'R'},
{"resolve-url", 1, NULL, RESOLVE_URL},
+86 -29
View File
@@ -367,6 +367,39 @@ parse_rc_param(fko_cli_options_t *options, const char *var, char * val)
if(val[0] == 'y' || val[0] == 'Y')
options->rand_port = 1;
}
/* Rijndael key */
else if(CONF_VAR_IS(var, "KEY"))
{
strlcpy(options->key, val, MAX_KEY_LEN);
options->have_key = 1;
}
/* Rijndael key (base-64 encoded) */
else if(CONF_VAR_IS(var, "KEY_BASE64"))
{
if (! is_base64((unsigned char *) val, strlen(val)))
{
fprintf(stderr,
"KEY_BASE64 argument '%s' doesn't look like base64-encoded data.\n",
val);
exit(EXIT_FAILURE);
}
strlcpy(options->key_base64, val, MAX_KEY_LEN);
options->have_base64_key = 1;
}
/* HMAC key */
else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64"))
{
if (! is_base64((unsigned char *) val, strlen(val)))
{
fprintf(stderr,
"HMAC_KEY_BASE64 argument '%s' doesn't look like base64-encoded data.\n",
val);
exit(EXIT_FAILURE);
}
strlcpy(options->hmac_key_base64, val, MAX_KEY_LEN);
options->have_hmac_base64_key = 1;
}
/* Key file */
else if(CONF_VAR_IS(var, "KEY_FILE"))
{
@@ -437,38 +470,45 @@ process_rc(fko_cli_options_t *options)
char *ndx, *emark, *homedir;
#ifdef WIN32
homedir = getenv("USERPROFILE");
#else
homedir = getenv("HOME");
#endif
if(homedir == NULL)
{
fprintf(stderr, "Warning: Unable to determine HOME directory.\n"
" No .fwknoprc file processed.\n");
return;
}
memset(rcfile, 0x0, MAX_PATH_LEN);
strlcpy(rcfile, homedir, MAX_PATH_LEN);
rcf_offset = strlen(rcfile);
/* Sanity check the path to .fwknoprc.
* The preceeding path plus the path separator and '.fwknoprc' = 11
* cannot exceed MAX_PATH_LEN.
*/
if(rcf_offset > (MAX_PATH_LEN - 11))
if(options->rc_file[0] == 0x0)
{
fprintf(stderr, "Warning: Path to .fwknoprc file is too long.\n"
" No .fwknoprc file processed.\n");
return;
}
#ifdef WIN32
homedir = getenv("USERPROFILE");
#else
homedir = getenv("HOME");
#endif
rcfile[rcf_offset] = PATH_SEP;
strlcat(rcfile, ".fwknoprc", MAX_PATH_LEN);
if(homedir == NULL)
{
fprintf(stderr, "Warning: Unable to determine HOME directory.\n"
" No .fwknoprc file processed.\n");
return;
}
strlcpy(rcfile, homedir, MAX_PATH_LEN);
rcf_offset = strlen(rcfile);
/* Sanity check the path to .fwknoprc.
* The preceeding path plus the path separator and '.fwknoprc' = 11
* cannot exceed MAX_PATH_LEN.
*/
if(rcf_offset > (MAX_PATH_LEN - 11))
{
fprintf(stderr, "Warning: Path to .fwknoprc file is too long.\n"
" No .fwknoprc file processed.\n");
return;
}
rcfile[rcf_offset] = PATH_SEP;
strlcat(rcfile, ".fwknoprc", MAX_PATH_LEN);
}
else
{
strlcpy(rcfile, options->rc_file, MAX_PATH_LEN);
}
/* Open the rc file for reading, if it does not exist, then create
* an initial .fwknoprc file with defaults and go on.
@@ -545,6 +585,13 @@ process_rc(fko_cli_options_t *options)
if((ndx = strrchr(var, ':')) != NULL)
*ndx = '\0';
/* Even though sscanf should automatically add a terminating
* NULL byte, an assumption is made that the input arrays are
* big enough, so we'll force a terminating NULL byte regardless
*/
var[MAX_LINE_LEN-1] = 0x0;
val[MAX_LINE_LEN-1] = 0x0;
if(options->verbose > 3)
fprintf(stderr,
"RC FILE: %s, LINE: %s\tVar: %s, Val: '%s'\n",
@@ -590,6 +637,7 @@ validate_options(fko_cli_options_t *options)
* the version, and must use one of [-s|-R|-a].
*/
if(!options->test
&& !options->key_gen
&& !options->version
&& !options->show_last_command
&& !options->run_last_command)
@@ -677,7 +725,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
*/
set_defaults(options);
/* First pass over cmd_line args to see if a named-stanza in the
/* First pass over cmd_line args to see if a named-stanza in the
* rc file is used.
*/
while ((cmd_arg = getopt_long(argc, argv,
@@ -690,6 +738,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
options->no_save_args = 1;
strlcpy(options->use_rc_stanza, optarg, MAX_LINE_LEN);
break;
case RC_FILE_PATH:
strlcpy(options->rc_file, optarg, MAX_PATH_LEN);
break;
case 'v':
options->verbose++;
break;
@@ -747,6 +798,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
options->spa_proto = FKO_PROTO_HTTP;
strlcpy(options->http_proxy, optarg, MAX_PATH_LEN);
break;
case 'k':
options->key_gen = 1;
break;
case 'l':
options->run_last_command = 1;
break;
@@ -798,6 +852,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case 'Q':
strlcpy(options->spoof_ip_src_str, optarg, MAX_IPV4_STR_LEN);
break;
case RC_FILE_PATH:
strlcpy(options->rc_file, optarg, MAX_PATH_LEN);
break;
case 'r':
options->rand_port = 1;
break;
+22 -2
View File
@@ -36,7 +36,7 @@
/* prototypes
*/
static char * get_user_pw(fko_cli_options_t *options, const int crypt_op);
static char *get_user_pw(fko_cli_options_t *options, const int crypt_op);
static void display_ctx(fko_ctx_t ctx);
static void errmsg(const char *msg, const int err);
static void show_last_command(void);
@@ -79,9 +79,20 @@ main(int argc, char **argv)
return(EXIT_FAILURE);
}
/* Generate Rijndael + HMAC keys from /dev/random (base64
* encoded) and exit.
*/
if(options.key_gen)
{
fko_key_gen(options.key_base64, options.hmac_key_base64);
printf("KEY_BASE64: %s\nHMAC_KEY_BASE64: %s\n", options.key_base64, options.hmac_key_base64);
return(EXIT_SUCCESS);
}
/* Display version info and exit.
*/
if (options.version) {
if(options.version)
{
fko_get_version(ctx, &version);
fprintf(stdout, "fwknop client %s, FKO protocol version %s\n",
@@ -738,6 +749,15 @@ get_user_pw(fko_cli_options_t *options, const int crypt_op)
{
pw_ptr = getpasswd_file(options->get_key_file, options->spa_server_str);
}
else if (options->have_key)
{
pw_ptr = options->key;
}
else if (options->have_base64_key)
{
fko_base64_decode(options->key_base64, (unsigned char *) options->key);
pw_ptr = options->key;
}
else if (options->use_gpg)
{
if(crypt_op == CRYPT_OP_DECRYPT)
+14 -1
View File
@@ -55,7 +55,7 @@
#define TIME_OFFSET_DAYS 86400
/* For resolving the allow IP via HTTP and sending SPA packets over
* HTTP - http://www.whatismyip.com/automation/n09230945.asp
* HTTP - http://www.whatismyip.com/automation/n09230945.asp
#define HTTP_RESOLVE_HOST "www.whatismyip.com"
#define HTTP_RESOLVE_URL "/automation/n09230945.asp"
* --DSS Note: The whatismyip.com site has some usage restrictions.
@@ -70,6 +70,7 @@
#define MAX_HOSTNAME_LEN 70
#define MAX_URL_HOST_LEN 256
#define MAX_URL_PATH_LEN 1024
#define MAX_KEY_LEN 128
/* fwknop client configuration parameters and values
*/
@@ -77,6 +78,8 @@ typedef struct fko_cli_options
{
char config_file[MAX_PATH_LEN];
char access_str[MAX_PATH_LEN];
char rc_file[MAX_PATH_LEN];
char key_gen_file[MAX_PATH_LEN];
char server_command[MAX_LINE_LEN];
char get_key_file[MAX_PATH_LEN];
char save_packet_file[MAX_PATH_LEN];
@@ -93,6 +96,15 @@ typedef struct fko_cli_options
char gpg_signer_key[MAX_GPG_KEY_ID];
char gpg_home_dir[MAX_PATH_LEN];
/* Encryption keys read from a .fwknoprc stanza
*/
char key[MAX_KEY_LEN+1];
char key_base64[MAX_KEY_LEN+1];
char hmac_key_base64[MAX_KEY_LEN+1];
int have_key;
int have_base64_key;
int have_hmac_base64_key;
/* NAT access
*/
char nat_access_str[MAX_PATH_LEN];
@@ -128,6 +140,7 @@ typedef struct fko_cli_options
int time_offset_plus;
int time_offset_minus;
int fw_timeout;
int key_gen;
char use_rc_stanza[MAX_LINE_LEN];
unsigned char got_named_stanza;
+3 -5
View File
@@ -40,14 +40,12 @@
#include "fwknop_common.h"
#include "getpasswd.h"
#define MAX_PASS_LEN 128
/* Function for accepting password input from users
*/
char*
getpasswd(const char *prompt)
{
static char pwbuf[MAX_PASS_LEN + 1] = {0};
static char pwbuf[MAX_KEY_LEN + 1] = {0};
char *ptr;
int c;
@@ -109,7 +107,7 @@ getpasswd(const char *prompt)
while((c = getc(fp)) != EOF && c != '\n')
{
#endif
if(ptr < &pwbuf[MAX_PASS_LEN])
if(ptr < &pwbuf[MAX_KEY_LEN])
*ptr++ = c;
}
@@ -146,7 +144,7 @@ getpasswd_file(const char *pw_file, const char *server_str)
FILE *pwfile_ptr;
unsigned int numLines = 0, i = 0, found_dst;
static char pwbuf[MAX_PASS_LEN + 1] = {0};
static char pwbuf[MAX_KEY_LEN + 1] = {0};
char conf_line_buf[MAX_LINE_LEN] = {0};
char tmp_char_buf[MAX_LINE_LEN] = {0};
char *lptr;
+21 -2
View File
@@ -28,8 +28,7 @@
*
*****************************************************************************
*/
#include <stdio.h>
#include <string.h>
#include "fwknop_common.h"
#include "utils.h"
/* Generic hex dump function.
@@ -69,5 +68,25 @@ hex_dump(const unsigned char *data, const int size)
}
}
/* Determine if a buffer contains only characters from the base64
* encoding set
*/
int
is_base64(const unsigned char *buf, const unsigned short int len)
{
unsigned short int i;
int rv = 1;
for(i=0; i<len; i++)
{
if(!(isalnum(buf[i]) || buf[i] == '/' || buf[i] == '+' || buf[i] == '='))
{
rv = 0;
break;
}
}
return rv;
}
/***EOF***/
+1
View File
@@ -35,6 +35,7 @@
/* Prototypes
*/
void hex_dump(const unsigned char *data, const int size);
int is_base64(const unsigned char *buf, const unsigned short int len);
size_t strlcat(char *dst, const char *src, size_t siz);
size_t strlcpy(char *dst, const char *src, size_t siz);
+1 -1
View File
@@ -107,7 +107,7 @@ b64_encode(unsigned char *in, char *out, int in_len)
return(dst - out);
}
/* Strip trailing equals ("=") charcters from a base64-encode
/* Strip trailing equals ("=") charcters from a base64-encoded
* message digest.
*/
void
+1 -1
View File
@@ -50,7 +50,7 @@
/* Get random data.
*/
static void
void
get_random_data(unsigned char *data, const size_t len)
{
uint32_t i;
+1
View File
@@ -47,6 +47,7 @@
*/
#define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4
void get_random_data(unsigned char *data, const size_t len);
size_t rij_encrypt(unsigned char *in, size_t len,
const char *key, unsigned char *out, int encryption_mode);
size_t rij_decrypt(unsigned char *in, size_t len,
+3
View File
@@ -232,6 +232,9 @@ DLL_API int fko_set_spa_data(fko_ctx_t ctx, const char *enc_msg);
*/
DLL_API const char* fko_errstr(const int err_code);
DLL_API int fko_encryption_type(const char *enc_data);
DLL_API int fko_key_gen(char *key_base64, char *hmac_key_base64);
DLL_API int fko_base64_encode(unsigned char *in, char *out, int in_len);
DLL_API int fko_base64_decode(const char *in, unsigned char *out);
DLL_API int fko_encode_spa_data(fko_ctx_t ctx);
DLL_API int fko_decode_spa_data(fko_ctx_t ctx);
+35
View File
@@ -31,6 +31,7 @@
#include "fko_common.h"
#include "fko.h"
#include "cipher_funcs.h"
#include "base64.h"
/* Initialize an fko context.
*/
@@ -313,6 +314,40 @@ fko_destroy(fko_ctx_t ctx)
free(ctx);
}
/* Generate Rijndael and HMAC keys from /dev/random and base-64
* encode them
*/
int
fko_key_gen(char *key_base64, char *hmac_key_base64)
{
unsigned char key[RIJNDAEL_MAX_KEYSIZE];
unsigned char hmac_key[RIJNDAEL_MAX_KEYSIZE];
get_random_data(key, RIJNDAEL_MAX_KEYSIZE);
get_random_data(hmac_key, RIJNDAEL_MAX_KEYSIZE);
b64_encode(key, key_base64, RIJNDAEL_MAX_KEYSIZE);
b64_encode(hmac_key, hmac_key_base64, RIJNDAEL_MAX_KEYSIZE);
return(FKO_SUCCESS);
}
/* Provide an FKO wrapper around base64 encode/decode functions
*/
int
fko_base64_encode(unsigned char *in, char *out, int in_len)
{
b64_encode(in, out, in_len);
return(FKO_SUCCESS);
}
int
fko_base64_decode(const char *in, unsigned char *out)
{
b64_decode(in, out);
return(FKO_SUCCESS);
}
/* Return the fko version
*/
int
+50
View File
@@ -578,6 +578,12 @@ free_acc_stanza_data(acc_stanza_t *acc)
if(acc->key != NULL)
free(acc->key);
if(acc->key_base64 != NULL)
free(acc->key_base64);
if(acc->hmac_key_base64 != NULL)
free(acc->hmac_key_base64);
if(acc->cmd_exec_user != NULL)
free(acc->cmd_exec_user);
@@ -744,6 +750,7 @@ static int
acc_data_is_valid(const acc_stanza_t *acc)
{
if((acc->key == NULL || !strlen(acc->key))
&& (acc->key_base64 == NULL || !strlen(acc->key_base64))
&& (acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw)))
{
fprintf(stderr,
@@ -826,6 +833,13 @@ parse_access_file(fko_srv_options_t *opts)
if((ndx = strrchr(var, ':')) != NULL)
*ndx = '\0';
/* Even though sscanf should automatically add a terminating
* NULL byte, an assumption is made that the input arrays are
* big enough, so we'll force a terminating NULL byte regardless
*/
var[MAX_LINE_LEN-1] = 0x0;
val[MAX_LINE_LEN-1] = 0x0;
/*
*/
if(opts->verbose > 3)
@@ -888,6 +902,42 @@ parse_access_file(fko_srv_options_t *opts)
}
add_acc_string(&(curr_acc->key), val);
}
else if(CONF_VAR_IS(var, "KEY_BASE64"))
{
if(strcasecmp(val, "__CHANGEME__") == 0)
{
fprintf(stderr,
"[*] KEY_BASE64 value is not properly set in stanza source '%s' in access file: '%s'\n",
curr_acc->source, opts->config[CONF_ACCESS_FILE]);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
if (! is_base64((unsigned char *) val, strlen(val)))
{
fprintf(stderr,
"KEY_BASE64 argument '%s' doesn't look like base64-encoded data.\n",
val);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
add_acc_string(&(curr_acc->key_base64), val);
}
else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64"))
{
if(strcasecmp(val, "__CHANGEME__") == 0)
{
fprintf(stderr,
"[*] HMAC_KEY_BASE64 value is not properly set in stanza source '%s' in access file: '%s'\n",
curr_acc->source, opts->config[CONF_ACCESS_FILE]);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
if (! is_base64((unsigned char *) val, strlen(val)))
{
fprintf(stderr,
"HMAC_KEY_BASE64 argument '%s' doesn't look like base64-encoded data.\n",
val);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
add_acc_string(&(curr_acc->hmac_key_base64), val);
}
else if(CONF_VAR_IS(var, "FW_ACCESS_TIMEOUT"))
{
add_acc_int(&(curr_acc->fw_access_timeout), val);
+2
View File
@@ -267,6 +267,8 @@ typedef struct acc_stanza
char *restrict_ports;
acc_port_list_t *rport_list;
char *key;
char *key_base64;
char *hmac_key_base64;
int fw_access_timeout;
unsigned char enable_cmd_exec;
char *cmd_exec_user;
+17
View File
@@ -242,8 +242,25 @@ incoming_spa(fko_srv_options_t *opts)
if(enc_type == FKO_ENCRYPTION_RIJNDAEL)
{
if(acc->key != NULL)
{
res = fko_new_with_data(&ctx,
(char *)spa_pkt->packet_data, acc->key, acc->encryption_mode);
}
else if (acc->key_base64 != NULL)
{
if ((acc->key = strdup(acc->key_base64)) == NULL)
{
log_msg(LOG_ERR,
"Fatal memory allocation error copying key_base64 -> key: %s",
acc->key_base64
);
exit(EXIT_FAILURE);
}
memset(acc->key, 0x0, strlen(acc->key_base64));
fko_base64_decode(acc->key_base64, (unsigned char *) acc->key);
res = fko_new_with_data(&ctx,
(char *)spa_pkt->packet_data, acc->key, acc->encryption_mode);
}
else
{
log_msg(LOG_ERR,
+1 -1
View File
@@ -164,7 +164,7 @@ is_valid_dir(const char *path)
* encoding set
*/
int
is_base64(const unsigned char *buf, unsigned short int len)
is_base64(const unsigned char *buf, const unsigned short int len)
{
unsigned short int i;
int rv = 1;
+1 -1
View File
@@ -60,7 +60,7 @@
*/
void hex_dump(const unsigned char *data, const int size);
char* dump_ctx(fko_ctx_t ctx);
int is_base64(const unsigned char *buf, unsigned short int len);
int is_base64(const unsigned char *buf, const unsigned short int len);
int is_valid_dir(const char *path);
size_t strlcat(char *dst, const char *src, size_t siz);
+3
View File
@@ -0,0 +1,3 @@
SOURCE: ANY;
KEY_BASE64: w8KMBQlKf4UCARNQmi25DPxw4xAUaRs21nf8nbRNzUo=;
FW_ACCESS_TIMEOUT: 3;
@@ -0,0 +1,71 @@
# .fwknoprc
##############################################################################
#
# Firewall Knock Operator (fwknop) client rc file.
#
# This file contains user-specific fwknop client configuration default
# and named parameter sets for specific invocations of the fwknop client.
#
# Each section (or stanza) is identified and started by a line in this
# file that contains a single identifier surrounded by square brackets.
#
# The parameters within the stanza typicaly match corresponding client
# command-line parameters.
#
# The first one should always be `[default]' as it defines the global
# default settings for the user. These override the program defaults
# for these parameter. If a named stanza is used, its entries will
# override any of the default. Command-line options will trump them
# all.
#
# Subsequent stanzas will have only the overriding and destination
# specific parameters.
#
# Lines starting with `#' and empty lines are ignored.
#
# See the fwknop.8 man page for a complete list of valid parameters
# and their values.
#
##############################################################################
#
# We start with the 'default' stanza. Uncomment and edit for your
# preferences. The client will use its build-in default for those items
# that are commented out.
#
[default]
#DIGEST_TYPE sha256
#FW_TIMEOUT 30
#SPA_SERVER_PORT 62201
#SPA_SERVER_PROTO udp
#ALLOW_IP <ip addr>
#SPOOF_USER <username>
#SPOOF_SOURCE_IP <IPaddr>
#TIME_OFFSET 0
#USE_GPG N
#GPG_HOMEDIR /path/to/.gnupg
#GPG_SIGNER <signer ID>
#GPG_RECIPIENT <recipient ID>
KEY_BASE64 w8KMBQlKf4UCARNQmi25DPxw4xAUaRs21nf8nbRNzUo=
# User-provided named stanzas:
# Example for a destination server of 192.168.1.20 to open access to
# SSH for an IP that is resoved exteranlly, and one with a NAT request
# for a specific source IP that maps port 8088 on the server
# to port 88 on 192.168.1.55 with timeout.
#
#[myssh]
#SPA_SERVER 192.168.1.20
#ACCESS tcp/22
#ALLOW_IP resolve
#
#[mynatreq]
#SPA_SERVER 192.168.1.20
#ACCESS tcp/8088
#ALLOW_IP 10.21.2.6
#NAT_ACCESS 192.168.1.55,88
#CLIENT_TIMEOUT 60
#
###EOF###
+71
View File
@@ -0,0 +1,71 @@
# .fwknoprc
##############################################################################
#
# Firewall Knock Operator (fwknop) client rc file.
#
# This file contains user-specific fwknop client configuration default
# and named parameter sets for specific invocations of the fwknop client.
#
# Each section (or stanza) is identified and started by a line in this
# file that contains a single identifier surrounded by square brackets.
#
# The parameters within the stanza typicaly match corresponding client
# command-line parameters.
#
# The first one should always be `[default]' as it defines the global
# default settings for the user. These override the program defaults
# for these parameter. If a named stanza is used, its entries will
# override any of the default. Command-line options will trump them
# all.
#
# Subsequent stanzas will have only the overriding and destination
# specific parameters.
#
# Lines starting with `#' and empty lines are ignored.
#
# See the fwknop.8 man page for a complete list of valid parameters
# and their values.
#
##############################################################################
#
# We start with the 'default' stanza. Uncomment and edit for your
# preferences. The client will use its build-in default for those items
# that are commented out.
#
[default]
#DIGEST_TYPE sha256
#FW_TIMEOUT 30
#SPA_SERVER_PORT 62201
#SPA_SERVER_PROTO udp
#ALLOW_IP <ip addr>
#SPOOF_USER <username>
#SPOOF_SOURCE_IP <IPaddr>
#TIME_OFFSET 0
#USE_GPG N
#GPG_HOMEDIR /path/to/.gnupg
#GPG_SIGNER <signer ID>
#GPG_RECIPIENT <recipient ID>
KEY fwknoptest
# User-provided named stanzas:
# Example for a destination server of 192.168.1.20 to open access to
# SSH for an IP that is resoved exteranlly, and one with a NAT request
# for a specific source IP that maps port 8088 on the server
# to port 88 on 192.168.1.55 with timeout.
#
#[myssh]
#SPA_SERVER 192.168.1.20
#ACCESS tcp/22
#ALLOW_IP resolve
#
#[mynatreq]
#SPA_SERVER 192.168.1.20
#ACCESS tcp/8088
#ALLOW_IP 10.21.2.6
#NAT_ACCESS 192.168.1.55,88
#CLIENT_TIMEOUT 60
#
###EOF###
+73
View File
@@ -0,0 +1,73 @@
# .fwknoprc
##############################################################################
#
# Firewall Knock Operator (fwknop) client rc file.
#
# This file contains user-specific fwknop client configuration default
# and named parameter sets for specific invocations of the fwknop client.
#
# Each section (or stanza) is identified and started by a line in this
# file that contains a single identifier surrounded by square brackets.
#
# The parameters within the stanza typicaly match corresponding client
# command-line parameters.
#
# The first one should always be `[default]' as it defines the global
# default settings for the user. These override the program defaults
# for these parameter. If a named stanza is used, its entries will
# override any of the default. Command-line options will trump them
# all.
#
# Subsequent stanzas will have only the overriding and destination
# specific parameters.
#
# Lines starting with `#' and empty lines are ignored.
#
# See the fwknop.8 man page for a complete list of valid parameters
# and their values.
#
##############################################################################
#
# We start with the 'default' stanza. Uncomment and edit for your
# preferences. The client will use its build-in default for those items
# that are commented out.
#
[default]
#DIGEST_TYPE sha256
#FW_TIMEOUT 30
#SPA_SERVER_PORT 62201
#SPA_SERVER_PROTO udp
#ALLOW_IP <ip addr>
#SPOOF_USER <username>
#SPOOF_SOURCE_IP <IPaddr>
#TIME_OFFSET 0
#USE_GPG N
#GPG_HOMEDIR /path/to/.gnupg
#GPG_SIGNER <signer ID>
#GPG_RECIPIENT <recipient ID>
# User-provided named stanzas:
# Example for a destination server of 192.168.1.20 to open access to
# SSH for an IP that is resoved exteranlly, and one with a NAT request
# for a specific source IP that maps port 8088 on the server
# to port 88 on 192.168.1.55 with timeout.
#
#[myssh]
#SPA_SERVER 192.168.1.20
#ACCESS tcp/22
#ALLOW_IP resolve
#
#[mynatreq]
#SPA_SERVER 192.168.1.20
#ACCESS tcp/8088
#ALLOW_IP 10.21.2.6
#NAT_ACCESS 192.168.1.55,88
#CLIENT_TIMEOUT 60
#
[testssh]
KEY fwknoptest;
###EOF###
+149
View File
@@ -23,6 +23,7 @@ my $gpg_client_home_dir = "$conf_dir/client-gpg";
my $nat_conf = "$conf_dir/nat_fwknopd.conf";
my $default_conf = "$conf_dir/default_fwknopd.conf";
my $default_access_conf = "$conf_dir/default_access.conf";
my $base64_key_access_conf = "$conf_dir/base64_key_access.conf";
my $ecb_mode_access_conf = "$conf_dir/ecb_mode_access.conf";
my $ctr_mode_access_conf = "$conf_dir/ctr_mode_access.conf";
my $cfb_mode_access_conf = "$conf_dir/cfb_mode_access.conf";
@@ -36,6 +37,10 @@ my $force_nat_access_conf = "$conf_dir/force_nat_access.conf";
my $gpg_access_conf = "$conf_dir/gpg_access.conf";
my $default_digest_file = "$run_dir/digest.cache";
my $default_pid_file = "$run_dir/fwknopd.pid";
my $tmp_rc_file = "$run_dir/fwknoprc";
my $rc_file_default_key = "$conf_dir/fwknoprc_with_default_key";
my $rc_file_default_base64_key = "$conf_dir/fwknoprc_with_default_base64_key";
my $rc_file_named_key = "$conf_dir/fwknoprc_with_named_key";
my $open_ports_access_conf = "$conf_dir/open_ports_access.conf";
my $multi_gpg_access_conf = "$conf_dir/multi_gpg_access.conf";
my $multi_stanzas_access_conf = "$conf_dir/multi_stanzas_access.conf";
@@ -145,11 +150,20 @@ my $default_client_args = "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
"$local_key_file --no-save-args --verbose --verbose";
my $default_client_args_no_get_key = "LD_LIBRARY_PATH=$lib_dir " .
"$valgrind_str $fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip " .
"--no-save-args --verbose --verbose";
my $default_client_gpg_args = "$default_client_args " .
"--gpg-recipient-key $gpg_server_key " .
"--gpg-signer-key $gpg_client_key " .
"--gpg-home-dir $gpg_client_home_dir";
my $default_client_gpg_args_no_get_key = "$default_client_args_no_get_key " .
"--gpg-recipient-key $gpg_server_key " .
"--gpg-signer-key $gpg_client_key " .
"--gpg-home-dir $gpg_client_home_dir";
my $default_server_conf_args = "-c $default_conf -a $default_access_conf " .
"-d $default_digest_file -p $default_pid_file";
@@ -612,6 +626,82 @@ my @tests = (
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'create rc file (tcp/22 ssh)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "$default_client_args --rc-file $tmp_rc_file",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'basic operations',
'subcategory' => 'client',
'detail' => "rc file created",
'err_msg' => "rc file $tmp_rc_file does not exist",
'function' => \&rc_file_exists,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'rc file default key (tcp/22 ssh)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "$default_client_args_no_get_key " .
"--rc-file $rc_file_default_key",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'rc file base64 key (tcp/22 ssh)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "$default_client_args_no_get_key " .
"--rc-file $rc_file_default_base64_key",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $default_conf -a $base64_key_access_conf " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'rc file named key (tcp/22 ssh)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "$default_client_args_no_get_key " .
"--rc-file $rc_file_named_key -n testssh",
'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd $default_server_conf_args $intf_str",
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
'detail' => 'rc file invalid stanza (tcp/22 ssh)',
'err_msg' => 'SPA packet generated/accepted',
'function' => \&generic_exec,
'cmdline' => "$default_client_args_no_get_key " .
"--rc-file $rc_file_named_key -n invalidstanza",
'positive_output_matches' => [qr/Named\sconfiguration.*not\sfound/],
'fatal' => $NO
},
{
'category' => 'Rijndael SPA',
'subcategory' => 'client+server',
@@ -1201,6 +1291,32 @@ my @tests = (
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GnuPG (GPG) SPA',
'subcategory' => 'client+server',
'detail' => 'rc file default key (tcp/22 ssh)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "$default_client_gpg_args_no_get_key " .
"--rc-file $rc_file_default_key",
'fwknopd_cmdline' => $default_server_gpg_args,
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GnuPG (GPG) SPA',
'subcategory' => 'client+server',
'detail' => 'rc file named key (tcp/22 ssh)',
'err_msg' => 'could not complete SPA cycle',
'function' => \&spa_cycle,
'cmdline' => "$default_client_gpg_args_no_get_key " .
"--rc-file $rc_file_named_key -n testssh",
'fwknopd_cmdline' => $default_server_gpg_args,
'fw_rule_created' => $NEW_RULE_REQUIRED,
'fw_rule_removed' => $NEW_RULE_REMOVED,
'fatal' => $NO
},
{
'category' => 'GnuPG (GPG) SPA',
'subcategory' => 'client+server',
@@ -1683,6 +1799,18 @@ sub spa_cycle() {
$rv = 0 if $fw_rule_removed;
}
if ($test_hr->{'client_positive_output_matches'}) {
$rv = 0 unless &file_find_regex(
$test_hr->{'client_positive_output_matches'},
$current_test_file);
}
if ($test_hr->{'client_negative_output_matches'}) {
$rv = 0 if &file_find_regex(
$test_hr->{'client_negative_output_matches'},
$current_test_file);
}
if ($test_hr->{'server_positive_output_matches'}) {
$rv = 0 unless &file_find_regex(
$test_hr->{'server_positive_output_matches'},
@@ -2256,6 +2384,24 @@ sub send_packets() {
return;
}
sub rc_file_exists() {
my $test_hr = shift;
my $rv = 1;
if (-e $tmp_rc_file) {
$rv = 0 unless &file_find_regex([qr/This\sfile\scontains/],
$tmp_rc_file);
} else {
&write_test_file("[-] $tmp_rc_file does not exist.\n",
$current_test_file);
$rv = 0;
}
return $rv;
}
sub generic_exec() {
my $test_hr = shift;
@@ -2623,6 +2769,9 @@ sub init() {
if (-e "$output_dir/init") {
unlink "$output_dir/init" or die $!;
}
if (-e $tmp_rc_file) {
unlink $tmp_rc_file or die $!;
}
if (-e $logfile) {
unlink $logfile or die $!;