#!/usr/bin/python
""" Pyroman, an iptables firewall configuration tool """
# where the pyroman libraries are found - e.g. /usr/share/pyroman
library_path = "./"
# where the rules are located - e.g. /etc/pyroman
default_rules_path = "./examples/base"
# timeout for the "safe" mode invocation
safe_timeout_default = 30

#Copyright (c) 2011 Erich Schubert erich@debian.org

#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:

#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.
import sys, glob, os, getopt

# path to the main pyroman code
sys.path.insert(0, library_path)

# usercommands, the Firewall class and the firewall object
# should be available to user rules
from pyroman import *

# Pyroman version
version = "0.5.0~alpha1"

def usage():
	print """\
Usage: pyroman [-hiVnspP] [--help] [--init] [--version] [--no-act]
       [-r rulesdir] [--rules=rulesdir] [--print] [--print-verbose]
       [-t seconds] [--timeout=seconds] [--verification-cmd=cmd] [--safe] [safe]\
"""

def main():
	rules_path = default_rules_path
	no_act = False
	print_only = False
	verbose_print = False
	terse_mode = False
	# parse options
	try:
		opts, args = getopt.getopt(sys.argv[1:], "hiVr:t:snpP", \
			["help", "init", "version", "rules=", "timeout=", "safe", "no-act",
			 "print", "print-verbose", "verification-cmd=", "verification-command="])
	except getopt.GetoptError:
		usage()
		sys.exit(2)

	for o, a in opts:
		# help screen
		if o in ("-h", "--help"):
			usage()
			sys.exit()
		# print version number
		if o in ("-V", "--version"):
			print "Pyroman version %s" % version
			sys.exit()
		# "init" mode (reduced output)
		if o in ("-i", "--init"):
			terse_mode = True
		# Use different directory for rules
		if o in ("-r", "--rules"):
			rules_path = a
		# Setup timeout, implies -s
		if o in ("-t", "--timeout"):
			Firewall.timeout = int(a)
		# When given the "safe" parameter, setup a timeout.
		if o in ("-s", "--safe"):
			if not Firewall.timeout:
				Firewall.timeout = safe_timeout_default
		# Use external verification command
		if o in ("--verification-cmd", "--verification-command"):
			Firewall.vercmd = a
		# Don't execute firewall
		if o in ("-n", "--no-act"):
			no_act = True
		# Print resulting firewall only
		if o in ("-p", "--print"):
			print_only = True
			verbose_print = False
		# Print resulting firewall only
		if o in ("-P", "--print-verbose"):
			print_only = True
			verbose_print = True

	# When given the "safe" parameter, setup a timeout.
	if len(args) > 0:
		if len(args) == 1 and args[0] == "safe":
			if not Firewall.timeout:
				Firewall.timeout = safe_timeout_default
		else:
			print "Unknown parameter passed."
			usage()
			sys.exit(2)
	run(rules_path, no_act, print_only, verbose_print, terse_mode)

def run(rules_path, no_act, print_only, verbose_print, terse_mode):
	# load user rules alphabetically
	rfiles = glob.glob(os.path.join(rules_path,"*.py"))
	rfiles.extend( glob.glob(os.path.join(rules_path,"*.xml")) )
	if len(rfiles) < 1:
		print "No rule files found in directory '%s'!" % rules_path
		sys.exit(1)
	rfiles.sort()
	for nam in rfiles:
		try:
			if nam.endswith(".py"):
				execfile(nam)
			elif nam.endswith(".xml"):
				parseXML(nam)
		except Exception, e:
			print "An exception occurred during parsing '%s':" % nam
			print e
			sys.exit(3)

	# do some consistency checks
	try:
		Firewall.verify()
	except Exception, e:
		print "An exception occurred during verification:"
		print e
		sys.exit(3)
	# generate...
	try:
		Firewall.generate()
	except Exception, e:
		print "An exception occurred during generation:"
		print e
		sys.exit(3)
	# execute firewall
	if no_act:
		print "Syntax checks passed, would commit to iptables now."
	elif print_only:
		Firewall.print_rules(verbose_print)
	else:
		Firewall.execute_rules(terse_mode)

if __name__ == "__main__":
	main()
