Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Franck Joncourt
2013-05-19 15:34:20 +02:00
14 changed files with 630 additions and 281 deletions
+4
View File
@@ -124,3 +124,7 @@ Shawn Wilson
- Added better SPA source IP logging for various fwknopd logging messages.
This helps to make it more clear why certain SPA packets are rejected
from some systems.
Dan Lauber
- Suggested a check for fwknopd to ensure that the jump rule on systems
running iptables is not duplicated if it already exists.
+15 -9
View File
@@ -2,10 +2,14 @@ fwknop-2.5 (//2013):
- Major release of new functionality - HMAC authenticated encryption
support in the encrypt-then-authenticate model for SPA communications.
Supported HMAC digests include MD5, SHA1, SHA256, SHA384, and SHA512.
The default is HMAC-SHA256 when HMAC is used. HMAC is supported for both
Rijndael and GPG encrypted SPA packet data, and provides a significant
security benefit since the HMAC verification is more simplisitic than
decryption operations (particularly for GPG).
The default is HMAC-SHA256 when an HMAC is used. The HMAC mode is
supported for both Rijndael and GPG encrypted SPA packet data, and
provides a significant security benefit for the fwknopd server since the
HMAC verification is more simplisitic than decryption operations. This
is particularly true for GPG. Beyond this, HMAC authenticated
encryption in the encrypt-then-authenticate mode does not suffer from
things like CBC-mode padding oracle attacks (see the Vaudenay attack and
the more recent "Lucky 13" attack against SSL).
- [libfko] Significant bug fix to honor the full encryption key length for
user-supplied Rijndael keys > 16 bytes long. Previous to this fix,
only the first 16 bytes of a key were actually used in the encryption/
@@ -13,13 +17,15 @@ fwknop-2.5 (//2013):
a weakening of expected security for users that had keys > 16 bytes,
although this is probably not too common. Note that "passphrase" is
perhaps technically a better word for "user-supplied key" in this
context since Rijndael in CBC mode derives a real encryption/decryption
key from the passphrase through a series of applications of md5 against
the passphrase and a random salt. This issue was reported by Michael T.
Dean. Closes issue #18 on github.
context since the actual key is generated with the PBKDF1 key derivation
algorithm. This issue was reported by Michael T. Dean. Closes issue #18
on github.
- [libfko] Added the ability to maintain backwards compatibility with the
now deprecated "zero padding" key derivation strategy in AES mode that
was a hold over from the old perl fwknop implementation.
was a hold over from the old perl fwknop implementation. This is NOT
compliant with PBKDF1 and is only brought forward into fwknop-2.5 for
backwards compatibility. Future versions of fwknop will remove this
code altogether since PBKDF1 is now implemented.
- [test suite] Added --enable-openssl-checks to send all SPA packets
encrypted via libfko through the OpenSSL library to ensure that the
libfko usage of AES is always compatible with OpenSSL. This ensures
+2
View File
@@ -151,6 +151,7 @@ EXTRA_DIST = \
test/conf/hmac_access.conf \
test/conf/hmac_get_key_access.conf \
test/conf/hmac_no_b64_access.conf \
test/conf/hmac_equal_keys_access.conf \
test/conf/hmac_dual_key_usage_access.conf \
test/conf/hmac_invalid_type_access.conf \
test/conf/hmac_md5_access.conf \
@@ -176,6 +177,7 @@ EXTRA_DIST = \
test/conf/fwknoprc_default_hmac_base64_key \
test/conf/fwknoprc_hmac_key2 \
test/conf/fwknoprc_gpg_hmac_key \
test/conf/fwknoprc_hmac_equal_keys \
test/conf/fwknoprc_hmac_invalid_type \
test/conf/fwknoprc_hmac_md5_key \
test/conf/fwknoprc_hmac_md5_long_key \
+43 -26
View File
@@ -507,13 +507,15 @@ create_fwknoprc(const char *rcfile)
"#\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"
"# It is this identifier (or name) that is used from the fwknop command line\n"
"# via the '-n <name>' argument to reference the corresponding stanza.\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"
"# for these parameters. 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"
@@ -1285,6 +1287,26 @@ update_rc(fko_cli_options_t *options, uint32_t args_bitmask)
static void
validate_options(fko_cli_options_t *options)
{
if ( (options->use_rc_stanza[0] != 0x0)
&& (options->got_named_stanza == 0)
&& (options->save_rc_stanza == 0) )
{
log_msg(LOG_VERBOSITY_ERROR,
"Named configuration stanza: [%s] was not found.",
options->use_rc_stanza);
exit(EXIT_FAILURE);
}
if ( (options->save_rc_stanza == 1) && (options->use_rc_stanza[0] == 0) )
{
log_msg(LOG_VERBOSITY_ERROR,
"The option --save-rc-stanza must be used with the "
"--named-config option to specify the stanza to update.");
exit(EXIT_FAILURE);
}
/* Gotta have a Destination unless we are just testing or getting the
* the version, and must use one of [-s|-R|-a].
*/
@@ -1304,33 +1326,23 @@ validate_options(fko_cli_options_t *options)
if (options->resolve_url != NULL)
options->resolve_ip_http = 1;
if (!options->resolve_ip_http && options->allow_ip_str[0] == 0x0)
if (!options->resolve_ip_http)
{
log_msg(LOG_VERBOSITY_ERROR,
"Must use one of [-s|-R|-a] to specify IP for SPA access.");
exit(EXIT_FAILURE);
if(options->allow_ip_str[0] == 0x0)
{
log_msg(LOG_VERBOSITY_ERROR,
"Must use one of [-s|-R|-a] to specify IP for SPA access.");
exit(EXIT_FAILURE);
}
else if(options->verbose
&& strncmp(options->allow_ip_str, "0.0.0.0", strlen("0.0.0.0")) == 0)
{
log_msg(LOG_VERBOSITY_WARNING,
"[-] WARNING: Should use -a or -R to harden SPA against potential MITM attacks");
}
}
}
if ( (options->use_rc_stanza[0] != 0x0)
&& (options->got_named_stanza == 0)
&& (options->save_rc_stanza == 0) )
{
log_msg(LOG_VERBOSITY_ERROR,
"Named configuration stanza: [%s] was not found.",
options->use_rc_stanza);
exit(EXIT_FAILURE);
}
if ( (options->save_rc_stanza == 1) && (options->use_rc_stanza[0] == 0) )
{
log_msg(LOG_VERBOSITY_ERROR,
"The option --save-rc-stanza must be used with the "
"--named-config option to specify the stanza to update.");
exit(EXIT_FAILURE);
}
if(options->resolve_ip_http || options->spa_proto == FKO_PROTO_HTTP)
if (options->http_user_agent[0] == '\0')
snprintf(options->http_user_agent, HTTP_MAX_USER_AGENT_LEN,
@@ -1360,6 +1372,9 @@ validate_options(fko_cli_options_t *options)
if(options->use_hmac && options->hmac_type == FKO_HMAC_UNKNOWN)
options->hmac_type = FKO_DEFAULT_HMAC_MODE;
if(options->key_gen && options->hmac_type == FKO_HMAC_UNKNOWN)
options->hmac_type = FKO_DEFAULT_HMAC_MODE;
return;
}
@@ -1410,8 +1425,10 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'n':
case NO_SAVE_ARGS:
options->no_save_args = 1;
break;
case 'n':
strlcpy(options->use_rc_stanza, optarg, sizeof(options->use_rc_stanza));
break;
case SAVE_RC_STANZA:
@@ -1492,7 +1509,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
strlcpy(options->get_key_file, optarg, sizeof(options->get_key_file));
cli_arg_bitmask |= FWKNOP_CLI_ARG_BM(FWKNOP_CLI_ARG_KEY_FILE);
break;
case GET_HMAC_KEY:
case GET_HMAC_KEY:
strlcpy(options->get_hmac_key_file, optarg,
sizeof(options->get_hmac_key_file));
options->use_hmac = 1;
+22 -1
View File
@@ -205,10 +205,19 @@ main(int argc, char **argv)
*/
if(options.key_gen)
{
fko_key_gen(options.key_base64, options.key_len,
memset(options.key_base64, 0x00, MAX_B64_KEY_LEN+1);
memset(options.hmac_key_base64, 0x00, MAX_B64_KEY_LEN+1);
res = fko_key_gen(options.key_base64, options.key_len,
options.hmac_key_base64, options.hmac_key_len,
options.hmac_type);
if(res != FKO_SUCCESS)
{
errmsg("fko_key_gen", res);
return(EXIT_FAILURE);
}
if(options.key_gen_file[0] != '\0')
{
if ((key_gen_file_ptr = fopen(options.key_gen_file, "w")) == NULL)
@@ -1263,6 +1272,18 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
clean_exit(ctx, options, EXIT_FAILURE);
}
/* Make sure the same key is not used for both encryption and the HMAC
*/
if(*hmac_key_len == *key_len)
{
if(memcmp(hmac_key, key, *key_len) == 0)
{
log_msg(LOG_VERBOSITY_ERROR,
"[*] The encryption passphrase and HMAC key should not be identical, no SPA packet sent. Exiting.");
clean_exit(ctx, options, EXIT_FAILURE);
}
}
res = fko_set_spa_hmac_type(ctx, options->hmac_type);
if(res != FKO_SUCCESS)
{
+343 -191
View File
@@ -16,40 +16,56 @@ SYNOPSIS
DESCRIPTION
-----------
*fwknop* implements an authorization scheme known as Single Packet
Authorization (SPA) for Linux systems running iptables. This mechanism
requires only a single encrypted and non-replayed packet to communicate
various pieces of information including desired access through an iptables
or ipfw policy. The main application of this program is to use iptables
in a default-drop stance to protect services such as 'SSH' with an
Authorization (SPA) for passive service protection. SPA requires only a single
non-replayed encrypted packet together with an HMAC in order to communicate
various pieces of information including desired access to a service that is
otherwise blocked by a firewall. The main application of SPA is to use a
firewall in a default-drop stance to protect services such as 'SSH' with an
additional layer of security in order to make the exploitation of
vulnerabilities (both 0-day and unpatched code) much more difficult.
vulnerabilities (both 0-day and unpatched code) more difficult. In
addition, services that are protected in this fashion naturally cannot be
scanned for with 'Nmap'.
An authorization server *fwknopd* passively monitors authorization packets
via 'libpcap' and hence there is no ``server'' to which to connect in the
traditional sense. Any service protected by *fwknop* is inaccessible (by
using 'iptables' or 'ipfw' to intercept packets within the kernel) before
authenticating; anyone scanning for the service will not be able to detect
that it is even listening. Single Packet Authorization offers many
advantages over port knocking, including non-replayability of SPA packets,
ability to use asymmetric ciphers (such as Elgamal), and SPA cannot be
broken by simply spoofing packets to duplicate ports within the knock
sequence on the server to break port knocking authentication.
SPA is essentially next generation Port Knocking (PK), but solves many of the
limitations exhibited by PK while retaining its core benefits. PK limitations
include a general difficulty in protecting against replay attacks, asymmetric
ciphers and HMAC schemes are not usually supported, and it is trivially easy
to mount a DoS attack against a PK server just by spoofing an additional
packet into a PK sequence as it traverses the network (thereby convincing the
PK server that the client doesn't know the proper sequence). All of these
limitation are solved by SPA. At the same time, SPA hides services behind a
default-drop firewall policy, acquires SPA data passively (usually via
libpcap or other means), and implements lightweight cryptographic operations
for SPA packet authentication and encryption/decryption.
SPA packets can easily be spoofed as well (this is a good thing in this
context), and this makes it possible to make it appear as though, say,
www.yahoo.com is trying to authenticate to a target system but in reality
the actual connection will come from a seemingly unrelated IP.
This is the manual page for the *fwknop* client which is responsible for
constructing SPA packets and sending them over the network. The server side is
implemented by the *fwknopd* daemon which sniffs the network for SPA packets,
and it is recommended to read the 'fwknopd(8)' manual page as well.
Authorization packets are either encrypted with the 'Rijndael' block cipher
or via 'GnuPG' and associated asymmetric ciphers. If the symmetric encryption
method is chosen, then the encryption key is shared between the client and
server (see the fwknopd 'access.conf' file for details). If the GnuPG method
SPA packets generated by *fwknop* leverage HMAC for authenticated encryption
in the encrypt-then-authenticate model. Although the usage of an HMAC is
currently optional, it is highly recommended for three reasons: '1)' without
an HMAC, cryptographically strong authentication is not possible with *fwknop*
unless GnuPG is used, '2)' an HMAC applied after encryption protects against
CBC-mode padding oracle attacks such as the Vaudenay attack and the more recent
"Lucky 13" attack against SSL, and '3)' the code required by the *fwknopd*
daemon to verify an HMAC is much more simplistic than the code required to
decrypt an SPA packet, so an SPA packet without a proper HMAC isn't even
sent through the decryption routines. Generating an HMAC for SPA
communications requires a dedicated key in addition to the normal encryption
key.
*fwknop* encrypts SPA packets either with the 'Rijndael' block cipher or via
'GnuPG' and associated asymmetric cipher. If the symmetric encryption method
is chosen, then as usual the encryption key is shared between the client and
server (see the *fwknopd* 'access.conf' file for details). If the GnuPG method
is chosen, then the encryption keys are derived from GnuPG key rings. SPA
packets generated by fwknop running as a client adhere to the following
format (before they are encrypted):
format (before encryption and the HMAC is applied):
..........................
random number (16 bytes)
random data (16 bytes)
username
timestamp
software version
@@ -59,38 +75,37 @@ format (before they are encrypted):
message digest (SHA512 / SHA384 / SHA256 / SHA1 / MD5)
..........................
Each of the above fields are separated by a ":" character due to the
variable length of several of the fields, and those that might contain
":" characters are base64 encoded. The message digest (*SHA256* by
default in all versions of *fwknop* greater than 1.9.1) allows the server
to check message integrity after decryption, and the 16 bytes of random data
ensures (with high probability) that no two messages are identical. This
ensures that replay attacks are not possible against *fwknop*.
For each packet coming from an *fwknop* client, the *fwknopd* server can
cache the digest calculated over the entire packet and compares against
previous packet digests in order to detect attempted replay attacks. Syslog
Each of the above fields are separated by a ":" character due to the variable
length of several of the fields, and those that might contain ":" characters
are base64 encoded. The message digest (*SHA256* by default) is part of the
data to be encrypted and is independent of the HMAC which is appended to the
SPA packet data after encryption. The 16 bytes of random data ensures that no
two SPA packets are identical, and this is in addition to and independent of
using PBKDF1 for key derivation for Rijndael in CBC mode. Because *fwknopd*
tracks the SHA256 digest of all incoming valid SPA packets and throws out
duplicates, replay attacks are not feasible against *fwknop*. Syslog
alerts are generated if a replay is detected.
By default, the *fwknop* client sends authorization packets over UDP port
62201, but this can be altered with the *--server-port* argument. The server
must first be configured to acquire the SPA data on the changed protocol-port.
62201, but this can be altered with the *--server-port* argument (this requires
*fwknopd* to be configured to acquire SPA data over the selected port).
Also, *fwknop* can send the SPA packet over a random port via the
*--rand-port* argument. See 'fwknopd(8)' for further details. See the
*EXAMPLES* section for example invocations of the *fwknop* client.
The *fwknop* client is quite portable, and is known to run on various Linux
distributions (all major distros and embedded ones as well such as OpenWRT),
FreeBSD, OpenBSD, and Cygwin on Windows. There is also a library *libfko*
that both *fwknop* and *fwknopd* use for SPA packet encryption/decryption
and HMAC authentication operations. This library can be used to allow
third party applications to use SPA.
REQUIRED ARGUMENTS
------------------
These required arguments can be specified via command-line or from within
the '.fwknoprc' file (see '-n, --named-config' option and the FWKNOPRC FILE
section below.
*-D, --destination*='<IP-address>'::
Direct the *fwknop* client to authenticate with the *fwknopd*
daemon/service at the specified destination hostname or IP address. The
connection mode is discovered by the *fwknopd* daemon/service when it
decrypts and parses the authentication packet.
section below).
*-A, --access*='<port list>'::
Provide a list of ports and protocols to access on a remote computer
@@ -100,9 +115,15 @@ section below.
sending full commands with the *--server-cmd* argument via an SPA
packet to be executed by *fwknopd* does not require this argument.
*-D, --destination*='<IP-address>'::
Direct the *fwknop* client to authenticate with the *fwknopd*
daemon/service at the specified destination hostname or IP address. The
connection mode is discovered by the *fwknopd* daemon/service when it
decrypts and parses the authentication packet.
*-R|-a|-s*::
One of these options (see below) is required to tell the remote
*fwknopd* daemon what IP should be let through the local firewall. It
*fwknopd* daemon what IP should be allowed through the local firewall. It
is recommend to use the *-R* or *-a* options instead of *-s* in order
to harden SPA communications against possible 'Man-In-The-Middle' (MITM)
attacks.
@@ -113,25 +134,17 @@ GENERAL OPTIONS
*-h, --help*::
Print a usage summary message and exit.
*-B, --save-packet*='<file>'::
Instruct the *fwknop* client to write a newly created SPA packet out
to the specified file so that it can be examined off-line.
*-b, --save-packet-append*::
Append the generated packet data to the file specified with the -B
option.
*-G, --get-key*='<file>'::
Load an encryption key/password from the specified file. The key file
contains a line for each destination hostname or IP address, a colon
(":"), optional space and the password, followed by a newline. Note
that the last line has to have a terminating newline character.
Also note: though this is a convenience, having a file on your system
with cleartext passwords is not a good idea and is not recommended.
with clear text passwords is not a good idea and is not recommended.
Having the *fwknop* client prompt you for the key is generally more
secure. Note also that if a key is stored on disk, the *fwknop* rc
file is a more powerful mechanism for specifying the key but other
options as well.
file is a more powerful mechanism for specifying not only the key but
other options as well.
*--get-hmac-key*='<file>'::
Load an HMAC key/password from the specified file. Similarly to the
@@ -139,36 +152,18 @@ GENERAL OPTIONS
each destination hostname or IP address, a colon (":"), optional space
and the password, followed by a newline. Note that the last line has
to have a terminating newline character. Also note: though this is a
convenience, having a file on your system with cleartext passwords is
convenience, having a file on your system with clear text passwords is
not a good idea and is not recommended. Having the *fwknop* client
prompt you for the HMAC key is generally more secure. Note also that
if a key is stored on disk, the *fwknop* rc file is a more powerful
mechanism for specifying the key but other options as well.
mechanism for specifying not only the HMAC key but other options as
well.
*--key-rijndael*='<key>'::
Specify the Rijndael key. Since the key may be visible to utilities
such as 'ps' under Unix, this form should only be used where security is
not critical. Having the *fwknop* client prompt you for the key is
generally more secure.
*--key-base64-rijndael*='<key>'::
Specify the base64 encoded Rijndael key. Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client prompt you for the
key is generally more secure.
*--key-base64-hmac*='<key>'::
Specify the base64 encoded HMAC key. Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client prompt you for the
key is generally more secure.
*--key-hmac*='<key>'::
Specify the raw HMAC key (not base64 encoded). Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client prompt you for the
key is generally more secure.
*--key-gen*::
Have *fwknop* generate both Rijndael and HMAC keys that can be used for SPA
packet encryption. These keys are derived from /dev/random and then base64
encoded before being printed to stdout, and are meant to be included within
the ``$HOME/.fwknoprc'' file (or the file referenced by *--get-key*).
*-l, --last-cmd*::
Execute *fwknop* with the command-line arguments from the previous
@@ -183,6 +178,34 @@ GENERAL OPTIONS
FWKNOPRC FILE below for a list of the valid configuration directives in
the '.fwknoprc' file.
*--key-rijndael*='<key>'::
Specify the Rijndael key on the command line. Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client either prompt you for
the key or acquire via the ``$HOME/.fwknoprc'' file is generally more
secure.
*--key-base64-rijndael*='<key>'::
Specify the base64 encoded Rijndael key. Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client either prompt you for
the key or acquire via the ``$HOME/.fwknoprc'' file is generally more
secure.
*--key-base64-hmac*='<key>'::
Specify the base64 encoded HMAC key. Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client either prompt you for
the key or acquire via the ``$HOME/.fwknoprc'' file is generally more
secure.
*--key-hmac*='<key>'::
Specify the raw HMAC key (not base64 encoded). Since the key may be visible
to utilities such as 'ps' under Unix, this form should only be used where
security is not critical. Having the *fwknop* client either prompt you for
the key or acquire via the ``$HOME/.fwknoprc'' file is generally more
secure.
*--rc-file*='<file>'::
Specify path to the fwknop rc file (default is $HOME/.fwknoprc).
@@ -211,6 +234,14 @@ GENERAL OPTIONS
the decryption and decoding process and print the break-down again.
This is primarily a debugging feature.
*-B, --save-packet*='<file>'::
Instruct the *fwknop* client to write a newly created SPA packet out
to the specified file so that it can be examined off-line.
*-b, --save-packet-append*::
Append the generated packet data to the file specified with the -B
option.
*-v, --verbose*::
Run the *fwknop* client in verbose mode. This causes *fwknop* to print
some extra information about the current command and the resulting SPA
@@ -222,6 +253,11 @@ GENERAL OPTIONS
SPA OPTIONS
-----------
*--use-hmac*::
Set HMAC mode for authenticated encryption of SPA communications. As of
*fwknop* 2.5, this is an optional feature, but this will become the
default in a future release.
*-a, --allow-ip*='<IP-address>'::
Specify IP address that should be permitted through the destination
*fwknopd* server firewall (this IP is encrypted within the SPA packet
@@ -238,48 +274,15 @@ SPA OPTIONS
system is connected to by querying a website that returns the actual
IP address it sees from the calling system.
*-C, --server-cmd*='<command to execute>'::
Instead of requesting access to a service with an SPA packet, the
*--server-cmd* argument specifies a command that will be executed by
the *fwknopd* server. The command is encrypted within the SPA packet
and sniffed off the wire (as usual) by the *fwknopd* server.
*-g, --gpg-encryption*::
Use GPG encryption on the SPA packet (default if not specified is
Rijndael). *Note:* Use of this option will require the specification of
a GPG recipient (see *--gpg-recipient* along with other GPG-related
options below).
*-H, --http-proxy*='<proxy-host>[:port]'::
Specify an HTTP proxy that the *fwknop* client will use to send the SPA
packet through. Using this option will automatically set the SPA packet
transmission mode (usually set via the *--server-proto* argument) to
"http". You can also specify the proxy port by adding ":<port>" to
the proxy host name or ip.
*-m, --digest-type*='<digest>'::
Specify the message digest algorithm to use in the SPA data. Choices
are: *MD5*, *SHA1*, *SHA256* (the default), *SHA384*, and *SHA512*.
*-M, --encryption-mode*='<mode>'::
Specify the encryption mode when AES is used for encrypting SPA packets.
The default is CBC mode, but others can be chosen such as CFB or OFB
as long as this is also specified in the 'access.conf' file on the
server side via the ENCRYPTION_MODE variable. In general, it is
recommended to not use this argument and just use the default. Note that
the string ``legacy'' can be specified in order to generate SPA packets
with the old initialization vector strategy used by versions of *fwknop*
before 2.5. With the 2.5 release, *fwknop* generates initialization
vectors in a manner that is compatible with OpenSSL.
*--hmac-digest-type*='<digest>'::
Set the HMAC digest algorithm (default is sha256). Options are md5, sha1,
sha256, sha384, or sha512.
*--use-hmac*::
Set HMAC mode for authenticated encryption of SPA communications. As of
*fwknop* 2.5, this is an optional feature, but this will become the
default in a future release.
Set the HMAC digest algorithm for authenticated encryption of SPA packets.
Choices are: *MD5*, *SHA1*, *SHA256* (the default), *SHA384*, and *SHA512*.
*-N, --nat-access*='<internalIP:forwardPort>'::
The *fwknopd* server offers the ability to provide SPA access through
@@ -368,13 +371,44 @@ SPA OPTIONS
*fwknopd* SPA server to use the source IP address from which the
SPA packet originates as the IP that will be allowed through upon
modification of the firewall ruleset. This option is useful if the
*fwknop* client is deployed on a machine that is behind a NAT device.
*fwknop* client is deployed on a machine that is behind a NAT device and
the external IP is not known. However, usage of this option is not
recommended, and either the *-a* or *-R* options should be used instead.
The permit-address options *-s*, *-R* and *-a* are mutually
exclusive.
*-S, --source-port*='<port>'::
Set the source port for outgoing SPA packet.
*-C, --server-cmd*='<command to execute>'::
Instead of requesting access to a service with an SPA packet, the
*--server-cmd* argument specifies a command that will be executed by
the *fwknopd* server. The command is encrypted within the SPA packet
and sniffed off the wire (as usual) by the *fwknopd* server.
*-H, --http-proxy*='<proxy-host>[:port]'::
Specify an HTTP proxy that the *fwknop* client will use to send the SPA
packet through. Using this option will automatically set the SPA packet
transmission mode (usually set via the *--server-proto* argument) to
"http". You can also specify the proxy port by adding ":<port>" to
the proxy host name or ip.
*-m, --digest-type*='<digest>'::
Specify the message digest algorithm to use in the SPA data. Choices
are: *MD5*, *SHA1*, *SHA256* (the default), *SHA384*, and *SHA512*.
*-M, --encryption-mode*='<mode>'::
Specify the encryption mode when AES is used for encrypting SPA packets.
The default is CBC mode, but others can be chosen such as CFB or OFB
as long as this is also specified in the 'access.conf' file on the
server side via the ENCRYPTION_MODE variable. In general, it is
recommended to not use this argument and just use the default (CBC).
Note that the string ``legacy'' can be specified in order to generate SPA
packets with the old initialization vector strategy used by versions of
*fwknop* prior to 2.5. With the 2.5 release, *fwknop* generates
initialization vectors in a manner that is compatible with OpenSSL via the
PBKDF1 algorithm.
*--time-offset-plus*='<time>'::
By default, the *fwknopd* daemon on the server side enforces time
synchronization between the clocks running on client and server
@@ -414,6 +448,24 @@ SPA OPTIONS
GPG-RELATED OPTIONS
-------------------
Note that the usage of GPG for SPA encryption/decryption can and should involve
GPG keys that are signed by each side (client and server). The basic procedure
for this involves the following steps after the client key has been transferred
the server and vice-versa:
..........................
[spaserver]# gpg --import client.asc
[spaserver]# gpg --edit-key 1234ABCD
Command> sign
[spaclient]$ gpg --import server.asc
[spaclient]$ gpg --edit-key ABCD1234
Command> sign
..........................
More comprehensive information on this can be found here:
'http://www.cipherdyne.org/fwknop/docs/gpghowto.html'.
*--gpg-agent*::
Instruct *fwknop* to acquire GnuPG key password from a running gpg-agent
instance (if available).
@@ -464,24 +516,9 @@ 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 its matching command-line option(s):
*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').
('-D, --destination').
*ALLOW_IP*::
Specify the address to allow within the SPA data. Note: This parameter
@@ -491,6 +528,49 @@ description and its matching command-line option(s):
to allow (the *-s* option), or use the word "resolve" to have *fwknop*
resolve the external network IP via HTTP request (the *-R* option).
*ACCESS*::
Set the one or more protocol/ports to open on the firewall ('-A, --access').
*SPA_SERVER_PORT*::
Set the server port to use for sending the SPA packet ('-p, --server-port').
*SPA_SERVER_PROTO*::
Set the protocol to use for sending the SPA packet ('-P, --server-proto').
*KEY*::
This is the passphrase that is used for SPA packet encryption and applies
to both Rijndael or GPG encryption modes. The actual encryption key that
is used for Rijndael is derived from the PBKDF1 algorithm, and the GPG key
is derived from the specified GPG key ring.
*KEY_BASE64*::
Specify the encryption passphrase as a base64 encoded string. This allows
non-ascii characters to be included.
*USE_HMAC*::
Set HMAC mode for authenticated encryption of SPA packets. This will have
*fwknop* prompt the user for a dedicated HMAC key that is independent of
the encryption key. Alternatively, the HMAC key can be specified with the
'HMAC_KEY' or 'HMAC_KEY_BASE64' directives (see below).
*HMAC_KEY*::
Specify the HMAC key for authenticated encryption of SPA packets.
*HMAC_KEY_BASE64*::
Specify the HMAC key as a base64 encoded string. This allows non-ascii
characters to be included.
*HMAC_DIGEST_TYPE*::
Set the HMAC digest algorithm used for authenticated encryption of SPA
packets. Choices are: *MD5*, *SHA1*, *SHA256* (the default), *SHA384*,
and *SHA512*.
*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').
*RESOLVE_URL*::
Set to a URL that will be used for resolving the source IP address
(--resolve-url).
@@ -503,9 +583,17 @@ description and its matching command-line option(s):
Specify the encryption mode when AES is used. This variable is a synonym
for the '--encryption-mode' command line argument.
*DIGEST_TYPE*::
Set the SPA message digest type ('-m, --digest-type').
*USE_GPG*::
Set to 'Y' to specify the use of GPG for encryption ('--gpg-encryption').
*USE_GPG*::
Set to 'Y' to have *fwknop* interface with a GPG agent instance for the GPG
key password ('--gpg-agent'). Agent information itself is specified with
the 'GPG_AGENT_INFO' environmental variable.
*GPG_SIGNER*::
Specify the GPG key name or ID for signing the GPG-encrypted SPA data
('--gpg-signer-key').
@@ -525,9 +613,6 @@ description and its matching command-line option(s):
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').
@@ -536,7 +621,7 @@ description and its matching command-line option(s):
*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').
sending SPA packets over HTTP ('-u, --user-agent').
*NAT_ACCESS*::
Gain NAT access to an internal service protected by the fwknop server
@@ -558,6 +643,19 @@ ENVIRONMENT
-----------
*SPOOF_USER*, *GPG_AGENT_INFO* (only used in *--gpg-agent* mode).
SPA PACKET SPOOFING
-------------------
Because *fwknop* places the IP to be allowed through the firewall within the
encrypted SPA payload (unless *-s* is used which is not recommended and can be
prohibited in the *fwknopd* server configuration), SPA packets can easily be
spoofed, and this is a good thing in this context. That is, the source IP of
an SPA packet is ignored by the *fwknopd* daemon and only the IP that is
contained within an authenticated and properly decrypted SPA packet is granted
access through the firewall. This makes it possible to make it appear as
though, say, www.yahoo.com is trying to authenticate to a target system but in
reality the actual connection will come from a seemingly unrelated IP.
EXAMPLES
--------
The following examples illustrate the command line arguments that could
@@ -565,89 +663,143 @@ be supplied to the fwknop client in a few situations:
Access mode examples
~~~~~~~~~~~~~~~~~~~~
Packet contents printed to stdout at the fwknop client when creating
an ``access mode'' SPA packet:
The most common usage of *fwknop* is to gain access to 'SSH' running on a
remote system that has the *fwknopd* daemon deployed along with a default-drop
firewall policy. The following command illustrates this where IP '1.1.1.1' is
the IP to be allowed through the firewall running on '2.2.2.2' (note that the
'access.conf' file consumed by *fwknopd* will need to have matching encryption
and HMAC keys, and configuration specifics can be found in the 'fwknopd(8)'
manual page):
..........................
Random data: 6565240948266426
Username: mbr
Timestamp: 1203863233
Version: 1.9.2
Type: 1 (access mode)
Access: 127.0.0.2,tcp/22
SHA256 sum: gngquSL8AuM7r27XsR4qPmJhuBo9pG2PYwII06AaJHw
$ fwknop -A tcp/22 --use-hmac -a 1.1.1.1 -D 2.2.2.2
Enter encryption key:
Enter HMAC key:
$ ssh -l user 2.2.2.2
user@2.2.2.2's password:
..........................
Use the Single Packet Authorization mode to gain access to
tcp/22 (ssh) and udp/53 running on the system 10.0.0.123 from
the IP 192.168.10.4:
If the *--verbose* flag is added to the command line, then some SPA packet
specifics are printed to stdout (not all output is shown for brevity):
..........................
$ fwknop -A "tcp/22,udp/53" -a 192.168.10.4 -D 10.0.0.123
$ fwknop -A tcp/22 --use-hmac -a 1.1.1.1 -D 2.2.2.2 --verbose
Enter encryption key:
Enter HMAC key:
Random Value: 1916307060193417
Username: mbr
Timestamp: 1368498909
FKO Version: 2.5.0
Message Type: 1 (Access msg)
Message String: 1.1.1.1,tcp/22
Nat Access: <NULL>
Server Auth: <NULL>
Client Timeout: 0 (seconds)
Digest Type: 3 (SHA256)
HMAC Type: 3 (SHA256)
Encryption Type: 1 (Rijndael)
Encryption Mode: 2 (CBC)
..........................
Same as above example, but gain access from whatever source IP
is seen by the fwknop server (useful if the fwknop client is
behind a NAT device):
Simultaneous access to multiple services is also supported, and here is an
example of requesting access to both 'SSH' and 'OpenVPN' on '2.2.2.2':
..........................
$ fwknop -A "tcp/22,udp/53" -s -D 10.0.0.123
$ fwknop -A "tcp/22,tcp/1194" --use-hmac -a 1.1.1.1 -D 2.2.2.2
..........................
Same as above example, but use an IP identification website to derive
the client IP address. This is a safer method of acquiring the client
IP address than using the *-s* option because the source IP is put within
the encrypted packet instead of having the *fwknopd* daemon grant the
requested access from whatever IP address the SPA packet originates:
There are many cases where an *fwknop* client is deployed on a network behind
a NAT device and the externally routable IP is not known to the user. In this
case, use the IP resolution service available at
'http://www.cipherdyne.org/cgi-bin/myip' via the *-R* command line switch in
order to derive the external client IP address. This is a safer method of
acquiring the client IP address than using the *-s* option mentioned earlier
in this manual page because the source IP is put within the encrypted packet
instead of having the *fwknopd* daemon grant the requested access from whatever
IP address the SPA packet originates (i.e. using *-s* opens the possibility of
a MITM attack):
..........................
$ fwknop -A "tcp/22,udp/53" -R -D 10.0.0.123
$ fwknop -A tcp/22 --use-hmac -R -D 2.2.2.2
..........................
Use the Single Packet Authorization mode to gain access to tcp/22
(ssh) and udp/53 running on the system 10.0.0.123, and use GnuPG keys
to encrypt and decrypt:
Use the Single Packet Authorization mode to gain access to 'SSH' and this time
use GnuPG keys to encrypt and decrypt:
..........................
$ fwknop -A "tcp/22,udp/53" --gpg-sign ABCD1234 --gpg--recipient
1234ABCD -R -D 10.0.0.123
$ fwknop -A tcp/22 --use-hmac --gpg-sign ABCD1234 --gpg--recipient 1234ABCD -R -D 2.2.2.2
..........................
Instruct the fwknop server running at 10.0.0.123 to allow 172.16.5.4
to connect to TCP/22, but spoof the authorization packet from an IP
associated with www.yahoo.com:
Instruct the fwknop server running at 2.2.2.2 to allow 1.1.1.1 to connect to
'SSH', but spoof the authorization packet from an IP associated with
'www.yahoo.com' (requires root on the *fwknop* client OS):
..........................
# fwknop --Spoof-src www.yahoo.com -A tcp/22 -a 172.16.5.4 -D
10.0.0.123
# fwknop --spoof-src "www.yahoo.com" -A tcp/22 --use-hmac -a 1.1.1.1 -D 2.2.2.2
..........................
When *fwknopd* is running on an iptables firewall with systems deployed behind
it, it is possible to take advantage of the 'NAT' capabilities offered by
iptables in order to transparently reach systems behind the firewall via SPA.
Here is an example where the *fwknop* client is used to gain access to 'SSH'
running on the non-routable IP '192.168.10.23' that is deployed on the network
behind '2.2.2.2'. In this case, the 'SSH' connection made to '2.2.2.2' is
translated into the '192.168.10.2' system automatically:
..........................
$ fwknop -A tcp/22 -N 192.168.10.2:22 -R -D 2.2.2.2
..........................
DEPENDENCIES
------------
*fwknop* requires 'libfko' (which is normally included with both source and
binary distributions).
The *fwknop* client requires 'libfko' which is normally included with both source
and binary distributions, and is a dedicated library developed by the fwknop
project. Whenever the *fwknopd* server is used, libpcap is a required 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.
To take advantage of all of the authentication and access management
features of the *fwknopd* daemon/service a functioning iptables firewall
is required on the underlying operating system.
To take advantage of all of the authentication and access management
features of the *fwknopd* daemon/service a functioning iptables, ipfw, or pf
firewall is required on the underlying operating system.
DIAGNOSTICS
-----------
fwknop can be run with the *-T* (or *--test*) command line option.
This will have *fwknop* simply create and print the SPA packet information,
then run it through a decrypt/decode cycle and print it again.
The most comprehensive way to gain diagnostic information on *fwknop* is to run
the test suite 'test-fwknop.pl' script located in the 'test/' directory in the fwknop
sources. The test suite runs sends fwknop through a large number of run time
tests, has 'valgrind' support, validates both SPA encryption and HMAC results
against OpenSSL, and even has its own built in fuzzer for SPA communications.
For more basic diagnostic information, *fwknop* can be executed with the *-T*
(or *--test*) command line option. This will have *fwknop* simply create and
print the SPA packet information, then run it through a decrypt/decode cycle
and print it again. In addition, the *--verbose* command line switch is useful
to see various SPA packet specifics printed to stdout.
SEE ALSO
--------
fwknopd(8), iptables(8), gpg(1), libfko documentation.
fwknopd(8), iptables(8), pf(4), pfctl(8), ipfw(8), gpg(1), libfko documentation.
More information on Single Packet Authorization can be found in the paper
``Single Packet Authorization with fwknop'' available at
'http://www.cipherdyne.org/fwknop/docs/SPA.html'.
'http://www.cipherdyne.org/fwknop/docs/SPA.html'. A comprehensive tutorial
on *fwknop* operations and theory can be found at
'http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html'. This tutorial
also includes information about the design of *fwknop* that may be worth
reading for those interested in why fwknop is different from other SPA
implementations.
*fwknop* uses the 'git' versioning system as its source code repository
along with 'Github' for tracking of issues and milestones:
..........................
$ git clone https://github.com/mrash/fwknop.git fwknop.git
..........................
AUTHORS
-------
@@ -660,19 +812,19 @@ This ``C'' version of fwknop was derived from the original Perl-based version
on which many people who are active in the open source community have
contributed. See the CREDITS file in the fwknop sources, or visit
'http://www.cipherdyne.org/fwknop/docs/contributors.html' to view the online
list of contributors.
list of contributors. A few contributors deserve to be singled out including:
Franck Joncourt, Max Kastanas, Vlad Glagolev, Sean Greven, Hank Leininger,
Fernando Arnaboldi, and Erik Gomez.
The phrase ``Single Packet Authorization'' was coined by MadHat and Simple
Nomad at the BlackHat Briefings of 2005 (see: 'http://www.nmrc.org').
Nomad at the BlackHat Briefings of 2005.
BUGS
----
Send bug reports to dstuart@dstuart.org or mbr@cipherdyne.org. Suggestions
Send bug reports to dstuart@dstuart.org or mbr@cipherdyne.org. Suggestions
and/or comments are always welcome as well.
DISTRIBUTION
------------
*fwknop* is distributed under the GNU General Public License (GPL), and
the latest version may be downloaded from 'http://www.cipherdyne.org'.
*fwknop* is distributed under the GNU General Public License (GPL) version 2,
and the latest version may be downloaded from 'http://www.cipherdyne.org'.
+53 -16
View File
@@ -19,12 +19,15 @@ DESCRIPTION
*fwknopd* is the server component for the FireWall Knock Operator, and
is responsible for monitoring and processing Single Packet Authorization
(SPA) packets that are generated by *fwknop* clients, modifying a firewall
or ACL policy to allow the desired access after decrypting a valid SPA packet,
and removing access after a configurable timeout.
or ACL policy to allow the desired access after authenticating and
decrypting a valid SPA packet (in that order), and removing access after a
configurable timeout.
The main application of this program is to protect services such as 'SSH'
with an additional layer of security in order to make the exploitation of
vulnerabilities (both 0-day and unpatched code) much more difficult.
vulnerabilities (both 0-day and unpatched code) much more difficult. In
addition, services that are protected in this fashion naturally cannot be
scanned for with 'Nmap'.
The main configuration for *fwknopd* is maintained within two files:
'fwknopd.conf' and 'access.conf'. The default location for these files
@@ -461,9 +464,19 @@ Defines all knock sequences and access control directives.
DEPENDENCIES
------------
The *fwknopd* daemon requires a functioning firewall on the underlying
operating system. Supported firewalls as of the fwknop-2.0 release are
iptables, ipfw, and pf.
*fwknopd* requires 'libfko' which is normally included with both source and
binary distributions, and is a dedicated library developed by the fwknop
project.
For packet sniffing, *fwknopd* currently requires libpcap, but future versions
still remove this as a dependency.
For GPG functionality, GnuPG must also be correctly installed and configured
along with the libgpgme library.
To take advantage of all of the authentication and access management
features of the *fwknopd* daemon/service a functioning iptables, ipfw, or pf
firewall is required on the underlying operating system.
DIAGNOSTICS
@@ -473,28 +486,52 @@ the *-v, --verbose* command line options. This will disable daemon mode
execution, and print verbose information to the screen on stderr as packets
are received.
The most comprehensive way to gain diagnostic information on *fwknopd* is to run
the test suite 'test-fwknop.pl' script located in the 'test/' directory in the fwknop
sources. The test suite runs sends fwknop through a large number of run time
tests, has 'valgrind' support, validates both SPA encryption and HMAC results
against OpenSSL, and even has its own built in fuzzer for SPA communications.
SEE ALSO
--------
fwknop(8), iptables(8), libfko documentation.
fwknopd(8), iptables(8), pf(4), pfctl(8), ipfw(8), gpg(1), libfko documentation.
More information on Single Packet Authorization can be found in the paper
``Single Packet Authorization with fwknop'' available at
'http://www.cipherdyne.org/fwknop/docs/SPA.html'. A comprehensive tutorial
on *fwknop* operations and theory can be found at
'http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html'. This tutorial
also includes information about the design of *fwknop* that may be worth
reading for those interested in why fwknop is different from other SPA
implementations.
*fwknop* uses the 'git' versioning system as its source code repository
along with 'Github' for tracking of issues and milestones:
..........................
$ git clone https://github.com/mrash/fwknop.git fwknop.git
..........................
AUTHOR
------
AUTHORS
-------
Damien Stuart <dstuart@dstuart.org>,
Michael Rash <mbr@cipherdyne.org>
CREDITS
-------
This ``C'' version of *fwknopd* was derived from the original Perl-based
version on which many people who are active in the open source community
have contributed. See the 'CREDITS' file in the fwknop sources, or visit
CONTRIBUTORS
------------
This ``C'' version of fwknop was derived from the original Perl-based version
on which many people who are active in the open source community have
contributed. See the CREDITS file in the fwknop sources, or visit
'http://www.cipherdyne.org/fwknop/docs/contributors.html' to view the online
list of contributors.
list of contributors. A few contributors deserve to be singled out including:
Franck Joncourt, Max Kastanas, Vlad Glagolev, Sean Greven, Hank Leininger,
Fernando Arnaboldi, and Erik Gomez.
The phrase ``Single Packet Authorization'' was coined by MadHat and Simple
Nomad at the BlackHat Briefings of 2005 (see: 'http://www.nmrc.org').
Nomad at the BlackHat Briefings of 2005.
BUGS
+8 -2
View File
@@ -381,6 +381,7 @@ fko_key_gen(char * const key_base64, const int key_len,
unsigned char hmac_key[SHA512_BLOCK_LEN];
int klen = key_len;
int hmac_klen = hmac_key_len;
int b64_len = 0;
if(key_len == FKO_DEFAULT_KEY_LEN)
klen = RIJNDAEL_MAX_KEYSIZE;
@@ -409,8 +410,13 @@ fko_key_gen(char * const key_base64, const int key_len,
get_random_data(key, klen);
get_random_data(hmac_key, hmac_klen);
b64_encode(key, key_base64, klen);
b64_encode(hmac_key, hmac_key_base64, hmac_klen);
b64_len = b64_encode(key, key_base64, klen);
if(b64_len < klen)
return(FKO_ERROR_INVALID_DATA);
b64_len = b64_encode(hmac_key, hmac_key_base64, hmac_klen);
if(b64_len < hmac_klen)
return(FKO_ERROR_INVALID_DATA);
return(FKO_SUCCESS);
}
+29 -1
View File
@@ -860,7 +860,7 @@ set_acc_defaults(fko_srv_options_t *opts)
static int
acc_data_is_valid(const acc_stanza_t *acc)
{
if(((acc->key == NULL || !strlen(acc->key))
if(((acc->key == NULL || acc->key_len == 0)
&& ((acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw))
&& acc->gpg_allow_no_pw == 0))
|| (acc->use_rijndael == 0 && acc->use_gpg == 0 && acc->gpg_allow_no_pw == 0))
@@ -871,6 +871,34 @@ acc_data_is_valid(const acc_stanza_t *acc)
return(0);
}
if(acc->hmac_key_len != 0)
{
if(((acc->key_len != 0) && (acc->key_len == acc->hmac_key_len)))
{
if(memcmp(acc->key, acc->hmac_key, acc->hmac_key_len) == 0)
{
fprintf(stderr,
"[*] The encryption passphrase and HMAC key should not be identical for access stanza source: '%s'\n",
acc->source
);
return(0);
}
}
else if((acc->gpg_allow_no_pw == 0)
&& acc->gpg_decrypt_pw != NULL
&& (strlen(acc->gpg_decrypt_pw) == acc->hmac_key_len))
{
if(memcmp(acc->gpg_decrypt_pw, acc->hmac_key, acc->hmac_key_len) == 0)
{
fprintf(stderr,
"[*] The encryption passphrase and HMAC key should not be identical for access stanza source: '%s'\n",
acc->source
);
return(0);
}
}
}
return(1);
}
+49 -17
View File
@@ -52,6 +52,14 @@ zero_cmd_buffers(void)
memset(cmd_out, 0x0, STANDARD_CMD_OUT_BUFSIZE);
}
static void
chop_newline(char *str)
{
if(str[0] != 0x0 && str[strlen(str)-1] == 0x0a)
str[strlen(str)-1] = 0x0;
return;
}
static int
comment_match_exists(const fko_srv_options_t * const opts)
{
@@ -61,7 +69,7 @@ comment_match_exists(const fko_srv_options_t * const opts)
zero_cmd_buffers();
/* Add a harmless rule to the iptables OUTPUT chain that uses the comment
/* Add a harmless rule to the iptables INPUT chain that uses the comment
* match and make sure it exists. If not, return zero. Otherwise, delete
* the rule and return true.
*/
@@ -74,6 +82,7 @@ comment_match_exists(const fko_srv_options_t * const opts)
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "comment_match_exists() CMD: '%s' (res: %d, err: %s)",
@@ -88,6 +97,7 @@ comment_match_exists(const fko_srv_options_t * const opts)
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
chop_newline(cmd_out);
if(!EXTCMD_IS_SUCCESS(res))
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
@@ -161,6 +171,7 @@ chain_exists(const fko_srv_options_t * const opts, const int chain_num)
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "chain_exists() CMD: '%s' (res: %d, err: %s)",
@@ -177,7 +188,7 @@ chain_exists(const fko_srv_options_t * const opts, const int chain_num)
}
static int
jump_rule_exists(const int chain_num)
jump_rule_exists(const fko_srv_options_t * const opts, const int chain_num)
{
int num, pos = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
@@ -220,6 +231,14 @@ jump_rule_exists(const int chain_num)
pclose(ipt);
if (opts->verbose)
{
if(pos > 0)
log_msg(LOG_INFO, "jump_rule_exists() jump rule position: %d", pos);
else
log_msg(LOG_INFO, "jump_rule_exists() jump rule not found");
}
return(pos);
}
@@ -325,7 +344,7 @@ delete_all_chains(const fko_srv_options_t * const opts)
/* First look for a jump rule to this chain and remove it if it
* is there.
*/
if((jump_rule_num = jump_rule_exists(i)) > 0)
if((jump_rule_num = jump_rule_exists(opts, i)) > 0)
{
zero_cmd_buffers();
@@ -337,6 +356,7 @@ delete_all_chains(const fko_srv_options_t * const opts)
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
@@ -362,6 +382,7 @@ delete_all_chains(const fko_srv_options_t * const opts)
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
@@ -389,6 +410,7 @@ create_chain(const fko_srv_options_t * const opts, const int chain_num)
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "create_chain() CMD: '%s' (res: %d, err: %s)",
@@ -421,10 +443,12 @@ create_fw_chains(const fko_srv_options_t * const opts)
if(! EXTCMD_IS_SUCCESS(create_chain(opts, i)))
got_err++;
/* Then create the jump rule to that chain.
/* Then create the jump rule to that chain if it
* doesn't already exist (which is possible)
*/
if(! EXTCMD_IS_SUCCESS(add_jump_rule(opts, i)))
got_err++;
if(jump_rule_exists(opts, i) == 0)
if(! EXTCMD_IS_SUCCESS(add_jump_rule(opts, i)))
got_err++;
}
}
@@ -603,7 +627,8 @@ fw_initialize(const fko_srv_options_t * const opts)
int
fw_cleanup(const fko_srv_options_t * const opts)
{
if(strncasecmp(opts->config[CONF_FLUSH_IPT_AT_EXIT], "N", 1) == 0)
if(strncasecmp(opts->config[CONF_FLUSH_IPT_AT_EXIT], "N", 1) == 0
&& opts->fw_flush == 0)
return(0);
delete_all_chains(opts);
@@ -619,9 +644,11 @@ rule_exists(const fko_srv_options_t * const opts,
zero_cmd_buffers();
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s -C %s %s", opts->fw_config->fw_command, fw_chain, fw_rule);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s -C %s %s",
opts->fw_config->fw_command, fw_chain, fw_rule);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "rule_exists() CMD: '%s' (res: %d, err: %s)",
@@ -630,13 +657,15 @@ rule_exists(const fko_srv_options_t * const opts,
if(EXTCMD_IS_SUCCESS(res) && strlen(err_buf))
{
rule_exists = 0;
log_msg(LOG_INFO, "rule_exists() Rule : '%s' in %s does not exist.", fw_rule, fw_chain);
log_msg(LOG_INFO, "rule_exists() Rule : '%s' in %s does not exist.",
fw_rule, fw_chain);
}
else
{
rule_exists = 1;
if (opts->verbose)
log_msg(LOG_INFO, "rule_exists() Rule : '%s' in %s already exist.", fw_rule, fw_chain);
log_msg(LOG_INFO, "rule_exists() Rule : '%s' in %s already exist.",
fw_rule, fw_chain);
}
return rule_exists;
@@ -653,6 +682,7 @@ create_rule(const fko_srv_options_t * const opts,
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s -A %s %s", opts->fw_config->fw_command, fw_chain, fw_rule);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "create_rule() CMD: '%s' (res: %d, err: %s)",
@@ -744,7 +774,7 @@ process_spa_request(const fko_srv_options_t * const opts,
if(chain_exists(opts, IPT_INPUT_ACCESS) == 0)
create_chain(opts, IPT_INPUT_ACCESS);
if(jump_rule_exists(IPT_INPUT_ACCESS) == 0)
if(jump_rule_exists(opts, IPT_INPUT_ACCESS) == 0)
add_jump_rule(opts, IPT_INPUT_ACCESS);
if(strlen(out_chain->to_chain))
@@ -752,7 +782,7 @@ process_spa_request(const fko_srv_options_t * const opts,
if(chain_exists(opts, IPT_OUTPUT_ACCESS) == 0)
create_chain(opts, IPT_OUTPUT_ACCESS);
if(jump_rule_exists(IPT_OUTPUT_ACCESS) == 0)
if(jump_rule_exists(opts, IPT_OUTPUT_ACCESS) == 0)
add_jump_rule(opts, IPT_OUTPUT_ACCESS);
}
@@ -899,7 +929,7 @@ process_spa_request(const fko_srv_options_t * const opts,
if(chain_exists(opts, IPT_FORWARD_ACCESS) == 0)
create_chain(opts, IPT_FORWARD_ACCESS);
if (jump_rule_exists(IPT_FORWARD_ACCESS) == 0)
if (jump_rule_exists(opts, IPT_FORWARD_ACCESS) == 0)
add_jump_rule(opts, IPT_FORWARD_ACCESS);
memset(rule_buf, 0, CMD_BUFSIZE);
@@ -941,7 +971,7 @@ process_spa_request(const fko_srv_options_t * const opts,
if(chain_exists(opts, IPT_DNAT_ACCESS) == 0)
create_chain(opts, IPT_DNAT_ACCESS);
if (jump_rule_exists(IPT_DNAT_ACCESS) == 0)
if (jump_rule_exists(opts, IPT_DNAT_ACCESS) == 0)
add_jump_rule(opts, IPT_DNAT_ACCESS);
memset(rule_buf, 0, CMD_BUFSIZE);
@@ -1081,10 +1111,11 @@ check_firewall_rules(const fko_srv_options_t * const opts)
);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
chop_newline(cmd_out);
if (opts->verbose)
log_msg(LOG_INFO, "check_firewall_rules() CMD: '%s' (res: %d, err: %s)",
cmd_buf, res, err_buf);
log_msg(LOG_INFO, "check_firewall_rules() CMD: '%s' (res: %d, cmd_out: %s)",
cmd_buf, res, cmd_out);
if(!EXTCMD_IS_SUCCESS(res))
{
@@ -1190,6 +1221,7 @@ check_firewall_rules(const fko_srv_options_t * const opts)
);
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
chop_newline(err_buf);
if (opts->verbose)
log_msg(LOG_INFO, "check_firewall_rules() CMD: '%s' (res: %d, err: %s)",
@@ -1207,7 +1239,7 @@ check_firewall_rules(const fko_srv_options_t * const opts)
ch[i].active_rules--;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
}
else
+6 -2
View File
@@ -97,9 +97,13 @@ init_logging(fko_srv_options_t *opts) {
else
strlcpy(log_name, my_name, strlen(MY_NAME)+1);
/* If we are running in the foreground, all logging will go to stderr.
/* If we are running in the foreground or performing firewall operations,
* all logging will go to stderr.
*/
if(opts->foreground != 0)
if(opts->foreground != 0
|| opts->fw_flush != 0
|| opts->fw_list != 0
|| opts->fw_list_all != 0)
static_log_flag = LOG_STDERR | LOG_STDERR_ONLY;
/* Parse the log facility as specified in the config struct. If, for some
+30 -15
View File
@@ -40,6 +40,7 @@ our %cf = (
'def_access' => "$conf_dir/default_access.conf",
'hmac_access' => "$conf_dir/hmac_access.conf",
'hmac_get_key_access' => "$conf_dir/hmac_get_key_access.conf",
'hmac_equal_keys_access' => "$conf_dir/hmac_equal_keys_access.conf",
'hmac_no_b64_access' => "$conf_dir/hmac_no_b64_access.conf",
'hmac_md5_access' => "$conf_dir/hmac_md5_access.conf",
'hmac_md5_short_key_access' => "$conf_dir/hmac_md5_short_key_access.conf",
@@ -108,6 +109,7 @@ our %cf = (
'rc_def_key' => "$conf_dir/fwknoprc_with_default_key",
'rc_def_b64_key' => "$conf_dir/fwknoprc_with_default_base64_key",
'rc_named_key' => "$conf_dir/fwknoprc_named_key",
'rc_hmac_equal_keys' => "$conf_dir/fwknoprc_hmac_equal_keys",
'rc_invalid_b64_key' => "$conf_dir/fwknoprc_invalid_base64_key",
'rc_hmac_b64_key' => "$conf_dir/fwknoprc_default_hmac_base64_key",
'rc_hmac_b64_key2' => "$conf_dir/fwknoprc_hmac_key2",
@@ -228,7 +230,8 @@ my $diff_dir1 = '';
my $diff_dir2 = '';
my $loopback_intf = '';
my $anonymize_results = 0;
my $curr_test_file = "$output_dir/init";
my $curr_test_file = 'init';
my $init_file = $curr_test_file;
my $tarfile = 'test_fwknop.tar.gz';
our $key_gen_file = "$output_dir/key_gen";
my $fuzzing_pkts_file = 'fuzzing/fuzzing_spa_packets';
@@ -346,6 +349,7 @@ exit 1 unless GetOptions(
### can set the following to "output.last/valgrind-coverage" if
### a full test suite run has already been executed with --enable-valgrind
'valgrind-prev-cov-dir=s' => \$previous_valgrind_coverage_dir,
'openssl-path=s' => \$openssl_path,
'output-dir=s' => \$output_dir,
'diff' => \$diff_mode,
'diff-dir1=s' => \$diff_dir1,
@@ -521,6 +525,8 @@ if ($saved_last_results) {
"to: ${output_dir}.last/\n\n");
}
copy $init_file, "$output_dir/init" if -e $init_file;
if ($enable_valgrind) {
if ($previous_valgrind_coverage_dir) {
die "[*] $previous_valgrind_coverage_dir does not exist"
@@ -4307,8 +4313,11 @@ sub key_gen_uniqueness() {
my %rijndael_keys = ();
my %hmac_keys = ();
my $rv = 1;
### collect key information
my $found_dup = 0;
for (my $i=0; $i < $uniq_keys; $i++) {
open CMD, "$test_hr->{'cmdline'} | " or die $!;
while (<CMD>) {
@@ -4324,7 +4333,12 @@ sub key_gen_uniqueness() {
last if $found_dup;
}
return ! $found_dup;
$rv = 0 if $found_dup;
$rv = 0 unless keys %rijndael_keys == $uniq_keys;
$rv = 0 unless keys %hmac_keys == $uniq_keys;
return $rv;
}
### check for PIE
@@ -4469,12 +4483,12 @@ sub openssl_hmac_verification() {
### for HMAC SHA512 this output will span two lines
my $openssl_hmac_line = '';
open F, "< $openssl_cmd_tmp" or die $!;
while (<F>) {
$openssl_hmac_line .= $_;
chomp $openssl_hmac_line;
{
local $/ = undef;
open F, "< $openssl_cmd_tmp" or die $!;
$openssl_hmac_line = <F>;
close F;
}
close F;
if ($base64_path) {
$openssl_hmac = $openssl_hmac_line;
@@ -5062,11 +5076,11 @@ sub init() {
}
if ($enable_openssl_compatibility_tests) {
$openssl_path = &find_command('openssl');
$openssl_path = &find_command('openssl') unless $openssl_path;
if ($openssl_path) {
require MIME::Base64;
MIME::Base64->import(qw(encode_base64 decode_base64));
$base64_path = &find_command('base64');
$base64_path = &find_command('base64') unless $base64_path;
### check for hmac openssl support
&openssl_hmac_style_check();
@@ -5079,7 +5093,7 @@ sub init() {
}
if ($enable_valgrind) {
$valgrind_path = &find_command('valgrind');
$valgrind_path = &find_command('valgrind') unless $valgrind_path;
unless ($valgrind_path) {
print "[-] --enable-valgrind mode requested ",
"but valgrind not found, disabling.\n";
@@ -5123,7 +5137,7 @@ sub init() {
die "[*] The python test script: $python_script doesn't exist ",
"or is not executable."
unless -e $python_script and -x $python_script;
$python_path = &find_command('python');
$python_path = &find_command('python') unless $python_path;
unless ($python_path) {
push @tests_to_exclude, qr/python fko extension/
}
@@ -5142,16 +5156,16 @@ sub init() {
push @tests_to_exclude, qr/perl FKO module.*FUZZING/;
}
$sudo_path = &find_command('sudo');
$killall_path = &find_command('killall');
$pgrep_path = &find_command('pgrep');
$sudo_path = &find_command('sudo') unless $sudo_path;
$killall_path = &find_command('killall') unless $killall_path;
$pgrep_path = &find_command('pgrep') unless $pgrep_path;
unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
### disable compilation checks
push @tests_to_exclude, qr/recompilation/;
}
$gcov_path = &find_command('gcov');
$gcov_path = &find_command('gcov') unless $gcov_path;
if ($gcov_path) {
if ($enable_profile_coverage_check) {
@@ -5730,6 +5744,7 @@ sub file_find_regex() {
}
sub remove_permissions_warnings() {
return unless -e "$output_dir/1.test";
system qq|perl -p -i -e 's/.*not owned by current effective.*\n//' $output_dir/*.test|;
system qq|perl -p -i -e 's/.*permissions should only be user.*\n//' $output_dir/*.test|;
return;
+2 -1
View File
@@ -325,7 +325,8 @@
'function' => \&generic_exec,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir " .
"$valgrind_str $fwknopCmd --key-gen",
'positive_output_matches' => [qr/BASE64/, qw/HMAC/, qw/KEY/],
'positive_output_matches' => [qr/^KEY_BASE64\:?\s\S{10}/,
qw/HMAC_KEY_BASE64\:?\s\S{10}/],
'fatal' => $NO
},
{
+24
View File
@@ -29,6 +29,30 @@
'exec_err' => $YES,
'fatal' => $NO
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'client',
'detail' => 'rc file HMAC+encryption keys not equal',
'function' => \&generic_exec,
'cmdline' => "$default_client_args_no_get_key " .
"--rc-file $cf{'rc_hmac_equal_keys'}",
'positive_output_matches' => [qr/should\snot\sbe\sidentical/i],
'exec_err' => $YES,
'fatal' => $NO
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'server',
'detail' => 'rc file HMAC+encryption keys not equal',
'function' => \&generic_exec,
'cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
"$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_equal_keys_access'} " .
"-d $default_digest_file -p $default_pid_file $intf_str",
'positive_output_matches' => [qr/should\snot\sbe\sidentical/i],
'exec_err' => $YES,
'fatal' => $NO
},
{
'category' => 'Rijndael+HMAC',
'subcategory' => 'server',