From d65c4f8f5d9ef0a7748ab6ad3149514225fe78fa Mon Sep 17 00:00:00 2001
From: Yaroslav Halchenko <debian@onerussian.com>
Date: Tue, 30 Dec 2014 16:44:51 -0500
Subject: [PATCH 1/4] moved debian's initd file to files/debian-initd from
 debian branch

---
 ChangeLog          |   2 +
 MANIFEST           |   1 +
 files/debian-initd | 248 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 251 insertions(+)
 create mode 100755 files/debian-initd

diff --git a/ChangeLog b/ChangeLog
index c80dac5a..853f603e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -32,6 +32,8 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released
 
 - Enhancements:
    * Enable multiport for firewallcmd-new action.  Closes gh-834
+   * files/debian-initd migrated from the debian branch and should be
+     suitable for manual installations now (thanks Juan Karlo de Guzman)
 
 
 ver. 0.9.1 (2014/10/29) - better, faster, stronger
diff --git a/MANIFEST b/MANIFEST
index eeb13eef..c6de80fd 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -328,6 +328,7 @@ man/fail2ban-server.h2m
 man/fail2ban-regex.1
 man/fail2ban-regex.h2m
 man/generate-man
+files/debian-initd
 files/gentoo-initd
 files/gentoo-confd
 files/redhat-initd
diff --git a/files/debian-initd b/files/debian-initd
new file mode 100755
index 00000000..d9bb3f50
--- /dev/null
+++ b/files/debian-initd
@@ -0,0 +1,248 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          fail2ban
+# Required-Start:    $local_fs $remote_fs
+# Required-Stop:     $local_fs $remote_fs
+# Should-Start:      $time $network $syslog iptables firehol shorewall ipmasq arno-iptables-firewall iptables-persistent ferm
+# Should-Stop:       $network $syslog iptables firehol shorewall ipmasq arno-iptables-firewall iptables-persistent ferm
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Start/stop fail2ban
+# Description:       Start/stop fail2ban, a daemon scanning the log files and
+#                    banning potential attackers.
+### END INIT INFO
+
+# Author: Aaron Isotton <aaron@isotton.com>
+# Modified: by Yaroslav Halchenko <debian@onerussian.com>
+#  reindented + minor corrections + to work on sarge without modifications
+# Modified: by Glenn Aaldering <glenn@openvideo.nl>
+#  added exit codes for status command
+# Modified: by Juan Karlo de Guzman <jkarlodg@gmail.com>
+#  corrected the DAEMON's path and the SOCKFILE
+#  rename this file: (sudo) mv /etc/init.d/fail2ban.init /etc/init.d/fail2ban
+#  same with the logrotate file: (sudo) mv /etc/logrotate.d/fail2ban.logrotate /etc/logrotate.d/fail2ban
+#
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+DESC="authentication failure monitor"
+NAME=fail2ban
+
+# fail2ban-client is not a daemon itself but starts a daemon and
+# loads its with configuration
+DAEMON=/usr/local/bin/$NAME-client
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Ad-hoc way to parse out socket file name
+SOCKFILE=`grep -h '^[^#]*socket *=' /etc/$NAME/$NAME.conf /etc/$NAME/$NAME.local 2>/dev/null \
+          | tail -n 1 | sed -e 's/.*socket *= *//g' -e 's/ *$//g'`
+[ -z "$SOCKFILE" ] && SOCKFILE='/var/run/fail2ban.sock'
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Run as root by default.
+FAIL2BAN_USER=root
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+DAEMON_ARGS="$FAIL2BAN_OPTS"
+
+# Load the VERBOSE setting and other rcS variables
+[ -f /etc/default/rcS ] && . /etc/default/rcS
+
+# Predefine what can be missing from lsb source later on -- necessary to run
+# on sarge. Just present it in a bit more compact way from what was shipped
+log_daemon_msg () {
+	[ -z "$1" ] && return 1
+	echo -n "$1:"
+	[ -z "$2" ] || echo -n " $2"
+}
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+# Actually has to (>=2.0-7) present in sarge. log_daemon_msg is predefined
+#  so we must be ok
+. /lib/lsb/init-functions
+
+#
+# Shortcut function for abnormal init script interruption
+#
+report_bug()
+{
+	echo $*
+	echo "Please submit a bug report to Debian BTS (reportbug fail2ban)"
+	exit 1
+}
+
+#
+# Helper function to check if socket is present, which is often left after
+# abnormal exit of fail2ban and needs to be removed
+#
+check_socket()
+{
+	# Return
+	#	0 if socket is present and readable
+	#	1 if socket file is not present
+	#	2 if socket file is present but not readable
+	#	3 if socket file is present but is not a socket
+	[ -e "$SOCKFILE" ] || return 1
+	[ -r "$SOCKFILE" ] || return 2
+	[ -S "$SOCKFILE" ] || return 3
+	return 0
+}
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#	0 if daemon has been started
+	#	1 if daemon was already running
+	#	2 if daemon could not be started
+	do_status && return 1
+
+	if [ -e "$SOCKFILE" ]; then
+		log_failure_msg "Socket file $SOCKFILE is present"
+		[ "$1" = "force-start" ] \
+			&& log_success_msg "Starting anyway as requested" \
+			|| return 2
+		DAEMON_ARGS="$DAEMON_ARGS -x"
+	fi
+
+	# Assure that /var/run/fail2ban exists
+	[ -d /var/run/fail2ban ] || mkdir -p /var/run/fail2ban
+
+	if [ "$FAIL2BAN_USER" != "root" ]; then
+		# Make the socket directory, IP lists and fail2ban log
+		# files writable by fail2ban
+		chown "$FAIL2BAN_USER" /var/run/fail2ban
+		# Create the logfile if it doesn't exist
+		touch /var/log/fail2ban.log
+		chown "$FAIL2BAN_USER" /var/log/fail2ban.log
+		find /proc/net/xt_recent -name 'fail2ban-*' -exec chown "$FAIL2BAN_USER" {} \;
+	fi
+
+	start-stop-daemon --start --quiet --chuid "$FAIL2BAN_USER" --exec $DAEMON -- \
+		$DAEMON_ARGS start > /dev/null\
+		|| return 2
+
+	return 0
+}
+
+
+#
+# Function that checks the status of fail2ban and returns
+# corresponding code
+#
+do_status()
+{
+	$DAEMON ping > /dev/null 2>&1
+	return $?
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#	0 if daemon has been stopped
+	#	1 if daemon was already stopped
+	#	2 if daemon could not be stopped
+	#	other if a failure occurred
+	$DAEMON status > /dev/null 2>&1 || return 1
+	$DAEMON stop > /dev/null || return 2
+
+	# now we need actually to wait a bit since it might take time
+	# for server to react on client's stop request. Especially
+	# important for restart command on slow boxes
+	count=1
+	while do_status && [ $count -lt 60 ]; do
+		sleep 1
+		count=$(($count+1))
+	done
+	[ $count -lt 60 ] || return 3 # failed to stop
+
+	return 0
+}
+
+#
+# Function to reload configuration
+#
+do_reload() {
+	$DAEMON reload > /dev/null && return 0 || return 1
+	return 0
+}
+
+# yoh:
+# shortcut function to don't duplicate case statements and to don't use
+# bashisms (arrays). Fixes #368218
+#
+log_end_msg_wrapper()
+{
+	if [ "$3" != "no" ]; then
+		[ $1 -lt $2 ] && value=0 || value=1
+		log_end_msg $value
+	fi
+}
+
+command="$1"
+case "$command" in
+	start|force-start)
+		[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+		do_start "$command"
+		log_end_msg_wrapper $? 2 "$VERBOSE"
+		;;
+
+	stop)
+		[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+		do_stop
+		log_end_msg_wrapper $? 2 "$VERBOSE"
+		;;
+
+	restart|force-reload)
+		log_daemon_msg "Restarting $DESC" "$NAME"
+		do_stop
+		case "$?" in
+			0|1)
+				do_start
+				log_end_msg_wrapper $? 1 "always"
+				;;
+			*)
+				# Failed to stop
+				log_end_msg 1
+				;;
+ 		esac
+		;;
+
+	reload|force-reload)
+        log_daemon_msg "Reloading $DESC" "$NAME"
+        do_reload
+        log_end_msg $?
+        ;;
+
+	status)
+		log_daemon_msg "Status of $DESC"
+		do_status
+		case $? in
+			0)  log_success_msg " $NAME is running" ;;
+			255)
+				check_socket
+				case $? in
+					1)  log_failure_msg " $NAME is not running" && exit 3 ;;
+					0)  log_failure_msg " $NAME is not running but $SOCKFILE exists" && exit 3 ;;
+					2)  log_failure_msg " $SOCKFILE not readable, status of $NAME is unknown" && exit 3 ;;
+					3)  log_failure_msg " $SOCKFILE exists but not a socket, status of $NAME is unknown" && exit 3 ;;
+					*)  report_bug "Unknown return code from $NAME:check_socket." && exit 4 ;;
+				esac
+				;;
+			*)  report_bug "Unknown $NAME status code" && exit 4
+		esac
+		;;
+	*)
+		echo "Usage: $SCRIPTNAME {start|force-start|stop|restart|force-reload|status}" >&2
+		exit 3
+		;;
+esac
+
+:

From 6c34cf2e1e65377106d501e7389aa324108b1998 Mon Sep 17 00:00:00 2001
From: Lee Clemens <droid@lc-cs.com>
Date: Tue, 30 Dec 2014 17:52:45 -0500
Subject: [PATCH 2/4] Add .idea dir to .gitignore

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index a8942050..780ecfb5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ htmlcov
 *.bak
 __pycache__
 .vagrant/
+.idea/

From 2d7429c47cfef27f89818e665c6b7634d9f6d140 Mon Sep 17 00:00:00 2001
From: Lee Clemens <droid@lc-cs.com>
Date: Tue, 30 Dec 2014 18:05:19 -0500
Subject: [PATCH 3/4] Add 'Client host rejected error message' regex Not sure
 if it was reworded (using Postfix 2.6) or a slightly different error, but I
 only have "Client host rejected: cannot find your hostname"

---
 ChangeLog                         | 1 +
 config/filter.d/postfix.conf      | 1 +
 fail2ban/tests/files/logs/postfix | 3 +++
 3 files changed, 5 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index c80dac5a..162071e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,6 +21,7 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released
    * filters.d/exim.conf - cover different settings of exim logs
      details. Thanks bes.internal
    * filter.d/postfix-sasl.conf - failregex is now case insensitive
+   * filters.d/postfix.conf - add 'Client host rejected error message' failregex
 
 - New Features:
    - New interpolation feature for config readers - `%(known/parameter)s`.
diff --git a/config/filter.d/postfix.conf b/config/filter.d/postfix.conf
index a7a05e47..a994d772 100644
--- a/config/filter.d/postfix.conf
+++ b/config/filter.d/postfix.conf
@@ -13,6 +13,7 @@ before = common.conf
 _daemon = postfix/(submission/)?smtp(d|s)
 
 failregex = ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1 .*$
+            ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 Client host rejected: cannot find your hostname, (\[\S*\]); from=<\S*> to=<\S+> proto=ESMTP helo=<\S*>$
             ^%(__prefix_line)sNOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo= *$
             ^%(__prefix_line)sNOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1 .*$
             ^%(__prefix_line)simproper command pipelining after \S+ from [^[]*\[<HOST>\]:?$
diff --git a/fail2ban/tests/files/logs/postfix b/fail2ban/tests/files/logs/postfix
index ccf2f8bc..fff25bb9 100644
--- a/fail2ban/tests/files/logs/postfix
+++ b/fail2ban/tests/files/logs/postfix
@@ -20,3 +20,6 @@ Dec 25 02:35:54 platypus postfix/smtpd[9144]: improper command pipelining after
 
 # failJSON: { "time": "2004-12-18T02:05:46", "match": true , "host": "216.245.198.245" }
 Dec 18 02:05:46 platypus postfix/smtpd[16349]: improper command pipelining after NOOP from unknown[216.245.198.245]
+
+# failJSON: { "time": "2014-12-21T21:17:29", "match": true , "host": "93.184.216.34" }
+Dec 21 21:17:29 xxx postfix/smtpd[7150]: NOQUEUE: reject: RCPT from badserver.example.com[93.184.216.34]: 450 4.7.1 Client host rejected: cannot find your hostname, [93.184.216.34]; from=<badactor@example.com> to=<goodguy@example.com> proto=ESMTP helo=<badserver.example.com>

From e6ffa2e4a19dbab4782d39cb066d5d1f196ab811 Mon Sep 17 00:00:00 2001
From: Lee Clemens <droid@lc-cs.com>
Date: Tue, 30 Dec 2014 18:10:19 -0500
Subject: [PATCH 4/4] Update year in postfix logs test file

---
 fail2ban/tests/files/logs/postfix | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fail2ban/tests/files/logs/postfix b/fail2ban/tests/files/logs/postfix
index fff25bb9..ee8720f8 100644
--- a/fail2ban/tests/files/logs/postfix
+++ b/fail2ban/tests/files/logs/postfix
@@ -21,5 +21,5 @@ Dec 25 02:35:54 platypus postfix/smtpd[9144]: improper command pipelining after
 # failJSON: { "time": "2004-12-18T02:05:46", "match": true , "host": "216.245.198.245" }
 Dec 18 02:05:46 platypus postfix/smtpd[16349]: improper command pipelining after NOOP from unknown[216.245.198.245]
 
-# failJSON: { "time": "2014-12-21T21:17:29", "match": true , "host": "93.184.216.34" }
+# failJSON: { "time": "2004-12-21T21:17:29", "match": true , "host": "93.184.216.34" }
 Dec 21 21:17:29 xxx postfix/smtpd[7150]: NOQUEUE: reject: RCPT from badserver.example.com[93.184.216.34]: 450 4.7.1 Client host rejected: cannot find your hostname, [93.184.216.34]; from=<badactor@example.com> to=<goodguy@example.com> proto=ESMTP helo=<badserver.example.com>