selinux-policy/refpolicy/support/sedoctool.py

437 lines
12 KiB
Python
Raw Normal View History

2005-06-07 18:23:00 +00:00
#!/usr/bin/python
# Author: Joshua Brindle <jbrindle@tresys.com>
#
# Copyright (C) 2003 - 2005 Tresys Technology, LLC
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 2.
"""
2005-06-09 18:16:51 +00:00
This module generates configuration files and documentation from the
SELinux reference policy XML format.
2005-06-07 18:23:00 +00:00
"""
import sys
import getopt
import pyplate
2005-06-09 18:16:51 +00:00
import os
2005-06-09 20:53:45 +00:00
import string
from xml.dom.minidom import parse, parseString
2005-06-07 18:23:00 +00:00
#modules enabled and disabled values
MOD_ENABLED = "on"
MOD_DISABLED = "off"
#tunables enabled and disabled values
TUN_ENABLED = "true"
TUN_DISABLED = "false"
2005-06-28 15:19:40 +00:00
2005-06-07 18:23:00 +00:00
def read_policy_xml(filename):
2005-06-09 19:02:32 +00:00
try:
xml_fh = open(filename)
except:
error("error opening " + filename)
2005-06-07 18:23:00 +00:00
try:
2005-06-09 20:53:45 +00:00
doc = parseString(xml_fh.read())
2005-06-07 18:23:00 +00:00
except:
2005-06-09 19:02:32 +00:00
xml_fh.close()
2005-06-07 18:23:00 +00:00
error("Error while parsing xml")
2005-06-09 19:02:32 +00:00
xml_fh.close()
2005-06-07 18:23:00 +00:00
return doc
def gen_tunable_conf(doc, file, namevalue_list):
2005-06-07 18:23:00 +00:00
for node in doc.getElementsByTagName("tunable"):
2005-06-13 17:41:38 +00:00
s = string.split(format_txt_desc(node), "\n")
2005-06-07 18:23:00 +00:00
for line in s:
file.write("# %s\n" % line)
tun_name = tun_val = None
for (name, value) in node.attributes.items():
2005-06-09 20:53:45 +00:00
if name == "name":
tun_name = value
elif name == "dftval":
tun_val = value
2005-06-07 18:23:00 +00:00
if [tun_name,TUN_ENABLED] in namevalue_list:
tun_val = TUN_ENABLED
elif [tun_name,TUN_DISABLED] in namevalue_list:
tun_val = TUN_DISABLED
2005-06-07 18:23:00 +00:00
if tun_name and tun_val:
file.write("%s = %s\n\n" % (tun_name, tun_val))
tun_name = tun_val = None
def gen_module_conf(doc, file, namevalue_list):
2005-06-28 15:19:40 +00:00
# If file exists, preserve settings and modify if needed.
# Otherwise, create it.
2005-06-09 18:16:51 +00:00
file.write("#\n# This file contains a listing of available modules.\n")
file.write("# To prevent a module from being used in policy\n")
file.write("# creation, set the module name to %s.\n#\n" % MOD_DISABLED)
2005-06-07 18:23:00 +00:00
for node in doc.getElementsByTagName("module"):
2005-06-09 18:16:51 +00:00
mod_name = mod_layer = None
mod_name = node.attributes.items()[0][1]
mod_layer = node.parentNode.attributes.items()[0][1]
2005-06-09 18:16:51 +00:00
if mod_name and mod_layer:
file.write("# Layer: %s\n# Module: %s\n#\n" % (mod_layer,mod_name))
2005-06-07 18:23:00 +00:00
for desc in node.getElementsByTagName("summary"):
2005-06-13 17:41:38 +00:00
if not desc.parentNode == node:
continue
s = string.split(format_txt_desc(desc), "\n")
2005-06-07 18:23:00 +00:00
for line in s:
2005-06-28 15:19:40 +00:00
file.write("# %s\n" % line)
if [mod_name, MOD_DISABLED] in namevalue_list:
file.write("%s = %s\n\n" % (mod_name, MOD_DISABLED))
2005-06-28 15:19:40 +00:00
else:
file.write("%s = %s\n\n" % (mod_name, MOD_ENABLED))
2005-06-28 15:19:40 +00:00
def get_old_conf(conf):
'''
Returns the objects in the config file with their values.
2005-06-28 15:19:40 +00:00
'''
conf_lines = conf.readlines()
namevalue_list = []
2005-06-28 15:19:40 +00:00
for line in conf_lines:
if line.strip() != '' and line.strip()[0] != "#":
namevalue = line.strip().split("=")
namevalue[0] = namevalue[0].strip()
namevalue[1] = namevalue[1].strip()
namevalue_list.append(namevalue)
return namevalue_list
2005-06-09 18:16:51 +00:00
2005-06-09 21:05:33 +00:00
def stupid_cmp(a, b):
return cmp(a[0], b[0])
2005-06-10 01:35:43 +00:00
def int_cmp(a, b):
return cmp(a["interface_name"], b["interface_name"])
2005-06-09 21:05:33 +00:00
2005-06-09 18:16:51 +00:00
def gen_doc_menu(mod_layer, module_list):
2005-06-09 21:05:33 +00:00
menu = []
for layer, value in module_list.iteritems():
cur_menu = (layer, [])
menu.append(cur_menu)
if layer != mod_layer and mod_layer != None:
continue
2005-06-09 18:16:51 +00:00
#we are in our layer so fill in the other modules or we want them all
2005-06-09 21:05:33 +00:00
for mod, desc in value.iteritems():
cur_menu[1].append((mod, desc))
menu.sort(stupid_cmp)
for x in menu:
x[1].sort(stupid_cmp)
2005-06-09 18:16:51 +00:00
return menu
2005-06-13 17:41:38 +00:00
def format_html_desc(node):
2005-06-10 20:39:41 +00:00
desc_buf = ''
for desc in node.childNodes:
if desc.nodeName == "#text":
2005-06-13 18:07:35 +00:00
if desc.data is not '':
desc_buf += "<p>" + desc.data + "</p>"
2005-06-10 20:39:41 +00:00
elif desc.nodeName == "p":
2005-06-13 18:07:35 +00:00
if desc.firstChild.data is not '':
desc_buf += "<p>" + desc.firstChild.data + "</p>"
2005-06-10 20:39:41 +00:00
for chld in desc.childNodes:
if chld.nodeName == "ul":
desc_buf += "<ul>"
for li in chld.getElementsByTagName("li"):
desc_buf += "<li>" + li.firstChild.data + "</li>"
2005-06-13 18:07:35 +00:00
desc_buf += "</ul>"
2005-06-10 20:39:41 +00:00
return desc_buf
2005-06-13 17:41:38 +00:00
def format_txt_desc(node):
desc_buf = ''
for desc in node.childNodes:
if desc.nodeName == "#text":
desc_buf += desc.data + "\n"
elif desc.nodeName == "p":
desc_buf += desc.firstChild.data + "\n"
for chld in desc.childNodes:
if chld.nodeName == "ul":
desc_buf += "\n"
for li in chld.getElementsByTagName("li"):
desc_buf += "\t -" + li.firstChild.data + "\n"
return desc_buf
2005-06-10 20:39:41 +00:00
2005-06-09 18:16:51 +00:00
def gen_docs(doc, dir, templatedir):
2005-06-07 18:23:00 +00:00
try:
2005-06-10 01:35:43 +00:00
#get the template data ahead of time so we don't reopen them over and over
2005-06-09 18:16:51 +00:00
bodyfile = open(templatedir + "/header.html", "r")
bodydata = bodyfile.read()
bodyfile.close()
intfile = open(templatedir + "/interface.html", "r")
intdata = intfile.read()
intfile.close()
menufile = open(templatedir + "/menu.html", "r")
menudata = menufile.read()
menufile.close()
indexfile = open(templatedir + "/module_list.html","r")
indexdata = indexfile.read()
indexfile.close()
modulefile = open(templatedir + "/module.html","r")
moduledata = modulefile.read()
modulefile.close()
2005-06-10 01:35:43 +00:00
intlistfile = open(templatedir + "/int_list.html", "r")
intlistdata = intlistfile.read()
intlistfile.close()
2005-06-07 18:23:00 +00:00
except:
error("Could not open templates")
2005-06-09 18:16:51 +00:00
try:
os.chdir(dir)
except:
error("Could not chdir to target directory")
2005-06-09 18:16:51 +00:00
#arg, i have to go through this dom tree ahead of time to build up the menus
module_list = {}
for node in doc.getElementsByTagName("module"):
mod_name = mod_layer = interface_buf = ''
mod_name = node.attributes.items()[0][1]
mod_layer = node.parentNode.attributes.items()[0][1]
2005-06-09 18:16:51 +00:00
for desc in node.getElementsByTagName("summary"):
2005-06-13 17:41:38 +00:00
if desc.parentNode == node and desc:
mod_summary = format_html_desc(desc)
2005-06-09 18:16:51 +00:00
if not module_list.has_key(mod_layer):
module_list[mod_layer] = {}
module_list[mod_layer][mod_name] = mod_summary
#generate index pages
main_content_buf = ''
for mod_layer,modules in module_list.iteritems():
menu = gen_doc_menu(mod_layer, module_list)
menu_args = { "menulist" : menu,
"mod_layer" : mod_layer }
menu_tpl = pyplate.Template(menudata)
menu_buf = menu_tpl.execute_string(menu_args)
content_tpl = pyplate.Template(indexdata)
content_buf = content_tpl.execute_string(menu_args)
main_content_buf += content_buf
body_args = { "menu" : menu_buf,
"content" : content_buf }
index_file = mod_layer + ".html"
index_fh = open(index_file, "w")
body_tpl = pyplate.Template(bodydata)
body_tpl.execute(index_fh, body_args)
index_fh.close()
menu = gen_doc_menu(None, module_list)
menu_args = { "menulist" : menu,
"mod_layer" : None }
menu_tpl = pyplate.Template(menudata)
menu_buf = menu_tpl.execute_string(menu_args)
body_args = { "menu" : menu_buf,
"content" : main_content_buf }
index_file = "index.html"
index_fh = open(index_file, "w")
body_tpl = pyplate.Template(bodydata)
body_tpl.execute(index_fh, body_args)
index_fh.close()
2005-06-10 01:35:43 +00:00
#now generate the individual module pages
2005-06-07 18:23:00 +00:00
2005-06-10 01:35:43 +00:00
all_interfaces = []
2005-06-07 18:23:00 +00:00
for node in doc.getElementsByTagName("module"):
2005-06-10 20:39:41 +00:00
mod_name = mod_layer = mod_desc = interface_buf = ''
mod_name = node.attributes.items()[0][1]
mod_layer = node.parentNode.attributes.items()[0][1]
2005-06-09 18:16:51 +00:00
for desc in node.getElementsByTagName("summary"):
2005-06-10 20:39:41 +00:00
if desc.parentNode == node:
2005-06-13 17:41:38 +00:00
mod_summary = format_html_desc(desc)
2005-06-23 16:06:25 +00:00
for desc in node.getElementsByTagName("desc"):
2005-06-10 20:39:41 +00:00
if desc.parentNode == node:
2005-06-13 17:41:38 +00:00
mod_desc = format_html_desc(desc)
2005-06-10 01:35:43 +00:00
interfaces = []
2005-06-07 18:23:00 +00:00
for interface in node.getElementsByTagName("interface"):
2005-06-09 18:16:51 +00:00
interface_parameters = []
interface_desc = interface_secdesc = interface_summary = None
2005-06-07 18:23:00 +00:00
for i,v in interface.attributes.items():
2005-06-09 20:53:45 +00:00
interface_name = v
2005-06-23 16:06:25 +00:00
for desc in interface.getElementsByTagName("desc"):
2005-06-13 17:41:38 +00:00
interface_desc = format_html_desc(desc)
2005-06-23 16:06:25 +00:00
for desc in interface.getElementsByTagName("secdesc"):
2005-06-07 18:23:00 +00:00
if desc:
2005-06-13 17:41:38 +00:00
interface_secdesc = format_html_desc(desc)
2005-06-10 20:39:41 +00:00
for desc in interface.getElementsByTagName("summary"):
2005-06-13 17:41:38 +00:00
interface_summary = format_html_desc(desc)
2005-06-07 18:23:00 +00:00
2005-06-23 16:06:25 +00:00
for args in interface.getElementsByTagName("param"):
2005-06-07 18:23:00 +00:00
paramdesc = args.firstChild.data
2005-06-09 18:16:51 +00:00
paramname = None
2005-06-09 19:02:32 +00:00
paramopt = "No"
2005-06-09 18:16:51 +00:00
for name,val in args.attributes.items():
2005-06-09 20:53:45 +00:00
if name == "name":
paramname = val
if name == "optional":
if val == "true":
2005-06-09 19:02:32 +00:00
paramopt = "yes"
2005-06-09 18:16:51 +00:00
parameter = { "name" : paramname,
"desc" : paramdesc,
"optional" : paramopt }
interface_parameters.append(parameter)
2005-06-10 01:35:43 +00:00
interfaces.append( { "interface_name" : interface_name,
2005-06-10 20:39:41 +00:00
"interface_summary" : interface_summary,
2005-06-09 18:16:51 +00:00
"interface_desc" : interface_desc,
"interface_parameters" : interface_parameters,
2005-06-10 01:35:43 +00:00
"interface_secdesc" : interface_secdesc })
#all_interfaces is for the main interface index with all interfaces
all_interfaces.append( { "interface_name" : interface_name,
2005-06-10 20:39:41 +00:00
"interface_summary" : interface_summary,
2005-06-10 01:35:43 +00:00
"interface_desc" : interface_desc,
"interface_parameters" : interface_parameters,
"interface_secdesc" : interface_secdesc,
"mod_name": mod_name,
"mod_layer" : mod_layer })
interfaces.sort(int_cmp)
interface_tpl = pyplate.Template(intdata)
interface_buf = interface_tpl.execute_string({"interfaces" : interfaces})
2005-06-09 18:16:51 +00:00
menu = gen_doc_menu(mod_layer, module_list)
menu_tpl = pyplate.Template(menudata)
2005-06-10 01:35:43 +00:00
menu_buf = menu_tpl.execute_string({ "menulist" : menu })
2005-06-09 18:16:51 +00:00
module_args = { "mod_layer" : mod_layer,
"mod_name" : mod_name,
"mod_summary" : mod_summary,
2005-06-10 20:39:41 +00:00
"mod_desc" : mod_desc,
2005-06-09 18:16:51 +00:00
"interfaces" : interface_buf }
module_tpl = pyplate.Template(moduledata)
module_buf = module_tpl.execute_string(module_args)
body_args = { "menu" : menu_buf,
"content" : module_buf }
module_file = mod_layer + "_" + mod_name + ".html"
module_fh = open(module_file, "w")
body_tpl = pyplate.Template(bodydata)
body_tpl.execute(module_fh, body_args)
module_fh.close()
2005-06-07 18:23:00 +00:00
2005-06-10 01:35:43 +00:00
#and last build the interface index
menu = gen_doc_menu(None, module_list)
menu_args = { "menulist" : menu,
"mod_layer" : None }
menu_tpl = pyplate.Template(menudata)
menu_buf = menu_tpl.execute_string(menu_args)
all_interfaces.sort(int_cmp)
interface_tpl = pyplate.Template(intlistdata)
interface_buf = interface_tpl.execute_string({"interfaces" : all_interfaces})
int_file = "interfaces.html"
int_fh = open(int_file, "w")
body_tpl = pyplate.Template(bodydata)
body_args = { "menu" : menu_buf,
"content" : interface_buf }
body_tpl.execute(int_fh, body_args)
int_fh.close()
2005-06-07 18:23:00 +00:00
def error(error):
sys.stderr.write("%s exiting for: " % sys.argv[0])
sys.stderr.write("%s\n" % error)
sys.stderr.flush()
sys.exit(1)
def usage():
2005-06-09 18:16:51 +00:00
sys.stdout.write("%s [-tmdT] -x <xmlfile>\n\n" % sys.argv[0])
2005-06-07 18:23:00 +00:00
sys.stdout.write("Options:\n")
2005-06-09 18:16:51 +00:00
sys.stdout.write("-t --tunables <file> -- write tunable config to <file>\n")
2005-06-07 18:23:00 +00:00
sys.stdout.write("-m --modules <file> -- write module config to <file>\n")
sys.stdout.write("-d --docs <dir> -- write interface documentation to <dir>\n")
sys.stdout.write("-x --xml <file> -- filename to read xml data from\n")
2005-06-09 18:16:51 +00:00
sys.stdout.write("-T --templates <dir> -- template directory for documents\n")
2005-06-07 18:23:00 +00:00
try:
2005-06-09 18:16:51 +00:00
opts, args = getopt.getopt(sys.argv[1:], "t:m:d:x:T:", ["tunables","modules","docs","xml", "templates"])
2005-06-07 18:23:00 +00:00
except getopt.GetoptError:
usage()
sys.exit(1)
2005-06-09 19:02:32 +00:00
tunables = modules = docsdir = None
2005-06-09 18:16:51 +00:00
templatedir = "templates/"
xmlfile = "policy.xml"
2005-06-07 18:23:00 +00:00
for opt, val in opts:
if opt in ("-t", "--tunables"):
tunables = val
if opt in ("-m", "--modules"):
modules = val
if opt in ("-d", "--docs"):
2005-06-09 18:16:51 +00:00
docsdir = val
2005-06-07 18:23:00 +00:00
if opt in ("-x", "--xml"):
xmlfile = val
2005-06-09 18:16:51 +00:00
if opt in ("-T", "--templates"):
templatedir = val
2005-06-07 18:23:00 +00:00
doc = read_policy_xml(xmlfile)
if tunables:
namevalue_list = []
if os.path.exists(tunables):
try:
conf = open(tunables, 'r')
except:
error("Could not open tunables file for reading")
namevalue_list = get_old_conf(conf)
conf.close()
2005-06-07 18:23:00 +00:00
try:
conf = open(tunables, 'w')
except:
error("Could not open tunables file for writing")
gen_tunable_conf(doc, conf, namevalue_list)
2005-06-07 18:23:00 +00:00
conf.close()
if modules:
namevalue_list = []
2005-06-28 15:19:40 +00:00
if os.path.exists(modules):
try:
conf = open(modules, 'r')
except:
error("Could not open modules file for reading")
namevalue_list = get_old_conf(conf)
2005-06-28 15:19:40 +00:00
conf.close()
2005-06-07 18:23:00 +00:00
try:
conf = open(modules, 'w')
except:
error("Could not open modules file for writing")
gen_module_conf(doc, conf, namevalue_list)
2005-06-07 18:23:00 +00:00
conf.close()
2005-06-09 18:16:51 +00:00
if docsdir:
gen_docs(doc, docsdir, templatedir)