pf-badhost 0.5 errata 001, January 25, 2021:

This is a hotfix release to address issues related to shell portability, RFC3330/5156 filtering and to also improve support for running pf-badhost on custom OS types.

Issues fixed:

* RFC3330 and/or RFC5156 addresses could sneak into the blockist when using subnet aggregation - we now explicitely whitelist these addresses.

* Explicitly specify stdin as input for myawk, mygrep and mysort functions as their stdin autodetection could get confused when invoked from certain shells.

* Tweak the pre-execution tests to make using a custom OS easier, including generating lists with '-x' on machines without PF.

* Make '-h' switch slightly more useful for new users.

Apply by doing: (Note: Provided file path is for OpenBSD, other platforms path may differ)

patch /usr/local/bin/pf-badhost < p0.patch


--- pf-badhost.sh.orig0	Sun Jan 10 21:49:10 2021
+++ pf-badhost.sh	Sun Jan 24 12:25:28 2021
@@ -36,7 +36,7 @@
 # If adding your own IPv6 lists, the addresses must be RFC 5952 compliant and
 # have one address per line with no leading or trailing whitespace.
 
-version='0.5'
+version='0.5p0'
 release_date='2021-01-10'
 release_name='Psychological Operations'
 
@@ -281,7 +281,7 @@
 # in RFC3330 & RFC5156 unless manually specified as a custom rule.
 # To disable this behavior, set the 2 options below to '0' 
   _RFC3330=1
-  _RFC3330=1
+  _RFC5156=1
 #
 # Manual filtering and whitelisting:
 # It usually makes more sense to negate an address using a custom
@@ -353,7 +353,9 @@
 	printf '# Supported Operating Systems:\n#\n# * OpenBSD\n# * FreeBSD\n# * NetBSD\n# * DragonflyBSD\n# * MacOS\n#\n'
 	printf '# OS Type Can Be Specified As An Argument:\n'
 	printf '# Example: "pf-badhost -O DragonflyBSD"\n#\n'
-	printf '# NOTE: OS arguments are case insensitive\n'
+	printf '# NOTE: OS arguments are case insensitive\n#\n'
+	printf '# The man page can be found at:\n'
+	printf '#    https://geoghegan.ca/pub/pf-badhost/0.5/man/man.txt\n'
 	printf '###################################################################\n\n'
 }
 
@@ -404,11 +406,11 @@
 # Opportunistically use mawk or GNU awk if they're available
 myawk() {
 	if command -v mawk >/dev/null 2>&1 ; then
-		nice mawk "$@"
+		nice mawk "$@" -
 	elif command -v gawk >/dev/null 2>&1 ; then
-		nice gawk "$@"
+		nice gawk "$@" -
 	else
-		nice awk "$@"
+		nice awk "$@" -
 	fi
 }
 
@@ -428,20 +430,20 @@
 # Opportunistically use RipGrep or GNU grep if they're available
 mygrep() {
 	if command -v rg >/dev/null 2>&1 ; then
-		nice rg "$@" || true
+		nice rg "$@" - || true
 	elif command -v ggrep >/dev/null 2>&1 ; then
-		nice ggrep -E "$@" || true
+		nice ggrep -E "$@" - || true
 	else
-		nice grep -E "$@" || true
+		nice grep -E "$@" - || true
 	fi
 }
 
 # Opportunistically use GNU sort if available (needed for NetBSD support)
 mysort() {
 	if command -v gsort >/dev/null 2>&1 ; then
-		nice gsort "$@"
+		nice gsort "$@" -
 	else
-		nice sort "$@"
+		nice sort "$@" -
 	fi
 }
 
@@ -566,7 +568,6 @@
 
 LIST_GEN() {
 	# Make sure there are no empty files in listdir
-	typeset _file
 	find "${listdir}" -type f -size 0 -delete || WARN_ERR 'ERROR: Failed to delete temporary files!'
 
 	# Filter and Generate IP Address List
@@ -667,6 +668,22 @@
 		printf '\n# Tor Blacklist:\n\n'
 		cat -- < "${tor_blacklist}"
 	fi
+	# System rules (RFC3330/5156 negation)
+	printf '\n# System Rules:\n\n'
+	if [ "${_RFC3330}" -ne 1 ] && [ "${_RFC5156}" -ne 1 ]; then
+		# Allow all private address ranges in blocklist (may break stuff)
+		true
+	elif [ "${_RFC3330}" -eq 1 ] && [ "${_RFC5156}" -ne 1 ]; then
+		# Allow RFC5156 addresses in blocklist, filter out RFC3330 addresses 
+		printf '%s\n' "${_rfc3330[@]}"
+	elif [ "${_RFC3330}" -ne 1 ] && [ "${_RFC5156}" -eq 1 ]; then
+		# Allow RFC3330 addresses in blocklist, filter out RFC5156 addresses 
+		printf '%s\n' "${_rfc5156[@]}"	
+	else
+		# Make sure RFC 3330 & 5156 address ranges are not in blocklist
+		printf '%s\n' "${_rfc3330[@]}"
+		printf '%s\n' "${_rfc5156[@]}"
+	fi
 	# Main ruleset
 	if [ "${_IPV4}" -eq 1 ]; then
 		printf '\n# IPv4 List Generated Rules:\n\n'
@@ -967,15 +984,18 @@
 	fi
 
 	# Make sure requisite utilities are installed
-	for _cmd in 'cmp' 'find' 'gunzip' 'nc' 'pfctl' ; do
+	for _cmd in 'cmp' 'find' 'gunzip' 'nc' "${netget}" ; do
 		CHECK_CMD "${_cmd}"
 	done > /dev/null
 
 	if [ "${_NO_UID_CHECK}" -ne 1 ]; then
 		CHECK_PRIVILEGE
 	fi
-
+	if [ "${_HAIL_MARY}" -eq 1 ]; then
+		CHECK_CMD "${authlog_unzip}" > /dev/null
+	fi
 	if [ "${_PRINT_ONLY}" -ne 1 ]; then
+		pfctl="$(CHECK_CMD pfctl)"
 		CHECK_DRIVE
 	fi
 
@@ -1030,11 +1050,6 @@
 	elif [ "${_TOR_BLOCK_ALL}" -eq 1 ] && [ "${_TOR_BLOCK_EXIT}" -eq 1 ]; then
 		ERR 'Tor Whitelisting/Blacklisting options are mutually exclusive!'
 	fi
-
-	# Make sure user provided OS is accurate and that specified utilities exist
-	for _cmd in "${getroot}" "${netget}" "${authlog_unzip}" ; do
-		command -v -- "${_cmd}" >/dev/null 2>&1 || ERR "'${_cmd}' not found! Did you specify the correct OS type?"
-	done
 }
 
 # ------------------------------------------------------------------------------
@@ -1145,17 +1160,46 @@
 	# Set trap handler
 	trap TRAP_ABORT ERR INT
 
-	# Registrar URL Array (this is declared late because zsh needs ksh array syntax enabled before it can ingest array data)
+	# These are declared late because zsh needs ksh array syntax enabled before it can ingest array data
 	_registrar_url[0]='https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest'
 	_registrar_url[1]='https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest'
 	_registrar_url[2]='https://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest'
 	_registrar_url[3]='https://ftp.apnic.net/stats/apnic/delegated-apnic-latest'
 	_registrar_url[4]='https://ftp.ripe.net/ripe/stats/delegated-ripencc-latest'
 
+	_rfc3330[0]='!0.0.0.0/8'
+	_rfc3330[1]='!10.0.0.0/8'
+	_rfc3330[2]='!14.0.0.0/8'
+	_rfc3330[3]='!24.0.0.0/8'
+	_rfc3330[4]='!39.0.0.0/8'
+	_rfc3330[5]='!127.0.0.0/8'
+	_rfc3330[6]='!128.0.0.0/16'
+	_rfc3330[7]='!169.254.0.0/16'
+	_rfc3330[8]='!172.16.0.0/12'
+	_rfc3330[9]='!191.255.0.0/16'
+	_rfc3330[10]='!192.0.0.0/24'
+	_rfc3330[11]='!192.0.2.0/24'
+	_rfc3330[12]='!192.88.99.0/24'
+	_rfc3330[14]='!192.168.0.0/16'
+	_rfc3330[14]='!198.18.0.0/15'
+	_rfc3330[15]='!223.255.255.0/24'
+	_rfc3330[16]='!224.0.0.0/3'
+
+	_rfc5156[0]='!2001:10::/28'
+	_rfc5156[1]='!2001::/32'
+	_rfc5156[2]='!2001:db8::/32'
+	_rfc5156[3]='!2002::/16'
+	_rfc5156[4]='!3ffe::/16'
+	_rfc5156[5]='!5f00::/8'
+	_rfc5156[6]='!::FFFF:0:0/96'
+	_rfc5156[7]='!fc00::/7'
+	_rfc5156[8]='!fe80::/10'
+	_rfc5156[9]='!ff00::/8'
+
 	# Mark program info read-only
 	readonly version release_date release_name
 	# Mark pf-badhost constants as read-only
-	readonly _registrar_url _SUBNET_MERGE_PERL
+	readonly _rfc3330 _rfc5156 _registrar_url _SUBNET_MERGE_PERL
 	# Mark user-defined lists as read-only
 	readonly _COUNTRY_CODES _ASN_LIST _BLOCKLISTS _USER_RULES
 
@@ -1167,7 +1211,7 @@
 	# Initialize local vars
 	typeset _i
 	# Initialize global configuration vars
-	 _CHECK_ONLY=0 ; _NO_UID_CHECK=0 ; _PRINT_ONLY=0 ; _VERBOSE=1 ; pfctl="$(CHECK_CMD pfctl)"
+	 _CHECK_ONLY=0 ; _NO_UID_CHECK=0 ; _PRINT_ONLY=0 ; _VERBOSE=1
 
 	# Command-line option handling
 	while getopts 46ABDE:F:GH:J:K:O:R:T:VZ:a:b:g:hj:l:no:r:u:w:x _opts ; do
@@ -1274,7 +1318,7 @@
 		else
 			ERR "File '${OPTARG}' either not found or has incorrect permissions!"
 		fi ;;
-	    x)  _PRINT_ONLY=1 ; _LOG=0 ; _NO_UID_CHECK=1 ;;  # Print generated list to stdout
+	    x)  _PRINT_ONLY=1 ; _LOG=0 ; _NO_UID_CHECK=1 ; confpath='/dev/null' ; getroot='false' ;;  # Print generated list to stdout
 	    ?)  HELP_MESSAGE 1>&2 ; exit 2 ;;
     	esac
 	done
@@ -1331,9 +1375,11 @@
 	custom)
 	  test -n "${getroot}" || ERR "Custom OS type specified - please set doas/sudo preference with '-Z' option"
 	  test -n "${netget}" || ERR "Custom OS type specified - please set curl/fetch/ftp/wget preference with '-F' option"
-	  test -n "${authlog_path1}" || ERR "Custom OS type specified - please specifiy path to SSH authlog with '-J' option"
-	  test -n "${authlog_path2}" || ERR "Custom OS type specified - please specifiy path to secondary SSH authlog with '-K' option"
-	  test -n "${authlog_unzip}" || ERR "Custom OS type specified - please specifiy zcat/bzcat for SSH authlog analysis with '-E' option"
+	  if [ "${_HAIL_MARY}" -eq 1 ]; then
+		test -n "${authlog_path1}" || ERR "Custom OS type specified - please specifiy path to SSH authlog with '-J' option"
+		test -n "${authlog_path2}" || ERR "Custom OS type specified - please specifiy path to secondary SSH authlog with '-K' option"
+		test -n "${authlog_unzip}" || ERR "Custom OS type specified - please specifiy zcat/bzcat for SSH authlog analysis with '-E' option"
+	  fi
 	  ;;
 	*)
 	  printf '\n\nUnknown Operating System Specified. Available Options Are:\n * -OpenBSD\n * -FreeBSD\n * -NetBSD\n * -DragonflyBSD\n * -MacOS\n\nQuitting Without Making Changes...\n\n'
@@ -1342,7 +1388,7 @@
 	esac
 
 	# Mark operating system specific variables as read-only
-	readonly getroot netget authlog_path1 authlog_path2 authlog_unzip pfctl
+	readonly getroot netget authlog_path1 authlog_path2 authlog_unzip
 
 	# Config test / dry run
 	if [ "${_CHECK_ONLY}" -eq 1 ]; then
