def __init__(self, filepath):
        self.tree = None
        try:
            with open(filepath, 'r') as xccdf_file:
                file_string = xccdf_file.read()
                tree = ElementTree.fromstring(file_string)
                self.tree = tree
        except IOError as ioerr:
            print("%s" % ioerr)
            sys.exit(1)

        self.indexed_rules = {}
        for rule in self.tree.findall(".//{%s}Rule" % (xccdf_ns)):
            rule_id = rule.get("id")
            if rule_id is None:
                raise RuntimeError("Can't index a rule with no id attribute!")

            assert (rule_id not in self.indexed_rules)
            self.indexed_rules[rule_id] = rule
Example #2
0
def add_sub_element(parent, tag, data):
    # This is used because our YAML data contain XML and XHTML elements
    # ET.SubElement() escapes the < > characters by &lt; and &gt;
    # and therefore it does not add child elements
    # we need to do a hack instead
    # TODO: Remove this function after we move to Markdown everywhere in SSG
    try:
        ustr = unicode("<{0}>{1}</{0}>").format(tag, data)
    except NameError:
        ustr = str("<{0}>{1}</{0}>").format(tag, data)

    try:
        element = ET.fromstring(ustr.encode("utf-8"))
    except Exception:
        msg = ("Error adding subelement to an element '{0}' from string: '{1}'"
               .format(parent.tag, ustr))
        raise RuntimeError(msg)

    parent.append(element)
    return element
Example #3
0
def _add_elements(body, header):
    """Add oval elements to the global Elements defined above"""
    global definitions
    global tests
    global objects
    global states
    global variables

    tree = ET.fromstring(header + body + footer)
    tree = replace_external_vars(tree)
    defname = None
    # parse new file(string) as an etree, so we can arrange elements
    # appropriately
    for childnode in tree.findall("./{%s}def-group/*" % ovalns):
        # print "childnode.tag is " + childnode.tag
        if childnode.tag is ET.Comment:
            continue
        if childnode.tag == ("{%s}definition" % ovalns):
            append(definitions, childnode)
            defname = childnode.get("id")
            # extend_definition is a special case:  must include a whole other
            # definition
            for defchild in childnode.findall(".//{%s}extend_definition" %
                                              ovalns):
                defid = defchild.get("definition_ref")
                extend_ref = find_testfile(defid + ".xml")
                includedbody = read_ovaldefgroup_file(extend_ref)
                # recursively add the elements in the other file
                _add_elements(includedbody, header)
        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)
    return defname
Example #4
0
def _check_oval_version_from_oval(xml_content, oval_version):
    try:
        argument = oval_header + xml_content + oval_footer
        oval_file_tree = ElementTree.fromstring(argument)
    except ElementTree.ParseError as p:
        line, column = p.position
        lines = argument.splitlines()
        before = '\n'.join(lines[:line])
        column_pointer = ' ' * (column - 1) + '^'
        sys.stderr.write(
            "%s\n%s\nError when parsing OVAL file.\n" %
            (before, column_pointer))
        sys.exit(1)
    for defgroup in oval_file_tree.findall("./{%s}def-group" % oval_ns):
        file_oval_version = defgroup.get("oval_version")

    if file_oval_version is None:
        # oval_version does not exist in <def-group/>
        # which means the OVAL is supported for any version.
        # By default, that version is 5.10
        file_oval_version = "5.10"

    if tuple(oval_version.split(".")) >= tuple(file_oval_version.split(".")):
        return True
Example #5
0
def main():
    global definitions
    global tests
    global objects
    global states
    global variables
    global silent_mode

    args = parse_options()
    silent_mode = args.silent_mode
    oval_version = args.oval_version

    testfile = args.xmlfile
    header = oval_generated_header("testoval.py", oval_version, "0.0.1")
    testfile = find_testfile(testfile)
    body = read_ovaldefgroup_file(testfile)
    defname = _add_elements(body, header)
    if defname is None:
        print("Error while evaluating oval: defname not set; missing "
              "definitions section?")
        sys.exit(1)

    ovaltree = ET.fromstring(header + footer)

    # append each major element type, if it has subelements
    for element in [definitions, tests, objects, states, variables]:
        if list(element) > 0:
            ovaltree.append(element)
    # re-map all the element ids from meaningful names to meaningless
    # numbers
    testtranslator = IDTranslator("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)
    if not silent_mode:
        print("Evaluating with OVAL tempfile: " + fname)
        print("OVAL Schema Version: %s" % oval_version)
        print("Writing results to: " + fname + "-results")
    cmd = "oscap oval eval --results " + fname + "-results " + fname
    oscap_child = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
    cmd_out = oscap_child.communicate()[0]
    if not silent_mode:
        print(cmd_out)
    if oscap_child.returncode != 0:
        if not silent_mode:
            print("Error launching 'oscap' command: \n\t" + cmd)
        sys.exit(2)
    if 'false' in cmd_out:
        # at least one from the evaluated OVAL definitions evaluated to
        # 'false' result, exit with '1' to indicate OVAL scan FAIL result
        sys.exit(1)
    # perhaps delete tempfile?
    definitions = ET.Element("definitions")
    tests = ET.Element("tests")
    objects = ET.Element("objects")
    states = ET.Element("states")
    variables = ET.Element("variables")

    # 'false' keyword wasn't found in oscap's command output
    # exit with '0' to indicate OVAL scan TRUE result
    sys.exit(0)