From 8bddd6b076190190748dbcd34a3463b0b9d6cf1f Mon Sep 17 00:00:00 2001
From: Jan Lieskovsky <jlieskov@redhat.com>
Date: Wed, 18 Sep 2013 17:27:51 +0200
Subject: [PATCH] Introduce FEDORA directory skeleton and 'common' profile
 having two gpgcheck scans


Signed-off-by: Jan Lieskovsky <jlieskov@redhat.com>
---
 Fedora/Makefile                                    |  59 +++
 Fedora/README                                      |  30 ++
 .../checks/ensure_gpgcheck_never_disabled.xml      |  28 ++
 Fedora/input/checks/idtranslate.py                 |   1 +
 Fedora/input/checks/installed_OS_is_fedora19.xml   |  41 ++
 .../checks/platform/fedora19-cpe-dictionary.xml    |  10 +
 Fedora/input/checks/testcheck.py                   | 124 ++++++
 .../checks/yum_gpgcheck_global_activation.xml      |  24 +
 Fedora/input/guide.xml                             |  40 ++
 Fedora/input/guide.xslt                            |  43 ++
 Fedora/input/intro/intro.xml                       | 167 +++++++
 Fedora/input/profiles/common.xml                   |   8 +
 Fedora/input/system/software/software.xml          |   8 +
 Fedora/input/system/software/updating.xml          |  68 +++
 Fedora/input/system/system.xml                     |   4 +
 Fedora/scap-security-guide.spec                    |  53 +++
 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                    | 109 +++++
 Fedora/transforms/shorthand2xccdf.xslt             | 494 +++++++++++++++++++++
 Fedora/transforms/xccdf-removeaux.xslt             |  22 +
 Fedora/transforms/xccdf-removetested.xslt          |  20 +
 Fedora/utils/README                                |  36 ++
 Fedora/utils/verify-input-sanity.py                | 151 +++++++
 Fedora/utils/verify-references.py                  | 185 ++++++++
 Makefile                                           |  42 ++
 28 files changed, 2117 insertions(+)
 create mode 100644 Fedora/Makefile
 create mode 100644 Fedora/README
 create mode 100644 Fedora/input/checks/ensure_gpgcheck_never_disabled.xml
 create mode 120000 Fedora/input/checks/idtranslate.py
 create mode 100644 Fedora/input/checks/installed_OS_is_fedora19.xml
 create mode 100644 Fedora/input/checks/platform/fedora19-cpe-dictionary.xml
 create mode 100755 Fedora/input/checks/testcheck.py
 create mode 100644 Fedora/input/checks/yum_gpgcheck_global_activation.xml
 create mode 100644 Fedora/input/guide.xml
 create mode 100644 Fedora/input/guide.xslt
 create mode 100644 Fedora/input/intro/intro.xml
 create mode 100644 Fedora/input/profiles/common.xml
 create mode 100644 Fedora/input/system/software/software.xml
 create mode 100644 Fedora/input/system/software/updating.xml
 create mode 100644 Fedora/input/system/system.xml
 create mode 100644 Fedora/scap-security-guide.spec
 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
 create mode 100644 Fedora/utils/README
 create mode 100755 Fedora/utils/verify-input-sanity.py
 create mode 100755 Fedora/utils/verify-references.py

diff --git a/Fedora/Makefile b/Fedora/Makefile
new file mode 100644
index 0000000..e608354
--- /dev/null
+++ b/Fedora/Makefile
@@ -0,0 +1,59 @@
+IN = input
+OUT = output
+TRANS = transforms
+UTILS = utils
+DIST = dist
+
+ID = ssg
+PROD = fedora19
+
+all: shorthand2xccdf guide content dist
+
+shorthand-guide:
+	xsltproc -o $(OUT)/$(ID)-$(PROD)-shorthand.xml $(IN)/guide.xslt $(IN)/guide.xml
+	xmllint --format --output $(OUT)/$(ID)-$(PROD)-shorthand.xml $(OUT)/$(ID)-$(PROD)-shorthand.xml
+
+shorthand2xccdf: shorthand-guide
+	xsltproc -o $(OUT)/unlinked-unresolved-$(PROD)-xccdf.xml $(TRANS)/shorthand2xccdf.xslt $(OUT)/$(ID)-$(PROD)-shorthand.xml
+	oscap xccdf resolve -o $(OUT)/unlinked-$(PROD)-xccdf.xml $(OUT)/unlinked-unresolved-$(PROD)-xccdf.xml
+
+checks:
+	xmlwf $(IN)/checks/*.xml
+	$(TRANS)/combinechecks.py $(IN)/checks > $(OUT)/unlinked-$(PROD)-oval.xml
+	xmllint --format --output $(OUT)/unlinked-$(PROD)-oval.xml $(OUT)/unlinked-$(PROD)-oval.xml
+
+guide: shorthand2xccdf
+#       remove auxiliary Groups which are only for use in tables, and not guide output.
+#       specifying a nonexistent profile, "allrules," to make oscap print all Rules
+	xsltproc -o $(OUT)/unlinked-$(PROD)-xccdf-guide.xml $(TRANS)/xccdf-removeaux.xslt $(OUT)/unlinked-$(PROD)-xccdf.xml
+	xsltproc -o $(OUT)/unlinked-notest-$(PROD)-xccdf-guide.xml $(TRANS)/xccdf-removetested.xslt $(OUT)/unlinked-$(PROD)-xccdf.xml
+	oscap xccdf generate guide --profile allrules $(OUT)/unlinked-notest-$(PROD)-xccdf-guide.xml > $(OUT)/$(ID)-$(PROD)-guide.html
+
+content: shorthand2xccdf guide checks
+	$(TRANS)/cpe_generate.py $(OUT)/unlinked-$(PROD)-oval.xml $(IN)/checks/platform/$(PROD)-cpe-dictionary.xml $(ID)
+	$(TRANS)/relabelids.py unlinked-$(PROD)-xccdf.xml $(ID)
+
+validate-xml:
+	oscap xccdf validate-xml $(OUT)/$(ID)-$(PROD)-xccdf.xml
+	oscap oval validate-xml $(OUT)/$(ID)-$(PROD)-oval.xml
+	oscap oval validate-xml $(OUT)/$(ID)-$(PROD)-cpe-oval.xml
+
+validate: validate-xml
+	cd $(OUT); ../$(UTILS)/verify-references.py --rules-with-invalid-checks --ovaldefs-unused $(ID)-$(PROD)-xccdf.xml
+	oscap oval validate-xml --schematron $(OUT)/$(ID)-$(PROD)-oval.xml
+
+# items in dist are expected for distribution in an rpm
+dist: guide content
+	mkdir -p $(DIST)/guide $(DIST)/content
+	cp $(OUT)/*-guide.html $(DIST)/guide
+	cp $(OUT)/$(ID)-$(PROD)-xccdf.xml $(DIST)/content
+	cp $(OUT)/$(ID)-$(PROD)-oval.xml $(DIST)/content
+	cp $(OUT)/$(ID)-$(PROD)-cpe-dictionary.xml $(DIST)/content
+	cp $(OUT)/$(ID)-$(PROD)-cpe-oval.xml $(DIST)/content
+
+eval-common: content
+	oscap xccdf eval --profile common $(OUT)/$(ID)-$(PROD)-xccdf.xml
+
+clean:
+	rm -f $(OUT)/*.xml $(OUT)/*.html $(OUT)/*.xhtml $(OUT)/*.pdf  $(OUT)/*.spec $(OUT)/*.tar $(OUT)/*.gz $(OUT)/*.ini $(OUT)/*.csv
+	rm -rf $(DIST)/content $(DIST)/guide
diff --git a/Fedora/README b/Fedora/README
new file mode 100644
index 0000000..c3c94db
--- /dev/null
+++ b/Fedora/README
@@ -0,0 +1,30 @@
+Directory Structure of scap-security-guide
+------------------------------------------
+
+The input directory contains source files that generate SCAP content, such as
+XCCDF and OVAL.  Since a single large XML file is an impractical format for
+multiple authors to collaborate on editing SCAP content, efforts are made to
+keep logically related guidance and checking content in individual files.
+
+The transforms directory contains resources that enable the files inside the
+input directory (or output directory) to be combined and reformatted into
+valid SCAP formats or human-readable formats.
+
+The output directory is used as a storage area for items generated by the files
+in the inputs directory.  It should be empty in the repository, and built on
+users' individual systems (and rely on its .gitignore file to keep such files
+out).  The output directory contains transitional output (which may only exist
+in order to be further transformed) as well as final output.
+
+The references directory should contain documents which are specified as
+references from within the SCAP content, or documents that are "seeds," viz.
+documents whose prose will be translated into SCAP formats, as well as other
+examples of SCAP content.
+
+The utils directory contains helper scripts and other items that are useful to
+developers but are not essential to producing the project's output.
+
+The dist directory contains final outputs, which could be shipped in an RPM for
+consumption by end-users.  Updating the Makefile to copy an item from the
+outputs directory to the dist directory indicates that an item is considered a
+final output.
diff --git a/Fedora/input/checks/ensure_gpgcheck_never_disabled.xml b/Fedora/input/checks/ensure_gpgcheck_never_disabled.xml
new file mode 100644
index 0000000..8c21e83
--- /dev/null
+++ b/Fedora/input/checks/ensure_gpgcheck_never_disabled.xml
@@ -0,0 +1,28 @@
+<def-group>
+  <definition class="compliance" id="ensure_gpgcheck_never_disabled"
+  version="1">
+    <metadata>
+      <title>Ensure gpgcheck Enabled For All Yum Package Repositories</title>
+      <affected family="unix">
+        <platform>Fedora 19</platform>
+      </affected>
+      <description>Ensure all yum repositories utilize signature checking.</description>
+    </metadata>
+    <criteria comment="ensure all yum repositories utilize signiature checking" operator="AND">
+      <criterion comment="verify no gpgpcheck=0 present in /etc/yum.repos.d files"
+      test_ref="test_ensure_gpgcheck_never_disabled" />
+    </criteria>
+  </definition>
+  <ind:textfilecontent54_test check="all" check_existence="none_exist"
+  comment="check for existence of gpgcheck=0 in /etc/yum.repos.d/ files"
+  id="test_ensure_gpgcheck_never_disabled" version="1">
+    <ind:object object_ref="obj_ensure_gpgcheck_never_disabled" />
+  </ind:textfilecontent54_test>
+  <ind:textfilecontent54_object id="obj_ensure_gpgcheck_never_disabled"
+  version="1">
+    <ind:path>/etc/yum.repos.d</ind:path>
+    <ind:filename operation="pattern match">.*</ind:filename>
+    <ind:pattern operation="pattern match">^\s*gpgcheck\s*=\s*0\s*$</ind:pattern>
+    <ind:instance datatype="int">1</ind:instance>
+  </ind:textfilecontent54_object>
+</def-group>
diff --git a/Fedora/input/checks/idtranslate.py b/Fedora/input/checks/idtranslate.py
new file mode 120000
index 0000000..fd33b1e
--- /dev/null
+++ b/Fedora/input/checks/idtranslate.py
@@ -0,0 +1 @@
+../../transforms/idtranslate.py
\ No newline at end of file
diff --git a/Fedora/input/checks/installed_OS_is_fedora19.xml b/Fedora/input/checks/installed_OS_is_fedora19.xml
new file mode 100644
index 0000000..7e2e7ac
--- /dev/null
+++ b/Fedora/input/checks/installed_OS_is_fedora19.xml
@@ -0,0 +1,41 @@
+<def-group>
+  <definition class="inventory"
+  id="installed_OS_is_fedora19" version="1">
+    <metadata>
+      <title>Fedora release 19 (Schrödinger's Cat)</title>
+      <affected family="unix">
+        <platform>Fedora 19</platform>
+      </affected>
+      <reference ref_id="cpe:/o:fedoraproject:fedora:19"
+      source="CPE" />
+      <description>The operating system installed on the system is
+      Fedora release 19 (Schrödinger's Cat)</description>
+    </metadata>
+    <criteria>
+      <criterion comment="Installed operating system is part of the unix family"
+      test_ref="test_unix_family" />
+      <criterion comment="Fedora release 19 is installed"
+      test_ref="test_fedora_release" />
+    </criteria>
+  </definition>
+
+  <ind:family_test check="all" check_existence="at_least_one_exists" comment="installed OS part of unix family" id="test_unix_family" version="1">
+    <ind:object object_ref="obj_unix_family" />
+    <ind:state state_ref="state_unix_family" />
+  </ind:family_test>
+  <ind:family_state id="state_unix_family" version="1">
+    <ind:family>unix</ind:family>
+  </ind:family_state>
+  <ind:family_object id="obj_unix_family" version="1" />
+
+  <linux:rpminfo_test check="all" check_existence="only_one_exists" comment="fedora-release is version 19" id="test_fedora_release" version="1">
+    <linux:object object_ref="obj_fedora_release" />
+    <linux:state state_ref="state_fedora_release" />
+  </linux:rpminfo_test>
+  <linux:rpminfo_state id="state_fedora_release" version="1">
+    <linux:version operation="pattern match">^19$</linux:version>
+  </linux:rpminfo_state>
+  <linux:rpminfo_object id="obj_fedora_release" version="1">
+    <linux:name>fedora-release</linux:name>
+  </linux:rpminfo_object>
+</def-group>
diff --git a/Fedora/input/checks/platform/fedora19-cpe-dictionary.xml b/Fedora/input/checks/platform/fedora19-cpe-dictionary.xml
new file mode 100644
index 0000000..b457e21
--- /dev/null
+++ b/Fedora/input/checks/platform/fedora19-cpe-dictionary.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cpe-list xmlns="http://cpe.mitre.org/dictionary/2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cpe.mitre.org/dictionary/2.0 http://cpe.mitre.org/files/cpe-dictionary_2.1.xsd">
+      <cpe-item name="cpe:/o:fedoraproject:fedora:19">
+            <title xml:lang="en-us">Fedora release 19 (Schrödinger's Cat)</title>
+            <!-- the check references an OVAL file that contains an inventory definition -->
+            <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="filename">installed_OS_is_fedora19</check>
+      </cpe-item>
+</cpe-list>
diff --git a/Fedora/input/checks/testcheck.py b/Fedora/input/checks/testcheck.py
new file mode 100755
index 0000000..72e724e
--- /dev/null
+++ b/Fedora/input/checks/testcheck.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+
+import sys, os, tempfile, subprocess, platform
+import idtranslate
+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:unix="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix"
+    xmlns:ind="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent"
+    xmlns:linux="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux"
+    xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd">
+       <generator>
+        <oval:product_name>testcheck.py</oval:product_name>
+        <oval:product_version>0.0.1</oval:product_version>
+        <oval:schema_version>5.10</oval:schema_version>
+        <oval:timestamp>2011-09-23T13:44:00</oval:timestamp>
+    </generator>'''
+footer = '</oval_definitions>'
+
+ovalns = "{http://oval.mitre.org/XMLSchema/oval-definitions-5}"
+
+# globals, to make recursion easier in case we encounter extend_definition
+definitions = ET.Element("definitions")
+tests = ET.Element("tests")
+objects = ET.Element("objects")
+states = ET.Element("states")
+variables = ET.Element("variables")
+
+# add oval elements to the global Elements defined above
+def add_oval_elements(body):
+    tree = ET.fromstring(header + body + footer)
+    tree = replace_external_vars(tree)
+    # parse new file(string) as an etree, so we can arrange elements appropriately 
+    for childnode in tree.findall("./" + ovalns + "def-group/*"):
+        # print "childnode.tag is " + childnode.tag
+        if childnode.tag is ET.Comment: continue 
+        if childnode.tag == ( ovalns + "definition"):
+            definitions.append(childnode)
+            defname = childnode.get("id")
+            # extend_definition is a special case: must include a whole other definition
+            for defchild in childnode.findall(".//" + ovalns + "extend_definition"):
+                defid = defchild.get("definition_ref")            
+                includedbody = read_ovaldefgroup_file(defid+".xml")
+                # recursively add the elements in the other file
+                add_oval_elements(includedbody)
+        if childnode.tag.endswith("_test"): tests.append(childnode)
+        if childnode.tag.endswith("_object"): objects.append(childnode)
+        if childnode.tag.endswith("_state"): states.append(childnode)
+        if childnode.tag.endswith("_variable"): variables.append(childnode)
+    return defname
+
+# replace external_variables with local_variables, so the definition can be tested
+# independently of an XCCDF file
+def replace_external_vars(tree):
+    # external_variable is a special case: we turn it into a local_variable so we can test
+    for node in tree.findall(".//"+ovalns+"external_variable"):
+        print "external_variable with id : " + node.get("id") 
+        extvar_id = node.get("id")
+        #for envkey, envval in os.environ.iteritems():
+        #    print envkey + " = " + envval
+        #sys.exit()
+        if extvar_id not in os.environ.keys():
+            sys.exit("external_variable specified, but no value provided via environment variable")
+        node.tag = ovalns + "local_variable"    # replace tag name: external -> local
+        literal = ET.Element("literal_component")
+        literal.text = os.environ[extvar_id]
+        node.append(literal)
+        # TODO: assignment of external_variable via environment vars, for testing
+    return tree
+
+
+def read_ovaldefgroup_file(testfile):
+    with open( testfile, 'r') as f:
+        body = f.read()
+    return body
+
+def main():
+    global definitions
+    global tests
+    global objects
+    global states
+    global variables
+
+    if len(sys.argv) < 2:
+        print "Provide the name of an XML file, which contains the definition to test."
+        sys.exit(1)
+
+    for testfile in sys.argv[1:]:
+        body = read_ovaldefgroup_file(testfile)
+        defname = add_oval_elements(body)
+        ovaltree = ET.fromstring(header + footer)
+        # append each major element type, if it has subelements
+        for element in [definitions, tests, objects, states, variables]:
+            if element.getchildren():
+                ovaltree.append(element)
+        # re-map all the element ids from meaningful names to meaningless numbers
+        testtranslator = idtranslate.idtranslator("testids.ini", "scap-security-guide.testing")
+        ovaltree = testtranslator.translate(ovaltree)
+        (ovalfile, fname) = tempfile.mkstemp(prefix=defname,suffix=".xml")
+        os.write(ovalfile, ET.tostring(ovaltree))
+        os.close(ovalfile)
+        print "Evaluating with OVAL tempfile : " + fname
+        print "Writing results to : " + fname + "-results"
+        subprocess.call("oscap oval eval --results "+ fname + "-results " + fname, shell=True)
+        # perhaps delete tempfile?
+        definitions = ET.Element("definitions")
+        tests = ET.Element("tests")
+        objects = ET.Element("objects")
+        states = ET.Element("states")
+        variables = ET.Element("variables")
+
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
+
diff --git a/Fedora/input/checks/yum_gpgcheck_global_activation.xml b/Fedora/input/checks/yum_gpgcheck_global_activation.xml
new file mode 100644
index 0000000..a313351
--- /dev/null
+++ b/Fedora/input/checks/yum_gpgcheck_global_activation.xml
@@ -0,0 +1,24 @@
+<def-group>
+  <definition class="compliance" id="yum_gpgcheck_global_activation" version="1">
+    <metadata>
+      <title>Ensure Yum gpgcheck Globally Activated</title>
+      <affected family="unix">
+        <platform>Fedora 19</platform>
+      </affected>
+      <description>The gpgcheck option should be used to ensure that checking
+      of an RPM package's signature always occurs prior to its
+      installation.</description>
+    </metadata>
+    <criteria>
+      <criterion comment="check value of gpgcheck in /etc/yum.conf" test_ref="test_yum_gpgcheck_global_activation" />
+    </criteria>
+  </definition>
+  <ind:textfilecontent54_test check="all" check_existence="all_exist" comment="check value of gpgcheck in /etc/yum.conf" id="test_yum_gpgcheck_global_activation" version="1">
+    <ind:object object_ref="object_yum_gpgcheck_global_activation" />
+  </ind:textfilecontent54_test>
+  <ind:textfilecontent54_object id="object_yum_gpgcheck_global_activation" comment="gpgcheck set in /etc/yum.conf" version="1">
+    <ind:filepath>/etc/yum.conf</ind:filepath>
+    <ind:pattern operation="pattern match">^\s*gpgcheck\s*=\s*1\s*$</ind:pattern>
+    <ind:instance datatype="int" operation="equals">1</ind:instance>
+  </ind:textfilecontent54_object>
+</def-group>
diff --git a/Fedora/input/guide.xml b/Fedora/input/guide.xml
new file mode 100644
index 0000000..c76b795
--- /dev/null
+++ b/Fedora/input/guide.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<Benchmark xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dc="http://purl.org/dc/elements/1.1/" id="FEDORA-19" xsi:schemaLocation="http://checklists.nist.gov/xccdf/1.1 xccdf-1.1.4.xsd" resolved="false" xml:lang="en-US" >
+
+<status date="2011-12-20">draft</status>
+<title>Guide to the Secure Configuration of Fedora release 19 (Schrödinger's Cat)</title>
+<description>This guide presents a catalog of security-relevant
+configuration settings for Fedora release 19 (Schrödinger's Cat) formatted in the
+eXtensible Configuration Checklist Description Format (XCCDF).  
+<br/>
+<br/>
+Providing system administrators with such guidance informs them how to securely
+configure systems under their control in a variety of network roles.  Policy
+makers and baseline creators can use this catalog of settings, with its
+associated references to higher-level security control catalogs, in order to
+assist them in security baseline creation.  This guide is a <i>catalog, not a
+checklist,</i> and satisfaction of every item is not likely to be possible or
+sensible in many operational scenarios.  However, the XCCDF format enables
+granular selection and adjustment of settings, and their association with OVAL
+and OCIL content provides an automated checking capability.  Transformations of
+this document, and its associated automated checking content, are capable of
+providing baselines that meet a diverse set of policy objectives.  Some example
+XCCDF <i>Profiles</i>, which are selections of items that form checklists and
+can be used as baselines, are available with this guide.  They can be
+processed, in an automated fashion, with tools that support the Security
+Content Automation Protocol (SCAP).
+</description>
+<notice id="terms_of_use">Do not attempt to implement any of the settings in
+this guide without first testing them in a non-operational environment. The
+creators of this guidance assume no responsibility whatsoever for its use by
+other parties, and makes no guarantees, expressed or implied, about its
+quality, reliability, or any other characteristic.</notice>
+
+<front-matter>The SCAP Security Guide Project<br/>https://fedorahosted.org/scap-security-guide</front-matter>
+<rear-matter>Red Hat and Fedora are either registered
+trademarks or trademarks of Red Hat, Inc. in the United States and other
+countries. All other names are registered trademarks or trademarks of their
+respective companies.</rear-matter>
+<platform idref="cpe:/o:fedoraproject:fedora:19" />
+<version>0.0.1</version>
+</Benchmark>
diff --git a/Fedora/input/guide.xslt b/Fedora/input/guide.xslt
new file mode 100644
index 0000000..a24bdd9
--- /dev/null
+++ b/Fedora/input/guide.xslt
@@ -0,0 +1,43 @@
+<?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/">
+
+<!-- This transform assembles all fragments into one "shorthand" XCCDF document -->
+
+  <xsl:template match="Benchmark">
+    <xsl:copy>
+      <xsl:copy-of select="@*|node()" />
+
+      <!-- adding profiles here -->
+      <xsl:apply-templates select="document('profiles/common.xml')" />
+
+      <Value id="conditional_clause" type="string" operator="equals">
+                <title>A conditional clause for check statements.</title>
+                <description>A conditional clause for check statements.</description>
+                <value>This is a placeholder.</value>
+      </Value>
+      <xsl:apply-templates select="document('intro/intro.xml')" />
+      <xsl:apply-templates select="document('system/system.xml')" />
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="Group[@id='system']">
+    <xsl:copy>
+      <xsl:copy-of select="@*|node()" />
+      <xsl:apply-templates select="document('system/software/software.xml')" />
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="Group[@id='software']">
+    <xsl:copy>
+      <xsl:copy-of select="@*|node()" />
+      <xsl:apply-templates select="document('system/software/updating.xml')" />
+    </xsl:copy>
+  </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/input/intro/intro.xml b/Fedora/input/intro/intro.xml
new file mode 100644
index 0000000..ca8608c
--- /dev/null
+++ b/Fedora/input/intro/intro.xml
@@ -0,0 +1,167 @@
+<Group id="intro">
+<title>Introduction</title>
+<description>
+<!-- purpose and scope of guidance -->
+The purpose of this guidance is to provide security configuration
+recommendations and baselines for the Fedora operating system.
+Recommended settings for the basic operating system are provided,
+as well as for many network services that the system can provide
+to other systems.
+<!-- audience -->The guide is intended for system administrators. Readers are assumed to
+possess basic system administration skills for Unix-like systems, as well
+as some familiarity with Fedora's documentation and administration
+conventions. Some instructions within this guide are complex.
+All directions should be followed completely and with understanding of
+their effects in order to avoid serious adverse effects on the system
+and its security.
+</description>
+
+<Group id="general-principles">
+<title>General Principles</title>
+<description>
+The following general principles motivate much of the advice in this
+guide and should also influence any configuration decisions that are
+not explicitly covered.
+</description>
+
+<Group id="principle-encrypt-transmitted-data">
+<title>Encrypt Transmitted Data Whenever Possible</title>
+<description>
+Data transmitted over a network, whether wired or wireless, is susceptible
+to passive monitoring. Whenever practical solutions for encrypting
+such data exist, they should be applied. Even if data is expected to
+be transmitted only over a local network, it should still be encrypted.
+Encrypting authentication data, such as passwords, is particularly
+important. Networks of Fedora machines can and should be configured
+so that no unencrypted authentication data is ever transmitted between
+machines.
+</description>
+</Group>
+
+
+<Group id="principle-minimize-software">
+<title>Minimize Software to Minimize Vulnerability</title>
+<description>
+The simplest way to avoid vulnerabilities in software is to avoid
+installing that software. On Fedora, the RPM Package Manager (originally
+Red Hat Package Manager, abbreviated RPM) allows for careful management of
+the set of software packages installed on a system. Installed software
+contributes to system vulnerability in several ways. Packages that
+include setuid programs may provide local attackers a potential path to
+privilege escalation. Packages that include network services may give
+this opportunity to network-based attackers. Packages that include
+programs which are predictably executed by local users (e.g. after
+graphical login) may provide opportunities for trojan horses or other
+attack code to be run undetected. The number of software packages
+installed on a system can almost always be significantly pruned to include
+only the software for which there is an environmental or operational need.
+</description>
+</Group>
+
+<Group id="principle-separate-servers">
+<title>Run Different Network Services on Separate Systems</title>
+<description>
+Whenever possible, a server should be dedicated to serving exactly one
+network service. This limits the number of other services that can
+be compromised in the event that an attacker is able to successfully
+exploit a software flaw in one network service.
+</description>
+</Group>
+
+<Group id="principle-use-security-tools">
+<title>Configure Security Tools to Improve System Robustness</title>
+<description>
+Several tools exist which can be effectively used to improve a system's
+resistance to and detection of unknown attacks. These tools can improve
+robustness against attack at the cost of relatively little configuration
+effort. In particular, this guide recommends and discusses the use of
+Iptables for host-based firewalling, SELinux for protection against
+vulnerable services, and a logging and auditing infrastructure for
+detection of problems.
+</description>
+</Group>
+
+<Group id="principle-least-privilege">
+<title>Least Privilege</title>
+<description>
+Grant the least privilege necessary for user accounts and software to perform tasks.
+For example, <tt>sudo</tt> can be implemented to limit authorization to super user
+accounts on the system only to designated personnel. Another example is to limit
+logins on server systems to only those administrators who need to log into them in
+order to perform administration tasks. Using SELinux also follows the principle of
+least privilege: SELinux policy can confine software to perform only actions on the
+system that are specifically allowed. This can be far more restrictive than the
+actions permissible by the traditional Unix permissions model.
+</description>
+</Group>
+
+</Group>
+
+
+
+<Group id="how-to-use">
+<title>How to Use This Guide</title>
+<description>
+Readers should heed the following points when using the guide.
+</description>
+
+
+<Group id="intro-read-sections-completely">
+<title>Read Sections Completely and in Order</title>
+<description>
+Each section may build on information and recommendations discussed in
+prior sections. Each section should be read and understood completely;
+instructions should never be blindly applied. Relevant discussion may
+occur after instructions for an action. 
+</description>
+</Group>
+
+
+<Group id="intro-test-non-production">
+<title>Test in Non-Production Environment</title>
+<description>
+This guidance should always be tested in a non-production environment
+before deployment. This test environment should simulate the setup in
+which the system will be deployed as closely as possible.
+</description>
+</Group>
+
+
+<Group id="intro-root-shell-assumed">
+<title>Root Shell Environment Assumed</title>
+<description>
+Most of the actions listed in this document are written with the
+assumption that they will be executed by the root user running the
+<tt>/bin/bash</tt> shell. Commands preceded with a hash mark (#)
+assume that the administrator will execute the commands as root, i.e.
+apply the command via <tt>sudo</tt> whenever possible, or use
+<tt>su</tt> to gain root privileges if <tt>sudo</tt> cannot be
+used. Commands which can be executed as a non-root user are are preceded
+by a dollar sign ($) prompt.
+</description>
+</Group>
+
+<Group id="intro-formatting-conventions">
+<title>Formatting Conventions</title>
+<description>
+Commands intended for shell execution, as well as configuration file text,
+are featured in a <tt>monospace font</tt>. <i>Italics</i> are used
+to indicate instances where the system administrator must substitute
+the appropriate information into a command or configuration file.
+</description>
+</Group>
+
+<Group id="intro-reboot-required">
+<title>Reboot Required</title>
+<description>
+A system reboot is implicitly required after some actions in order to
+complete the reconfiguration of the system. In many cases, the changes
+will not take effect until a reboot is performed. In order to ensure
+that changes are applied properly and to test functionality, always
+reboot the system after applying a set of recommendations from this guide.
+</description>
+</Group>
+
+</Group>
+
+</Group>
diff --git a/Fedora/input/profiles/common.xml b/Fedora/input/profiles/common.xml
new file mode 100644
index 0000000..18c8f3e
--- /dev/null
+++ b/Fedora/input/profiles/common.xml
@@ -0,0 +1,8 @@
+<Profile id="common">
+<title>Common Profile for General-Purpose Fedora Systems</title>
+<description>This profile contains items common to general-purpose Fedora installations.</description>
+
+<select idref="ensure_gpgcheck_globally_activated" selected="true"/>
+<select idref="ensure_gpgcheck_never_disabled" selected="true"/>
+
+</Profile>
diff --git a/Fedora/input/system/software/software.xml b/Fedora/input/system/software/software.xml
new file mode 100644
index 0000000..97558fb
--- /dev/null
+++ b/Fedora/input/system/software/software.xml
@@ -0,0 +1,8 @@
+<Group id="software">
+<title>Installing and Maintaining Software</title>
+<description>The following sections contain information on
+security-relevant choices during the initial operating system
+installation process and the setup of software
+updates.</description>
+
+</Group>
diff --git a/Fedora/input/system/software/updating.xml b/Fedora/input/system/software/updating.xml
new file mode 100644
index 0000000..248c0d5
--- /dev/null
+++ b/Fedora/input/system/software/updating.xml
@@ -0,0 +1,68 @@
+<Group id="updating">
+<title>Updating Software</title>
+<description>The <tt>yum</tt> command line tool is used to install and
+update software packages. The system also provides a graphical
+software update tool in the <b>System</b> menu, in the <b>Administration</b> submenu,
+called <b>Software Update</b>.
+<br /><br />
+Fedora systems contain an installed software catalog called
+the RPM database, which records metadata of installed packages.  Tools such as
+<tt>yum</tt> or the graphical <b>Software Update</b> ensure usage of RPM
+packages for software installation.  This allows for insight into the current
+inventory of installed software on the system, and is highly recommended.
+</description>
+
+<!-- REMINDER: Before telling people to update their systems
+     via the security_patches_up_to_date rule, we must
+     ensure they have configured an update source! -->
+<Rule id="ensure_gpgcheck_globally_activated" severity="high">
+<title>Ensure gpgcheck Enabled In Main Yum Configuration</title>
+<description>The <tt>gpgcheck</tt> option should be used to ensure
+checking of an RPM package's signature always occurs prior to its
+installation. To configure yum to check package signatures before installing
+them, ensure the following line appears in <tt>/etc/yum.conf</tt> in
+the <tt>[main]</tt> section:
+<pre>gpgcheck=1</pre>
+</description>
+<ocil clause="GPG checking is not enabled">
+To determine whether <tt>yum</tt> is configured to use <tt>gpgcheck</tt>,
+inspect <tt>/etc/yum.conf</tt> and ensure the following appears in the
+<tt>[main]</tt> section:
+<pre>gpgcheck=1</pre>
+A value of <tt>1</tt> indicates that <tt>gpgcheck</tt> is enabled. Absence of a
+<tt>gpgcheck</tt> line or a setting of <tt>0</tt> indicates that it is
+disabled.
+</ocil>
+<rationale>
+Ensuring the validity of packages' cryptographic signatures prior to
+installation ensures the provenance of the software and
+protects against malicious tampering.
+</rationale>
+<oval id="yum_gpgcheck_global_activation" />
+<ref nist="SI-7,MA-1(b)" disa="352,663" />
+</Rule>
+
+<Rule id="ensure_gpgcheck_never_disabled" severity="high">
+<title>Ensure gpgcheck Enabled For All Yum Package Repositories</title>
+<description>To ensure signature checking is not disabled for
+any repos, remove any lines from files in <tt>/etc/yum.repos.d</tt> of the form:
+<pre>gpgcheck=0</pre>
+</description>
+<ocil clause="GPG checking is disabled">
+To determine whether <tt>yum</tt> has been configured to disable
+<tt>gpgcheck</tt> for any repos,  inspect all files in
+<tt>/etc/yum.repos.d</tt> and ensure the following does not appear in any
+sections:
+<pre>gpgcheck=0</pre>
+A value of <tt>0</tt> indicates that <tt>gpgcheck</tt> has been disabled for that repo. 
+</ocil>
+<rationale>
+Ensuring all packages' cryptographic signatures are valid prior to
+installation ensures the provenance of the software and
+protects against malicious tampering.
+</rationale>
+<oval id="ensure_gpgcheck_never_disabled" />
+<ref nist="SI-7,MA-1(b)" disa="352,663"/>
+</Rule>
+
+</Group>
diff --git a/Fedora/input/system/system.xml b/Fedora/input/system/system.xml
new file mode 100644
index 0000000..1814ce1
--- /dev/null
+++ b/Fedora/input/system/system.xml
@@ -0,0 +1,4 @@
+<Group id="system">
+<title>System Settings</title>
+
+</Group>
diff --git a/Fedora/scap-security-guide.spec b/Fedora/scap-security-guide.spec
new file mode 100644
index 0000000..2268a17
--- /dev/null
+++ b/Fedora/scap-security-guide.spec
@@ -0,0 +1,53 @@
+
+# IMPORTANT NOTE: This spec file is solely dedicated to make changes to the
+# Fedora's scap-security-guide package. If you want to apply changes against
+# the main RHEL-6 scap-security-guide RPM content, use scap-security-guide.spec
+# file one level up - in the main scap-security-guide directory (instead of
+# this one).
+
+Name:		scap-security-guide
+Version:	0.1
+Release:	1.fc19
+Summary:	Security guidance and baselines in SCAP formats
+Group:		Applications/System
+License:	Public Domain
+URL:		https://fedorahosted.org/scap-security-guide/
+Source0:	http://fedorapeople.org/~jlieskov/%{name}-%{version}.tar.gz
+BuildRoot:	%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+BuildArch:	noarch
+BuildRequires:	coreutils, libxslt, expat, python, openscap-utils >= 0.9.1, python-lxml
+Requires:	filesystem, openscap-utils >= 0.9.1
+
+%description
+The scap-security-guide project provides security configuration guidance in
+formats of the Security Content Automation Protocol (SCAP).  It provides a
+catalog of practical hardening advice and links it to government requirements
+where applicable. The project bridges the gap between generalized policy
+requirements and specific implementation guidance.
+%prep
+%setup -q
+
+
+%build
+cd Fedora && make dist
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/share/xml/scap/ssg/fedora/19
+
+# Add in core content (SCAP, guide)
+cp -r Fedora/dist/* $RPM_BUILD_ROOT/usr/share/xml/scap/ssg/fedora/19
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%files
+%defattr(-,root,root,-)
+/usr/share/xml/scap/ssg/fedora/19/*
+
+%changelog
+* Tue Sep 17 2013 Jan iankko Lieskovsky <jlieskov@redhat.com> 0.1-1
+- Initial Fedora SSG RPM.
diff --git a/Fedora/transforms/combinechecks.py b/Fedora/transforms/combinechecks.py
new file mode 100755
index 0000000..ca49350
--- /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..fe98482
--- /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", idname)
+	ET.ElementTree(ovaltree).write(newovalfile)
+
+	# replace and sync IDs, href filenames in input cpe dictionary file
+	cpedicttree = parse_xml_file(cpedictfile)
+
+        newcpedictfile = idname + "-" + os.path.basename(cpedictfile)
+	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..77f078a
--- /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..ad56fb5
--- /dev/null
+++ b/Fedora/transforms/relabelids.py
@@ -0,0 +1,109 @@
+#!/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", 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", 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", 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..b804153
--- /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-fedora19-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..eeb2049
--- /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>
diff --git a/Fedora/utils/README b/Fedora/utils/README
new file mode 100644
index 0000000..89c6ded
--- /dev/null
+++ b/Fedora/utils/README
@@ -0,0 +1,36 @@
+This file is meant to give a quick overview to some of the 
+scripts located in this directory.
+
+verify-input-sanity.py
+	Purpose:
+		This script can be invoked without arguments to examine the 
+		files within src/input to make sure that they are in good 
+		shape *prior to* building the XCCDF and OVAL content with the 
+		various make commands.
+	Intent:
+		Help XCCDF and OVAL developers spot common mistakes *before*
+		utilizing the Makefile to build the XCCDF and OVAL content.
+	Usage:
+		./verify-input-sanity.py
+
+verify-references.py
+	Purpose:
+		This script can be used to perform various checks on the XCCDF
+		and OVAL that is generated by the Makefile. Unlike the
+		verify-input-sanity.py script, this script limits its focus to
+		the files in the src/output directory. This script is to be
+		used as a development tool to aid in the creation of concise
+		and structurally correct XCCDF and OVAL. 
+	Intent:
+		Help XCCDF and OVAL developers spot potential mistakes in the
+		XCCDF and OVAL content that is generated by the Makefile.
+	Usage:
+		The script assumes that your current working directory is
+		src/output so if you are currently in the transforms directory:
+
+		cd ../output
+		../transforms/verify-references.py --all-checks ./rhel6-xccdf.xml
+
+		You may find this informative as well:
+
+		./verify-references.py -h
diff --git a/Fedora/utils/verify-input-sanity.py b/Fedora/utils/verify-input-sanity.py
new file mode 100755
index 0000000..1e0ec2c
--- /dev/null
+++ b/Fedora/utils/verify-input-sanity.py
@@ -0,0 +1,151 @@
+#!/usr/bin/python
+
+#
+# verify-input-sanity.py
+#   perform sanity checks on the individual OVAL checks that exist within the src/input/checks directory
+#
+
+# the python modules that we need
+import os, re
+import lxml.etree as ET
+
+# the "oval_header" variable must be prepended to the body of the check to form valid XML
+oval_header = '''<?xml version="1.0" encoding="UTF-8"?>
+<oval_definitions
+    xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5"
+    xmlns:unix="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix"
+    xmlns:ind="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent"
+    xmlns:linux="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux"
+    xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd
+        http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd">
+       <generator>
+        <oval:product_name>testcheck.py</oval:product_name>
+        <oval:product_version>0.0.1</oval:product_version>
+        <oval:schema_version>5.10</oval:schema_version>
+        <oval:timestamp>2011-09-23T13:44:00</oval:timestamp>
+    </generator>'''
+
+# the "oval_footer" variable must be appended to the body of the check to form valid XML
+oval_footer = '</oval_definitions>'
+
+# the namespace we are working in
+oval_namespace = "{http://oval.mitre.org/XMLSchema/oval-definitions-5}"
+
+xccdf_header = '<?xml version="1.0" encoding="UTF-8"?><xccdf>'
+xccdf_footer = '</xccdf>'
+
+# print a blank line to keep things pretty
+print
+
+#
+##################################################################################
+#
+# The directory src/input/checks contains all of the OVAL checks that are implemented within scap-security-guide.
+# In order to build the XCCDF and OVAL properly, several helper scripts expect that the ID assigned to each OVAL
+# check matches its file name.
+#
+# Assume we have an OVAL check called "mount_option_var_tmp_bind.xml" in the src/input/checks directory. The ID
+# of this check *must* be "mount_option_var_tmp_bind" like so:
+#
+# <def-group>
+#   <definition class="compliance" id="mount_option_var_tmp_bind" version="1">
+#     <metadata>
+#
+# This piece of Python will step through each OVAL check in src/input/checks and verify that the ID assigned to the
+# check matches the name of the file. If a mismatch is found, then a warning is printed to stdout.
+#
+##################################################################################
+#
+
+# make the checks directory our working directory
+os.chdir("../input/checks")
+
+# generate a list of all the OVAL checks
+oval_file_list = []
+for root, dirs, files in os.walk("."):
+    if (root == "."):
+        for name in files:
+            if (name.find(".xml") > -1):
+                oval_file_list.append(root + "/" + name)
+
+# step through each file and open it for reading
+for oval_check in oval_file_list:
+    with open(oval_check, 'r') as infile:
+        # form valid XML so that we can parse it
+        oval_xml_contents = oval_header + infile.read() + oval_footer
+        # parse the XML at this point
+        tree = ET.fromstring(oval_xml_contents)
+        # extract the ID of the check
+        definition_node = tree.findall("./" + oval_namespace + "def-group/*")
+        oval_id = "Error"
+        for node in definition_node:
+            if (node.tag == (oval_namespace + "definition")):
+                oval_id = node.get("id")
+        # at this point the variable oval_id should contain the id of the oval check
+        # now we make sure that the name of the file matches the oval id
+        if (oval_check.find(oval_id + ".xml") < 0):
+            print "  WARNING: OVAL check " + oval_check.replace("./", "src/input/checks/") + " has ID \"" + oval_id + "\""
+            print "           the ID should match the file name without the .xml\n"
+
+#
+##################################################################################
+#
+# This section of Python looks through all of the XCCDF files for references to OVAL checks. If a reference is found we
+# want to make sure that a corresponding OVAL check exists in the src/input/checks directory. We print a relatively polite
+# warning if a XCCDF Rule references an OVAL check that does not exist.
+#
+# Again, lots of regex-fu here. In their raw state the XCCDF files are not valid XML. The next iteration of this file may
+# add all of the XML complexity so that we can perform these validations by parsing XML.  That would form a more complete
+# solution.
+#
+##################################################################################
+#
+
+# make the input directory our working directory
+# remember that we are currently at "../input/checks"
+os.chdir("..")
+
+# exclude these directories in the search for XCCDF files
+exclude_subdirs = ['.', './checks', './checks/templates', './checks/templates/output']
+
+# generate a list of all the XML files that are used to generate the XCCDF
+xccdf_xml_files = []
+for root, dirs, files in os.walk("."):
+    if not (root in exclude_subdirs):
+        for name in files:
+            if (name.find(".xml") > -1):
+                xccdf_xml_files.append(root + "/" + name)
+
+# step through each file and open it for reading
+for xccdf_file in xccdf_xml_files:
+    with open(xccdf_file, 'r') as infile:
+        # form valid XML so that we can parse it
+        xccdf_xml_contents = xccdf_header + infile.read() + xccdf_footer
+        # parse the XML at this point
+        try:
+            tree = ET.fromstring(xccdf_xml_contents)
+        except ET.XMLSyntaxError:
+            print "  XML syntax error in file: %s" % xccdf_file.replace("./", "src/input/")
+        # extract all of the rules that are defined within the XCCDF
+        xccdf_rules = tree.findall(".//Rule")
+        for xccdf_rule in xccdf_rules:
+            # extract any reference to an OVAL check
+            oval_check_refs = xccdf_rule.findall(".//oval")
+            # make sure the OVAL references point to an actual check
+            for oval_ref in oval_check_refs:
+                # build a path to look for
+                if (oval_ref.get("id")):
+                    file_name = "./checks/" + oval_ref.get("id") + ".xml"
+                    if (not os.access(file_name, os.F_OK)):
+                        print "  WARNING: XCCDF Rule \"" + xccdf_rule.get("id") + "\" references OVAL check \"" + oval_ref.get("id") + "\" which does not exist"
+                        print "           problem occurs in file: " + xccdf_file.replace("./", "src/input/") + "\n"
+                else:
+                    print "  WARNING: XCCDF Rule \"" + xccdf_rule.get("id") + "\" in file " + xccdf_file.replace("./", "src/input/") + " contains a null OVAL check\n"
+
+# we are done
+exit()
diff --git a/Fedora/utils/verify-references.py b/Fedora/utils/verify-references.py
new file mode 100755
index 0000000..bac9723
--- /dev/null
+++ b/Fedora/utils/verify-references.py
@@ -0,0 +1,185 @@
+#!/usr/bin/python
+
+import sys, os, optparse
+import lxml.etree as ET
+
+#
+# This script can verify consistency of references (linkage) between XCCDF and
+# OVAL, and also search based on other criteria such as existence of policy
+# references in XCCDF.
+#
+# It must be run from the same directory as the XCCDF and OVAL content
+# it references.
+
+xccdf_ns = "http://checklists.nist.gov/xccdf/1.1" 
+oval_ns = "http://oval.mitre.org/XMLSchema/oval-definitions-5"
+
+# we use these strings to look for references within the XCCDF rules
+nist_ref_href = "http://csrc.nist.gov/publications/nistpubs/800-53-Rev3/sp800-53-rev3-final.pdf"
+disa_ref_href = "http://iase.disa.mil/cci/index.html"
+
+def parse_options():
+	usage = "usage: %prog [options] xccdf_file"
+	parser = optparse.OptionParser(usage=usage, version="%prog ")
+	# only some options are on by default
+	parser.add_option("-p", "--profile", default=False, action="store", dest="profile_name",
+					  help="act on Rules from this XCCDF Profile only")
+	parser.add_option("--rules-with-invalid-checks", default=False, action="store_true", dest="rules_with_invalid_checks",
+					  help="print XCCDF Rules that reference an invalid/nonexistent check")
+	parser.add_option("--rules-without-checks", default=False, action="store_true", dest="rules_without_checks",
+					  help="print XCCDF Rules that do not include a check")
+	parser.add_option("--rules-without-severity", default=False, action="store_true", dest="rules_without_severity",
+					  help="print XCCDF Rules that do not include a severity")
+	parser.add_option("--rules-without-nistrefs", default=False, action="store_true", dest="rules_without_nistrefs",
+					  help="print XCCDF Rules which do not include any NIST 800-53 references")
+	parser.add_option("--rules-without-disarefs", default=False, action="store_true", dest="rules_without_disarefs",
+					  help="print XCCDF Rules which do not include any DISA CCI references")
+	parser.add_option("--rules-with-nistrefs-outside-profile", default=False, action="store_true", dest="nistrefs_not_in_profile",
+					  help="print XCCDF Rules which have a NIST reference, but are not part of the Profile specified")
+	parser.add_option("--rules-with-disarefs-outside-profile", default=False, action="store_true", dest="disarefs_not_in_profile",
+					  help="print XCCDF Rules which have a DISA CCI reference, but are not part of the Profile specified")
+	parser.add_option("--ovaldefs-unused", default=False, action="store_true", dest="ovaldefs_unused",
+					  help="print OVAL definitions which are not used by any XCCDF Rule")
+	parser.add_option("--all-checks", default=False, action="store_true", dest="all_checks",
+					  help="perform all checks on the given XCCDF file")
+	(options, args) = parser.parse_args()
+	if len(args) < 1:
+		parser.print_help()
+		sys.exit(1)
+	return (options, args)
+
+def get_ovalfiles(checks):
+	# iterate over all checks, grab the OVAL files referenced within
+	ovalfiles = set()
+	for check in checks:
+		if check.get("system") == oval_ns:
+			checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns)
+			ovalfiles.add(checkcontentref.get("href"))
+		elif check.get("system") != "ocil-transitional":
+			print "Non-OVAL checking system found: " + check.get("system")
+	return ovalfiles
+
+
+def get_profileruleids(xccdftree, profile_name):
+	ruleids = []
+
+	while profile_name:
+		profile = xccdftree.find(".//{%s}Profile[@id='%s']" % (xccdf_ns, profile_name))
+		if profile is None:
+			sys.exit("Specified XCCDF Profile %s was not found.")
+		for select in profile.findall(".//{%s}select" % xccdf_ns):
+			ruleids.append(select.get("idref"))
+		profile_name = profile.get("extends")
+
+	return ruleids
+
+def main():
+	(options, args) = parse_options()
+	xccdffilename = args[0]
+
+	# extract all of the rules within the xccdf
+	xccdftree = ET.parse(xccdffilename)
+	rules = xccdftree.findall(".//{%s}Rule" % xccdf_ns)
+
+	# if a profile was specified, get rid of any Rules that aren't in it
+	if options.profile_name:
+		profile_ruleids = get_profileruleids(xccdftree, options.profile_name)
+		prunedrules = rules[:]
+		for rule in rules:
+			if rule.get("id") not in profile_ruleids:
+				prunedrules.remove(rule)	
+		rules = prunedrules
+
+	# step over xccdf file, and find referenced oval files
+	checks = xccdftree.findall(".//{%s}check" % xccdf_ns)
+	ovalfiles = get_ovalfiles(checks)
+
+	# this script only supports the inclusion of one OVAL file
+	if len(ovalfiles) > 1:
+		sys.exit("Referencing more than one OVAL file is not yet supported by this script.")
+
+	# find important elements within the XCCDF and the OVAL
+	ovalfile = ovalfiles.pop()
+	ovaltree = ET.parse(ovalfile) 
+	# collect all compliance checks (not inventory checks, which are needed by CPE)
+	ovaldefs = ovaltree.findall(".//{%s}definition[@class='compliance']" % oval_ns)
+	ovaldef_ids = [ovaldef.get("id") for ovaldef in ovaldefs] 
+
+	oval_extenddefs = ovaltree.findall(".//{%s}extend_definition" % oval_ns)
+	ovaldef_ids_extended = [oval_extenddef.get("definition_ref") for oval_extenddef in oval_extenddefs]
+	ovaldef_ids_extended = list(set(ovaldef_ids_extended))
+
+	check_content_refs = xccdftree.findall(".//{%s}check-content-ref" % xccdf_ns)
+
+	# now we can actually do the verification work here
+	if options.rules_with_invalid_checks or options.all_checks:
+		for check_content_ref in check_content_refs:
+			refname = check_content_ref.get("name")
+			if refname not in ovaldef_ids:
+				rule = check_content_ref.getparent().getparent() 
+				print "Invalid OVAL definition referenced by XCCDF Rule: " + rule.get("id")
+
+	if options.rules_without_checks or options.all_checks:
+		for rule in rules:
+			check = rule.find("./{%s}check" % xccdf_ns) 
+			if check is None:
+				print "No reference to OVAL definition in XCCDF Rule: " + rule.get("id")
+
+	if options.rules_without_severity or options.all_checks:
+		for rule in rules:
+			if rule.get("severity") is None:
+				print "No severity assigned to XCCDF Rule: " + rule.get("id")
+
+	if options.rules_without_nistrefs or options.rules_without_disarefs or options.all_checks:
+		for rule in rules:
+			# find all references in the current rule
+			refs = rule.findall(".//{%s}reference" % xccdf_ns)
+			if refs is None:
+				print "No reference assigned to XCCDF Rule: " + rule.get("id")
+			else:
+				# loop through the Rule's references and put their hrefs in a list
+				ref_href_list = [ref.get("href") for ref in refs]
+				# print warning if rule does not have a NIST reference
+				if (not nist_ref_href in ref_href_list) and options.rules_without_nistrefs:
+					print "No valid NIST reference in XCCDF Rule: " + rule.get("id")
+				# print warning if rule does not have a DISA reference
+				if (not disa_ref_href in ref_href_list) and options.rules_without_disarefs:
+					print "No valid DISA CCI reference in XCCDF Rule: " + rule.get("id")
+
+	if options.disarefs_not_in_profile or options.nistrefs_not_in_profile:
+		if options.profile_name is None:
+			sys.exit("The options for finding Rules with a reference, but which are not in a Profile, requires specifying a Profile.")
+		allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns)
+		for rule in allrules:
+			# find all references in the current rule
+			refs = rule.findall(".//{%s}reference" % xccdf_ns)
+			ref_href_list = [ref.get("href") for ref in refs]
+			# print warning if Rule is outside Profile and has a NIST reference
+			if options.nistrefs_not_in_profile:
+				if (nist_ref_href in ref_href_list) and (rule.get("id") not in profile_ruleids):
+					print "XCCDF Rule found with NIST reference outside Profile %s: " % options.profile_name + rule.get("id")
+			# print warning if Rule is outside Profile and has a DISA reference
+			if options.disarefs_not_in_profile:
+				if (disa_ref_href in ref_href_list) and (rule.get("id") not in profile_ruleids):
+					print "XCCDF Rule found with DISA CCI reference outside Profile %s: " % options.profile_name + rule.get("id")
+
+	if options.ovaldefs_unused or options.all_checks:
+		# create a list of all of the OVAL compliance check ids that are defined in the oval file
+		oval_checks_list = [ovaldef.get("id") for ovaldef in ovaldefs]
+		# now loop through the xccdf rules; if a rule references an oval check we remove the oval check from our list
+		for check_content in check_content_refs:
+			# remove from the list
+			if (check_content.get("name") in oval_checks_list):
+				oval_checks_list.remove(check_content.get("name"))
+		# the list should now contain the OVAL checks that are not referenced by any XCCDF rule
+		oval_checks_list.sort()
+		for oval_id in oval_checks_list:
+			# don't print out the OVAL defs that are extended by others, as they're not unused
+			if oval_id not in ovaldef_ids_extended:
+				print "OVAL Check is not referenced by XCCDF: %s" % oval_id
+
+	sys.exit(0)
+
+if __name__ == "__main__":
+	main()
+
diff --git a/Makefile b/Makefile
index 0816734..7f3dc95 100644
--- a/Makefile
+++ b/Makefile
@@ -10,10 +10,12 @@ PACKAGER := scap-security-guide
 ROOT_DIR ?= $(CURDIR)
 
 RPM_SPEC := $(ROOT_DIR)/scap-security-guide.spec
+FEDORA_SPEC := $(ROOT_DIR)/Fedora/scap-security-guide.spec
 
 TARBALL = $(RPM_TOPDIR)/SOURCES/$(PKG).tar.gz
 
 RPM_DEPS := tarball $(RPM_SPEC) Makefile
+FEDORA_RPM_DEPS := $(FEDORA_SPEC) Makefile
 
 RPM_TMPDIR ?= $(ROOT_DIR)/rpmbuild
 RPM_TOPDIR ?= $(RPM_TMPDIR)/src/redhat
@@ -63,6 +65,21 @@ tarball:
 	cd $(RPM_TMPDIR) && tar -czf $(PKG).tar.gz $(PKG)
 	cp $(RPM_TMPDIR)/$(PKG).tar.gz $(TARBALL)
 
+fedora-tarball:
+	$(call rpm-prep)
+
+	# Copy the source tree for Fedora content
+	cp -r Fedora $(RPM_TMPDIR)/$(PKG)
+
+        # Don't trust the developers, clean out the build
+        # environment before packaging
+	cd $(RPM_TMPDIR)/$(PKG)/Fedora && $(MAKE) clean
+
+        # Create the source tar, copy it to $TARBALL
+        # (e.g. somewhere in the SOURCES directory)
+	cd $(RPM_TMPDIR) && tar -czf $(PKG).tar.gz $(PKG)
+	cp $(RPM_TMPDIR)/$(PKG).tar.gz $(TARBALL)
+
 zipfile:
 	# Create a zipfile release, since many SCAP
 	# tools desire content in that format
@@ -86,14 +103,39 @@ srpm: $(RPM_DEPS)
 	cat $(RPM_SPEC) >> $(RPM_TOPDIR)/SPECS/$(notdir $(RPM_SPEC))
 	cd $(RPM_TOPDIR) && rpmbuild $(RPMBUILD_ARGS) --target=$(ARCH) -bs SPECS/$(notdir $(RPM_SPEC)) --nodeps
 
+fedora-srpm: $(FEDORA_RPM_DEPS)
+	# Create the necessary directory structure
+	$(call rpm-prep)
+	# Obtain name, version, and source from Fedora's spec file
+	$(eval FEDORA_NAME := $(shell sed -ne 's/Name:\t\t\(.*\)/\1/p' $(FEDORA_SPEC)))
+	$(eval FEDORA_VERSION := $(shell sed -ne 's/Version:\t\(.*\)/\1/p' $(FEDORA_SPEC)))
+	$(eval FEDORA_SOURCE := $(shell sed -ne 's/Source0:\t\(.*\)/\1/p' $(FEDORA_SPEC)))
+	# Substitute %{name} and %{version} with actual values
+	$(eval FEDORA_TARBALL := $(shell echo $(FEDORA_SOURCE) | sed -ne "s/%{name}/$(FEDORA_NAME)/p"))
+	$(eval FEDORA_TARBALL := $(shell echo $(FEDORA_TARBALL) | sed -ne "s/%{version}/$(FEDORA_VERSION)/p"))
+	# Download the tarball
+	@echo "Downloading the $(FEDORA_TARBALL) tarball..."
+	@wget -O $(TARBALL) $(FEDORA_TARBALL)
+	@echo "Copying $(FEDORA_SPEC) file to proper location..."
+	cat $(FEDORA_SPEC) > $(RPM_TOPDIR)/SPECS/$(notdir $(FEDORA_SPEC))
+	@echo "Building Fedora source $(PKGNAME) RPM package..."
+	cd $(RPM_TOPDIR) && rpmbuild $(RPMBUILD_ARGS) --target=$(ARCH) -bs SPECS/$(notdir $(FEDORA_SPEC)) --nodeps
+
 rpm: srpm
 	 @echo "Building $(PKG) RPM..."
 	 cd $(RPM_TOPDIR)/SRPMS && rpmbuild --rebuild --target=$(ARCH) $(RPMBUILD_ARGS) --buildroot $(RPM_BUILDROOT) -bb $(PKG)-$(RELEASE).src.rpm
 
+fedora-rpm: fedora-srpm
+	# Obtain Fedora package release from Fedora spec file
+	$(eval FEDORA_RELEASE := $(shell sed -ne 's/Release:\t\(.*\)/\1/p' $(FEDORA_SPEC)))
+	@echo "Building Fedora $(PKG) RPM package..."
+	cd $(RPM_TOPDIR)/SRPMS && rpmbuild --rebuild --target=$(ARCH) $(RPMBUILD_ARGS) --buildroot $(RPM_BUILDROOT) -bb $(PKG)-$(FEDORA_RELEASE).src.rpm
+
 clean:
 	rm -rf $(RPM_TMPDIR)
 	cd RHEL6 && $(MAKE) clean
 	cd OpenStack && $(MAKE) clean
 	cd RHEVM3 && $(MAKE) clean
+	cd Fedora && $(MAKE) clean
 
 .PHONY: rhel6 tarball srpm rpm clean all
-- 
1.7.11.7

