Imported Upstream version 2.7
[ossec-hids.git] / active-response / firewall-drop.sh
index 65b1dbd..f0e634b 100755 (executable)
@@ -6,12 +6,15 @@
 # Expect: srcip
 # Author: Ahmet Ozturk (ipfilter and IPSec)
 # Author: Daniel B. Cid (iptables)
-# Last modified: Feb 14, 2006
+# Author: cgzones 
+# Last modified: Oct 04, 2012
 
 UNAME=`uname`
 ECHO="/bin/echo"
 GREP="/bin/grep"
-IPTABLES="/sbin/iptables"
+IPTABLES=""
+IP4TABLES="/sbin/iptables"
+IP6TABLES="/sbin/ip6tables"
 IPFILTER="/sbin/ipf"
 if [ "X$UNAME" = "XSunOS" ]; then
     IPFILTER="/usr/sbin/ipf"
@@ -27,11 +30,18 @@ ACTION=$1
 USER=$2
 IP=$3
 
+
 LOCAL=`dirname $0`;
 cd $LOCAL
 cd ../
 PWD=`pwd`
-echo "`date` $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log
+filename=$(basename "$0")
+
+LOCK="${PWD}/fw-drop"
+LOCK_PID="${LOCK}/pid"
+LOG_FILE="${PWD}/../logs/active-responses.log"
+
+echo "`date` $0 $1 $2 $3 $4 $5" >> ${LOG_FILE}
 
 
 # Checking for an IP
@@ -40,6 +50,84 @@ if [ "x${IP}" = "x" ]; then
    exit 1;
 fi
 
+case "${IP}" in
+    *:* ) IPTABLES=$IP6TABLES;;
+    *.* ) IPTABLES=$IP4TABLES;;
+    * ) echo "`date` Unable to run active response (invalid IP: '${IP}')." >> ${LOG_FILE} && exit 1;;
+esac
+
+# This number should be more than enough (even if a hundred
+# instances of this script is ran together). If you have
+# a really loaded env, you can increase it to 75 or 100.
+MAX_ITERATION="50"
+
+# Lock function
+lock()
+{
+    i=0;
+    # Providing a lock.
+    while [ 1 ]; do
+        mkdir ${LOCK} > /dev/null 2>&1
+        MSL=$?
+        if [ "${MSL}" = "0" ]; then
+            # Lock aquired (setting the pid)
+            echo "$$" > ${LOCK_PID}
+            return;
+        fi
+
+        # Getting currently/saved PID locking the file
+        C_PID=`cat ${LOCK_PID} 2>/dev/null`
+        if [ "x" = "x${S_PID}" ]; then
+            S_PID=${C_PID}
+        fi
+
+        # Breaking out of the loop after X attempts
+        if [ "x${C_PID}" = "x${S_PID}" ]; then
+            i=`expr $i + 1`;
+        fi
+
+        # Sleep 1 after 10/25 interactions
+        if [ "$i" = "10" -o "$i" = "25" ]; then
+            sleep 1;
+        fi
+
+        i=`expr $i + 1`;
+
+        # So i increments 2 by 2 if the pid does not change.
+        # If the pid keeps changing, we will increments one
+        # by one and fail after MAX_ITERACTION
+
+        if [ "$i" = "${MAX_ITERATION}" ]; then
+            kill="false"
+            for pid in `pgrep -f "${filename}"`; do
+                if [ "x${pid}" = "x${C_PID}" ]; then
+                    # Unlocking and exiting
+                    kill -9 ${C_PID}
+                    echo "`date` Killed process ${C_PID} holding lock." >> ${LOG_FILE}
+                    kill="true"
+                    unlock;
+                    i=0;
+                    S_PID="";
+                    break;
+                fi
+            done
+
+            if [ "x${kill}" = "xfalse" ]; then
+                echo "`date` Unable kill process ${C_PID} holding lock." >> ${LOG_FILE}
+                # Unlocking and exiting
+                unlock;
+                exit 1;
+            fi
+        fi
+    done
+}
+
+# Unlock function
+unlock()
+{
+   rm -rf ${LOCK} 
+}
+
 
 
 # Blocking IP
@@ -61,17 +149,17 @@ if [ "X${UNAME}" = "XLinux" ]; then
    fi
    
    # Checking if iptables is present
-   ls ${IPTABLES} >> /dev/null 2>&1
-   if [ $? != 0 ]; then
+   if [ ! -x ${IPTABLES} ]; then
       IPTABLES="/usr"${IPTABLES}
-      ls ${IPTABLES} >> /dev/null 2>&1
-      if [ $? != 0 ]; then
-         exit 0;
+      if [ ! -x ${IPTABLES} ]; then
+        echo "$0: can not find iptables"
+        exit 0;
       fi
    fi
 
    # Executing and exiting
    COUNT=0;
+   lock;
    while [ 1 ]; do
        echo ".."
         ${IPTABLES} ${ARG1}
@@ -80,7 +168,7 @@ if [ "X${UNAME}" = "XLinux" ]; then
             break;
         else
             COUNT=`expr $COUNT + 1`;
-            echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log     
+            echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${LOG_FILE}
             sleep $COUNT;
 
             if [ $COUNT -gt 4 ]; then
@@ -96,7 +184,7 @@ if [ "X${UNAME}" = "XLinux" ]; then
             break;
         else
             COUNT=`expr $COUNT + 1`;
-            echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${PWD}/../logs/active-responses.log     
+            echo "`date` Unable to run (iptables returning != $RES): $COUNT - $0 $1 $2 $3 $4 $5" >> ${LOG_FILE}
             sleep $COUNT;
 
             if [ $COUNT -gt 4 ]; then
@@ -104,6 +192,7 @@ if [ "X${UNAME}" = "XLinux" ]; then
             fi       
         fi
    done
+   unlock;
             
    exit 0;