This change ensures that we only cache replay digests for those SPA packets
that actually decrypt. Not doing this would have allowed an attacker to
potentially fill up digest cache space with digests for garbage packets.
This commit fixes a bug where the same encryption key used for two stanzas in
the access.conf file would result in access requests that matched the second
stanza to always be treated as a replay attack. This has been fixed for
the fwknop-2.0.1 release, and was reported by Andy Rowland. Now the fwknopd
server computes the SHA256 digest of raw incoming payload data before
decryption, and compares this against all previous hashes. Previous to this
commit, fwknopd would add a new hash to the replay digest list right after
the first access.conf stanza match, so when SPA packet data matched the
second access.conf stanza a matching replay digest would already be there.
This commit adds a new configuration variable "FORCE_NAT" to the access.conf
file:
For any valid SPA packet, force the requested connection to be NAT'd
through to the specified (usually internal) IP and port value. This is
useful if there are multiple internal systems running a service such as
SSHD, and you want to give transparent access to only one internal system
for each stanza in the access.conf file. This way, multiple external
users can each directly access only one internal system per SPA key.
This commit also implements a few minor code cleanups.
This commit does two major things:
1) Two new access.conf variables are added "ACCESS_EXPIRE" and
"ACCESS_EXPIRE_EPOCH" to allow access stanzas to be expired without having
to modify the access.conf file and restart fwknopd.
2) Allow an access stanza that matches the SPA source address to not
automatically short circuit other stanzas if there is an error (such as when
there are multiple encryption keys involved and an incoming SPA packet is
meant for, say, the second stanza and the first therefore doesn't allow
proper decryption).
The two memory leaks were found with the test suite running in
--enable-valgrind mode - here are the relevant error messages:
For fwknopd server GPG clean up:
==345== 9 bytes in 1 blocks are definitely lost in loss record 2 of 2
==345== at 0x4C2815C: malloc (vg_replace_malloc.c:236)
==345== by 0x52F6B81: strdup (strdup.c:43)
==345== by 0x10FA57: add_string_list_ent (access.c:308)
==345== by 0x110513: parse_access_file (access.c:387)
==345== by 0x10B5FB: main (fwknopd.c:193)
For fwknop client rc file processing:
==8045== 568 bytes in 1 blocks are still reachable in loss record 12 of 12
==8045== at 0x4C2815C: malloc (vg_replace_malloc.c:236)
==8045== by 0x50A53AA: __fopen_internal (iofopen.c:76)
==8045== by 0x10C3FF: process_rc (config_init.c:446)
==8045== by 0x10C8F6: config_init (config_init.c:671)
==8045== by 0x10AC9E: main (fwknop.c:62)
There is also a new clean_exit() function that makes it easier to ensure that
resources are deallocated upon existing.
This commit does several things. First, a memory leak in fwknopd has been
fixed by ensuring to free access.conf stanzas. This bug was found with the
new test suite running in --enable-valgrind mode. Here is what some of the
valgrind output looked like to find the leak:
==19217== 11 bytes in 1 blocks are indirectly lost in loss record 3 of 5
==19217== at 0x4C2815C: malloc (vg_replace_malloc.c:236)
==19217== by 0x52F6B81: strdup (strdup.c:43)
==19217== by 0x10FC8B: add_acc_string (access.c:49)
==19217== by 0x1105C8: parse_access_file (access.c:756)
==19217== by 0x10B79B: main (fwknopd.c:194)
==19217==
==19217== 16 bytes in 1 blocks are indirectly lost in loss record 4 of 5
==19217== at 0x4C27480: calloc (vg_replace_malloc.c:467)
==19217== by 0x10FEC0: add_source_mask (access.c:88)
==19217== by 0x110100: expand_acc_source (access.c:191)
==19217== by 0x1104B0: parse_access_file (access.c:500)
==19217== by 0x10B79B: main (fwknopd.c:194)
==19217==
==19217== 183 (152 direct, 31 indirect) bytes in 1 blocks are definitely lost in loss record 5 of 5
==19217== at 0x4C27480: calloc (vg_replace_malloc.c:467)
==19217== by 0x1103E4: parse_access_file (access.c:551)
==19217== by 0x10B79B: main (fwknopd.c:194)
==19217==
==19217== LEAK SUMMARY:
==19217== definitely lost: 152 bytes in 1 blocks
==19217== indirectly lost: 31 bytes in 3 blocks
==19217== possibly lost: 0 bytes in 0 blocks
==19217== still reachable: 8 bytes in 1 blocks
==19217== suppressed: 0 bytes in 0 blocks
Second, this commit changes how fwknopd acquires packet data with
pcap_dispatch() - packets are now processed within the callback function
process_packet() that is provided to pcap_dispatch(), the global packet
counter is incremented by the return value from pcap_dispatch() (since this is
the number of packets processed per pcap loop), and there are two new
fwknopd.conf variables PCAP_DISPATCH_COUNT and PCAP_LOOP_SLEEP to control the
number of packets that pcap_dispatch() should process per loop and the number
of microseconds that fwknopd should sleep per loop respectively. Without this
change, it was fairly easy to cause fwknopd to miss packets by creating bursts
of packets that would all be processed one at time with the usleep() delay
between each. For fwknopd deployed on a busy network and with a permissive
pcap filter (i.e. something other than the default that causes fwknopd to look
at, say, TCP ACK's), this change should help.
Third, the criteria that a packet must reach before data copying into the
buffer designed for SPA processing has been tightened. A packet less than
/greater than the minimum/maximum expected sizes is ignored before data is
copied, and the base64 check is done as well.
This commit makes it easier to determine exactly which commands fwknopd
runs in --verbose mode when interacting with the underlying firewall.
This commit also adds --verbose --verbose mode to the test suite.
Added the 'const' qualifier to function prototype variables where possible.
In addition, reduced some functions to file-scope with 'static' where possible.
Also made a few minor changes to remove extra whitespace, and fixed a bug
in create_fwknoprc() to ensure the new fwknoprc filehandle is closed.
This commit fixes the following gcc warning on freebsd systems:
replay_cache.c: In function 'replay_file_cache_init':
replay_cache.c:312: warning: format '%ld' expects type 'long int *', but argument 9 has type 'time_t *'
Changed PID string length to 7 to accomodate an ending newline and NULL
char when writing to the fwknopd .pid file. Without this fix, with a
5 digit PID the trailing newline would be truncated (no room for the
ending NULL char).
Added new command line options --fw-list-all and --fw-flush to allow all
firewall rules to be displayed including those not created by fwknopd, and
allow all firewall rules created by fwknopd to be deleted.
Also switched -D config dump output to stdout.
In the fw_config struct the active_rules member is unsigned, so this change
ensures that we don't try to decrement it below zero whenever a firewall rule
is deleted or an error condition occurs.
Replaced all instances of "_exp_" with the #define EXPIRE_COMMENT_PREFIX so
that the prefix can easily be changed. so
that the prefix can easily be changed. so
that the prefix can easily be changed. so
that the prefix can easily be changed.
This commit adds the ability to fwknopd to delete PF rules after the SPA timer
expires. The strategy implemented is similar to iptables and ipfw, except
that all PF rules are added to an 'anchor', and deleting a specific expired
rule is done by listing all rules in the anchor and reinstantiating it via
'pfctl -a <anchor> -f -' with the expired rule deleted. fwknopd uses the
"_exp_<expire time>" convention in a PF rule label similarly to how fwknopd
interfaces with iptables (via the 'comment' match), and ipfw (via the
"//<comment>" feature).
This commit implements the ability to add PF firewall rules to the fwknop
anchor after a valid SPA packet is sniffed off the wire. A subsequent commit
will add the ability to delete these rules.
This commit ensures that for PF firewalls that the fwknop anchor is active and
linked into the running PF policy. This is accomplished by looking for the
string 'anchor "fwknop"' in the output of "pfctl -s rules". If the anchor
exists, then fwknopd will be able to influence traffic via rules added and
removed from the fwknop anchor.
This commit fixes an issue on ipfw firewalls where fwknopd would always require
seeing ipfw 'Dynamic' rules associated with newly added connections. But, such
connections may never be established for various reasons. Previous to this
commit the following warning was frequently generated by fwknopd:
Unexpected error: did not find 'Dynamic rules' string in list output.
This commit fixes an issues on systems running the ipfw firewall where the
'set' where fwknopd puts new access rules was attempted to be deleted without
first checking to see whether it exists. The following errors would be
generated (now fixed):
ipfw: rule 16777217: setsockopt(IP_FW_DEL): Invalid argument
Error 17664 from cmd:'/sbin/ipfw delete set 1':
Fatal: Errors detected during ipfw rules initialization.
Bug fix to ensure that the digest.cache file gets created at fwknopd init time
so fwknopd does not throw the following error:
Error opening digest cache file. Incoming digests will not be remembered.