Chris PeBenito 89ec23
#!/usr/bin/python
Chris PeBenito 89ec23
Chris PeBenito 89ec23
#  Author: Joshua Brindle <jbrindle@tresys.com>
Chris PeBenito 89ec23
#
Chris PeBenito 89ec23
# Copyright (C) 2003 - 2005 Tresys Technology, LLC
Chris PeBenito 89ec23
#      This program is free software; you can redistribute it and/or modify
Chris PeBenito 89ec23
#      it under the terms of the GNU General Public License as published by
Chris PeBenito 89ec23
#      the Free Software Foundation, version 2.
Chris PeBenito 89ec23
Chris PeBenito 89ec23
"""
Chris PeBenito 5a3299
	This module generates configuration files and documentation from the 
Chris PeBenito 5a3299
	SELinux reference policy XML format. 
Chris PeBenito 89ec23
"""
Chris PeBenito 89ec23
Chris PeBenito 89ec23
import sys
Chris PeBenito 89ec23
import getopt
Chris PeBenito 89ec23
import pyplate
Chris PeBenito 5a3299
import os
Chris PeBenito 89ec23
from xml.dom.ext import *
Chris PeBenito 89ec23
from xml.dom.ext.reader import Sax2
Chris PeBenito 89ec23
Chris PeBenito 89ec23
def read_policy_xml(filename):
Chris PeBenito 89ec23
	try:
Chris PeBenito 1601fb
		xml_fh = open(filename)
Chris PeBenito 1601fb
	except:
Chris PeBenito 1601fb
		error("error opening " + filename)
Chris PeBenito 1601fb
Chris PeBenito 1601fb
	try:
Chris PeBenito 89ec23
		reader = Sax2.Reader()
Chris PeBenito 1601fb
		doc = reader.fromString(xml_fh.read())
Chris PeBenito 89ec23
	except: 
Chris PeBenito 1601fb
		xml_fh.close()
Chris PeBenito 89ec23
		error("Error while parsing xml")
Chris PeBenito 1601fb
Chris PeBenito 1601fb
	xml_fh.close()	
Chris PeBenito 89ec23
	return doc
Chris PeBenito 89ec23
Chris PeBenito 89ec23
def gen_tunable_conf(doc, file):
Chris PeBenito 89ec23
	for node in doc.getElementsByTagName("tunable"):
Chris PeBenito 89ec23
		s = string.split(node.firstChild.data, "\n")
Chris PeBenito 89ec23
		for line in s:
Chris PeBenito 89ec23
			file.write("# %s\n" % line)
Chris PeBenito 89ec23
		tun_name = tun_val = None
Chris PeBenito 89ec23
        	for (name, value) in node.attributes.items():
Chris PeBenito 89ec23
			if name[1] == "name":
Chris PeBenito 89ec23
				tun_name = value.value
Chris PeBenito 89ec23
			elif name[1] == "dftval":
Chris PeBenito 89ec23
				tun_val = value.value
Chris PeBenito 89ec23
Chris PeBenito 89ec23
			if tun_name and tun_val:
Chris PeBenito 89ec23
	            		file.write("%s = %s\n\n" % (tun_name, tun_val))
Chris PeBenito 89ec23
				tun_name = tun_val = None
Chris PeBenito 89ec23
Chris PeBenito 89ec23
def gen_module_conf(doc, file):
Chris PeBenito 5a3299
	file.write("#\n# This file contains a listing of available modules.\n")
Chris PeBenito 5a3299
	file.write("# To prevent a module from  being used in policy\n")
Chris PeBenito 5a3299
	file.write("# creation, uncomment the line with its name.\n#\n")
Chris PeBenito 89ec23
	for node in doc.getElementsByTagName("module"):
Chris PeBenito 5a3299
		mod_name = mod_layer = None
Chris PeBenito 5a3299
		for (name, value) in node.attributes.items():
Chris PeBenito 5a3299
			if name[1] == "name":
Chris PeBenito 5a3299
				mod_name = value.value
Chris PeBenito 5a3299
			if name[1] == "layer":
Chris PeBenito 5a3299
				mod_layer = value.value
Chris PeBenito 5a3299
Chris PeBenito 5a3299
			if mod_name and mod_layer:
Chris PeBenito 5a3299
				file.write("# Layer: %s\n# Module: %s\n#\n" % (mod_layer,mod_name))
Chris PeBenito 5a3299
Chris PeBenito 89ec23
		for desc in node.getElementsByTagName("summary"):
Chris PeBenito 89ec23
			s = string.split(desc.firstChild.data, "\n")
Chris PeBenito 89ec23
			for line in s:
Chris PeBenito 89ec23
				file.write("# %s\n" % line)	
Chris PeBenito 5a3299
			file.write("#\n#%s\n\n" % mod_name)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
def gen_doc_menu(mod_layer, module_list):
Chris PeBenito 5a3299
	menu = {}
Chris PeBenito 5a3299
	for name, value in module_list.iteritems():
Chris PeBenito 5a3299
		if not menu.has_key(name):
Chris PeBenito 5a3299
			menu[name] = {}
Chris PeBenito 5a3299
		if name == mod_layer or mod_layer == None:
Chris PeBenito 5a3299
		#we are in our layer so fill in the other modules or we want them all
Chris PeBenito 5a3299
			for mod, desc in value.iteritems():
Chris PeBenito 5a3299
				menu[name][mod] = desc
Chris PeBenito 5a3299
	return menu
Chris PeBenito 5a3299
Chris PeBenito 5a3299
def gen_docs(doc, dir, templatedir):
Chris PeBenito 89ec23
Chris PeBenito 89ec23
	try:
Chris PeBenito 5a3299
		bodyfile = open(templatedir + "/header.html", "r")
Chris PeBenito 5a3299
		bodydata = bodyfile.read()
Chris PeBenito 5a3299
		bodyfile.close()
Chris PeBenito 5a3299
		intfile = open(templatedir + "/interface.html", "r")
Chris PeBenito 5a3299
		intdata = intfile.read()
Chris PeBenito 5a3299
		intfile.close()
Chris PeBenito 5a3299
		menufile = open(templatedir + "/menu.html", "r")
Chris PeBenito 5a3299
		menudata = menufile.read()
Chris PeBenito 5a3299
		menufile.close()
Chris PeBenito 5a3299
		indexfile = open(templatedir + "/module_list.html","r")
Chris PeBenito 5a3299
		indexdata = indexfile.read()
Chris PeBenito 5a3299
		indexfile.close()
Chris PeBenito 5a3299
		modulefile = open(templatedir + "/module.html","r")
Chris PeBenito 5a3299
		moduledata = modulefile.read()
Chris PeBenito 5a3299
		modulefile.close()
Chris PeBenito 89ec23
	except:
Chris PeBenito 89ec23
		error("Could not open templates")
Chris PeBenito 89ec23
Chris PeBenito 5a3299
Chris PeBenito 5a3299
	try:
Chris PeBenito 5a3299
		os.chdir(dir)
Chris PeBenito 5a3299
	except:
Chris PeBenito 5a3299
		error("Could now chdir to target directory")	
Chris PeBenito 5a3299
Chris PeBenito 5a3299
Chris PeBenito 5a3299
#arg, i have to go through this dom tree ahead of time to build up the menus
Chris PeBenito 5a3299
	module_list = {}
Chris PeBenito 5a3299
	for node in doc.getElementsByTagName("module"):
Chris PeBenito 5a3299
                mod_name = mod_layer = interface_buf = ''
Chris PeBenito 5a3299
		for (name, value) in node.attributes.items():
Chris PeBenito 5a3299
			if name[1] == "name":
Chris PeBenito 5a3299
				mod_name = value.value
Chris PeBenito 5a3299
			if name[1] == "layer":
Chris PeBenito 5a3299
				mod_layer = value.value
Chris PeBenito 5a3299
		for desc in node.getElementsByTagName("summary"):
Chris PeBenito 5a3299
			mod_summary = desc.firstChild.data
Chris PeBenito 5a3299
	
Chris PeBenito 5a3299
		if not module_list.has_key(mod_layer):
Chris PeBenito 5a3299
			module_list[mod_layer] = {}
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		module_list[mod_layer][mod_name] = mod_summary
Chris PeBenito 5a3299
Chris PeBenito 5a3299
#generate index pages
Chris PeBenito 5a3299
	main_content_buf = ''
Chris PeBenito 5a3299
	for mod_layer,modules in module_list.iteritems():
Chris PeBenito 5a3299
		menu = gen_doc_menu(mod_layer, module_list)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		menu_args = { "menulist" : menu,
Chris PeBenito 5a3299
			      "mod_layer" : mod_layer }
Chris PeBenito 5a3299
		menu_tpl = pyplate.Template(menudata)
Chris PeBenito 5a3299
		menu_buf = menu_tpl.execute_string(menu_args)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		content_tpl = pyplate.Template(indexdata)
Chris PeBenito 5a3299
		content_buf = content_tpl.execute_string(menu_args)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		main_content_buf += content_buf
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		body_args = { "menu" : menu_buf,
Chris PeBenito 5a3299
			      "content" : content_buf }
Chris PeBenito 5a3299
	
Chris PeBenito 5a3299
		index_file = mod_layer + ".html"
Chris PeBenito 5a3299
		index_fh = open(index_file, "w")
Chris PeBenito 5a3299
		body_tpl = pyplate.Template(bodydata)
Chris PeBenito 5a3299
		body_tpl.execute(index_fh, body_args)
Chris PeBenito 5a3299
		index_fh.close()	
Chris PeBenito 5a3299
Chris PeBenito 5a3299
	menu = gen_doc_menu(None, module_list)
Chris PeBenito 5a3299
	menu_args = { "menulist" : menu,
Chris PeBenito 5a3299
		      "mod_layer" : None }
Chris PeBenito 5a3299
	menu_tpl = pyplate.Template(menudata)
Chris PeBenito 5a3299
	menu_buf = menu_tpl.execute_string(menu_args)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
	body_args = { "menu" : menu_buf,
Chris PeBenito 5a3299
		      "content" : main_content_buf }
Chris PeBenito 5a3299
Chris PeBenito 5a3299
	index_file = "index.html"
Chris PeBenito 5a3299
	index_fh = open(index_file, "w")
Chris PeBenito 5a3299
	body_tpl = pyplate.Template(bodydata)
Chris PeBenito 5a3299
	body_tpl.execute(index_fh, body_args)
Chris PeBenito 5a3299
	index_fh.close()
Chris PeBenito 5a3299
	
Chris PeBenito 89ec23
Chris PeBenito 89ec23
	for node in doc.getElementsByTagName("module"):
Chris PeBenito 5a3299
                mod_name = mod_layer = interface_buf = ''
Chris PeBenito 5a3299
		for (name, value) in node.attributes.items():
Chris PeBenito 5a3299
			if name[1] == "name":
Chris PeBenito 5a3299
				mod_name = value.value
Chris PeBenito 5a3299
			if name[1] == "layer":
Chris PeBenito 5a3299
				mod_layer = value.value
Chris PeBenito 5a3299
		for desc in node.getElementsByTagName("summary"):
Chris PeBenito 5a3299
			mod_summary = desc.firstChild.data
Chris PeBenito 89ec23
		for interface in node.getElementsByTagName("interface"):
Chris PeBenito 5a3299
			interface_parameters = []
Chris PeBenito 5a3299
			interface_secdesc = None
Chris PeBenito 5a3299
			interface_tpl = pyplate.Template(intdata)
Chris PeBenito 89ec23
			for i,v in interface.attributes.items():
Chris PeBenito 5a3299
				interface_name = v.value
Chris PeBenito 89ec23
			for desc in interface.getElementsByTagName("description"):
Chris PeBenito 89ec23
				interface_desc = desc.firstChild.data
Chris PeBenito 89ec23
			for desc in interface.getElementsByTagName("securitydesc"):
Chris PeBenito 89ec23
				if desc:
Chris PeBenito 89ec23
					interface_secdesc = desc.firstChild.data
Chris PeBenito 89ec23
			
Chris PeBenito 89ec23
			for args in interface.getElementsByTagName("parameter"):
Chris PeBenito 89ec23
				paramdesc = args.firstChild.data
Chris PeBenito 5a3299
				paramname = None
Chris PeBenito 1601fb
				paramopt = "No"
Chris PeBenito 5a3299
				for name,val in args.attributes.items():
Chris PeBenito 5a3299
					if name[1] == "name":
Chris PeBenito 5a3299
						paramname = val.value
Chris PeBenito 5a3299
					if name[1] == "optional":
Chris PeBenito 1601fb
						if val.value == "true":
Chris PeBenito 1601fb
							paramopt = "yes"
Chris PeBenito 5a3299
				parameter = { "name" : paramname,
Chris PeBenito 5a3299
					      "desc" : paramdesc,
Chris PeBenito 5a3299
					      "optional" : paramopt }
Chris PeBenito 5a3299
				interface_parameters.append(parameter)
Chris PeBenito 5a3299
			interface_args = { "interface_name" : interface_name,
Chris PeBenito 5a3299
					   "interface_desc" : interface_desc,
Chris PeBenito 5a3299
					   "interface_parameters" : interface_parameters,
Chris PeBenito 5a3299
					   "interface_secdesc" : interface_secdesc }
Chris PeBenito 5a3299
			interface_buf += interface_tpl.execute_string(interface_args)
Chris PeBenito 5a3299
		
Chris PeBenito 5a3299
		menu = gen_doc_menu(mod_layer, module_list)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		menu_args = { "menulist" : menu }
Chris PeBenito 5a3299
		menu_tpl = pyplate.Template(menudata)
Chris PeBenito 5a3299
		menu_buf = menu_tpl.execute_string(menu_args)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		module_args = { "mod_layer" : mod_layer,
Chris PeBenito 5a3299
			      "mod_name" : mod_name,	
Chris PeBenito 5a3299
			      "mod_summary" : mod_summary,
Chris PeBenito 5a3299
			      "interfaces" : interface_buf }
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		module_tpl = pyplate.Template(moduledata)
Chris PeBenito 5a3299
		module_buf = module_tpl.execute_string(module_args)
Chris PeBenito 5a3299
Chris PeBenito 5a3299
		body_args = { "menu" : menu_buf,
Chris PeBenito 5a3299
			      "content" : module_buf }
Chris PeBenito 5a3299
			  
Chris PeBenito 5a3299
		module_file = mod_layer + "_" + mod_name + ".html"
Chris PeBenito 5a3299
		module_fh = open(module_file, "w")
Chris PeBenito 5a3299
		body_tpl = pyplate.Template(bodydata)
Chris PeBenito 5a3299
		body_tpl.execute(module_fh, body_args)
Chris PeBenito 5a3299
		module_fh.close()
Chris PeBenito 89ec23
Chris PeBenito 89ec23
def error(error):
Chris PeBenito 89ec23
        sys.stderr.write("%s exiting for: " % sys.argv[0])
Chris PeBenito 89ec23
        sys.stderr.write("%s\n" % error)
Chris PeBenito 89ec23
        sys.stderr.flush()
Chris PeBenito 89ec23
        sys.exit(1)
Chris PeBenito 89ec23
Chris PeBenito 89ec23
def usage():
Chris PeBenito 5a3299
	sys.stdout.write("%s [-tmdT] -x <xmlfile>\n\n" % sys.argv[0])
Chris PeBenito 89ec23
	sys.stdout.write("Options:\n")
Chris PeBenito 5a3299
	sys.stdout.write("-t --tunables	<file>		--	write tunable config to <file>\n")
Chris PeBenito 89ec23
	sys.stdout.write("-m --modules <file>		--	write module config to <file>\n")
Chris PeBenito 89ec23
	sys.stdout.write("-d --docs <dir>		--	write interface documentation to <dir>\n")
Chris PeBenito 89ec23
	sys.stdout.write("-x --xml <file>		--	filename to read xml data from\n")
Chris PeBenito 5a3299
	sys.stdout.write("-T --templates <dir>		--	template directory for documents\n")
Chris PeBenito 89ec23
Chris PeBenito 89ec23
Chris PeBenito 89ec23
try:
Chris PeBenito 5a3299
	opts, args = getopt.getopt(sys.argv[1:], "t:m:d:x:T:", ["tunables","modules","docs","xml", "templates"])
Chris PeBenito 89ec23
except getopt.GetoptError:
Chris PeBenito 89ec23
	usage()
Chris PeBenito 89ec23
	sys.exit(1)
Chris PeBenito 89ec23
Chris PeBenito 1601fb
tunables = modules = docsdir = None
Chris PeBenito 5a3299
templatedir = "templates/"
Chris PeBenito 5a3299
xmlfile = "policy.xml"
Chris PeBenito 89ec23
Chris PeBenito 89ec23
for opt, val in opts:
Chris PeBenito 89ec23
	if opt in ("-t", "--tunables"):
Chris PeBenito 89ec23
		tunables = val
Chris PeBenito 89ec23
	if opt in ("-m", "--modules"):
Chris PeBenito 89ec23
		modules = val
Chris PeBenito 89ec23
	if opt in ("-d", "--docs"):
Chris PeBenito 5a3299
		docsdir = val
Chris PeBenito 89ec23
	if opt in ("-x", "--xml"):
Chris PeBenito 89ec23
		xmlfile = val
Chris PeBenito 5a3299
	if opt in ("-T", "--templates"):
Chris PeBenito 5a3299
		templatedir = val
Chris PeBenito 89ec23
Chris PeBenito 89ec23
doc = read_policy_xml(xmlfile)
Chris PeBenito 89ec23
		
Chris PeBenito 89ec23
if tunables:
Chris PeBenito 89ec23
	try:
Chris PeBenito 89ec23
		conf = open(tunables, 'w')
Chris PeBenito 89ec23
	except:
Chris PeBenito 89ec23
		error("Could not open tunables file for writing")
Chris PeBenito 89ec23
	gen_tunable_conf(doc, conf)
Chris PeBenito 89ec23
	conf.close()
Chris PeBenito 89ec23
Chris PeBenito 89ec23
Chris PeBenito 89ec23
if modules:
Chris PeBenito 89ec23
	try:
Chris PeBenito 89ec23
		conf = open(modules, 'w')
Chris PeBenito 89ec23
	except:
Chris PeBenito 89ec23
		error("Could not open modules file for writing")
Chris PeBenito 89ec23
	gen_module_conf(doc, conf)
Chris PeBenito 89ec23
	conf.close()
Chris PeBenito 89ec23
Chris PeBenito 5a3299
if docsdir: 
Chris PeBenito 5a3299
	gen_docs(doc, docsdir, templatedir)