From 4d9a5188a002922eb2c718f2349537f75008f3e9 Mon Sep 17 00:00:00 2001
From: Jan Lieskovsky <jlieskov@redhat.com>
Date: Thu, 12 Sep 2013 17:25:48 +0200
Subject: [PATCH 6/8] Add transformation *.py scripts and *.xslt content,
 required for building Fedora's XCCDF, OVAL, and guide
 content.


Signed-off-by: Jan Lieskovsky <jlieskov@redhat.com>
---
 FEDORA/transforms/combinechecks.py        |  79 +++++
 FEDORA/transforms/constants.xslt          |  21 ++
 FEDORA/transforms/cpe_generate.py         | 112 +++++++
 FEDORA/transforms/idtranslate.py          | 138 +++++++++
 FEDORA/transforms/relabelids.py           | 108 +++++++
 FEDORA/transforms/shorthand2xccdf.xslt    | 494 ++++++++++++++++++++++++++++++
 FEDORA/transforms/xccdf-removeaux.xslt    |  22 ++
 FEDORA/transforms/xccdf-removetested.xslt |  20 ++
 8 files changed, 994 insertions(+)
 create mode 100755 FEDORA/transforms/combinechecks.py
 create mode 100644 FEDORA/transforms/constants.xslt
 create mode 100755 FEDORA/transforms/cpe_generate.py
 create mode 100755 FEDORA/transforms/idtranslate.py
 create mode 100755 FEDORA/transforms/relabelids.py
 create mode 100644 FEDORA/transforms/shorthand2xccdf.xslt
 create mode 100644 FEDORA/transforms/xccdf-removeaux.xslt
 create mode 100644 FEDORA/transforms/xccdf-removetested.xslt

diff --git a/FEDORA/transforms/combinechecks.py b/FEDORA/transforms/combinechecks.py
new file mode 100755
index 0000000..64e2d09
--- /dev/null
+++ b/FEDORA/transforms/combinechecks.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python
+
+import sys, os
+import lxml.etree as ET
+
+header = '''<?xml version="1.0" encoding="UTF-8"?>
+<oval_definitions
+	xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5"
+	xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
+	xmlns:ind="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent"
+	xmlns:unix="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix"
+	xmlns:linux="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd
+		http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd
+		http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd
+		http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd
+		http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd">
+	<generator>
+		<oval:product_name>python</oval:product_name>
+		<oval:product_version>2.6.6</oval:product_version>
+		<oval:schema_version>5.10</oval:schema_version>
+		<oval:timestamp>2011-09-21T13:44:00</oval:timestamp>
+	</generator>'''
+
+footer = '</oval_definitions>'
+
+# append new child ONLY if it's not a duplicate
+def append(element, newchild):
+    newid = newchild.get("id")
+    existing = element.find(".//*[@id='" + newid + "']")
+    if existing is not None:
+        sys.stderr.write( "Duplicate ID, which will not be added: " + newid + "\n")
+    else:
+        element.append(newchild)
+
+def main():
+	if len(sys.argv) < 2:
+		print "Provide a directory name, which contains the checks."
+		sys.exit(1)
+
+        # concatenate all XML files in the checks directory, to create the document body
+	body = ""
+	for filename in os.listdir(sys.argv[1]):
+		if filename.endswith(".xml"):
+			with open( sys.argv[1] + "/" + filename, 'r') as f:
+				body = body + f.read()
+
+	# parse new file(string) as an ElementTree, so we can reorder elements appropriately
+	tree = ET.fromstring(header + body + footer)
+	definitions = ET.Element("definitions")
+	tests = ET.Element("tests")
+	objects = ET.Element("objects")
+	states = ET.Element("states")
+	variables = ET.Element("variables")
+
+	for childnode in tree.findall("./{http://oval.mitre.org/XMLSchema/oval-definitions-5}def-group/*"):
+                if childnode.tag is ET.Comment: continue
+		if childnode.tag.endswith("definition"): append(definitions, childnode)
+		if childnode.tag.endswith("_test"): append(tests, childnode)
+		if childnode.tag.endswith("_object"): append(objects, childnode)
+		if childnode.tag.endswith("_state"): append(states, childnode)
+		if childnode.tag.endswith("_variable"): append(variables, childnode)
+
+	tree = ET.fromstring(header + footer)
+	tree.append(definitions)
+	tree.append(tests)
+	tree.append(objects)
+	tree.append(states)
+	# append <variables> tag only in case there are some child variables defined
+        if variables.__len__():
+		tree.append(variables)
+
+	ET.dump(tree)
+	sys.exit(0)
+
+if __name__ == "__main__":
+    main()
+
diff --git a/FEDORA/transforms/constants.xslt b/FEDORA/transforms/constants.xslt
new file mode 100644
index 0000000..afe719b
--- /dev/null
+++ b/FEDORA/transforms/constants.xslt
@@ -0,0 +1,21 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<!-- This file is used to hold constants used across several transforms. -->
+<!-- Constants are called variables in XSLT.  At this point this is not a surprise. -->
+
+<!-- abbreviated as idents in the XCCDF-->
+<xsl:variable name="cceuri">http://cce.mitre.org</xsl:variable>
+
+<!-- abbreviated as references in the XCCDF-->
+<xsl:variable name="nist800-53uri">http://csrc.nist.gov/publications/nistpubs/800-53-Rev3/sp800-53-rev3-final.pdf</xsl:variable>
+<xsl:variable name="cnss1253uri">http://www.cnss.gov/Assets/pdf/CNSSI-1253.pdf</xsl:variable>
+<xsl:variable name="dcid63uri">not_officially_available</xsl:variable>
+<xsl:variable name="disa-cciuri">http://iase.disa.mil/cci/index.html</xsl:variable>
+<xsl:variable name="disa-srguri">http://iase.disa.mil/srgs</xsl:variable>
+
+<xsl:variable name="ovaluri">http://oval.mitre.org/XMLSchema/oval-definitions-5</xsl:variable>
+
+<xsl:variable name="ociltransitional">ocil-transitional</xsl:variable>
+<xsl:variable name="ocil_cs">http://scap.nist.gov/schema/ocil/2</xsl:variable>
+<xsl:variable name="ocil_ns">http://scap.nist.gov/schema/ocil/2.0</xsl:variable>
+</xsl:stylesheet>
diff --git a/FEDORA/transforms/cpe_generate.py b/FEDORA/transforms/cpe_generate.py
new file mode 100755
index 0000000..3199fff
--- /dev/null
+++ b/FEDORA/transforms/cpe_generate.py
@@ -0,0 +1,112 @@
+#!/usr/bin/python
+
+import sys, os, idtranslate
+import lxml.etree as ET
+
+# This script requires two arguments: an OVAL file and a CPE dictionary file.
+# It is designed to extract any inventory definitions and the tests, states,
+# objects and variables it references and then write them into a standalone
+# OVAL CPE file, along with a synchronized CPE dictionary file.
+
+oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+xccdf_ns = "http://checklists.nist.gov/xccdf/1.1"
+cpe_ns = "http://cpe.mitre.org/dictionary/2.0"
+
+def parse_xml_file(xmlfile):
+    with open( xmlfile, 'r') as f:
+        filestring = f.read()
+        tree = ET.fromstring(filestring)
+        #print filestring
+    return tree
+
+
+def extract_referred_nodes(tree_with_refs, tree_with_ids, attrname):
+	reflist = []
+	elementlist = []
+	iter = tree_with_refs.getiterator()
+	for element in iter:
+		value = element.get(attrname)
+		if value is not None:
+			reflist.append(value)
+
+	iter = tree_with_ids.getiterator()
+	for element in iter:
+		if element.get("id") in reflist:
+			elementlist.append(element)
+	return elementlist
+
+
+def collect_nodes(tree, reflist):
+	elementlist = []
+	iter = tree.getiterator()
+	for element in iter:
+		if element.get("id") in reflist:
+			elementlist.append(element)
+	return elementlist
+
+def main():
+	if len(sys.argv) < 2:
+		print "Provide an OVAL file that contains inventory definitions."
+		print "This script extracts these definitions and writes them to STDOUT."
+		sys.exit(1)
+
+	ovalfile = sys.argv[1]
+	cpedictfile = sys.argv[2]
+	idname = sys.argv[3]
+
+    # parse oval file
+	ovaltree = parse_xml_file(ovalfile)
+
+	# extract inventory definitions
+	# making (dubious) assumption that all inventory defs are CPE
+	defs = ovaltree.find("./{%s}definitions" % oval_ns)
+	inventory_defs = defs.findall(".//{%s}definition[@class='inventory']" % oval_ns)
+	defs.clear()
+	[defs.append(inventory_def) for inventory_def in inventory_defs]
+
+	tests = ovaltree.find("./{%s}tests" % oval_ns)
+	cpe_tests = extract_referred_nodes(defs, tests, "test_ref")
+	tests.clear()
+	[tests.append(cpe_test) for cpe_test in cpe_tests]
+
+	states = ovaltree.find("./{%s}states" % oval_ns)
+	cpe_states = extract_referred_nodes(tests, states, "state_ref")
+	states.clear()
+	[states.append(cpe_state) for cpe_state in cpe_states]
+
+	objects = ovaltree.find("./{%s}objects" % oval_ns)
+	cpe_objects = extract_referred_nodes(tests, objects, "object_ref")
+	objects.clear()
+	[objects.append(cpe_object) for cpe_object in cpe_objects]
+
+	variables = ovaltree.find("./{%s}variables" % oval_ns)
+	# try to extract referred nodes from variables only if <variables> tag is defined
+	if variables:
+		cpe_variables = extract_referred_nodes(ovaltree, variables, "var_ref")
+		if cpe_variables:
+			variables.clear()
+			[variables.append(cpe_variable) for cpe_variable in cpe_variables]
+		else:
+			ovaltree.remove(variables)
+
+	# turn IDs into meaningless numbers
+	translator = idtranslate.idtranslator("./output/"+idname+".ini", idname)
+	ovaltree = translator.translate(ovaltree)
+
+	newovalfile = ovalfile.replace("oval", "cpe-oval")
+        newovalfile = newovalfile.replace("unlinked-fedora", idname)
+	ET.ElementTree(ovaltree).write(newovalfile)
+
+	# replace and sync IDs, href filenames in input cpe dictionary file
+	cpedicttree = parse_xml_file(cpedictfile)
+        newcpedictfile = os.path.basename(cpedictfile)
+        newcpedictfile = newcpedictfile.replace("fedora", idname)
+	for check in cpedicttree.findall(".//{%s}check" % cpe_ns):
+		check.set("href",os.path.basename(newovalfile))
+		check.text = translator.assign_id("{" + oval_ns + "}definition", check.text)
+	ET.ElementTree(cpedicttree).write("./output/"+newcpedictfile)
+
+	sys.exit(0)
+
+if __name__ == "__main__":
+	main()
diff --git a/FEDORA/transforms/idtranslate.py b/FEDORA/transforms/idtranslate.py
new file mode 100755
index 0000000..feca4cf
--- /dev/null
+++ b/FEDORA/transforms/idtranslate.py
@@ -0,0 +1,138 @@
+import ConfigParser, sys
+import lxml.etree as ET
+
+# This class is designed to handle the mapping of meaningful, human-readable
+# names to IDs in the formats required by the SCAP checking systems, such as
+# OVAL and OCIL.
+
+oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+oval_cs = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+
+ocil_ns = "http://scap.nist.gov/schema/ocil/2.0"
+ocil_cs = "http://scap.nist.gov/schema/ocil/2"
+
+ovaltag_to_abbrev = {
+	'definition' : 'def',
+	'criteria' : 'crit',
+	'test' : 'tst',
+	'object' : 'obj',
+	'state' : 'ste',
+	'variable' : 'var',
+}
+
+ociltag_to_abbrev = {
+	'questionnaire' : 'questionnaire',
+	'action' : 'testaction',
+	'question' : 'question',
+	'artifact' : 'artifact',
+	'variable' : 'variable',
+}
+
+ovalrefattr_to_tag = {
+	"definition_ref" : "definition",
+	"test_ref" : "test",
+	"object_ref" : "object",
+	"state_ref" : "state",
+	"var_ref" : "variable",
+}
+
+ocilrefattr_to_tag = {
+	"question_ref" : "question",
+}
+
+ocilrefchild_to_tag = {
+	"test_action_ref" : "action",
+}
+
+def split_namespace(tag):
+	# returns a tuple of (namespace,name) removing any fragment id from namespace
+	if tag[:1] == "{":
+		namespace, name = tag[1:].split("}", 1)
+		return namespace.split("#")[0], name
+	else:
+		return (None,tag)
+
+def namespace_to_prefix(tag):
+	namespace, name = split_namespace(tag)
+	if namespace == ocil_ns:
+		return "ocil"
+	if namespace == oval_ns:
+		return "oval"
+	sys.exit("Error: unknown checksystem referenced in tag : %s" % tag)
+
+def tagname_to_abbrev(tag):
+	namespace, tag = split_namespace(tag)
+	if tag == "extend_definition":
+		return tag
+	# grab the last part of the tag name to determine its type
+	tag = tag.rsplit("_", 1)[-1]
+	if namespace == ocil_ns:
+		return ociltag_to_abbrev[tag]
+	if namespace == oval_ns:
+		return ovaltag_to_abbrev[tag]
+	sys.exit("Error: unknown checksystem referenced in tag : %s" % tag)
+
+class idtranslator:
+	def __init__(self, fname, content_id):
+		self.fname = fname
+		self.content_id = content_id
+		self.config = ConfigParser.ConfigParser()
+		f = self.config.read(fname)
+		if len(f) == 0:
+			self.__setup()
+
+	def __get_next_id(self):
+		i = self.config.getint("general", "next_id")
+		n = "%d" % (i + 1)
+		self.config.set("general", "next_id", n)
+		return i
+
+	def save(self):
+		fd = open(self.fname, "wb")
+		self.config.write(fd)
+
+	def __setup(self):
+		self.config.add_section("general")
+		self.config.set("general", "next_id", "100")
+		self.config.add_section("assigned")
+
+	def assign_id(self, tagname, name):
+		i = None
+		try:
+			i = self.config.getint("assigned", name)
+		except:
+			i = self.__get_next_id()
+			self.config.set("assigned", name, str(i))
+
+		str_id = "%s:%s:%s:%d" % (namespace_to_prefix(tagname), self.content_id, tagname_to_abbrev(tagname), i)
+		return str_id
+
+	def translate(self, tree, store_defname=False):
+		for element in tree.getiterator():
+			idname = element.get("id")
+			if idname:
+				# store the old name if requested (for OVAL definitions)
+				if store_defname and element.tag == "{" + oval_ns + "}definition":
+					metadata = element.find("{" + oval_ns + "}metadata")
+					if metadata is None:
+						metadata = ET.SubElement(element, "metadata")
+					defnam = ET.SubElement(metadata, "reference", ref_id=idname, source=self.content_id)
+				# set the element to the new identifier
+				element.set("id", self.assign_id(element.tag, idname))
+				#continue
+			if element.tag == "{" + oval_ns + "}filter":
+				element.text = self.assign_id("{" + oval_ns + "}state", element.text)
+				continue
+			for attr in element.keys():
+				if attr in ovalrefattr_to_tag.keys():
+					element.set(attr,self.assign_id( "{" + oval_ns + "}" + ovalrefattr_to_tag[attr], element.get(attr)))
+				if attr in ocilrefattr_to_tag.keys():
+					element.set(attr, self.assign_id("{" + ocil_ns + "}" + ocilrefattr_to_tag[attr], element.get(attr)))
+			if element.tag == "{" + ocil_ns + "}test_action_ref":
+					element.text = self.assign_id("{" + ocil_ns + "}action", element.text)
+
+		self.save()
+		# note: the ini file is not tracked by git, see .gitignore
+		return tree
+
+
diff --git a/FEDORA/transforms/relabelids.py b/FEDORA/transforms/relabelids.py
new file mode 100755
index 0000000..77db7f4
--- /dev/null
+++ b/FEDORA/transforms/relabelids.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+
+import sys, os
+import idtranslate
+import lxml.etree as ET
+
+# This script requires two arguments: an "unlinked" XCCDF file and an ID name scheme.
+# This script is designed to convert and synchronize check IDs referenced from
+# the XCCDF document for the supported checksystems, which are currently OVAL
+# and OCIL.  The IDs are to be converted from strings to meaningless numbers.
+
+
+oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+oval_cs = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+
+ocil_ns = "http://scap.nist.gov/schema/ocil/2.0"
+ocil_cs = "http://scap.nist.gov/schema/ocil/2"
+
+xccdf_ns = "http://checklists.nist.gov/xccdf/1.1"
+
+
+def parse_xml_file(xmlfile):
+	with open( xmlfile, 'r') as f:
+		filestring = f.read()
+		tree = ET.fromstring(filestring)
+		#print filestring
+	return tree
+
+
+def get_checkfiles(checks, checksystem):
+	# iterate over all checks, grab the OVAL files referenced within
+	checkfiles = set()
+	for check in checks:
+		if check.get("system") == checksystem:
+			checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
+			checkfiles.add(checkcontentref.get("href"))
+	return checkfiles
+
+
+def main():
+	if len(sys.argv) < 3:
+		print "Provide an XCCDF file and an ID name scheme."
+		print "This script finds check-content files (currently, OVAL and OCIL) referenced from XCCDF and synchronizes all IDs."
+		sys.exit(1)
+
+	xccdffile = sys.argv[1]
+	idname = sys.argv[2]
+
+	os.chdir("./output")
+	# step over xccdf file, and find referenced check files
+	xccdftree = parse_xml_file(xccdffile)
+
+	checks = xccdftree.findall(".//{%s}check" % xccdf_ns)
+	ovalfiles = get_checkfiles(checks, oval_cs)
+	ocilfiles = get_checkfiles(checks, ocil_cs)
+
+	if len(ovalfiles) > 1 or len(ocilfiles) > 1:
+		sys.exit("referencing more than one file per check system is not yet supported by this script.")
+	ovalfile = ovalfiles.pop() if ovalfiles else None
+	ocilfile = ocilfiles.pop() if ocilfiles else None
+
+	translator = idtranslate.idtranslator(idname+".ini", idname)
+
+	# rename all IDs in the oval file
+	if ovalfile:
+		ovaltree = parse_xml_file(ovalfile)
+		ovaltree = translator.translate(ovaltree, store_defname=True)
+                newovalfile = ovalfile.replace("unlinked-fedora", idname)
+		ET.ElementTree(ovaltree).write(newovalfile)
+
+	# rename all IDs in the ocil file
+	if ocilfile:
+		ociltree = parse_xml_file(ocilfile)
+		ociltree = translator.translate(ociltree)
+                newocilfile = ocilfile.replace("unlinked-fedora", idname)
+		ET.ElementTree(ociltree).write(newocilfile)
+
+	# rename all IDs and file refs in the xccdf file
+	for check in checks:
+		checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
+		if checkcontentref is None:
+			continue
+
+		if check.get("system") == oval_cs:
+			checkid = translator.assign_id("{" + oval_ns + "}definition", checkcontentref.get("name"))
+			checkcontentref.set("name", checkid)
+			checkcontentref.set("href", newovalfile)
+			checkexport = check.find("./{%s}check-export" % xccdf_ns)
+			if checkexport is not None:
+				newexportname = translator.assign_id("{"+ oval_ns + "}variable", checkexport.get("export-name"))
+				checkexport.set("export-name", newexportname)
+
+		if check.get("system") == ocil_cs:
+			checkid = translator.assign_id("{" + ocil_ns + "}questionnaire", checkcontentref.get("name"))
+			checkcontentref.set("name", checkid)
+			checkcontentref.set("href", newocilfile)
+			checkexport = check.find("./{%s}check-export" % xccdf_ns)
+			if checkexport is not None:
+				newexportname = translator.assign_id("{"+ oval_ns + "}variable", checkexport.get("export-name"))
+				checkexport.set("export-name", newexportname)
+
+        newxccdffile = xccdffile.replace("unlinked-fedora", idname)
+	#ET.dump(xccdftree)
+	ET.ElementTree(xccdftree).write(newxccdffile)
+	sys.exit(0)
+
+if __name__ == "__main__":
+	main()
diff --git a/FEDORA/transforms/shorthand2xccdf.xslt b/FEDORA/transforms/shorthand2xccdf.xslt
new file mode 100644
index 0000000..720c343
--- /dev/null
+++ b/FEDORA/transforms/shorthand2xccdf.xslt
@@ -0,0 +1,494 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:xccdf="http://checklists.nist.gov/xccdf/1.1"
+  xmlns:xhtml="http://www.w3.org/1999/xhtml"
+  xmlns:dc="http://purl.org/dc/elements/1.1/"
+  xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date"
+  exclude-result-prefixes="xccdf xhtml dc">
+
+  <!-- This transform takes a "shorthand" variant of XCCDF
+       and expands its elements into proper XCCDF elements.
+       It also assigns all elements into the proper namespace,
+       whether it be xccdf, xhtml, or simply maintained from the
+       input. -->
+
+<xsl:include href="constants.xslt"/>
+
+<xsl:variable name="ovalfile">unlinked-fedora-oval.xml</xsl:variable>
+<xsl:variable name="defaultseverity" select="'low'" />
+
+<!-- put elements created in this stylesheet into the xccdf namespace,
+     if no namespace explicitly indicated -->
+<xsl:namespace-alias result-prefix="xccdf" stylesheet-prefix="#default" />
+
+
+  <xsl:template match="Benchmark">
+    <xsl:element name="{local-name()}" namespace="http://checklists.nist.gov/xccdf/1.1">
+        <xsl:apply-templates select="node()|@*"/>
+    </xsl:element>
+  </xsl:template>
+
+
+  <!-- insert current date -->
+  <xsl:template match="Benchmark/status/@date">
+    <xsl:attribute name="date">
+       <xsl:value-of select="date:date()"/>
+    </xsl:attribute>
+  </xsl:template>
+
+  <!-- hack for OpenSCAP validation quirk: must place reference after description/warning, but prior to others -->
+  <xsl:template match="Rule">
+    <Rule selected="false">
+    <!-- set selected attribute to false, to enable profile-driven evaluation -->
+      <xsl:apply-templates select="@*" />
+      <!-- also: add severity of "low" to each Rule if otherwise unspecified -->
+      <xsl:if test="not(@severity)">
+          <xsl:attribute name="severity">
+              <xsl:value-of select="$defaultseverity" />
+          </xsl:attribute>
+      </xsl:if>
+      <xsl:apply-templates select="title"/>
+      <xsl:apply-templates select="description"/>
+      <xsl:apply-templates select="warning"/>
+      <xsl:apply-templates select="ref"/>
+      <xsl:apply-templates select="tested"/>
+      <xsl:apply-templates select="rationale"/>
+      <xsl:apply-templates select="ident"/>
+      <!-- order oval (shorthand tag) first, to indicate to tools to prefer its automated checks -->
+      <xsl:apply-templates select="oval"/>
+      <xsl:apply-templates select="node()[not(self::title|self::description|self::warning|self::ref|self::tested|self::rationale|self::ident|self::oval)]"/>
+    </Rule>
+  </xsl:template>
+
+
+  <xsl:template match="Group">
+    <Group>
+      <xsl:apply-templates select="@*" />
+      <xsl:apply-templates select="title"/>
+      <xsl:apply-templates select="description"/>
+      <xsl:apply-templates select="warning"/>
+      <xsl:apply-templates select="ref"/>
+      <xsl:apply-templates select="rationale"/>
+      <xsl:apply-templates select="node()[not(self::title|self::description|self::warning|self::ref|self::rationale)]"/>
+    </Group>
+  </xsl:template>
+
+  <!-- XHTML, such as tt, is not allowed in titles -->
+  <xsl:template match="title/tt">
+        <xsl:apply-templates select="@*|node()" />
+  </xsl:template>
+
+  <!-- expand reference to ident types -->
+  <xsl:template match="Rule/ident">
+    <xsl:for-each select="@*">
+      <ident>
+        <xsl:choose>
+          <xsl:when test="name() = 'cce'">
+            <xsl:attribute name="system">
+              <xsl:value-of select="$cceuri" />
+            </xsl:attribute>
+            <xsl:choose>
+              <xsl:when test="starts-with(translate(., 'ce', 'CE'), 'CCE')">
+                <xsl:value-of select="." />
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:value-of select="concat('CCE-', .)" />
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="." />
+          </xsl:otherwise>
+        </xsl:choose>
+      </ident>
+    </xsl:for-each>
+  </xsl:template>
+
+  <!-- expand ref attributes to reference tags, one item per reference -->
+  <xsl:template match="ref">
+    <xsl:for-each select="@*">
+       <xsl:call-template name="ref-info" >
+          <xsl:with-param name="refsource" select="name()" />
+          <xsl:with-param name="refitems" select="." />
+       </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+  <!-- expands individual reference source -->
+  <xsl:template name="ref-info">
+      <xsl:param name="refsource"/>
+      <xsl:param name="refitems"/>
+      <xsl:variable name="delim" select="','" />
+       <xsl:choose>
+           <xsl:when test="$delim and contains($refitems, $delim)">
+             <!-- output the reference -->
+             <xsl:call-template name="ref-output" >
+               <xsl:with-param name="refsource" select="$refsource" />
+               <xsl:with-param name="refitem" select="substring-before($refitems, $delim)" />
+             </xsl:call-template>
+             <!-- recurse for additional refs -->
+             <xsl:call-template name="ref-info">
+               <xsl:with-param name="refsource" select="$refsource" />
+               <xsl:with-param name="refitems" select="substring-after($refitems, $delim)" />
+             </xsl:call-template>
+           </xsl:when>
+
+           <xsl:otherwise>
+             <xsl:call-template name="ref-output" >
+               <xsl:with-param name="refsource" select="$refsource" />
+               <xsl:with-param name="refitem" select="$refitems" />
+             </xsl:call-template>
+           </xsl:otherwise>
+       </xsl:choose>
+  </xsl:template>
+
+  <!-- output individual reference -->
+  <xsl:template name="ref-output">
+      <xsl:param name="refsource"/>
+      <xsl:param name="refitem"/>
+      <reference>
+        <xsl:attribute name="href">
+        <!-- populate the href attribute with a global reference-->
+          <xsl:if test="$refsource = 'nist'">
+            <xsl:value-of select="$nist800-53uri" />
+          </xsl:if>
+          <xsl:if test="$refsource = 'cnss'">
+            <xsl:value-of select="$cnss1253uri" />
+          </xsl:if>
+          <xsl:if test="$refsource = 'disa'">
+            <xsl:value-of select="$disa-cciuri" />
+          </xsl:if>
+        </xsl:attribute>
+        <xsl:value-of select="normalize-space($refitem)" />
+      </reference>
+  </xsl:template>
+
+  <!-- expand reference to OVAL ID -->
+  <xsl:template match="Rule/oval">
+    <check>
+      <xsl:attribute name="system">
+        <xsl:value-of select="$ovaluri" />
+      </xsl:attribute>
+
+      <xsl:if test="@value">
+      <check-export>
+      <xsl:attribute name="export-name">
+        <xsl:value-of select="@value" />
+      </xsl:attribute>
+      <xsl:attribute name="value-id">
+        <xsl:value-of select="@value" />
+      </xsl:attribute>
+      </check-export>
+      </xsl:if>
+
+      <check-content-ref>
+        <xsl:attribute name="href">
+          <xsl:value-of select="$ovalfile" />
+        </xsl:attribute>
+        <xsl:attribute name="name">
+          <xsl:value-of select="@id" />
+        </xsl:attribute>
+      </check-content-ref>
+    </check>
+  </xsl:template>
+
+
+  <!-- expand reference to would-be OCIL (inline) -->
+  <xsl:template match="Rule/ocil">
+      <check>
+        <xsl:attribute name="system">ocil-transitional</xsl:attribute>
+          <check-export>
+
+          <xsl:attribute name="export-name">
+          <!-- add clauses if specific macros are found within -->
+            <xsl:if test="sysctl-check-macro">the correct value is not returned</xsl:if>
+            <xsl:if test="fileperms-check-macro or fileowner-check-macro or filegroupowner-check-macro">it does not</xsl:if>
+            <xsl:if test="partition-check-macro">no line is returned</xsl:if>
+            <xsl:if test="service-disable-check-macro">the service is running</xsl:if>
+            <xsl:if test="service-enable-check-macro">the service is not running</xsl:if>
+            <xsl:if test="package-check-macro">the package is installed</xsl:if>
+            <xsl:if test="module-disable-check-macro">no line is returned</xsl:if>
+            <xsl:if test="audit-syscall-check-macro">no line is returned</xsl:if>
+            <xsl:if test="sshd-check-macro">the required value is not set</xsl:if>
+          </xsl:attribute>
+
+          <!-- add clause if explicitly specified (and also override any above) -->
+          <xsl:if test="@clause">
+            <xsl:attribute name="export-name"><xsl:value-of select="@clause" /></xsl:attribute>
+          </xsl:if>
+
+          <xsl:attribute name="value-id">conditional_clause</xsl:attribute>
+          </check-export>
+        <!-- add the actual manual checking text -->
+        <check-content>
+        <xsl:apply-templates select="node()"/>
+        </check-content>
+      </check>
+   </xsl:template>
+
+   <xsl:template match="tested">
+      <reference>
+        <xsl:attribute name="href">test_attestation</xsl:attribute>
+            <dc:contributor><xsl:value-of select="@by" /></dc:contributor>
+            <dc:date><xsl:value-of select="@on" /></dc:date>
+      </reference>
+   </xsl:template>
+
+  <!-- The next set of templates places elements into the correct namespaces,
+       so that content authors never have to bother with them.
+       XHTML elements are explicitly identified and the xhtml
+       namespace is added.  Any element with an empty namespace
+       is assigned to the xccdf namespace. -->
+
+  <!-- put table and list-related xhtml tags into xhtml namespace -->
+  <xsl:template match="table | tr | th | td | ul | li | ol" >
+    <xsl:element name="{local-name()}" namespace="http://www.w3.org/1999/xhtml">
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:element>
+  </xsl:template>
+
+  <!-- put general formatting xhtml into xhtml namespace -->
+  <xsl:template match="code | strong | b | em | i | pre | br | hr" >
+    <xsl:element name="{local-name()}" namespace="http://www.w3.org/1999/xhtml">
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:element>
+  </xsl:template>
+
+  <!-- convert tt to code, which seems better-supported -->
+  <xsl:template match="tt">
+    <xhtml:code>
+      <xsl:apply-templates select="@*|node()"/>
+    </xhtml:code>
+  </xsl:template>
+
+  <!-- if no namespace is indicated, put into xccdf namespace-->
+  <xsl:template match="*[namespace-uri()='']" priority="-1">
+    <xsl:element name="{local-name()}" namespace="http://checklists.nist.gov/xccdf/1.1">
+      <xsl:apply-templates select="node()|@*"/>
+    </xsl:element>
+  </xsl:template>
+
+  <!-- identity transform: pass anything else through -->
+  <xsl:template match="@*|node()" priority="-2">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()" />
+    </xsl:copy>
+  </xsl:template>
+
+
+
+  <!-- The next set of templates expand convenience macros for XCCDF prose -->
+  <xsl:template match="sysctl-desc-macro">
+    To set the runtime status of the <xhtml:code><xsl:value-of select="@sysctl"/></xhtml:code> kernel parameter,
+    run the following command:
+    <xhtml:pre xml:space="preserve"># sysctl -w <xsl:value-of select="@sysctl"/>=<xsl:value-of select="@value"/></xhtml:pre>
+
+	<!-- The following text could also be included conditionally, if the defaultness of the sysctl were indicated. -->
+    If this is not the system's default value, add the following line to <xhtml:code>/etc/sysctl.conf</xhtml:code>:
+    <xhtml:pre xml:space="preserve"><xsl:value-of select="@sysctl"/> = <xsl:value-of select="@value"/></xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="sysctl-check-macro">
+    The status of the <xhtml:code><xsl:value-of select="@sysctl"/></xhtml:code> kernel parameter can be queried
+    by running the following command:
+    <xhtml:pre xml:space="preserve">$ sysctl <xsl:value-of select="@sysctl"/></xhtml:pre>
+    The output of the command should indicate a value of <xhtml:code><xsl:value-of select="@value"/></xhtml:code>.
+    If this value is not the default value, investigate how it could have been
+    adjusted at runtime, and verify it is not set improperly in
+    <xhtml:code>/etc/sysctl.conf</xhtml:code>.
+    <!--
+	The following text could be conditionally added, for any cases where the default sysctl value
+	is not the required one. We could indicate this with an additional attribute
+	in the macro.  (Adding default values to sysctl.conf just increases C&A cost with no benefit; it makes default
+	systems fail compliance checks when they shouldn't.)
+
+    <xhtml:br />
+    To verify persistent configuration of the <xhtml:code><xsl:value-of select="@sysctl"/></xhtml:code> kernel parameter,
+    verify that the following line is present in <xhtml:code>/etc/sysctl.conf</xhtml:code>:
+    <xhtml:pre xml:space="preserve">$ sysctl <xsl:value-of select="@sysctl"/></xhtml:pre>    -->
+  </xsl:template>
+
+  <xsl:template match="mount-desc-macro">
+	Add the <xhtml:code><xsl:value-of select="@option"/></xhtml:code> option to the fourth column of
+	<xhtml:code>/etc/fstab</xhtml:code> for the line which controls mounting of
+	<xsl:if test="starts-with(@part,'/')">
+		<xhtml:code><xsl:value-of select="@part"/></xhtml:code>.
+	</xsl:if>
+	<xsl:if test="not(starts-with(@part,'/'))">
+		<xsl:value-of select="@part"/>.
+	</xsl:if>
+  </xsl:template>
+
+  <xsl:template match="fileperms-desc-macro">
+    To properly set the permissions of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre xml:space="preserve"># chmod <xsl:value-of select="@perms"/> <xsl:value-of select="@file"/></xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="fileowner-desc-macro">
+    To properly set the owner of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre xml:space="preserve"># chown <xsl:value-of select="@owner"/> <xsl:value-of select="@file"/> </xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="filegroupowner-desc-macro">
+    To properly set the group owner of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre xml:space="preserve"># chgrp <xsl:value-of select="@group"/> <xsl:value-of select="@file"/> </xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="fileperms-check-macro">
+    To check the permissions of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre>$ ls -l <xsl:value-of select="@file"/></xhtml:pre>
+    If properly configured, the output should indicate the following permissions:
+    <xhtml:code><xsl:value-of select="@perms"/></xhtml:code>
+  </xsl:template>
+
+  <xsl:template match="fileowner-check-macro">
+    To check the ownership of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre>$ ls -lL <xsl:value-of select="@file"/></xhtml:pre>
+    If properly configured, the output should indicate the following owner:
+    <xhtml:code><xsl:value-of select="@owner"/></xhtml:code>
+  </xsl:template>
+
+  <xsl:template match="filegroupowner-check-macro">
+    To check the group ownership of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre>$ ls -lL <xsl:value-of select="@file"/></xhtml:pre>
+    If properly configured, the output should indicate the following group-owner.
+    <xhtml:code><xsl:value-of select="@group"/></xhtml:code>
+  </xsl:template>
+
+  <xsl:template match="fileperms-check-macro">
+    To check the permissions of <xhtml:code><xsl:value-of select="@file"/></xhtml:code>, run the command:
+    <xhtml:pre>$ ls -l <xsl:value-of select="@file"/></xhtml:pre>
+    If properly configured, the output should indicate the following permissions:
+    <xhtml:code><xsl:value-of select="@perms"/></xhtml:code>
+  </xsl:template>
+
+  <xsl:template match="package-install-macro">
+    The <xhtml:code><xsl:value-of select="@package"/></xhtml:code> package can be installed with the following command:
+    <xhtml:pre># yum install <xsl:value-of select="@package"/></xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="package-remove-macro">
+    The <xhtml:code><xsl:value-of select="@package"/></xhtml:code> package can be removed with the following command:
+    <xhtml:pre># yum erase <xsl:value-of select="@package"/></xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="partition-check-macro">
+    Run the following command to determine if  <xhtml:code><xsl:value-of select="@part"/></xhtml:code>
+    is on its own partition or logical volume:
+
+  <xhtml:pre>$ mount | grep "on <xsl:value-of select="@part"/>"</xhtml:pre>
+  If <xhtml:code><xsl:value-of select="@part"/></xhtml:code> has its own partition or volume group, a line
+  will be returned.
+  </xsl:template>
+
+  <xsl:template match="service-disable-macro">
+    The <xhtml:code><xsl:value-of select="@service"/></xhtml:code> service can be disabled with the following command:
+    <xhtml:pre># chkconfig <xsl:value-of select="@service"/> off</xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="service-enable-macro">
+    The <xhtml:code><xsl:value-of select="@service"/></xhtml:code> service can be enabled with the following command:
+    <xhtml:pre># chkconfig --level 2345 <xsl:value-of select="@service"/> on</xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="service-disable-check-macro">
+    To check that the <xhtml:code><xsl:value-of select="@service"/></xhtml:code> service is disabled in system boot configuration, run the following command: 
+    <xhtml:pre># chkconfig <xhtml:code><xsl:value-of select="@service"/></xhtml:code> --list</xhtml:pre>
+    Output should indicate the <xhtml:code><xsl:value-of select="@service"/></xhtml:code> service has either not been installed,
+    or has been disabled at all runlevels, as shown in the example below:
+    <xhtml:pre># chkconfig <xhtml:code><xsl:value-of select="@service"/></xhtml:code> --list
+<xhtml:code><xsl:value-of select="@service"/></xhtml:code>       0:off   1:off   2:off   3:off   4:off   5:off   6:off</xhtml:pre>
+
+    Run the following command to verify <xhtml:code><xsl:value-of select="@service"/></xhtml:code> is disabled through current runtime configuration:
+    <xhtml:pre># service <xsl:value-of select="@service"/> status</xhtml:pre>
+
+    If the service is disabled the command will return the following output:
+    <xhtml:pre><xsl:value-of select="@service"/> is stopped</xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="service-enable-check-macro">
+    Run the following command to determine the current status of the
+<xhtml:code><xsl:value-of select="@service"/></xhtml:code> service:
+  <xhtml:pre># service <xsl:value-of select="@service"/> status</xhtml:pre>
+    If the service is enabled, it should return the following: <xhtml:pre><xsl:value-of select="@service"/> is running...</xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="package-check-macro">
+    Run the following command to determine if the <xhtml:code><xsl:value-of select="@package"/></xhtml:code> package is installed:
+    <xhtml:pre># rpm -q <xsl:value-of select="@package"/></xhtml:pre>
+  </xsl:template>
+
+
+  <xsl:template match="module-disable-macro">
+To configure the system to prevent the <xhtml:code><xsl:value-of select="@module"/></xhtml:code>
+kernel module from being loaded, add the following line to a file in the directory <xhtml:code>/etc/modprobe.d</xhtml:code>:
+<xhtml:pre xml:space="preserve">install <xsl:value-of select="@module"/> /bin/false</xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="module-disable-check-macro">
+If the system is configured to prevent the loading of the
+<xhtml:code><xsl:value-of select="@module"/></xhtml:code> kernel module,
+it will contain lines inside any file in <xhtml:code>/etc/modprobe.d</xhtml:code> or the deprecated<xhtml:code>/etc/modprobe.conf</xhtml:code>.
+These lines instruct the module loading system to run another program (such as
+<xhtml:code>/bin/false</xhtml:code>) upon a module <xhtml:code>install</xhtml:code> event.
+Run the following command to search for such lines in all files in <xhtml:code>/etc/modprobe.d</xhtml:code>
+and the deprecated <xhtml:code>/etc/modprobe.conf</xhtml:code>:
+<xhtml:pre xml:space="preserve">$ grep -r <xsl:value-of select="@module"/> /etc/modprobe.conf /etc/modprobe.d</xhtml:pre>
+  </xsl:template>
+
+  <xsl:template match="audit-syscall-check-macro">
+To determine if the system is configured to audit calls to
+the <xhtml:code><xsl:value-of select="@syscall"/></xhtml:code>
+system call, run the following command:
+<xhtml:pre xml:space="preserve"># auditctl -l | grep syscall | grep <xsl:value-of select="@syscall"/></xhtml:pre>
+If the system is configured to audit this activity, it will return a line.
+  </xsl:template>
+
+  <!--Example usage: <iptables-desc-macro allow="true" net="false" proto="tcp"
+       port="80" />  -->
+    <!-- allow (boolean): optional attribute which defaults to true, or to
+         allow this traffic through -->
+    <!-- net (boolean): optional attribute which determines if -s netwk/mask
+         is put in.  By defaults this is false -->
+    <!-- proto (string): protocol in question, typically tcp or udp -->
+    <!-- port (integer): port in question -->
+  <xsl:template match="iptables-desc-macro">
+    <xsl:choose>
+      <xsl:when test="@allow = 'false'">
+      <!-- allow: optional attribute which defaults to true, or to allow this traffic through -->
+        To configure <xhtml:code>iptables</xhtml:code> to not allow port
+        <xsl:value-of select="@port"/> traffic one must edit
+        <xhtml:code>/etc/sysconfig/iptables</xhtml:code> and
+        <xhtml:code>/etc/sysconfig/ip6tables</xhtml:code> (if IPv6 is in use).
+        Remove the following line, ensuring that it does not appear in the INPUT
+        chain:
+        <xhtml:pre xml:space="preserve">-A INPUT <xsl:if test="@net = 'true'">-s netwk/mask </xsl:if>-m state --state NEW -p <xsl:value-of select="@proto"/> --dport <xsl:value-of select="@port"/> -j ACCEPT</xhtml:pre>
+      </xsl:when>
+      <xsl:otherwise>
+        To configure <xhtml:code>iptables</xhtml:code> to allow port
+        <xsl:value-of select="@port"/> traffic one must edit
+        <xhtml:code>/etc/sysconfig/iptables</xhtml:code>  and
+        <xhtml:code>/etc/sysconfig/ip6tables</xhtml:code> (if IPv6 is in use).
+        Add the following line, ensuring that it appears before the final LOG
+        and DROP lines for the INPUT chain:
+        <xhtml:pre xml:space="preserve">-A INPUT <xsl:if test="@net = 'true'">-s netwk/mask </xsl:if>-m state --state NEW -p <xsl:value-of select="@proto"/> --dport <xsl:value-of select="@port"/> -j ACCEPT</xhtml:pre>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="sshd-check-macro">
+  <!-- could also do this with sshd -T to test live configuration -->
+    To determine how the SSH daemon's
+    <xhtml:code><xsl:value-of select="@option"/></xhtml:code>
+    option is set, run the following command:
+    <xhtml:pre xml:space="preserve"># grep -i <xsl:value-of select="@option"/> /etc/ssh/sshd_config</xhtml:pre>
+    <xsl:if test="@default='yes'">
+      If no line, a commented line, or a line indicating the value
+      <xhtml:code><xsl:value-of select="@value"/></xhtml:code> is returned, then the required value is set.
+    </xsl:if>
+    <xsl:if test="@default='no' or @default=''">
+      If a line indicating <xsl:value-of select="@value"/> is returned, then the required value is set.
+    </xsl:if>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/FEDORA/transforms/xccdf-removeaux.xslt b/FEDORA/transforms/xccdf-removeaux.xslt
new file mode 100644
index 0000000..788969e
--- /dev/null
+++ b/FEDORA/transforms/xccdf-removeaux.xslt
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xccdf="http://checklists.nist.gov/xccdf/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xccdf">
+
+<!-- This transform removes Groups from the XCCDF document.  In general, these
+     are expected to be Groups added from files in the inputs/auxiliary
+     directory.  -->
+
+
+  <!-- remove the srg_support Group from final output, as it exists only to
+       support the OS SRG mapping -->
+  <xsl:template match="xccdf:Group[@id='srg_support']">
+  </xsl:template>
+
+
+  <!-- copy everything else through to final output -->
+  <xsl:template match="@*|node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()" />
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/FEDORA/transforms/xccdf-removetested.xslt b/FEDORA/transforms/xccdf-removetested.xslt
new file mode 100644
index 0000000..48019b0
--- /dev/null
+++ b/FEDORA/transforms/xccdf-removetested.xslt
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xccdf="http://checklists.nist.gov/xccdf/1.1" xmlns:dc="http://purl.org/dc/elements/1.1/" 
+xmlns:xhtml="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xccdf">
+
+<!-- This transform removes test contributor information from the XCCDF document. -->
+
+
+  <!-- remove the test contributor name from final output -->
+  <xsl:template match="xccdf:Rule/xccdf:reference[@href='test_attestation']">
+  </xsl:template>
+
+
+  <!-- copy everything else through to final output -->
+  <xsl:template match="@*|node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()" />
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
-- 
1.7.11.7

