#!/usr/bin/python
#written by Nicholas Nachefski

#init
import getopt, sys, datetime, re, os, subprocess

#subs
def usage():
    print "Usage: %s -w"%sys.argv[0]
    sys.exit(2)

#get options
if len(sys.argv) < 1:
    usage()

#globals
#global array for watched files
Files = []

#global array for syscall and other rules
System = []

#get date and time for report info
t = datetime.datetime.now()
timestamp = t.strftime("%m/%d/%Y %H:%M:%S\n")

#discover what arch this system is
if re.match('^x86_64$', os.uname()[4]):
    arch='b64' 
if re.match('^i\d*86$', os.uname()[4]):
    arch='b32'

#check our args
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-d", "--debug",
                  action="store_true", dest="debug", default=False,
                  help="do not write the policy, print to stdout")
		
(options, args) = parser.parse_args()

#main function
def main():
    print "Starting run:", timestamp

#check for httpd
# look for active httpd conf files with 'httpd -S'
    try:
        retcode = subprocess.call(['/sbin/service httpd status &> /dev/null'], shell=True)
        if retcode == 0:
	    if os.path.isfile('/etc/httpd/conf/httpd.conf'):
		Files.append(['/etc/httpd/conf/httpd.conf', 'ids-file-low'])
		f = open('/etc/httpd/conf/httpd.conf', 'r')
		for line in f:
		    if re.match('^\s*Include', line):
	                m = re.match(r"^\s*Include\s*(.+)", line)
	                test = m.group(1)
			if re.match('^/.+', test):
			    lsline = test
			else:
			    lsline = "/etc/httpd/" + test
			output = subprocess.Popen(['ls ' + lsline], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ).communicate()[0]
			array = output.split("\n")
			for a in array:
			    if re.match('^$', a):
				continue
			    else:
				Files.append([a, 'ids-file-low'])
	    output = subprocess.Popen(['httpd -S'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0]
	    if re.search('\(.+\:\d\)', output):
                m = re.findall('\(.+\:', output)
		for line in m:
		    c = line.strip(':')
		    conf = c.strip('(')

		    inc = 0
		    for test in Files:
			if test[0] == conf:
			    inc = inc+1

		    if inc == 0:
			Files.append([conf, 'ids-file-low'])

    except OSError, e:
        print >>sys.stderr, "Execution failed:", e
	sys.exit(1)

#check for mysql
    retcode = subprocess.call(['/sbin/service mysqld status &> /dev/null'], shell=True)
    if retcode == 0:
        if os.path.isfile('/etc/my.cnf'):
            Files.append(['/etc/my.cnf', 'ids-file-hi'])

#check for yum
    if os.path.isfile('/etc/yum.conf'):
        Files.append(['/etc/yum.conf', 'ids-file-med'])

#check for user cronjobs
    files = os.listdir('/var/spool/cron')
    for i in files:
	Files.append(['/var/spool/cron/' + i, 'ids-file-hi'])

#check for xinetd services
    files = os.listdir('/etc/xinetd.d')
    for i in files:
        Files.append(['/etc/xinetd.d/' + i, 'ids-file-low'])

#check for pam files
    files = os.listdir('/etc/pam.d')
    for i in files:
        Files.append(['/etc/pam.d/' + i, 'ids-file-hi'])

#check for system crons
    if os.path.isfile('/etc/crontab'):
	Files.append(['/etc/crontab', 'ids-file-hi'])

    files = os.listdir('/etc/cron.hourly')
    for i in files:
        Files.append(['/etc/cron.hourly/' + i, 'ids-file-low'])

    files = os.listdir('/etc/cron.daily')
    for i in files:
	Files.append(['/etc/cron.daily/' + i, 'ids-file-low'])

    files = os.listdir('/etc/cron.weekly')
    for i in files:
        Files.append(['/etc/cron.weekly/' + i, 'ids-file-low'])

    files = os.listdir('/etc/cron.monthly')
    for i in files:
        Files.append(['/etc/cron.monthly/' + i, 'ids-file-low'])

#check for ldap/nss files
    if os.path.isfile('/etc/ldap.conf'):
        Files.append(['/etc/ldap.conf', 'ids-file-hi'])

    if os.path.isfile('/etc/nsswitch.conf'):
        Files.append(['/etc/nsswitch.conf', 'ids-file-hi'])

    if os.path.isfile('/etc/nscd.conf'):
	Files.append(['/etc/nscd.conf', 'ids-file-hi'])

#user stuff
    if os.path.isfile('/etc/passwd'):
        Files.append(['/etc/passwd', 'ids-file-low'])
    if os.path.isfile('/etc/shadow'):
        Files.append(['/etc/shadow', 'ids-file-low'])
    if os.path.isfile('/etc/group'):
        Files.append(['/etc/group', 'ids-file-low'])

#grub
    if os.path.isfile('/boot/grub/grub.conf'):
        Files.append(['/boot/grub/grub.conf', 'ids-file-hi'])

#check for ssh configs
    if os.path.isfile('/etc/ssh/sshd_config'):
        Files.append(['/etc/ssh/sshd_config', 'ids-file-hi'])

    if os.path.isfile('/etc/ssh/ssh_config'):
        Files.append(['/etc/ssh/ssh_config', 'ids-file-hi'])

#shell files
    if os.path.isfile('/etc/bashrc'):
        Files.append(['/etc/bashrc', 'ids-file-low'])

#iptables policy
    if os.path.isfile('/etc/sysconfig/iptables.save'):
        Files.append(['/etc/sysconfig/iptables.save', 'ids-file-low'])
    if os.path.isfile('/etc/sysconfig/iptables'):
        Files.append(['/etc/sysconfig/iptables', 'ids-file-low'])

#host stuff
    if os.path.isfile('/etc/hosts'):
        Files.append(['/etc/hosts', 'ids-file-low'])
    if os.path.isfile('/etc/resolv.conf'):
        Files.append(['/etc/resolv.conf', 'ids-file-med'])
    if os.path.isfile('/etc/sysconfig/network'):
        Files.append(['/etc/sysconfig/network', 'ids-file-hi'])

#network scripts
    files = os.listdir('/etc/sysconfig/network-scripts/')
    for i in files:
        if re.search('ifcfg-eth', i):
            Files.append(['/etc/sysconfig/network-scripts/' + i, 'ids-file-hi'])

#system stuff
    if os.path.isfile('/etc/sysctl.conf'):
        Files.append(['/etc/sysctl.conf', 'ids-file-hi'])

#check sudoers file
    if os.path.isfile('/etc/sudoers'):
        Files.append(['/etc/sudoers', 'ids-file-hi'])

#check fstab
    if os.path.isfile('/etc/fstab'):
        Files.append(['/etc/fstab', 'ids-file-hi'])

#inittab
    if os.path.isfile('/etc/inittab'):
        Files.append(['/etc/inittab', 'ids-file-hi'])

#prelude stuff
    if os.path.isfile('/etc/prelude/default/global.conf'):
        Files.append(['/etc/prelude/default/global.conf', 'ids-file-med'])
    if os.path.isfile('/etc/prelude/default/client.conf'):
        Files.append(['/etc/prelude/default/client.conf', 'ids-file-med'])

#audit config
    if os.path.isfile('/etc/audit/audit.rules'):
        Files.append(['/etc/audit/audit.rules', 'ids-file-hi'])
    if os.path.isfile('/etc/audisp/audispd.conf'):
        Files.append(['/etc/audisp/audispd.conf', 'ids-file-hi'])
    if os.path.isfile('/etc/audisp/audisp-prelude.conf'):
        Files.append(['/etc/audisp/audisp-prelude.conf', 'ids-file-hi'])
    if os.path.isfile('/etc/audisp/audisp-remote.conf'):
        Files.append(['/etc/audisp/audisp-remote.conf', 'ids-file-hi'])

#finished finding configs to monitor

##now add syscall related stuff to monitor here
##- Unauthorized access attempts to files (unsuccessful) 
    System.append('-a always,exit -F arch=' + arch + ' -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k ids-exec-hi')
    System.append('-a always,exit -F arch=' + arch + ' -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k ids-exec-hi')

##watch for nmap usage
    System.append('-a always,exit -F path=/usr/bin/nmap -F perm=x -k ids-exec-hi')

###now build the audit plolicy
    if options.debug:
        print "-D\n-b 1024"
        for path, pri in Files:
            print '-a exit,always -F arch=' + arch + ' -S open -F path=' + path + ' -F perm=wa ' + '-k ' + pri

    else:
        filename = "/etc/audit/audit.rules"
        print "Writing audit policy to: %s" % filename
        file = open(filename, 'w')
        file.write("#policy created: " + timestamp)
        file.write("-D\n-b 1024\n")
        for path, pri in Files:
            file.write('-a exit,always -F arch=' + arch + ' -S open -F path=' + path + ' -F perm=wa ' + '-k ' + pri + '\n')
        file.close()

        #now restart auditd for the changes to take effect
        retcode = subprocess.call(['/sbin/service auditd restart &> /dev/null'], shell=True)
        if retcode != 0:
            print "Restart of auditd failed!!!!!"
            sys.exit(1)
        else:
            print "auditd restarted...."

    #exit cleanly
    sys.exit(0)

#call main
if __name__ == "__main__":
    main()
