def main():
    global definitions
    global tests
    global objects
    global states
    global variables
    global silent_mode

    silent_mode = False
    silent_mode_options = ['-q', '--quiet', '--silent']

    if len(sys.argv) < 2 or len(sys.argv) > 3:
        print("Provide the name of an XML file, which contains" +
              " the definition to test.")
        usage()

    if len(sys.argv) == 3 and sys.argv[1] in silent_mode_options:
        if sys.argv[2].rfind('.xml') != -1:
            silent_mode = True
            sys.argv.pop(1)
        else:
            usage()

    if len(sys.argv) != 2 or sys.argv[1].rfind('.xml') == -1:
        usage()

    if not len(sys.argv) == 4:
        try:
            from openscap import oscap_get_version
            if oscap_get_version() < 1.2:
                schema = 5.10
            else:
                schema = 5.11
        except ImportError:
            schema = parse_conf_file(conf_file)
    else:
        # FUTURE: replace with sys arg
        schema = '5.10'

    testfile = sys.argv[1]
    header = _header(schema)
    testfile = find_testfile(testfile)
    body = read_ovaldefgroup_file(testfile)
    defname = add_oval_elements(body, header)
    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("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("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)
示例#2
0
def main():
    if len(sys.argv) < 3:
        sys.stderr.write("Provide an XCCDF file and an ID name scheme.\n")
        sys.stderr.write("This script finds check-content files (currently, "
                         "OVAL and OCIL) referenced from XCCDF and "
                         "synchronizes all IDs.\n")
        sys.exit(1)

    xccdffile = sys.argv[1]
    idname = sys.argv[2]

    # Step over xccdf file, and find referenced check files
    xccdftree = parse_xml_file(xccdffile)

    # Create XCCDF rule ID to assigned CCE ID mapping
    xccdf_to_cce_id_mapping = create_xccdf_id_to_cce_id_mapping(xccdftree)

    # Check that OVAL IDs and XCCDF Rule IDs match
    if 'unlinked-ocilref' not in xccdffile:
        allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns)
        for rule in allrules:
            xccdf_rule = rule.get("id")
            if xccdf_rule is not None:
                checks = rule.find("./{%s}check" % xccdf_ns)
                if checks is not None:
                    for check in checks:
                        check_name = check.get("name")
                        # Verify match of XCCDF vs OVAL / OCIL IDs for
                        # * the case of OVAL <check>
                        # * the case of OCIL <check>
                        if (not xccdf_rule == check_name and check_name is not None \
                            and not xccdf_rule + '_ocil' == check_name \
                            and not xccdf_rule == 'sample_rule'):
                            sys.stderr.write("The OVAL / OCIL ID does not "
                                             "match the XCCDF Rule ID!\n")
                            if '_ocil' in check_name:
                                sys.stderr.write("  OCIL ID:       \'%s\'\n" %
                                                 (check_name))
                            else:
                                sys.stderr.write("  OVAL ID:       \'%s\'\n" %
                                                 (check_name))
                            sys.stderr.write("  XCCDF Rule ID: \'%s\'\n" %
                                             (xccdf_rule))
                            sys.stderr.write("Both OVAL/OCIL and XCCDF Rule "
                                             "IDs must match!" % (xccdf_rule))
                            sys.exit(1)

    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)

    # Rename all IDs in the oval file
    if ovalfile:
        ovaltree = parse_xml_file(ovalfile)

        drop_oval_checks_extending_non_existing_checks(ovaltree)

        # Add new <reference source="CCE" ref_id="CCE-ID" /> element to those OVAL
        # checks having CCE ID already assigned in XCCDF for particular rule.
        # But add the <reference> only in the case CCE is in valid form!
        # Exit with failure if the assignment wasn't successful
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1230
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1229
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1228
        add_cce_id_refs_to_oval_checks(ovaltree, xccdf_to_cce_id_mapping)

        # Verify all by XCCDF referenced (local) OVAL checks are defined in OVAL file
        # If not drop the <check-content> OVAL checksystem reference from XCCDF
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1095
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1098
        ensure_by_xccdf_referenced_oval_def_is_defined_in_oval_file(
            xccdftree, ovaltree)

        # Verify the XCCDF to OVAL datatype export matching constraints
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1089
        check_and_correct_xccdf_to_oval_data_export_matching_constraints(
            xccdftree, ovaltree)

        # Verify if CCE identifiers present in the XCCDF follow the required form
        # (either CCE-XXXX-X, or CCE-XXXXX-X). Drop from XCCDF those who don't follow it
        verify_correct_form_of_referenced_cce_identifiers(xccdftree)

        ovaltree = translator.translate(ovaltree, store_defname=True)
        newovalfile = ovalfile.replace("unlinked", "linked")
        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", "linked")
        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)

        # Don't attempt to relabel ID on empty <check-content-ref> element
        if checkcontentref is None:
            continue
        # Obtain the value of the 'href' attribute of particular
        # <check-content-ref> element
        checkcontentref_hrefattr = checkcontentref.get("href")

        # Don't attempt to relabel ID on <check-content-ref> element having
        # its "href" attribute set either to "http://" or to "https://" values
        if checkcontentref_hrefattr.startswith("http://") or \
           checkcontentref_hrefattr.startswith("https://"):
            continue

        if check.get("system") == oval_cs:
            checkid = translator.generate_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.generate_id(
                    "{" + oval_ns + "}variable",
                    checkexport.get("export-name"))
                checkexport.set("export-name", newexportname)

        if check.get("system") == ocil_cs:
            checkid = translator.generate_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.generate_id(
                    "{" + oval_ns + "}variable",
                    checkexport.get("export-name"))
                checkexport.set("export-name", newexportname)

    newxccdffile = xccdffile.replace("unlinked", "linked")
    # ET.dump(xccdftree)
    ET.ElementTree(xccdftree).write(newxccdffile)
    sys.exit(0)
示例#3
0
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)
    # Keep the list of 'id' attributes from untranslated inventory def elements
    inventory_defs_id_attrs = []

    defs.clear()
    [defs.append(inventory_def) for inventory_def in inventory_defs]
    # Fill in that list
    [inventory_defs_id_attrs.append(inventory_def.get("id")) 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")
    env_objects = extract_referred_nodes(objects, objects, "id")
    objects.clear()
    [objects.append(cpe_object) for cpe_object in cpe_objects]

    # if any subelements in an object contain var_ref, return it here
    local_var_ref = extract_subelement(objects, 'var_ref')

    variables = ovaltree.find("./{%s}variables" % oval_ns)
    if variables is not None:
        cpe_variables = extract_referred_nodes(tests, variables, "var_ref")
        local_variables = extract_referred_nodes(variables, variables, "id")
        if cpe_variables:
            variables.clear()
            [variables.append(cpe_variable) for cpe_variable in cpe_variables]
        elif local_var_ref:
            for local_var in local_variables:
                if local_var.get('id') == local_var_ref:
                    variables.clear()
                    variables.append(local_var)
                    env_obj = extract_env_obj(env_objects, local_var)
                    objects.append(env_obj)
        else:
            ovaltree.remove(variables)

    # turn IDs into meaningless numbers
    translator = idtranslate.idtranslator(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):
        checkhref = check.get("href")
        # If CPE OVAL references another OVAL file
        if checkhref == 'filename':
            # Sanity check -- Verify the referenced OVAL is truly defined
            # somewhere in the (sub)directory tree below CWD. In correct
            # scenario is should be located:
            # * either in input/oval/*.xml
            # * or copied by former run of "combineovals.py" script from
            #   shared/ directory into build/ subdirectory
            refovalfilename = check.text
            refovalfilefound = False
            for dirpath, dirnames, filenames in os.walk(os.curdir,
                                                        topdown=True):
                # Case when referenced OVAL file exists
                for location in fnmatch.filter(filenames,
                                               refovalfilename + '.xml'):
                    refovalfilefound = True
                    break  # break from the inner for loop

                if refovalfilefound:
                    break  # break from the outer for loop

            shared_dir = \
                os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
            if shared_dir is not None:
                for dirpath, dirnames, filenames in os.walk(shared_dir,
                                                            topdown=True):
                    # Case when referenced OVAL file exists
                    for location in fnmatch.filter(filenames,
                                                   refovalfilename + '.xml'):
                        refovalfilefound = True
                        break  # break from the inner for loop

                    if refovalfilefound:
                        break  # break from the outer for loop

            # Referenced OVAL doesn't exist in the subdirtree below CWD:
            # * there's either typo in the refenced OVAL filename, or
            # * is has been forgotten to be placed into input/oval, or
            # * the <platform> tag of particular shared/ OVAL wasn't modified
            #   to include the necessary referenced file.
            # Therefore display an error and exit with failure in such cases
            if not refovalfilefound:
                error_msg = "\n\tError: Can't locate \"%s\" OVAL file in the \
                \n\tlist of OVAL checks for this product! Exiting..\n" % refovalfilename
                sys.stderr.write(error_msg)
                # sys.exit(1)
        check.set("href", os.path.basename(newovalfile))

        # Sanity check to verify if inventory check OVAL id is present in the
        # list of known "id" attributes of inventory definitions. If not it
        # means provided ovalfile (sys.argv[1]) doesn't contain this OVAL
        # definition (it wasn't included due to <platform> tag restrictions)
        # Therefore display an error and exit with failure, since otherwise
        # we might end up creating invalid $(ID)-$(PROD)-cpe-oval.xml file
        if check.text not in inventory_defs_id_attrs:
            error_msg = "\n\tError: Can't locate \"%s\" definition in \"%s\". \
            \n\tEnsure <platform> element is configured properly for \"%s\".  \
            \n\tExiting..\n" % (check.text, ovalfile, check.text)
            sys.stderr.write(error_msg)
            # sys.exit(1)

        # Referenced OVAL checks passed both of the above sanity tests
        check.text = translator.generate_id("{" + oval_ns + "}definition",
                                            check.text)

    ET.ElementTree(cpedicttree).write("./output/" + newcpedictfile)

    sys.exit(0)
def main():
    global definitions
    global tests
    global objects
    global states
    global variables
    global silent_mode

    silent_mode = False
    silent_mode_options = ['-q', '--quiet', '--silent']

    if len(sys.argv) < 2 or len(sys.argv) > 3:
        print ("Provide the name of an XML file, which contains" +
               " the definition to test.")
        usage()

    if len(sys.argv) == 3 and sys.argv[1] in silent_mode_options:
        if sys.argv[2].rfind('.xml') != -1:
            silent_mode = True
            sys.argv.pop(1)
        else:
            usage()

    if len(sys.argv) != 2 or sys.argv[1].rfind('.xml') == -1:
        usage()

    if not len(sys.argv) == 4:
        try:
            from openscap import oscap_get_version
            if oscap_get_version() < 1.2:
                schema = 5.10
            else:
                schema = 5.11
        except ImportError:
            schema = parse_conf_file(conf_file)
    else:
        # FUTURE: replace with sys arg
        schema = '5.10'

    testfile = sys.argv[1]
    header = _header(schema)
    testfile = find_testfile(testfile)
    body = read_ovaldefgroup_file(testfile)
    defname = add_oval_elements(body, header)
    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("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 ("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)
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)

    product = sys.argv[1]
    idname = sys.argv[2]
    cpeoutdir = sys.argv[3]
    ovalfile = sys.argv[4]
    cpedictfile = sys.argv[5]

    # 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)
    # Keep the list of 'id' attributes from untranslated inventory def elements
    inventory_defs_id_attrs = []

    defs.clear()
    [defs.append(inventory_def) for inventory_def in inventory_defs]
    # Fill in that list
    inventory_defs_id_attrs = \
        [inventory_def.get("id") 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")
    env_objects = extract_referred_nodes(objects, objects, "id")
    objects.clear()
    [objects.append(cpe_object) for cpe_object in cpe_objects]

    # if any subelements in an object contain var_ref, return it here
    local_var_ref = extract_subelement(objects, 'var_ref')

    variables = ovaltree.find("./{%s}variables" % oval_ns)
    if variables is not None:
        cpe_variables = extract_referred_nodes(tests, variables, "var_ref")
        local_variables = extract_referred_nodes(variables, variables, "id")
        if cpe_variables:
            variables.clear()
            [variables.append(cpe_variable) for cpe_variable in cpe_variables]
        elif local_var_ref:
            for local_var in local_variables:
                if local_var.get('id') == local_var_ref:
                    variables.clear()
                    variables.append(local_var)
                    env_obj = extract_env_obj(env_objects, local_var)
                    objects.append(env_obj)
        else:
            ovaltree.remove(variables)

    # turn IDs into meaningless numbers
    translator = idtranslate.idtranslator(idname)
    ovaltree = translator.translate(ovaltree)

    newovalfile = idname + "-" + product + "-" + os.path.basename(ovalfile)
    newovalfile = newovalfile.replace("oval-unlinked", "cpe-oval")
    ET.ElementTree(ovaltree).write(cpeoutdir + "/" + 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):
        checkhref = check.get("href")
        # If CPE OVAL references another OVAL file
        if checkhref == 'filename':
            # Sanity check -- Verify the referenced OVAL is truly defined
            # somewhere in the (sub)directory tree below CWD. In correct
            # scenario is should be located:
            # * either in input/oval/*.xml
            # * or copied by former run of "combine-ovals.py" script from
            #   shared/ directory into build/ subdirectory
            refovalfilename = check.text
            refovalfilefound = False
            for dirpath, dirnames, filenames in os.walk(os.curdir, topdown=True):
                # Case when referenced OVAL file exists
                for location in fnmatch.filter(filenames, refovalfilename + '.xml'):
                    refovalfilefound = True
                    break                     # break from the inner for loop

                if refovalfilefound:
                    break                     # break from the outer for loop

            shared_dir = \
                os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
            if shared_dir is not None:
                for dirpath, dirnames, filenames in os.walk(shared_dir, topdown=True):
                    # Case when referenced OVAL file exists
                    for location in fnmatch.filter(filenames, refovalfilename + '.xml'):
                        refovalfilefound = True
                        break                     # break from the inner for loop

                    if refovalfilefound:
                        break                     # break from the outer for loop

            # Referenced OVAL doesn't exist in the subdirtree below CWD:
            # * there's either typo in the refenced OVAL filename, or
            # * is has been forgotten to be placed into input/oval, or
            # * the <platform> tag of particular shared/ OVAL wasn't modified
            #   to include the necessary referenced file.
            # Therefore display an error and exit with failure in such cases
            if not refovalfilefound:
                error_msg = "\n\tError: Can't locate \"%s\" OVAL file in the \
                \n\tlist of OVAL checks for this product! Exiting..\n" % refovalfilename
                sys.stderr.write(error_msg)
                # sys.exit(1)
        check.set("href", os.path.basename(newovalfile))

        # Sanity check to verify if inventory check OVAL id is present in the
        # list of known "id" attributes of inventory definitions. If not it
        # means provided ovalfile (sys.argv[1]) doesn't contain this OVAL
        # definition (it wasn't included due to <platform> tag restrictions)
        # Therefore display an error and exit with failure, since otherwise
        # we might end up creating invalid $(ID)-$(PROD)-cpe-oval.xml file
        if check.text not in inventory_defs_id_attrs:
            error_msg = "\n\tError: Can't locate \"%s\" definition in \"%s\". \
            \n\tEnsure <platform> element is configured properly for \"%s\".  \
            \n\tExiting..\n" % (check.text, ovalfile, check.text)
            sys.stderr.write(error_msg)
            # sys.exit(1)

        # Referenced OVAL checks passed both of the above sanity tests
        check.text = translator.generate_id("{" + oval_ns + "}definition", check.text)

    ET.ElementTree(cpedicttree).write(cpeoutdir + '/' + newcpedictfile)

    sys.exit(0)
def main():
    if len(sys.argv) < 3:
        sys.stderr.write("Provide an XCCDF file and an ID name scheme.\n")
        sys.stderr.write("This script finds check-content files (currently, "
                         "OVAL and OCIL) referenced from XCCDF and "
                         "synchronizes all IDs.\n")
        sys.exit(1)

    xccdffile = sys.argv[1]
    idname = sys.argv[2]

    # Step over xccdf file, and find referenced check files
    xccdftree = parse_xml_file(xccdffile)

    # Create XCCDF rule ID to assigned CCE ID mapping
    xccdf_to_cce_id_mapping = create_xccdf_id_to_cce_id_mapping(xccdftree)

    # Check that OVAL IDs and XCCDF Rule IDs match
    if 'unlinked-ocilref' not in xccdffile:
        allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns)
        for rule in allrules:
            xccdf_rule = rule.get("id")
            if xccdf_rule is not None:
                checks = rule.find("./{%s}check" % xccdf_ns)
                if checks is not None:
                    for check in checks:
                        check_name = check.get("name")
                        # Verify match of XCCDF vs OVAL / OCIL IDs for
                        # * the case of OVAL <check>
                        # * the case of OCIL <check>
                        if (not xccdf_rule == check_name and check_name is not None \
                            and not xccdf_rule + '_ocil' == check_name \
                            and not xccdf_rule == 'sample_rule'):
                            sys.stderr.write("The OVAL / OCIL ID does not "
                                             "match the XCCDF Rule ID!\n")
                            if '_ocil' in check_name:
                                sys.stderr.write("  OCIL ID:       \'%s\'\n"
                                                 % (check_name))
                            else:
                                sys.stderr.write("  OVAL ID:       \'%s\'\n"
                                                 % (check_name))
                            sys.stderr.write("  XCCDF Rule ID: \'%s\'\n"
                                             % (xccdf_rule))
                            sys.stderr.write("Both OVAL/OCIL and XCCDF Rule "
                                             "IDs must match!" % (xccdf_rule))
                            sys.exit(1)

    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)

    # Rename all IDs in the oval file
    if ovalfile:
        ovaltree = parse_xml_file(ovalfile)

        drop_oval_checks_extending_non_existing_checks(ovaltree)

        # Add new <reference source="CCE" ref_id="CCE-ID" /> element to those OVAL
        # checks having CCE ID already assigned in XCCDF for particular rule.
        # But add the <reference> only in the case CCE is in valid form!
        # Exit with failure if the assignment wasn't successful
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1230
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1229
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1228
        add_cce_id_refs_to_oval_checks(ovaltree, xccdf_to_cce_id_mapping)

        # Verify all by XCCDF referenced (local) OVAL checks are defined in OVAL file
        # If not drop the <check-content> OVAL checksystem reference from XCCDF
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1095
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1098
        ensure_by_xccdf_referenced_oval_def_is_defined_in_oval_file(xccdftree, ovaltree)

        # Verify the XCCDF to OVAL datatype export matching constraints
        # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1089
        check_and_correct_xccdf_to_oval_data_export_matching_constraints(xccdftree, ovaltree)

        # Verify if CCE identifiers present in the XCCDF follow the required form
        # (either CCE-XXXX-X, or CCE-XXXXX-X). Drop from XCCDF those who don't follow it
        verify_correct_form_of_referenced_cce_identifiers(xccdftree)

        ovaltree = translator.translate(ovaltree, store_defname=True)
        newovalfile = ovalfile.replace("unlinked", "linked")
        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", "linked")
        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)

        # Don't attempt to relabel ID on empty <check-content-ref> element
        if checkcontentref is None:
            continue
        # Obtain the value of the 'href' attribute of particular
        # <check-content-ref> element
        checkcontentref_hrefattr = checkcontentref.get("href")

        # Don't attempt to relabel ID on <check-content-ref> element having
        # its "href" attribute set either to "http://" or to "https://" values
        if checkcontentref_hrefattr.startswith("http://") or \
           checkcontentref_hrefattr.startswith("https://"):
            continue

        if check.get("system") == oval_cs:
            checkid = translator.generate_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.generate_id("{" + oval_ns + "}variable",
                                                       checkexport.get("export-name"))
                checkexport.set("export-name", newexportname)

        if check.get("system") == ocil_cs:
            checkid = translator.generate_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.generate_id("{" + oval_ns + "}variable",
                                                       checkexport.get("export-name"))
                checkexport.set("export-name", newexportname)

    newxccdffile = xccdffile.replace("unlinked", "linked")
    # ET.dump(xccdftree)
    ET.ElementTree(xccdftree).write(newxccdffile)
    sys.exit(0)