#!/bin/bash

# The purpose of this script is to download any Emerging Threat files you want and combine
# them with any existing ClearOS snort rules you want. It removes any rules with duplicate
# sid's leaving the one with a higher revision number. It also copies snortsam rules from any
# rule revision and adds them into later rule revisions. As a by-product of this, it enables
# you to add snortsam rules to the ET rules in a permanent way
#
# In order to use the script, you need to add a line "include $RULE_PATH/combined.rules" to
# /etc/snort.conf and disable any includes there where you are combining the files in this
# script
#
# Set EXIT_ON_FAILED_DOWNLOAD to 1 if you want the script to exit if you have a failed
# download. This has the advantage that if the download of the emerging-all.rules fails you
# do not get left with a rule set just made up of the ClearOS rules. Instead the old combined
# rule set remains intact. Setting it to 0 may be useful if you are downloading many small
# rule files and you do not want the script to abort if one file in unavailable

# script variables
SNORT_HOME=/etc/snort/
RULES_DOWNLOAD_DIR=/etc/snort/ET-downloads/
EXIT_ON_FAILED_DOWNLOAD=1

# This function 
# - removes leading spaces, comments and blank lines and trailing spaces and tabs
# - picks out the sid and revision number for each rule then it sticks the rule number,
#   revision number source file name and line number line number and if there is a snortsam
#   rule and puts them in front of the rule
# - It then output appends to rule to the temporary file

function indexrules {
	RULEFILE=$1
	sed '/^$/d; s/^[ \t]*//; /^#/d; s/[ \t]*$//' $1 | awk -v FILE=$RULEFILE '{ 
	test = match($0, /sid:[[:blank:][:digit:]]*;/)
	sid = substr($0 , RSTART+4, RLENGTH-5)
	gsub(/ */, "", sid)

	rev = match($0, /rev:[-[:blank:][:digit:]]*;/)
	if (rev > 0)
		rev = substr($0 , RSTART+4, RLENGTH-5)
	gsub(/ */, "", rev)


	samrule = /fwsam:/
	newtext = sid " " rev " " FILE " " NR " " samrule " " $0
	print newtext }' >> $RULES_DOWNLOAD_DIR"indexed.tmp"
}

# This function
# - deletes the old rule file you are about to download
# - downloads the new file
# - calls the above function to build the temp file


function getrules {
	ET_RULES_URL="http://rules.emergingthreats.net/open/snort-2.8.4/rules/"
	cd $RULES_DOWNLOAD_DIR
	rm -f $1
	wget -q $ET_RULES_URL$1
	if [ ! -e $1 ]; then
		echo "$1 not downloaded"
		DOWNLOAD_FAIL=1
	else
		indexrules $1
	fi
}

function getblockrules {
	ET_RULES_URL="http://rules.emergingthreats.net/blockrules/"
	cd $RULES_DOWNLOAD_DIR
	rm -f $1
	wget -q $ET_RULES_URL$1
	if [ ! -e $1 ]; then
		echo "$1 not downloaded"
		DOWNLOAD_FAIL=1
	else
		indexrules $1
	fi
}

# Create the download directory if it does not exist

if [ -d $SNORT_HOME ]; then
	cd $SNORT_HOME
	if [ ! -d $RULES_DOWNLOAD_DIR ]; then
		mkdir $RULES_DOWNLOAD_DIR
	fi
fi

# Clear the temp file

rm -f $RULES_DOWNLOAD_DIR"indexed.tmp"

DOWNLOAD_FAIL=0

# Download the rules from Emerging Threats
# Note that you can download some or all of the individual rule sets of you want instead.
# To do that change ET_RULES_URL to http://rules.emergingthreats.net/open/snort-2.8.4/rules/
# in the getrules function then repeat the line below as many times as you want changing the
# file name you want to download

#commented for not downloading all ET rules
#getrules emerging-all.rules

getrules emerging-activex.rules
getrules emerging-attack_response.rules
getrules emerging-ciarmy.rules
getrules emerging-current_events.rules
getrules emerging-dns.rules
getrules emerging-dos.rules
getrules emerging-exploit.rules
getrules emerging-ftp.rules
getrules emerging-icmp.rules
getrules emerging-icmp_info.rules
getrules emerging-imap.rules
getrules emerging-malware.rules
getrules emerging-misc.rules
getrules emerging-mobile_malware.rules
getrules emerging-policy.rules
getrules emerging-pop3.rules
getrules emerging-rpc.rules
getrules emerging-scan.rules
getrules emerging-smtp.rules
getrules emerging-snmp.rules
getrules emerging-sql.rules
getrules emerging-telnet.rules
getrules emerging-tftp.rules
getrules emerging-trojan.rules
getrules emerging-user_agents.rules
getrules emerging-virus.rules
getrules emerging-web_client.rules
getrules emerging-web_server.rules
getrules emerging-web_specific_apps.rules
getrules emerging-worm.rules

#download BLOCK rules from ET
getblockrules emerging-botcc-BLOCK.rules
getblockrules emerging-compromised-BLOCK.rules
getblockrules emerging-dshield-BLOCK.rules
getblockrules emerging-rbn-BLOCK.rules
getblockrules emerging-rbn-malvertisers-BLOCK.rules

if [ $DOWNLOAD_FAIL -eq 1 ]; then
	if [ $EXIT_ON_FAILED_DOWNLOAD -eq 1 ]; then
		echo "Exiting"
		exit
	else
		echo "Continuing"
	fi
fi

# Append all the current rules to the temp file
# The list below is all the files in ClearOS 5.2 except local.rules
# I have also indicated which are the ones enabled in /etc/snort.conf by default
# I have not included local.rules as they are never downloaded from ET and if you add a local
# rule manually you would have to remember to run this script before the changes took effect
# instead of simply doing a service snort restart
###############################################################
#                                                             #
#                     IMPORTANT                               #
#                                                             #
# Any rules enabled below MUST be disabled in /etc/snort.conf #
#                                                             #
###############################################################

cd $SNORT_HOME
indexrules attack-responses.rules	# rule set used by default
indexrules backdoor.rules		# rule set used by default
indexrules bad-traffic.rules	# rule set used by default
#indexrules chat.rules
indexrules ddos.rules		# rule set used by default
#indexrules deleted.rules
indexrules dns.rules			# rule set used by default
indexrules dos.rules			# rule set used by default
#indexrules experimental.rules
indexrules exploit.rules
indexrules finger.rules		# rule set used by default
indexrules ftp.rules			# rule set used by default
#indexrules icmp-info.rules
indexrules icmp.rules		# rule set used by default
indexrules imap.rules		# rule set used by default
#indexrules info.rules
indexrules malware-user-agents.rules
indexrules misc.rules		# rule set used by default
#indexrules multimedia.rules
indexrules mysql.rules		# rule set used by default
#indexrules netbios.rules
indexrules nntp.rules		# rule set used by default
indexrules oracle.rules		# rule set used by default
#indexrules other-ids.rules
#indexrules p2p.rules
#indexrules policy.rules
indexrules pop2.rules		# rule set used by default
indexrules pop3.rules		# rule set used by default
#indexrules porn.rules
indexrules rpc.rules			# rule set used by default
indexrules rservices.rules		# rule set used by default
indexrules scan.rules		# rule set used by default
#indexrules shellcode.rules
indexrules smtp.rules
indexrules snmp.rules		# rule set used by default
indexrules sql-injection.rules
indexrules sql.rules			# rule set used by default
indexrules telnet.rules		# rule set used by default
indexrules tftp.rules		# rule set used by default
indexrules virus.rules
indexrules web-attacks.rules	# rule set used by default
indexrules web-cgi.rules		# rule set used by default
indexrules web-client.rules		# rule set used by default
indexrules web-coldfusion.rules	# rule set used by default
indexrules web-frontpage.rules	# rule set used by default
indexrules web-iis.rules		# rule set used by default
indexrules web-misc.rules		# rule set used by default
indexrules web-php.rules		# rule set used by default
#indexrules x11.rules			# rule set used by default
indexrules snortsam.rules		# magic rule set for injecting snortsam rules

cd $RULES_DOWNLOAD_DIR

# This next bit:
# - sorts by sid (asc), rev (asc), snortsam_rule_indicator (desc) then
# - pipes into an awk which checks if the rule has a snortsam_rule_indicator and reads the
#   snortsam rule if it does and inserts it into all occurrences of the same rule number then
# - sorts by sid and revision in descending order then
# - pipes it into awk which prints the first line of any sid only unless the revision is < 0
#   (therefore the one with the highest revision but not a manually added snortsam rule then
# - pipes it into sort which sorts by the original file name and original line number so the
#   lines from any file go back to the original order they were in then
# - pipes it into awk again which strips out the sid, revision number, original file name,
#   original line number and snortsam rule indicator fields which were added earlier to
#   facilitate all the file sorting
# - the result is output to a file called combined.rules

sort -n -k 1,2 -k 5,5r indexed.tmp | \
	awk '{
		if ($5 == 1)
			{
			temp = match($0, /fwsam:[^;]*;/)
			fwsamrule = " " substr($0, RSTART, RLENGTH) ")"
			}
		else
			{
			if ($1 == lastrulenum)
				{
				if (fwsamrule != "")
					sub(/)$/, fwsamrule )
				}
			else
				fwsamrule = ""
			}
		
		lastrulenum = $1
		print $0 }' | \
	sort -nr -k 1,2  | \
	awk '{ if ($1 != lastrule && $2 >= 0) { print $0 } lastrule = $1 }' | \
	sort -k 3,3 -k 4,4n | \
	awk '{ sub(/^.*\.rules [[:digit:]]* [[:digit:]]* /, ""); print $0 }' > $SNORT_HOME"combined.rules"

# Remove the temp file

rm -f $RULES_DOWNLOAD_DIR"indexed.tmp"

# restart snort
/sbin/service snort restart

#create sid-msg.map
#/root/tools/create-sidmap.pl /etc/snort > /etc/snort/sid-msg.map 2>/dev/null



