Added .fwknoprc file creation and processing. This allows for saved default and named configuration profiles. Updated fwknop manpage to reflect the new capability. Also cleaned up messages (errors, info) from the program.

git-svn-id: file:///home/mbr/svn/fwknop/trunk@234 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart
2010-07-05 22:49:03 +00:00
parent a1531a56e3
commit 5035cf0fed
12 changed files with 854 additions and 101 deletions

39
README
View File

@@ -13,15 +13,20 @@ it is all about, go to http://www.cipherdyne.org/fwknop.
CURRENT STATE
=============
At present, we have an initial implementation of the Firewall Knock
Operator library; `libfko'. This library provides the back-end functionality
for managing the Single Packet Authorization (SPA) data that fwknop
employs.
At present, we have an implementation of the Firewall Knock Operator
library; `libfko', as well as the fwknop client and server applications.
The library provides the API and back-end functionality for managing the
Single Packet Authorization (SPA) data that the other fwknop components
employ. It also can be used by other programs that need SPA functonality
(see the `perl' directory for the FKO perl module as an example).
This first version is planned to be compatible with fwknop version 1.9.x.
This first version of the C implementation is planned to be compatible
with legacy Perl-based fwknop version 1.9.x. However, it was decided to
start the version number at 2.0.0 to differentiate it from the current
Perl implementation.
BUILDING libfko
BUILDING fwknop
===============
This distribution uses GNU autoconf for setting up the build. Please see
the `INSTALL' file for the general basics on using autoconf.
@@ -29,6 +34,10 @@ the `INSTALL' file for the general basics on using autoconf.
There are some "configure" options that are specific to fwknop. They are
(extracted from ./configure --help):
--disable-client Do not build the fwknop client component. The
default is to build the client.
--disable-server Do not build the fwknop server component. The
default is to build the server.
--with-gpgme support for gpg encryption using libgpgme
[default=check]
--with-gpgme-prefix=PFX prefix where GPGME is installed (optional)
@@ -44,6 +53,24 @@ There are some "configure" options that are specific to fwknop. They are
path]
NOTE to those who may be migrating from the Perl version of fwknop
==================================================================
For those of you who are currently using the Perl version and plan to
migrate to this version, there are some things to be aware of:
- Not all of the features and functionality of the Perl-based
fwknop were ported to this implementation. We felt it important
to keep the C version as lean and lightweight as possible. Most
of the omitted feature/functions (like email alerts) can be
accomplished through other means (i.e. use an external script
to monitor log files and alert based on appropriate log messages).
- There are some diffences in the fwknop configuration and access
file directives and values. Some of these are fairly subtle. You
should pay careful attention to the documentation and comments in
those files.
NOTE FOR DEVELOPERS
===================
If you are pulling this distribution from Subversion, you will need to

3
TODO
View File

@@ -10,7 +10,6 @@ To whom it may concern, this is -*- outline -*- mode.
* The fwknopd server:
** Sniffer support to acquire SPA packet data ala the fwknopd Perl server:
*** Packets acquired via a file (supports the ulogd pcap writer).
** SPA packet decryption:
*** Add support for ipfw and pf support eventually.
** Test on embedded platforms - especially OpenWRT on a Linksys router.
@@ -30,7 +29,7 @@ To whom it may concern, this is -*- outline -*- mode.
*** PHP module wrapping libfko.
Copyright 2009 - Damien Stuart
Copyright 2009-2010 - Damien Stuart
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without

View File

@@ -29,6 +29,44 @@
#include "utils.h"
#include "ctype.h"
/* Convert a digest_type string to its intger value.
*/
static int
digest_strtoint(char *dt_str)
{
if(strcasecmp(dt_str, "md5") == 0)
return(FKO_DIGEST_MD5);
else if(strcasecmp(dt_str, "sha1") == 0)
return(FKO_DIGEST_SHA1);
else if(strcasecmp(dt_str, "sha256") == 0)
return(FKO_DIGEST_SHA256);
else if(strcasecmp(dt_str, "sha384") == 0)
return(FKO_DIGEST_SHA384);
else if(strcasecmp(dt_str, "sha512") == 0)
return(FKO_DIGEST_SHA512);
else
return(-1);
}
/* Convert a protocol string to its intger value.
*/
static int
proto_strtoint(char *pr_str)
{
if (strcasecmp(optarg, "udp") == 0)
return(FKO_PROTO_UDP);
else if (strcasecmp(optarg, "tcpraw") == 0)
return(FKO_PROTO_TCP_RAW);
else if (strcasecmp(optarg, "tcp") == 0)
return(FKO_PROTO_TCP);
else if (strcasecmp(optarg, "icmp") == 0)
return(FKO_PROTO_ICMP);
else if (strcasecmp(optarg, "http") == 0)
return(FKO_PROTO_HTTP);
else
return(-1);
}
/* Parse any time offset from the command line
*/
static int
@@ -61,14 +99,14 @@ parse_time_offset(char *offset_str)
offset_digits[j] = '\0';
if (j < 1) {
fprintf(stderr, "[*] Invalid time offset: %s", offset_str);
fprintf(stderr, "Invalid time offset: %s", offset_str);
exit(EXIT_FAILURE);
}
offset = atoi(offset_digits);
if (offset < 0) {
fprintf(stderr, "[*] Invalid time offset: %s", offset_str);
fprintf(stderr, "Invalid time offset: %s", offset_str);
exit(EXIT_FAILURE);
}
@@ -79,6 +117,393 @@ parse_time_offset(char *offset_str)
return offset;
}
static int
create_fwknoprc(char *rcfile)
{
FILE *rc;
int res;
fprintf(stderr, "Creating initial rc file: %s.\n", rcfile);
if ((rc = fopen(rcfile, "w")) == NULL)
{
fprintf(stderr, "Unable to create rc file: %s: %s\n",
rcfile, strerror(errno));
return(-1);
}
fprintf(rc,
"# .fwknoprc\n"
"##############################################################################\n"
"#\n"
"# Firewall Knock Operator (fwknop) client rc file.\n"
"#\n"
"# This file contains user-specific fwknop client configuration default\n"
"# and named parameter sets for specific invocations of the fwknop client.\n"
"#\n"
"# Each section (or stanza) is identified and started by a line in this\n"
"# file that contains a single identifier surrounded by square brackets.\n"
"#\n"
"# The parameters within the stanza typicaly match corresponding client \n"
"# command-line parameters.\n"
"#\n"
"# The first one should always be `[default]' as it defines the global\n"
"# default settings for the user. These override the program defaults\n"
"# for these parameter. If a named stanza is used, its entries will\n"
"# override any of the default. Command-line options will trump them\n"
"# all.\n"
"#\n"
"# Subsequent stanzas will have only the overriding and destination\n"
"# specific parameters.\n"
"#\n"
"# Lines starting with `#' and empty lines are ignored.\n"
"#\n"
"# See the fwknop.8 man page for a complete list of valid parameters\n"
"# and thier values.\n"
"#\n"
"##############################################################################\n"
"#\n"
"# We start with the 'default' stanza. Uncomment and edit for your\n"
"# preferences. The client will use its build-in default for those items\n"
"# that are commented out.\n"
"#\n"
"[default]\n"
"\n"
"#DIGEST_TYPE sha256\n"
"#FW_TIMEOUT 30\n"
"#SPA_SERVER_PORT 62201\n"
"#SPA_SERVER_PROTO udp\n"
"#ALLOW_IP <ip addr>\n"
"#SPOOF_USER <username>\n"
"#SPOOF_SOURCE_IP <IPaddr>\n"
"#TIME_OFFSET 0\n"
"#USE_GPG N\n"
"#GPG_HOMEDIR /path/to/.gnupg\n"
"#GPG_SIGNER <signer ID>\n"
"#GPG_RECIPIENT <recipient ID>\n"
"\n"
"# User-provided named stanzas:\n"
"\n"
"# Example for a destination server of 192.168.1.20 to open access to \n"
"# SSH for an IP that is resoved exteranlly, and one with a nat request\n"
"# for a specific source IP that maps port 8088 on the server\n"
"# to port 88 on 192.168.1.55 with timeout.\n"
"#\n"
"#[myssh]\n"
"#SPA_SERVER 192.168.1.20\n"
"#ACCESS tcp/22\n"
"#RESOLVE_IP_HTTP Y\n"
"#\n"
"#[mynatreq]\n"
"#SERVER 192.168.1.20\n"
"#ACCESS tcp/8088\n"
"#ALLOW_IP 10.21.2.6\n"
"#NAT_ACCESS 192.168.1.55,88\n"
"#CLIENT_TIMEOUT 60\n"
"#\n"
"\n"
"###EOF###\n"
);
return(0);
}
static int
parse_rc_param(fko_cli_options_t *options, char *var, char * val)
{
int tmpint;
/* Digest Type */
if(CONF_VAR_IS(var, "DIGEST_TYPE"))
{
tmpint = digest_strtoint(val);
if(tmpint < 0)
return(-1);
else
options->digest_type = tmpint;
}
/* Server protocol */
else if(CONF_VAR_IS(var, "SPA_SERVER_PROTO"))
{
tmpint = proto_strtoint(val);
if(tmpint < 0)
return(-1);
else
options->spa_proto = tmpint;
}
/* Server port */
else if(CONF_VAR_IS(var, "SPA_SERVER_PORT"))
{
tmpint = atoi(val);
if(tmpint < 0 || tmpint > 65535)
return(-1);
else
options->spa_dst_port = tmpint;
}
/* Source port */
else if(CONF_VAR_IS(var, "SPA_SOURCE_PORT"))
{
tmpint = atoi(val);
if(tmpint < 0 || tmpint > 65535)
return(-1);
else
options->spa_src_port = tmpint;
}
/* Firewall rule timeout */
else if(CONF_VAR_IS(var, "FW_TIMEOUT"))
{
tmpint = atoi(val);
if(tmpint < 0)
return(-1);
else
options->fw_timeout = tmpint;
}
/* Allow IP */
else if(CONF_VAR_IS(var, "ALLOW_IP"))
{
/* use source, resolve, or an actual IP
*/
if(strcasecmp(val, "source") == 0)
strlcpy(options->allow_ip_str, "0.0.0.0", 8);
else if(strcasecmp(val, "resolve") == 0)
options->resolve_ip_http = 1;
else /* Assume IP address */
strlcpy(options->allow_ip_str, val, MAX_IP_STR_LEN);
}
/* Time Offset */
else if(CONF_VAR_IS(var, "TIME_OFFSET"))
{
if(val[0] == '-')
{
val++;
options->time_offset_minus = parse_time_offset(val);
}
else
options->time_offset_plus = parse_time_offset(val);
}
/* Use GPG ? */
else if(CONF_VAR_IS(var, "USE_GPG"))
{
if(val[0] == 'y' || val[0] == 'Y')
options->use_gpg = 1;
}
/* GPG Recipient */
else if(CONF_VAR_IS(var, "GPG_RECIPIENT"))
{
strlcpy(options->gpg_recipient_key, val, MAX_GPG_KEY_ID);
}
/* GPG Signer */
else if(CONF_VAR_IS(var, "GPG_SIGNER"))
{
strlcpy(options->gpg_signer_key, val, MAX_GPG_KEY_ID);
}
/* GPG Homedir */
else if(CONF_VAR_IS(var, "GPG_HOMEDIR"))
{
strlcpy(options->gpg_home_dir, val, MAX_PATH_LEN);
}
/* Spoof User */
else if(CONF_VAR_IS(var, "SPOOF_USER"))
{
strlcpy(options->spoof_user, val, MAX_USERNAME_LEN);
}
/* Spoof Source IP */
else if(CONF_VAR_IS(var, "SPOOF_SOURCE_IP"))
{
strlcpy(options->spoof_ip_src_str, val, MAX_IP_STR_LEN);
}
/* ACCESS request */
else if(CONF_VAR_IS(var, "ACCESS"))
{
strlcpy(options->access_str, val, MAX_LINE_LEN);
}
/* SPA Server (destination) */
else if(CONF_VAR_IS(var, "SPA_SERVER"))
{
strlcpy(options->spa_server_str, val, MAX_SERVER_STR_LEN);
}
/* Rand port ? */
else if(CONF_VAR_IS(var, "RAND_PORT"))
{
if(val[0] == 'y' || val[0] == 'Y')
options->rand_port = 1;
}
/* Key file */
else if(CONF_VAR_IS(var, "KEY_FILE"))
{
strlcpy(options->get_key_file, val, MAX_PATH_LEN);
}
/* NAT Access Request */
else if(CONF_VAR_IS(var, "NAT_ACCESS"))
{
strlcpy(options->nat_access_str, val, MAX_PATH_LEN);
}
/* HTTP User Agent */
else if(CONF_VAR_IS(var, "HTTP_USER_AGENT"))
{
strlcpy(options->http_user_agent, val, HTTP_MAX_USER_AGENT_LEN);
}
/* NAT Local ? */
else if(CONF_VAR_IS(var, "NAT_LOCAL"))
{
if(val[0] == 'y' || val[0] == 'Y')
options->nat_local = 1;
}
/* NAT rand port ? */
else if(CONF_VAR_IS(var, "NAT_RAND_PORT"))
{
if(val[0] == 'y' || val[0] == 'Y')
options->nat_rand_port = 1;
}
/* NAT port */
else if(CONF_VAR_IS(var, "NAT_PORT"))
{
tmpint = atoi(val);
if(tmpint < 0 || tmpint > 65535)
return(-1);
else
options->nat_port = tmpint;
}
return(0);
}
/* Process (create if necessary) the users ~/.fwknoprc file.
*/
static void
process_rc(fko_cli_options_t *options)
{
FILE *rc;
int tmpint, line_num = 0;
char rcfile[MAX_PATH_LEN];
char line[MAX_LINE_LEN];
char curr_stanza[MAX_LINE_LEN] = {0};
char var[MAX_LINE_LEN] = {0};
char val[MAX_LINE_LEN] = {0};
char *ndx, *emark, *homedir = getenv("HOME");
if(homedir == NULL)
{
fprintf(stderr, "Warning: Unable to determine HOME directory.\n"
" No .fwknoprc file processed.\n");
return;
}
strlcpy(rcfile, homedir, MAX_PATH_LEN);
strlcat(rcfile, PATH_SEP);
strlcat(rcfile, ".fwknoprc");
/* Open the rc file for reading, if it does not exist, then create
* an initial .fwknoprc file with defaults and go on.
*/
if ((rc = fopen(rcfile, "r")) == NULL)
{
if(errno == ENOENT)
{
if(create_fwknoprc(rcfile) != 0)
return;
}
else
fprintf(stderr, "Unable to open rc file: %s: %s\n",
rcfile, strerror(errno));
return;
}
/* Read in and parse the rc file parameters.
*/
while ((fgets(line, MAX_LINE_LEN, rc)) != NULL)
{
line_num++;
line[MAX_LINE_LEN-1] = '\0';
ndx = line;
/* Skip any leading whitespace.
*/
while(isspace(*ndx))
ndx++;
/* Get past comments and empty lines (note: we only look at the
* first character.
*/
if(IS_EMPTY_LINE(line[0]))
continue;
if(*ndx == '[')
{
ndx++;
emark = strchr(ndx, ']');
if(emark == NULL)
{
fprintf(stderr, "Unterminated stanza line: '%s'. Skipping.\n",
line);
continue;
}
*emark = '\0';
strlcpy(curr_stanza, ndx, MAX_LINE_LEN);
if(options->verbose > 3)
fprintf(stderr,
"RC FILE: %s, LINE: %s\tSTANZA: %s:\n",
rcfile, line, curr_stanza
);
continue;
}
if(sscanf(line, "%s %[^;\n\r#]", var, val) != 2)
{
fprintf(stderr,
"*Invalid entry in %s at line %i.\n - '%s'",
rcfile, line_num, line
);
continue;
}
/* Remove any colon that may be on the end of the var
*/
if((ndx = strrchr(var, ':')) != NULL)
*ndx = '\0';
if(options->verbose > 3)
fprintf(stderr,
"RC FILE: %s, LINE: %s\tVar: %s, Val: '%s'\n",
rcfile, line, var, val
);
/* We do not proceed with parsing until we know we are in
* a stanza.
*/
if(strlen(curr_stanza) < 1)
continue;
/* Process the values. We assume we will see the default stanza
* first, then if a named-stanza is specified, we process its
* entries as well.
*/
if(strcasecmp(curr_stanza, "default") == 0 || (options->use_rc_stanza[0] != '\0'
&& strncasecmp(curr_stanza, options->use_rc_stanza, MAX_LINE_LEN)==0))
{
if(parse_rc_param(options, var, val) < 0)
fprintf(stderr, "Parameter error in %s, line %i: var=%s, val=%i\n",
rcfile, line_num, var, val);
}
else if(options->use_rc_stanza[0] != '\0'
&& strncasecmp(curr_stanza, options->use_rc_stanza, MAX_LINE_LEN)==0)
{
options->got_named_stanza = 1;
if(parse_rc_param(options, var, val) < 0)
fprintf(stderr, "Parameter error in %s, stanza: %s, line %i: var=%s, val=%i\n",
rcfile, curr_stanza, line_num, var, val);
}
} /* end while fgets rc */
}
/* Sanity and bounds checks for the various options.
*/
static void
@@ -92,19 +517,27 @@ validate_options(fko_cli_options_t *options)
&& !options->show_last_command
&& !options->run_last_command)
{
if (options->spa_server_str[0] == 0x0)
if(options->use_rc_stanza[0] != 0x0 && options->got_named_stanza == 0)
{
fprintf(stderr,
"[*] Must use --destination unless --test mode is used\n");
exit(EXIT_FAILURE);
}
if (!options->resolve_ip_http && options->allow_ip_str[0] == 0x0)
{
fprintf(stderr,
"[*] Must use one of [-s|-R|-a] to specify IP for SPA access.\n");
fprintf(stderr, "Named configuration stanza: [%s] was not found.\n",
options->use_rc_stanza);
exit(EXIT_FAILURE);
}
if (options->spa_server_str[0] == 0x0)
{
fprintf(stderr,
"Must use --destination unless --test mode is used\n");
exit(EXIT_FAILURE);
}
if (!options->resolve_ip_http && options->allow_ip_str[0] == 0x0)
{
fprintf(stderr,
"Must use one of [-s|-R|-a] to specify IP for SPA access.\n");
exit(EXIT_FAILURE);
}
}
if(options->resolve_ip_http || options->spa_proto == FKO_PROTO_HTTP)
@@ -115,7 +548,7 @@ validate_options(fko_cli_options_t *options)
if(options->http_proxy[0] != 0x0 && options->spa_proto != FKO_PROTO_HTTP)
{
fprintf(stderr,
"[*] Cannot set --http-proxy with a non-HTTP protocol.\n");
"Cannot set --http-proxy with a non-HTTP protocol.\n");
exit(EXIT_FAILURE);
}
@@ -127,7 +560,7 @@ validate_options(fko_cli_options_t *options)
|| strlen(options->gpg_recipient_key) == 0)
{
fprintf(stderr,
"[*] Must specify --gpg-recipient-key when GPG is used.\n");
"Must specify --gpg-recipient-key when GPG is used.\n");
exit(EXIT_FAILURE);
}
}
@@ -154,6 +587,33 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
options->spa_dst_port = FKO_DEFAULT_PORT;
options->fw_timeout = -1;
/* 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,
GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
switch(cmd_arg) {
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'n':
options->no_save_args = 1;
strlcpy(options->use_rc_stanza, optarg, MAX_LINE_LEN);
break;
case 'v':
options->verbose++;
break;
}
}
/* First process the .fwknoprc file.
*/
process_rc(options);
/* Reset the options index so we can run through them again.
*/
optind = 0;
while ((cmd_arg = getopt_long(argc, argv,
GETOPTS_OPTION_STRING, cmd_opts, &index)) != -1) {
@@ -179,7 +639,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case 'f':
options->fw_timeout = atoi(optarg);
if (options->fw_timeout < 0) {
fprintf(stderr, "[*] --fw-timeout must be >= 0\n");
fprintf(stderr, "--fw-timeout must be >= 0\n");
exit(EXIT_FAILURE);
}
break;
@@ -202,48 +662,34 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
break;
case 'm':
case FKO_DIGEST_NAME:
if(strncasecmp(optarg, "md5", 3) == 0)
options->digest_type = FKO_DIGEST_MD5;
else if(strncasecmp(optarg, "sha1", 4) == 0)
options->digest_type = FKO_DIGEST_SHA1;
else if(strncasecmp(optarg, "sha256", 6) == 0)
options->digest_type = FKO_DIGEST_SHA256;
else if(strncasecmp(optarg, "sha384", 6) == 0)
options->digest_type = FKO_DIGEST_SHA384;
else if(strncasecmp(optarg, "sha512", 6) == 0)
options->digest_type = FKO_DIGEST_SHA512;
else
if((options->digest_type = digest_strtoint(optarg)) < 0)
{
fprintf(stderr, "* Invalid digest type: %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case 'NO_SAVE_ARGS':
options->no_save_args = 1;
break;
case 'n':
options->no_save = 1;
/* We already handled this earlier, so we do nothing here
*/
break;
case 'N':
strlcpy(options->nat_access_str, optarg, MAX_LINE_LEN);
break;
case 'p':
options->spa_dst_port = atoi(optarg);
if (options->spa_dst_port < 0 || options->spa_dst_port > 65535) {
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
if (options->spa_dst_port < 0 || options->spa_dst_port > 65535)
{
fprintf(stderr, "Unrecognized port: %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case 'P':
if (strncmp(optarg, "udp", strlen("udp")) == 0)
options->spa_proto = FKO_PROTO_UDP;
else if (strncmp(optarg, "tcpraw", strlen("tcpraw")) == 0)
options->spa_proto = FKO_PROTO_TCP_RAW;
else if (strncmp(optarg, "tcp", strlen("tcp")) == 0)
options->spa_proto = FKO_PROTO_TCP;
else if (strncmp(optarg, "icmp", strlen("icmp")) == 0)
options->spa_proto = FKO_PROTO_ICMP;
else if (strncmp(optarg, "http", strlen("http")) == 0)
options->spa_proto = FKO_PROTO_HTTP;
else {
fprintf(stderr, "[*] Unrecognized protocol: %s\n", optarg);
if((options->spa_proto = proto_strtoint(optarg)) < 0)
{
fprintf(stderr, "Unrecognized protocol: %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
@@ -264,8 +710,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
break;
case 'S':
options->spa_src_port = atoi(optarg);
if (options->spa_src_port < 0 || options->spa_src_port > 65535) {
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
if (options->spa_src_port < 0 || options->spa_src_port > 65535)
{
fprintf(stderr, "Unrecognized port: %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
@@ -279,7 +726,8 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
strlcpy(options->spoof_user, optarg, MAX_USERNAME_LEN);
break;
case 'v':
options->verbose = 1;
/* Handled earlier.
*/
break;
case 'V':
options->version = 1;
@@ -308,8 +756,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
break;
case NAT_PORT:
options->nat_port = atoi(optarg);
if (options->nat_port < 0 || options->nat_port > 65535) {
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
if (options->nat_port < 0 || options->nat_port > 65535)
{
fprintf(stderr, "Unrecognized port: %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
@@ -353,6 +802,9 @@ usage(void)
" -C, --server-cmd Specify a command that the fwknop server will\n"
" execute on behalf of the fwknop client..\n"
" -D, --destination Specify the IP address of the fwknop server.\n"
" -n, --named-config Specify an named configuration stanza in the\n"
" '$HOME/.fwknoprc' file to provide some of all\n"
" of the configuration parameters.\n"
" -N, --nat-access Gain NAT access to an internal service\n"
" protected by the fwknop server.\n"
" -p, --server-port Set the destination port for outgoing SPA\n"

View File

@@ -29,6 +29,10 @@
#include <getopt.h>
#include <sys/stat.h>
/* String compare macro.
*/
#define CONF_VAR_IS(n, v) (strcmp(n, v) == 0)
/* Long options values (for those without a short option).
*/
enum {
@@ -51,7 +55,7 @@ enum {
/* Our getopt_long options string.
*/
#define GETOPTS_OPTION_STRING "a:A:bB:C:D:f:gG:hH:lm:nN:p:P:Q:rRsS:Tu:U:vV"
#define GETOPTS_OPTION_STRING "a:A:bB:C:D:f:gG:hH:lm:n:N:p:P:Q:rRsS:Tu:U:vV"
/* Our program command-line options...
*/
@@ -76,6 +80,7 @@ static struct option cmd_opts[] =
{"http-proxy", 1, NULL, 'H'},
{"last-cmd", 0, NULL, 'l'},
{"nat-access", 1, NULL, 'N'},
{"named-config", 1, NULL, 'n'},
{"nat-local", 0, NULL, NAT_LOCAL},
{"nat-port", 1, NULL, NAT_PORT},
{"nat-rand-port", 0, NULL, NAT_RAND_PORT},

View File

@@ -2,12 +2,12 @@
.\" Title: fwknop
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" Date: 06/27/2010
.\" Date: 07/05/2010
.\" Manual: Fwknop Client
.\" Source: Fwknop Client
.\" Language: English
.\"
.TH "FWKNOP" "8" "06/27/2010" "Fwknop Client" "Fwknop Client"
.TH "FWKNOP" "8" "07/05/2010" "Fwknop Client" "Fwknop Client"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
@@ -126,6 +126,13 @@ with the command\-line arguments from the previous invocation (if any)\&. The pr
file\&.
.RE
.PP
\fB\-n, \-\-named\-config\fR=\fI<stanza name>\fR
.RS 4
The
\fBfwknop\fR
client program can use parameters specified in it rc file, \(oq`\&.fwknoprc\'\' which is found in the user\'s home directory\&. If *fwknop* does not detect the $HOME/\&.fwknoprc file, it will create it\&. The \'\&.fwkoprc\' file contains a default configuration area or \'stanza\' which holds global configuration directives that override the program defaults\&. You can edit this file and create additonal \'named stanzas\' that can be specified with this (\'\-n\') option\&. Parameters defined in the named stanzas will override any matching \'default\' stanza directives\&. See the section: FWKNOPRC FILE below for a list of the valid configuration directives in the ``\&.fwknoprc\(cq\' file\&.
.RE
.PP
\fB\-\-show\-last\fR
.RS 4
Display the last command\-line arguments used by
@@ -408,6 +415,139 @@ Specify the GnuPG key ID, e\&.g\&. \(oq`+ABCD1234+\'\' (see the output of ``gpg
\fBfwknopd\fR
daemon on the remote server to authenticate who created the SPA message\&.
.RE
.SH "FWKNOPRC FILE"
.sp
The \(lq\&.fwknoprc\(rq file is used to set various parameters to override default program parameters at runtime\&. It also allows for additional named configuration \fIstanzas\fR for setting program parameters for a particular invocation\&.
.sp
The \fBfwkop\fR client will create this file if it does not exist in the user\(cqs home directory\&. This initial version has some sample directives that are commented out\&. It is up to the user to edit this file to meet their needs\&.
.sp
There are directives to match most of the command\-line parameters \fBfwknop\fR supports\&. Here is the current list of each directive along with a brief description and (if applicable) it matching command\-line option:
.PP
\fBDIGEST_TYPE\fR
.RS 4
Set the SPA message digest type (\'\-m, \-\-digest\-type)\&.
.RE
.PP
\fBSPA_SERVER_PROTO\fR
.RS 4
Set the protocol to use for sending the SPA packet (\fI\-P, \-\-server\-proto\fR)\&.
.RE
.PP
\fBSPA_SERVER\fR
.RS 4
Specify the IP or hostname of the destination (\fBfwknopd\fR) server (\'\-D, \-\-destination)\&.
.RE
.PP
\fBSPA_SERVER_PORT\fR
.RS 4
Set the server port to use for sending the SPA packet (\fI\-p, \-\-server\-port\fR)\&.
.RE
.PP
\fBSPA_SOURCE_PORT\fR
.RS 4
Set the source port to use for sending the SPA packet (\fI\-S, \-\-source\-port\fR)\&.
.RE
.PP
\fBFW_TIMEOUT\fR
.RS 4
Set the firewall rule timeout value (\fI\-f, \-\-fw\-timeout\fR)\&.
.RE
.PP
\fBALLOW_IP\fR
.RS 4
Specify the address to allow within the SPA data\&. Note: This parameter covers the
\fI\-a\fR,
\fI\-s\fR, and
\fI\-R\fR
command\-line options\&. You can specify an IP address (the
\fI\-a\fR
option), specify the word "source" to tell the
\fBfwknopd\fR
server to accept the source IP of the packet as the IP to allow (the
\fI\-s\fR
option), or use the word "resolve" to have
\fBfwknop\fR
resolve the external network IP via HTTP request (the
\fI\-R\fR
option)\&.
.RE
.PP
\fBTIME_OFFSET\fR
.RS 4
Set a value to apply to the timestamp in the SPA packet\&. This can be either a positive or negative value (\fI\-\-time\-offset\-plus/minus\fR)\&.
.RE
.PP
\fBUSE_GPG\fR
.RS 4
Set to
\fIY\fR
to specify the use of GPG for encryption (\fI\-\-gpg\-encryption\fR)\&.
.RE
.PP
\fBGPG_SIGNER\fR
.RS 4
Specify the GPG key name or ID for signing the GPG\-encrypted SPA data (\fI\-\-gpg\-signer\-key\fR)\&.
.RE
.PP
\fBGPG_RECIPIENT\fR
.RS 4
Specify the GPG key name or ID for the recipient of the GPG\-encrypted SPA data (\fI\-\-gpg\-recipient\-key\fR)\&.
.RE
.PP
\fBGPG_HOMEDIR\fR
.RS 4
Specify the GPG home directory (\fI\-\-gpg\-home\-dir\fR)\&.
.RE
.PP
\fBSPOOF_USER\fR
.RS 4
Set the username in the SPA data to the specified value (\fI\-U, \-\-spoof\-user\fR)\&.
.RE
.PP
\fBSPOOF_SOURCE_IP\fR
.RS 4
Set the source IP of the outgoing SPA packet to the specified value (\fI\-Q, \-\-spoof\-source\fR)\&.
.RE
.PP
\fBACCESS\fR
.RS 4
Set the one or more protocol/ports to open on the firewall (\fI\-A, \-\-access\fR)\&.
.RE
.PP
\fBRAND_PORT\fR
.RS 4
Send the SPA packet over a randomly assigned port (\fI\-r, \-\-rand\-port\fR)\&.
.RE
.PP
\fBKEY_FILE\fR
.RS 4
Load an encryption key/password from a file (\fI\-G, \-\-get\-key\fR)\&.
.RE
.PP
\fBHTTP_USER_AGENT\fR
.RS 4
Set the HTTP User\-Agent for resolving the external IP via \-R, or for sending SPA packets over HTTP (\fI\-u, \-\-user\-agent\fR)\&.
.RE
.PP
\fBNAT_ACCESS\fR
.RS 4
Gain NAT access to an internal service protected by the fwknop server (\fI\-N, \-\-nat\-access\fR)\&.
.RE
.PP
\fBNAT_LOCAL\fR
.RS 4
Access a local service via a forwarded port on the fwknopd server system (\fI\-\-nat\-local\fR)\&.
.RE
.PP
\fBNAT_PORT\fR
.RS 4
Specify the port to forward to access a service via NAT (\fI\-\-nat\-port\fR)\&.
.RE
.PP
\fBNAT_RAND_PORT\fR
.RS 4
Have the fwknop client assign a random port for NAT access (\fI\-\-nat\-rand\-port\fR)\&.
.RE
.SH "ENVIRONMENT"
.sp
\fBGPG_AGENT_INFO\fR (only used in \fB\-\-gpg\-agent\fR mode)\&.

View File

@@ -58,6 +58,7 @@ main(int argc, char **argv)
/* Handle command line
*/
config_init(&options, argc, argv);
/* Handle options that don't require a libfko context
*/
if(options.run_last_command)
@@ -81,7 +82,7 @@ main(int argc, char **argv)
if (options.version) {
fko_get_version(ctx, &version);
fprintf(stdout, "[+] fwknop client %s, FKO protocol version %s\n",
fprintf(stdout, "fwknop client %s, FKO protocol version %s\n",
MY_VERSION, version);
return(EXIT_SUCCESS);
@@ -274,13 +275,13 @@ main(int argc, char **argv)
res = send_spa_packet(ctx, &options);
if(res < 0)
{
fprintf(stderr, "[*] send_spa_packet: packet not sent.\n");
fprintf(stderr, "send_spa_packet: packet not sent.\n");
return(EXIT_FAILURE);
}
else
{
if(options.verbose)
fprintf(stderr, "[+] send_spa_packet: bytes sent: %i\n", res);
fprintf(stderr, "send_spa_packet: bytes sent: %i\n", res);
}
/* Run through a decode cycle in test mode (--DSS XXX: This test/decode
@@ -346,7 +347,7 @@ main(int argc, char **argv)
* an unrecoverable error), but print the error string for
debugging purposes. */
fprintf(stderr, "GPG ERR: %s\n%s\n", fko_gpg_errstr(ctx2),
"[*] No access to recipient private key?\n");
"No access to recipient private key?\n");
return(EXIT_SUCCESS);
}
@@ -422,7 +423,7 @@ get_rand_port(fko_ctx_t ctx)
static void
dump_transmit_options(fko_cli_options_t *options)
{
printf("[+] Generating SPA packet:\n protocol: ");
printf("Generating SPA packet:\n protocol: ");
print_proto(options->spa_proto),
printf("\n port: %d\n", options->spa_dst_port);
return;
@@ -524,20 +525,20 @@ show_last_command(void)
/* Not sure what the right thing is here on Win32, just exit
* for now.
*/
fprintf(stderr, "[*] --show-last not implemented on Win32 yet.");
fprintf(stderr, "--show-last not implemented on Win32 yet.");
exit(EXIT_FAILURE);
#endif
if (get_save_file(args_save_file)) {
if ((args_file_ptr = fopen(args_save_file, "r")) == NULL) {
fprintf(stderr, "[*] Could not open args file: %s\n",
fprintf(stderr, "Could not open args file: %s\n",
args_save_file);
exit(EXIT_FAILURE);
}
if ((fgets(args_str, MAX_LINE_LEN, args_file_ptr)) != NULL) {
printf("[+] Last fwknop client command line: %s", args_str);
printf("Last fwknop client command line: %s", args_str);
} else {
printf("[-] Could not read line from file: %s\n", args_save_file);
printf("Could not read line from file: %s\n", args_save_file);
}
fclose(args_file_ptr);
}
@@ -573,7 +574,7 @@ run_last_args(fko_cli_options_t *options)
{
if ((args_file_ptr = fopen(args_save_file, "r")) == NULL)
{
fprintf(stderr, "[*] Could not open args file: %s\n",
fprintf(stderr, "Could not open args file: %s\n",
args_save_file);
exit(EXIT_FAILURE);
}
@@ -581,7 +582,7 @@ run_last_args(fko_cli_options_t *options)
{
args_str[MAX_LINE_LEN-1] = '\0';
if (options->verbose)
printf("[+] Executing: %s\n", args_str);
printf("Executing: %s\n", args_str);
for (i=0; i < (int)strlen(args_str); i++)
{
if (!isspace(args_str[i]))
@@ -595,7 +596,7 @@ run_last_args(fko_cli_options_t *options)
argv_new[argc_new] = malloc(strlen(arg_tmp)+1);
if (argv_new[argc_new] == NULL)
{
fprintf(stderr, "[*] malloc failure for cmd line arg.\n");
fprintf(stderr, "malloc failure for cmd line arg.\n");
exit(EXIT_FAILURE);
}
strcpy(argv_new[argc_new], arg_tmp);
@@ -636,14 +637,14 @@ save_args(int argc, char **argv)
if (get_save_file(args_save_file)) {
if ((args_file_ptr = fopen(args_save_file, "w")) == NULL) {
fprintf(stderr, "[*] Could not open args file: %s\n",
fprintf(stderr, "Could not open args file: %s\n",
args_save_file);
exit(EXIT_FAILURE);
}
for (i=0; i < argc; i++) {
args_str_len += strlen(argv[i]);
if (args_str_len >= MAX_PATH_LEN) {
fprintf(stderr, "[*] argument string too long, exiting.\n");
fprintf(stderr, "argument string too long, exiting.\n");
exit(EXIT_FAILURE);
}
strlcat(args_str, argv[i], MAX_PATH_LEN);
@@ -739,7 +740,7 @@ get_user_pw(fko_cli_options_t *options, int crypt_op)
*/
if (pw_ptr == NULL)
{
fprintf(stderr, "[*] Received no password data, exiting.\n");
fprintf(stderr, "Received no password data, exiting.\n");
exit(EXIT_FAILURE);
}
@@ -750,7 +751,7 @@ get_user_pw(fko_cli_options_t *options, int crypt_op)
*/
void
errmsg(char *msg, int err) {
fprintf(stderr, "[*] %s: %s: Error %i - %s\n",
fprintf(stderr, "%s: %s: Error %i - %s\n",
MY_NAME, msg, err, fko_errstr(err));
}

View File

@@ -113,7 +113,6 @@ typedef struct fko_cli_options
/* Various command-line flags */
unsigned char verbose; /* --verbose mode */
unsigned char version; /* --version */
unsigned char no_save;
unsigned char test;
unsigned char use_gpg;
unsigned char use_gpg_agent;
@@ -121,6 +120,9 @@ typedef struct fko_cli_options
int time_offset_minus;
int fw_timeout;
char use_rc_stanza[MAX_LINE_LEN];
unsigned char got_named_stanza;
//char config_file[MAX_PATH_LEN];
} fko_cli_options_t;

View File

@@ -148,7 +148,7 @@ getpasswd_file(const char *pw_file, const char *server_str)
if ((pwfile_ptr = fopen(pw_file, "r")) == NULL)
{
fprintf(stderr, "[*] Could not open config file: %s\n", pw_file);
fprintf(stderr, "Could not open config file: %s\n", pw_file);
exit(1);
}
@@ -202,7 +202,7 @@ getpasswd_file(const char *pw_file, const char *server_str)
fclose(pwfile_ptr);
if (pwbuf[0] == '\0') {
fprintf(stderr, "[*] Could not get password for IP: %s from: %s\n",
fprintf(stderr, "Could not get password for IP: %s from: %s\n",
server_str, pw_file);
exit(1);
}

View File

@@ -57,7 +57,7 @@ resolve_ip_http(fko_cli_options_t *options)
res = WSAStartup( MAKEWORD(1,1), &wsa_data );
if( res != 0 )
{
fprintf(stderr, "[*] Winsock initialization error %d\n", res );
fprintf(stderr, "Winsock initialization error %d\n", res );
return(-1);
}
#endif
@@ -82,7 +82,7 @@ resolve_ip_http(fko_cli_options_t *options)
error = getaddrinfo(HTTP_RESOLVE_HOST, "80", &hints, &result);
if (error != 0)
{
fprintf(stderr, "[*] error in getaddrinfo: %s\n", gai_strerror(error));
fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
return(-1);
}
@@ -103,7 +103,7 @@ resolve_ip_http(fko_cli_options_t *options)
}
if (rp == NULL) {
perror("[*] resolve_ip_http: Could not create socket: ");
perror("resolve_ip_http: Could not create socket: ");
return(-1);
}
@@ -113,7 +113,7 @@ resolve_ip_http(fko_cli_options_t *options)
if(res < 0)
{
perror("[*] resolve_ip_http: write error: ");
perror("resolve_ip_http: write error: ");
}
else if(res != http_buf_len)
{
@@ -137,7 +137,7 @@ resolve_ip_http(fko_cli_options_t *options)
ndx = strstr(http_response, "\r\n\r\n");
if(ndx == NULL)
{
fprintf(stderr, "[*] Did not find the end of HTTP header.\n");
fprintf(stderr, "Did not find the end of HTTP header.\n");
return(-1);
}
ndx += 4;
@@ -167,14 +167,14 @@ resolve_ip_http(fko_cli_options_t *options)
strlcpy(options->allow_ip_str, ndx, MAX_IP_STR_LEN);
if(options->verbose)
printf("[+] Resolved external IP (via http://%s%s) as: %s\n",
printf("Resolved external IP (via http://%s%s) as: %s\n",
HTTP_RESOLVE_HOST, HTTP_RESOLVE_URL, options->allow_ip_str);
return(0);
}
else
{
fprintf(stderr, "[*] Invalid IP (%s) in HTTP response.\n", ndx);
fprintf(stderr, "Invalid IP (%s) in HTTP response.\n", ndx);
return(-1);
}
}

View File

@@ -82,7 +82,7 @@ send_spa_packet_tcp_or_udp(char *spa_data, int sd_len, fko_cli_options_t *option
if (options->test)
{
fprintf(stderr,
"[+] test mode enabled, SPA packet not actually sent.\n");
"test mode enabled, SPA packet not actually sent.\n");
return res;
}
@@ -112,7 +112,7 @@ send_spa_packet_tcp_or_udp(char *spa_data, int sd_len, fko_cli_options_t *option
if (error != 0)
{
fprintf(stderr, "[*] error in getaddrinfo: %s\n", gai_strerror(error));
fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
exit(EXIT_FAILURE);
}
@@ -133,7 +133,7 @@ send_spa_packet_tcp_or_udp(char *spa_data, int sd_len, fko_cli_options_t *option
}
if (rp == NULL) {
perror("[*] send_spa_packet_tcp_or_udp: Could not create socket: ");
perror("send_spa_packet_tcp_or_udp: Could not create socket: ");
exit(EXIT_FAILURE);
}
@@ -143,7 +143,7 @@ send_spa_packet_tcp_or_udp(char *spa_data, int sd_len, fko_cli_options_t *option
if(res < 0)
{
perror("[*] send_spa_packet_tcp_or_udp: write error: ");
perror("send_spa_packet_tcp_or_udp: write error: ");
}
else if(res != sd_len)
{
@@ -170,7 +170,7 @@ send_spa_packet_tcp_raw(char *spa_data, int sd_len, struct sockaddr_in *saddr,
{
#ifdef WIN32
fprintf(stderr,
"[*] send_spa_packet_tcp_raw: raw packets are not yet supported.\n");
"send_spa_packet_tcp_raw: raw packets are not yet supported.\n");
return(-1);
#else
int sock, res = 0;
@@ -189,14 +189,14 @@ send_spa_packet_tcp_raw(char *spa_data, int sd_len, struct sockaddr_in *saddr,
if (options->test)
{
fprintf(stderr,
"[+] test mode enabled, SPA packet not actually sent.\n");
"test mode enabled, SPA packet not actually sent.\n");
return res;
}
sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock < 0)
{
perror("[*] send_spa_packet_tcp_raw: create socket: ");
perror("send_spa_packet_tcp_raw: create socket: ");
return(sock);
}
@@ -250,14 +250,14 @@ send_spa_packet_tcp_raw(char *spa_data, int sd_len, struct sockaddr_in *saddr,
* doesn't try to insert its own header into the packet.
*/
if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, so_val, sizeof(one)) < 0)
perror("[*] send_spa_packet_tcp_raw: setsockopt HDRINCL: ");
perror("send_spa_packet_tcp_raw: setsockopt HDRINCL: ");
res = sendto (sock, pkt_data, iph->tot_len, 0,
(struct sockaddr *)daddr, sizeof(*daddr));
if(res < 0)
{
perror("[*] send_spa_packet_tcp_raw: sendto error: ");
perror("send_spa_packet_tcp_raw: sendto error: ");
}
else if(res != sd_len + hdrlen) /* account for the header ?*/
{
@@ -281,7 +281,7 @@ send_spa_packet_icmp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
struct sockaddr_in *daddr, fko_cli_options_t *options)
{
#ifdef WIN32
fprintf(stderr, "[*] send_spa_packet_icmp: raw packets are not yet supported.\n");
fprintf(stderr, "send_spa_packet_icmp: raw packets are not yet supported.\n");
return(-1);
#else
int res = 0, sock;
@@ -300,7 +300,7 @@ send_spa_packet_icmp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
if (options->test)
{
fprintf(stderr,
"[+] test mode enabled, SPA packet not actually sent.\n");
"test mode enabled, SPA packet not actually sent.\n");
return res;
}
@@ -308,7 +308,7 @@ send_spa_packet_icmp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
if (sock < 0)
{
perror("[*] send_spa_packet_icmp: create socket: ");
perror("send_spa_packet_icmp: create socket: ");
return(sock);
}
@@ -348,14 +348,14 @@ send_spa_packet_icmp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
* doesn't try to insert its own header into the packet.
*/
if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, so_val, sizeof(one)) < 0)
perror("[*] send_spa_packet_icmp: setsockopt HDRINCL: ");
perror("send_spa_packet_icmp: setsockopt HDRINCL: ");
res = sendto (sock, pkt_data, iph->tot_len, 0,
(struct sockaddr *)daddr, sizeof(*daddr));
if(res < 0)
{
perror("[*] send_spa_packet_icmp: sendto error: ");
perror("send_spa_packet_icmp: sendto error: ");
}
else if(res != sd_len + hdrlen) /* account for icmp header */
{
@@ -451,7 +451,7 @@ send_spa_packet_http(char *spa_data, int sd_len, fko_cli_options_t *options)
fprintf(stderr, "%s\n", http_buf);
fprintf(stderr,
"[+] Test mode enabled, SPA packet not actually sent.\n");
"Test mode enabled, SPA packet not actually sent.\n");
return 0;
}
@@ -493,7 +493,7 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
res = WSAStartup( MAKEWORD(1,1), &wsa_data );
if( res != 0 )
{
fprintf(stderr, "[*] Winsock initialization error %d\n", res );
fprintf(stderr, "Winsock initialization error %d\n", res );
return(-1);
}
#endif
@@ -531,7 +531,7 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
if (saddr.sin_addr.s_addr == -1)
{
fprintf(stderr, "[*] Could not set source IP.\n");
fprintf(stderr, "Could not set source IP.\n");
exit(EXIT_FAILURE);
}
@@ -542,7 +542,7 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
if (daddr.sin_addr.s_addr == -1)
{
fprintf(stderr, "[*] Could not set destination IP.\n");
fprintf(stderr, "Could not set destination IP.\n");
exit(EXIT_FAILURE);
}
@@ -558,7 +558,7 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
else
{
/* --DSS XXX: What to we really want to do here? */
fprintf(stderr, "[*] %i is not a valid or supported protocol.\n",
fprintf(stderr, "%i is not a valid or supported protocol.\n",
options->spa_proto);
res = -1;
}

View File

@@ -56,8 +56,10 @@
#define strncasecmp _strnicmp
#define snprintf _snprintf
#define unlink _unlink
#define PATH_SEP "\\"
#else
#include <signal.h>
#define PATH_SEP "/"
#endif
#include "fko.h"
@@ -92,6 +94,23 @@ enum {
#define MAX_GPG_KEY_ID 128
#define MAX_USERNAME_LEN 30
/* Some convenience macros */
/* Characters allowed between a config parameter and its value.
*/
#define IS_CONFIG_PARAM_DELIMITER(x) (x == ' ' || x == '\t' || x == '=');
/* End of line characters.
*/
#define IS_LINE_END(x) (x == '\n' || x == '\r' || x == ';');
/* Characters in the first position of a line that make it considered
* empty or otherwise non-interesting (like a comment).
*/
#define IS_EMPTY_LINE(x) ( \
x == '#' || x == '\n' || x == '\r' || x == ';' || x == '\0' \
)
#endif /* _COMMON_H */
/***EOF***/

View File

@@ -122,6 +122,18 @@ GENERAL OPTIONS
invocation (if any). The previous arguments are parsed out of the
'~/.fwknop.run' file.
*-n, --named-config*='<stanza name>'::
The *fwknop* client program can use parameters specified in it rc file,
``.fwknoprc'' which is found in the user's home directory. If *fwknop*
does not detect the $HOME/.fwknoprc file, it will create it. The
'.fwkoprc' file contains a default configuration area or 'stanza'
which holds global configuration directives that override the program
defaults. You can edit this file and create additonal 'named stanzas'
that can be specified with this ('-n') option. Parameters defined
in the named stanzas will override any matching 'default' stanza
directives. See the section: FWKNOPRC FILE below for a list of the
valid configuration directives in the ``.fwknoprc'' file.
*--show-last*::
Display the last command-line arguments used by *fwknop*.
@@ -321,6 +333,102 @@ GPG-RELATED OPTIONS
the SPA message.
FWKNOPRC FILE
-------------
The ``.fwknoprc'' file is used to set various parameters to override default
program parameters at runtime. It also allows for additional named configuration
'stanzas' for setting program parameters for a particular invocation.
The *fwkop* client will create this file if it does not exist in the user's
home directory. This initial version has some sample directives that are
commented out. It is up to the user to edit this file to meet their needs.
There are directives to match most of the command-line parameters *fwknop*
supports. Here is the current list of each directive along with a brief
description and (if applicable) it matching command-line option:
*DIGEST_TYPE*::
Set the SPA message digest type ('-m, --digest-type).
*SPA_SERVER_PROTO*::
Set the protocol to use for sending the SPA packet ('-P, --server-proto').
*SPA_SERVER*::
Specify the IP or hostname of the destination (*fwknopd*) server
('-D, --destination).
*SPA_SERVER_PORT*::
Set the server port to use for sending the SPA packet ('-p, --server-port').
*SPA_SOURCE_PORT*::
Set the source port to use for sending the SPA packet ('-S, --source-port').
*FW_TIMEOUT*::
Set the firewall rule timeout value ('-f, --fw-timeout').
*ALLOW_IP*::
Specify the address to allow within the SPA data. Note: This parameter
covers the '-a', '-s', and '-R' command-line options. You can specify
an IP address (the '-a' option), specify the word "source" to tell the
*fwknopd* server to accept the source IP of the packet as the IP to
allow (the '-s' option), or use the word "resolve" to have *fwknop*
resolve the external network IP via HTTP request (the '-R' option).
*TIME_OFFSET*::
Set a value to apply to the timestamp in the SPA packet. This can
be either a positive or negative value ('--time-offset-plus/minus').
*USE_GPG*::
Set to 'Y' to specify the use of GPG for encryption ('--gpg-encryption').
*GPG_SIGNER*::
Specify the GPG key name or ID for signing the GPG-encrypted SPA data
('--gpg-signer-key').
*GPG_RECIPIENT*::
Specify the GPG key name or ID for the recipient of the GPG-encrypted SPA
data ('--gpg-recipient-key').
*GPG_HOMEDIR*::
Specify the GPG home directory ('--gpg-home-dir').
*SPOOF_USER*::
Set the username in the SPA data to the specified value ('-U,
--spoof-user').
*SPOOF_SOURCE_IP*::
Set the source IP of the outgoing SPA packet to the specified value
('-Q, --spoof-source').
*ACCESS*::
Set the one or more protocol/ports to open on the firewall ('-A, --access').
*RAND_PORT*::
Send the SPA packet over a randomly assigned port ('-r, --rand-port').
*KEY_FILE*::
Load an encryption key/password from a file ('-G, --get-key').
*HTTP_USER_AGENT*::
Set the HTTP User-Agent for resolving the external IP via -R, or for
sending SPA packets over HTTP ('-u, --user-agent').
*NAT_ACCESS*::
Gain NAT access to an internal service protected by the fwknop server
('-N, --nat-access').
*NAT_LOCAL*::
Access a local service via a forwarded port on the fwknopd server
system ('--nat-local').
*NAT_PORT*::
Specify the port to forward to access a service via NAT ('--nat-port').
*NAT_RAND_PORT*::
Have the fwknop client assign a random port for NAT access
('--nat-rand-port').
ENVIRONMENT
-----------
*GPG_AGENT_INFO* (only used in *--gpg-agent* mode).