static struct oscap_list *xccdf_benchmark_resolve_dependencies(void *itemptr, void *userdata) { struct xccdf_item *item = XITEM(itemptr); struct oscap_list *ret = oscap_list_new(); struct xccdf_value_iterator *val_it = NULL; const char *extends = xccdf_item_get_extends(item); if (extends) oscap_list_add(ret, xccdf_benchmark_get_member(xccdf_item_get_benchmark(item), xccdf_item_get_type(item), extends)); switch (xccdf_item_get_type(item)) { case XCCDF_BENCHMARK: { OSCAP_FOR(xccdf_profile, profile, xccdf_benchmark_get_profiles(xccdf_item_to_benchmark(item))) oscap_list_add(ret, profile); val_it = xccdf_benchmark_get_values(xccdf_item_to_benchmark(item)); break; } case XCCDF_GROUP: val_it = xccdf_group_get_values(xccdf_item_to_group(item)); default: break; /* no-op */ } OSCAP_FOR(xccdf_item, child, xccdf_item_get_content(item)) oscap_list_add(ret, child); OSCAP_FOR(xccdf_value, val, val_it) oscap_list_add(ret, val); return ret; }
bool xccdf_tailoring_remove_profile(struct xccdf_tailoring *tailoring, struct xccdf_profile *profile) { assert(xccdf_profile_get_tailoring(profile)); // We have to make sure there is no other profile in tailoring that inherits // the profile we are about to remove. const char *profile_id = xccdf_profile_get_id(profile); struct xccdf_profile_iterator* it = xccdf_tailoring_get_profiles(tailoring); while (xccdf_profile_iterator_has_more(it)) { struct xccdf_profile* prof = xccdf_profile_iterator_next(it); if (prof == profile) continue; const char *extends = xccdf_profile_get_extends(prof); if (oscap_strcmp(profile_id, extends) == 0) { oscap_seterr(OSCAP_EFAMILY_XML, "Can't remove given profile '%s' from tailoring. Other profiles are inheriting from it!", profile_id); return false; xccdf_profile_iterator_free(it); } } xccdf_profile_iterator_free(it); return oscap_list_remove(tailoring->profiles, XITEM(profile), (oscap_cmp_func)_list_ptreq_cmp, NULL); }
struct xccdf_benchmark *xccdf_benchmark_import_source(struct oscap_source *source) { xmlTextReader *reader = oscap_source_get_xmlTextReader(source); while (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) ; struct xccdf_benchmark *benchmark = xccdf_benchmark_new(); const bool parse_result = xccdf_benchmark_parse(XITEM(benchmark), reader); xmlFreeTextReader(reader); if (!parse_result) { // parsing fatal error oscap_seterr(OSCAP_EFAMILY_XML, "Failed to import XCCDF content from '%s'.", oscap_source_readable_origin(source)); xccdf_benchmark_free(benchmark); return NULL; } // This is sadly the only place where we can pass origin file information // to the CPE1 embedded dictionary (if any). It is necessary to figure out // proper paths to OVAL files referenced from CPE1 dictionaries. // FIXME: Refactor and move this somewhere else struct cpe_dict_model* embedded_dict = xccdf_benchmark_get_cpe_list(benchmark); if (embedded_dict != NULL) { cpe_dict_model_set_origin_file(embedded_dict, oscap_source_readable_origin(source)); } // same situation with embedded CPE2 lang model // FIXME: Refactor and move this somewhere else struct cpe_lang_model* embedded_lang_model = xccdf_benchmark_get_cpe_lang_model(benchmark); if (embedded_lang_model != NULL) { cpe_lang_model_set_origin_file(embedded_lang_model, oscap_source_readable_origin(source)); } return benchmark; }
struct xccdf_group * xccdf_group_clone(const struct xccdf_group * group) { struct xccdf_item *new_group = calloc(1, sizeof(struct xccdf_item) + sizeof(struct xccdf_group_item)); struct xccdf_item *old = XITEM(group); xccdf_item_base_clone(&new_group->item, &(old->item)); new_group->type = old->type; xccdf_group_item_clone(new_group, &(old->sub.group)); return XGROUP(new_group); }
struct xccdf_rule *xccdf_rule_clone(const struct xccdf_rule * rule) { struct xccdf_item *new_rule = calloc(1, sizeof(struct xccdf_item) + sizeof(struct xccdf_rule_item)); struct xccdf_item *old = XITEM(rule); xccdf_item_base_clone(&new_rule->item, &(old->item)); new_rule->type = old->type; xccdf_rule_item_clone(&new_rule->sub.rule, &old->sub.rule); return XRULE(new_rule); }
struct xccdf_benchmark *xccdf_benchmark_clone(const struct xccdf_benchmark *old_benchmark) { struct xccdf_item *new_benchmark = oscap_calloc(1, sizeof(struct xccdf_item) + sizeof(struct xccdf_benchmark_item)); struct xccdf_item *old = XITEM(old_benchmark); xccdf_item_base_clone(&new_benchmark->item, &old->item); new_benchmark->type = old->type; //second argument is a pointer to the benchmark being created which will be the parent of all of its sub elements. xccdf_benchmark_item_clone(new_benchmark, old_benchmark); return XBENCHMARK(new_benchmark); }
bool xccdf_benchmark_resolve(struct xccdf_benchmark *benchmark) { struct oscap_list *resolve_order = NULL, *root_nodes = oscap_list_new(); oscap_list_add(root_nodes, benchmark); bool ret = false; if (oscap_tsort(root_nodes, &resolve_order, xccdf_benchmark_resolve_dependencies, NULL, NULL)) { OSCAP_FOR(xccdf_item, item, oscap_iterator_new(resolve_order)) xccdf_resolve_item(item, NULL); ret = true; } oscap_list_free(root_nodes, NULL); oscap_list_free(resolve_order, NULL); xccdf_resolve_cleanup(XITEM(benchmark)); return ret; }
struct xccdf_benchmark *xccdf_benchmark_import(const char *file) { xmlTextReaderPtr reader = xmlReaderForFile(file, NULL, 0); if (!reader) { oscap_seterr(OSCAP_EFAMILY_GLIBC, "Unable to open file: '%s'", file); return NULL; } xmlTextReaderSetErrorHandler(reader, &libxml_error_handler, NULL); while (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) ; struct xccdf_benchmark *benchmark = xccdf_benchmark_new(); const bool parse_result = xccdf_benchmark_parse(XITEM(benchmark), reader); xmlFreeTextReader(reader); if (!parse_result) { // parsing fatal error oscap_seterr(OSCAP_EFAMILY_XML, "Failed to parse '%s'.", file); xccdf_benchmark_free(benchmark); return NULL; } // This is sadly the only place where we can pass origin file information // to the CPE1 embedded dictionary (if any). It is necessary to figure out // proper paths to OVAL files referenced from CPE1 dictionaries. // FIXME: Refactor and move this somewhere else struct cpe_dict_model* embedded_dict = xccdf_benchmark_get_cpe_list(benchmark); if (embedded_dict != NULL) { cpe_dict_model_set_origin_file(embedded_dict, file); } // same situation with embedded CPE2 lang model // FIXME: Refactor and move this somewhere else struct cpe_lang_model* embedded_lang_model = xccdf_benchmark_get_cpe_lang_model(benchmark); if (embedded_lang_model != NULL) { cpe_lang_model_set_origin_file(embedded_lang_model, file); } return benchmark; }
struct xccdf_tailoring *xccdf_tailoring_import(const char *file, struct xccdf_benchmark *benchmark) { xmlTextReaderPtr reader = xmlReaderForFile(file, NULL, 0); if (!reader) { oscap_seterr(OSCAP_EFAMILY_GLIBC, "Unable to open file: '%s'", file); return NULL; } xmlTextReaderSetErrorHandler(reader, &libxml_error_handler, NULL); while (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) ; struct xccdf_tailoring *tailoring = xccdf_tailoring_parse(reader, XITEM(benchmark)); xmlFreeTextReader(reader); if (!tailoring) { // parsing fatal error oscap_seterr(OSCAP_EFAMILY_XML, "Failed to parse '%s'.", file); xccdf_tailoring_free(tailoring); return NULL; } return tailoring; }
bool xccdf_rule_add_conflicts(struct xccdf_rule* rule, const char* conflicts) { oscap_stringlist_add_string((struct oscap_stringlist*)(XITEM(rule)->sub.rule.conflicts), conflicts); return true; }
bool xccdf_group_add_requires(struct xccdf_group* group, struct oscap_stringlist* requires) { oscap_list_add(XITEM(group)->sub.group.requires, requires); return true; }
bool xccdf_rule_add_requires(struct xccdf_rule* rule, struct oscap_stringlist* requires) { oscap_list_add(XITEM(rule)->sub.rule.requires, requires); return true; }
struct oscap_stringlist_iterator *xccdf_group_get_requires(const struct xccdf_group* group) { return oscap_iterator_new(XITEM(group)->sub.group.requires); }
struct oscap_stringlist_iterator *xccdf_rule_get_requires(const struct xccdf_rule* rule) { return oscap_iterator_new(XITEM(rule)->sub.rule.requires); }
struct oscap_string_iterator *xccdf_group_get_conflicts(const struct xccdf_group* group) { return oscap_iterator_new(XITEM(group)->sub.group.conflicts); }
struct oscap_string_iterator *xccdf_rule_get_conflicts(const struct xccdf_rule* rule) { return oscap_iterator_new(XITEM(rule)->sub.rule.conflicts); }
xmlNode *xccdf_benchmark_to_dom(struct xccdf_benchmark *benchmark, xmlDocPtr doc, xmlNode *parent, void *user_args) { xmlNodePtr root_node = NULL; if (parent) { root_node = xccdf_item_to_dom(XITEM(benchmark), doc, parent); } else { root_node = xccdf_item_to_dom(XITEM(benchmark), doc, parent); xmlDocSetRootElement(doc, root_node); } // FIXME! //xmlNewProp(root_node, BAD_CAST "xsi:schemaLocation", BAD_CAST XCCDF_SCHEMA_LOCATION); xmlNs *ns_xccdf = xmlNewNs(root_node, (const xmlChar*)xccdf_version_info_get_namespace_uri(xccdf_benchmark_get_schema_version(benchmark)), NULL); xmlNs *ns_xsi = xmlNewNs(root_node, XCCDF_XSI_NAMESPACE, BAD_CAST "xsi"); xmlSetNs(root_node, ns_xsi); xmlSetNs(root_node, ns_xccdf); /* Handle attributes */ if (xccdf_benchmark_get_resolved(benchmark)) xmlNewProp(root_node, BAD_CAST "resolved", BAD_CAST "1"); else xmlNewProp(root_node, BAD_CAST "resolved", BAD_CAST "0"); const char *xmllang = xccdf_benchmark_get_lang(benchmark); if (xmllang) xmlNewProp(root_node, BAD_CAST "xml:lang", BAD_CAST xmllang); const char *style = xccdf_benchmark_get_style(benchmark); if (style) xmlNewProp(root_node, BAD_CAST "style", BAD_CAST style); const char *style_href = xccdf_benchmark_get_style_href(benchmark); if (style_href) xmlNewProp(root_node, BAD_CAST "style-href", BAD_CAST style_href); // Export plain-text elements struct xccdf_plain_text_iterator *plain_text_it = xccdf_benchmark_get_plain_texts(benchmark); while (xccdf_plain_text_iterator_has_more(plain_text_it)) { struct xccdf_plain_text *plain_text = xccdf_plain_text_iterator_next(plain_text_it); xccdf_plain_text_to_dom(plain_text, doc, root_node, xccdf_benchmark_get_schema_version(benchmark)); } xccdf_plain_text_iterator_free(plain_text_it); /* Handle children */ if (xccdf_benchmark_get_cpe_list(benchmark)) { // CPE API can only export via xmlTextWriter, we export via DOM // this is used to bridge both methods xmlTextWriterPtr writer = xmlNewTextWriterTree(doc, root_node, 0); cpe_dict_export(xccdf_benchmark_get_cpe_list(benchmark), writer); xmlFreeTextWriter(writer); } if (xccdf_benchmark_get_cpe_lang_model(benchmark)) { // CPE API can only export via xmlTextWriter, we export via DOM // this is used to bridge both methods xmlTextWriterPtr writer = xmlNewTextWriterTree(doc, root_node, 0); cpe_lang_export(xccdf_benchmark_get_cpe_lang_model(benchmark), writer); xmlFreeTextWriter(writer); } struct oscap_string_iterator *platforms = xccdf_benchmark_get_platforms(benchmark); while (oscap_string_iterator_has_more(platforms)) { xmlNode *platform_node = xmlNewTextChild(root_node, ns_xccdf, BAD_CAST "platform", NULL); const char *idref = oscap_string_iterator_next(platforms); if (idref) xmlNewProp(platform_node, BAD_CAST "idref", BAD_CAST idref); } oscap_string_iterator_free(platforms); const char *version = xccdf_benchmark_get_version(benchmark); if (version) xmlNewTextChild(root_node, ns_xccdf, BAD_CAST "version", BAD_CAST version); struct oscap_string_iterator* metadata = xccdf_item_get_metadata(XITEM(benchmark)); while (oscap_string_iterator_has_more(metadata)) { const char* meta = oscap_string_iterator_next(metadata); oscap_xmlstr_to_dom(root_node, "metadata", meta); } oscap_string_iterator_free(metadata); OSCAP_FOR(xccdf_model, model, xccdf_benchmark_get_models(benchmark)) { xmlNode *model_node = xmlNewTextChild(root_node, ns_xccdf, BAD_CAST "model", NULL); xmlNewProp(model_node, BAD_CAST "system", BAD_CAST xccdf_model_get_system(model)); }
bool xccdf_group_add_conflicts(struct xccdf_group* group, const char* conflicts) { oscap_stringlist_add_string((struct oscap_stringlist*)(XITEM(group)->sub.group.conflicts), conflicts); return true; }
xmlNodePtr xccdf_tailoring_to_dom(struct xccdf_tailoring *tailoring, xmlDocPtr doc, xmlNodePtr parent, const struct xccdf_version_info *version_info) { xmlNs *ns_xccdf = xmlSearchNsByHref(doc, parent, BAD_CAST xccdf_version_info_get_namespace_uri(version_info)); xmlNs *ns_tailoring = NULL; xmlNode *tailoring_node = xmlNewNode(ns_xccdf, BAD_CAST "Tailoring"); const char *xccdf_version = xccdf_version_info_get_version(version_info); #ifdef __USE_GNU if (strverscmp(xccdf_version, "1.1") >= 0 && strverscmp(xccdf_version, "1.2") < 0) { #else if (strcmp(xccdf_version, "1.1") >= 0 && strcmp(xccdf_version, "1.2") < 0) { #endif // XCCDF 1.1 does not support Tailoring! // However we will allow Tailoring export if it is done to an external // file. The namespace will be our custom xccdf-1.1-tailoring extension // namespace. if (parent != NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "XCCDF 1.1 does not support embedded Tailoring elements!"); xmlFreeNode(tailoring_node); return NULL; } ns_tailoring = xmlNewNs(tailoring_node, BAD_CAST "http://open-scap.org/page/Xccdf-1.1-tailoring", BAD_CAST "cdf-11-tailoring" ); } #ifdef __USE_GNU else if (strverscmp(xccdf_version, "1.1") < 0) { #else else if (strcmp(xccdf_version, "1.1") < 0) { #endif oscap_seterr(OSCAP_EFAMILY_XML, "XCCDF Tailoring isn't supported in XCCDF version '%s'," "nor does openscap have a custom extension for this scenario. " "XCCDF Tailoring requires XCCDF 1.1 and higher, 1.2 is recommended."); xmlFreeNode(tailoring_node); return NULL; } if (!ns_xccdf) { // In cases where tailoring ends up being the root node we have to create // a namespace at the node itself. ns_xccdf = xmlNewNs(tailoring_node, BAD_CAST xccdf_version_info_get_namespace_uri(version_info), BAD_CAST "xccdf"); } if (!ns_tailoring) ns_tailoring = ns_xccdf; // We intentionally set the wrong namespace here since children of tailoring // will reuse it and we want them to have the xccdf namespace, the namespace // is set to the proper namespace before returning the tailoring. xmlSetNs(tailoring_node, ns_xccdf); if (parent) xmlAddChild(parent, tailoring_node); else xmlDocSetRootElement(doc, tailoring_node); if (tailoring->id) { xmlNewProp(tailoring_node, BAD_CAST "id", BAD_CAST tailoring->id); } if (tailoring->benchmark_ref || tailoring->benchmark_ref_version) { xmlNodePtr benchmark_ref_node = xmlNewChild(tailoring_node, ns_tailoring, BAD_CAST "benchmark", NULL); if (tailoring->benchmark_ref) xmlNewProp(benchmark_ref_node, BAD_CAST "href", BAD_CAST tailoring->benchmark_ref); if (tailoring->benchmark_ref_version) xmlNewProp(benchmark_ref_node, BAD_CAST "version", BAD_CAST tailoring->benchmark_ref_version); } struct xccdf_status_iterator *statuses = xccdf_tailoring_get_statuses(tailoring); while (xccdf_status_iterator_has_more(statuses)) { struct xccdf_status *status = xccdf_status_iterator_next(statuses); xccdf_status_to_dom(status, doc, tailoring_node, version_info); } xccdf_status_iterator_free(statuses); struct oscap_reference_iterator *dc_statuses = xccdf_tailoring_get_dc_statuses(tailoring); while (oscap_reference_iterator_has_more(dc_statuses)) { struct oscap_reference *ref = oscap_reference_iterator_next(dc_statuses); oscap_reference_to_dom(ref, tailoring_node, doc, "dc-status"); } oscap_reference_iterator_free(dc_statuses); /* version and attributes */ const char *version = xccdf_tailoring_get_version(tailoring); if (version) { xmlNode* version_node = xmlNewTextChild(tailoring_node, ns_tailoring, BAD_CAST "version", BAD_CAST version); const char *version_update = xccdf_tailoring_get_version_update(tailoring); if (version_update) xmlNewProp(version_node, BAD_CAST "update", BAD_CAST version_update); const char *version_time = xccdf_tailoring_get_version_time(tailoring); if (version_time) xmlNewProp(version_node, BAD_CAST "time", BAD_CAST version_time); } struct oscap_string_iterator* metadata = xccdf_tailoring_get_metadata(tailoring); while (oscap_string_iterator_has_more(metadata)) { const char* meta = oscap_string_iterator_next(metadata); oscap_xmlstr_to_dom(tailoring_node, "metadata", meta); } oscap_string_iterator_free(metadata); struct xccdf_profile_iterator *profiles = xccdf_tailoring_get_profiles(tailoring); while (xccdf_profile_iterator_has_more(profiles)) { struct xccdf_profile *profile = xccdf_profile_iterator_next(profiles); xccdf_item_to_dom(XITEM(profile), doc, tailoring_node); } xccdf_profile_iterator_free(profiles); xmlSetNs(tailoring_node, ns_tailoring); return tailoring_node; } int xccdf_tailoring_export(struct xccdf_tailoring *tailoring, const char *file, const struct xccdf_version_info *version_info) { __attribute__nonnull__(file); LIBXML_TEST_VERSION; xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); if (doc == NULL) { oscap_setxmlerr(xmlGetLastError()); return -1; } xccdf_tailoring_to_dom(tailoring, doc, NULL, version_info); return oscap_xml_save_filename(file, doc); } const char *xccdf_tailoring_get_id(const struct xccdf_tailoring *tailoring) { return tailoring->id; } const char *xccdf_tailoring_get_version(const struct xccdf_tailoring *tailoring) { return tailoring->version; } const char *xccdf_tailoring_get_version_update(const struct xccdf_tailoring *tailoring) { return tailoring->version_update; } const char *xccdf_tailoring_get_version_time(const struct xccdf_tailoring *tailoring) { return tailoring->version_time; } const char *xccdf_tailoring_get_benchmark_ref(const struct xccdf_tailoring *tailoring) { return tailoring->benchmark_ref; } const char *xccdf_tailoring_get_benchmark_ref_version(const struct xccdf_tailoring *tailoring) { return tailoring->benchmark_ref_version; } bool xccdf_tailoring_set_id(struct xccdf_tailoring *tailoring, const char* newval) { if (tailoring->id) oscap_free(tailoring->id); tailoring->id = oscap_strdup(newval); return true; } bool xccdf_tailoring_set_version(struct xccdf_tailoring *tailoring, const char *newval) { if (tailoring->version) oscap_free(tailoring->version); tailoring->version = oscap_strdup(newval); return true; } bool xccdf_tailoring_set_version_update(struct xccdf_tailoring *tailoring, const char *newval) { if (tailoring->version_update) oscap_free(tailoring->version_update); tailoring->version_update = oscap_strdup(newval); return true; } bool xccdf_tailoring_set_version_time(struct xccdf_tailoring *tailoring, const char *newval) { if (tailoring->version_time) oscap_free(tailoring->version_time); tailoring->version_time = oscap_strdup(newval); return true; } bool xccdf_tailoring_set_benchmark_ref(struct xccdf_tailoring *tailoring, const char *newval) { if (tailoring->benchmark_ref) oscap_free(tailoring->benchmark_ref); tailoring->benchmark_ref = oscap_strdup(newval); return true; } bool xccdf_tailoring_set_benchmark_ref_version(struct xccdf_tailoring *tailoring, const char *newval) { if (tailoring->benchmark_ref_version) oscap_free(tailoring->benchmark_ref_version); tailoring->benchmark_ref_version = oscap_strdup(newval); return true; } struct oscap_string_iterator *xccdf_tailoring_get_metadata(const struct xccdf_tailoring *tailoring) { return (struct oscap_string_iterator*) oscap_iterator_new(tailoring->metadata); } struct xccdf_profile_iterator *xccdf_tailoring_get_profiles(const struct xccdf_tailoring *tailoring) { return (struct xccdf_profile_iterator*) oscap_iterator_new(tailoring->profiles); } struct xccdf_status_iterator *xccdf_tailoring_get_statuses(const struct xccdf_tailoring *tailoring) { return (struct xccdf_status_iterator*) oscap_iterator_new(tailoring->statuses); } struct oscap_reference_iterator *xccdf_tailoring_get_dc_statuses(const struct xccdf_tailoring *tailoring) { return (struct oscap_reference_iterator*) oscap_iterator_new(tailoring->dc_statuses); } struct xccdf_profile * xccdf_tailoring_get_profile_by_id(const struct xccdf_tailoring *tailoring, const char *profile_id) { struct xccdf_profile_iterator *profit = xccdf_tailoring_get_profiles(tailoring); while (xccdf_profile_iterator_has_more(profit)) { struct xccdf_profile *profile = xccdf_profile_iterator_next(profit); if (profile == NULL) { assert(profile != NULL); continue; } if (oscap_streq(xccdf_profile_get_id(profile), profile_id)) { xccdf_profile_iterator_free(profit); return profile; } } xccdf_profile_iterator_free(profit); return NULL; }
static void xccdf_resolve_item(struct xccdf_item *item, struct xccdf_tailoring *tailoring) { assert(item != NULL); if (xccdf_item_get_type(item) == XCCDF_BENCHMARK) { xccdf_benchmark_set_resolved(xccdf_item_to_benchmark(item), true); return; // benchmark has no extends } assert(!xccdf_item_get_extends(item) || xccdf_item_get_type(item) & (XCCDF_PROFILE | XCCDF_ITEM)); struct xccdf_item *parent = NULL; if (xccdf_item_get_type(item) == XCCDF_PROFILE && tailoring != NULL) { parent = XITEM(_xccdf_tailoring_profile_get_real_parent(tailoring, XPROFILE(item))); } else { parent = xccdf_benchmark_get_member(xccdf_item_get_benchmark(item), xccdf_item_get_type(item), xccdf_item_get_extends(item)); } if (parent == NULL) return; if (xccdf_item_get_type(item) != xccdf_item_get_type(parent)) return; if (xccdf_item_get_type(item) == XCCDF_GROUP && xccdf_version_cmp(xccdf_item_get_schema_version(item), "1.2") >= 0) return; // Group/@extends= has been obsoleted in XCCDF 1.2 // resolve flags XCCDF_RESOLVE_FLAG(item, parent, selected); XCCDF_RESOLVE_FLAG(item, parent, hidden); XCCDF_RESOLVE_FLAG(item, parent, prohibit_changes); XCCDF_RESOLVE_FLAG(item, parent, interactive); XCCDF_RESOLVE_FLAG(item, parent, multiple); // resolve weight & version if (!item->item.defined_flags.weight) xccdf_item_set_weight(item, xccdf_item_get_weight(parent)); if (xccdf_item_get_version(item) == NULL) { xccdf_item_set_version(item, xccdf_item_get_version(parent)); xccdf_item_set_version_update(item, xccdf_item_get_version_update(parent)); xccdf_item_set_version_time(item, xccdf_item_get_version_time(parent)); } // resolve textual elements xccdf_resolve_textlist(item->item.title, parent->item.title, NULL); xccdf_resolve_textlist(item->item.description, parent->item.description, NULL); xccdf_resolve_textlist(item->item.question, parent->item.question, NULL); xccdf_resolve_textlist(item->item.rationale, parent->item.rationale, NULL); xccdf_resolve_textlist(item->item.warnings, parent->item.warnings, xccdf_resolve_warning); xccdf_resolve_textlist(item->item.references, parent->item.references, NULL); // resolve platforms OSCAP_FOR_STR(platform, xccdf_item_get_platforms(parent)) xccdf_item_add_platform(item, platform); // resolve properties specific to particular item type switch (xccdf_item_get_type(item)) { case XCCDF_PROFILE: xccdf_resolve_profile(item, parent); break; case XCCDF_GROUP: xccdf_resolve_group(item, parent); break; case XCCDF_RULE: xccdf_resolve_rule(item, parent); break; case XCCDF_VALUE: xccdf_resolve_value(item, parent); break; default: assert(false); } // item resolved -> it no longer has a parent xccdf_item_set_extends(item, NULL); }
bool xccdf_tailoring_add_profile(struct xccdf_tailoring *tailoring, struct xccdf_profile *profile) { xccdf_profile_set_tailoring(profile, true); return oscap_list_add(tailoring->profiles, XITEM(profile)); }
void xccdf_rule_to_dom(struct xccdf_rule *rule, xmlNode *rule_node, xmlDoc *doc, xmlNode *parent) { const struct xccdf_version_info* version_info = xccdf_item_get_schema_version(XITEM(rule)); xmlNs *ns_xccdf = lookup_xccdf_ns(doc, parent, version_info); /* Handle Attributes */ const char *extends = xccdf_rule_get_extends(rule); if (extends) xmlNewProp(rule_node, BAD_CAST "extends", BAD_CAST extends); if (xccdf_rule_get_multiple(rule)) xmlNewProp(rule_node, BAD_CAST "multiple", BAD_CAST "true"); if (xccdf_rule_get_selected(rule)) xmlNewProp(rule_node, BAD_CAST "selected", BAD_CAST "true"); else xmlNewProp(rule_node, BAD_CAST "selected", BAD_CAST "false"); if (XITEM(rule)->item.defined_flags.weight) { char *weight_str = oscap_sprintf("%f", xccdf_rule_get_weight(rule)); xmlNewProp(rule_node, BAD_CAST "weight", BAD_CAST weight_str); free(weight_str); } xccdf_role_t role = xccdf_rule_get_role(rule); if (role != 0) xmlNewProp(rule_node, BAD_CAST "role", BAD_CAST XCCDF_ROLE_MAP[role - 1].string); xccdf_level_t severity = xccdf_rule_get_severity(rule); if (severity != XCCDF_LEVEL_NOT_DEFINED) xmlNewProp(rule_node, BAD_CAST "severity", BAD_CAST XCCDF_LEVEL_MAP[severity - 1].string); /* Handle Child Nodes */ xccdf_texts_to_dom(xccdf_rule_get_rationale(rule), rule_node, "rationale"); struct oscap_string_iterator *platforms = xccdf_rule_get_platforms(rule); while (oscap_string_iterator_has_more(platforms)) { const char *platform = oscap_string_iterator_next(platforms); xmlNode * child = xmlNewTextChild(rule_node, ns_xccdf, BAD_CAST "platform", BAD_CAST NULL); xmlNewProp(child, BAD_CAST "idref", BAD_CAST platform); } oscap_string_iterator_free(platforms); struct oscap_stringlist_iterator *lists = xccdf_rule_get_requires(rule); while (oscap_stringlist_iterator_has_more(lists)) { struct oscap_stringlist *list = oscap_stringlist_iterator_next(lists); struct oscap_string_iterator *strings = oscap_stringlist_get_strings(list); while (oscap_string_iterator_has_more(strings)) { const char *requires = oscap_string_iterator_next(strings); xmlNode * child = xmlNewTextChild(rule_node, ns_xccdf, BAD_CAST "requires", BAD_CAST NULL); xmlNewProp(child, BAD_CAST "idref", BAD_CAST requires); } oscap_string_iterator_free(strings); } oscap_stringlist_iterator_free(lists); struct oscap_string_iterator *conflicts = xccdf_rule_get_conflicts(rule); while (oscap_string_iterator_has_more(conflicts)) { const char *conflict = oscap_string_iterator_next(conflicts); xmlNode * child = xmlNewTextChild(rule_node, ns_xccdf, BAD_CAST "conflicts", BAD_CAST NULL); xmlNewProp(child, BAD_CAST "idref", BAD_CAST conflict); } oscap_string_iterator_free(conflicts); struct xccdf_ident_iterator *idents = xccdf_rule_get_idents(rule); while (xccdf_ident_iterator_has_more(idents)) { struct xccdf_ident *ident = xccdf_ident_iterator_next(idents); xccdf_ident_to_dom(ident, doc, rule_node, version_info); } xccdf_ident_iterator_free(idents); struct xccdf_profile_note_iterator *notes = xccdf_rule_get_profile_notes(rule); while (xccdf_profile_note_iterator_has_more(notes)) { struct xccdf_profile_note *note = xccdf_profile_note_iterator_next(notes); xccdf_profile_note_to_dom(note, doc, rule_node); } xccdf_profile_note_iterator_free(notes); struct xccdf_fixtext_iterator *fixtexts = xccdf_rule_get_fixtexts(rule); while (xccdf_fixtext_iterator_has_more(fixtexts)) { struct xccdf_fixtext *fixtext = xccdf_fixtext_iterator_next(fixtexts); xccdf_fixtext_to_dom(fixtext, doc, rule_node); } xccdf_fixtext_iterator_free(fixtexts); struct xccdf_fix_iterator *fixes = xccdf_rule_get_fixes(rule); while (xccdf_fix_iterator_has_more(fixes)) { struct xccdf_fix *fix = xccdf_fix_iterator_next(fixes); xccdf_fix_to_dom(fix, doc, rule_node, version_info); } xccdf_fix_iterator_free(fixes); struct xccdf_check_iterator *checks = xccdf_rule_get_checks(rule); while (xccdf_check_iterator_has_more(checks)) { struct xccdf_check *check = xccdf_check_iterator_next(checks); xccdf_check_to_dom(check, doc, rule_node, version_info); } xccdf_check_iterator_free(checks); }
void xccdf_group_to_dom(struct xccdf_group *group, xmlNode *group_node, xmlDoc *doc, xmlNode *parent) { const struct xccdf_version_info* version_info = xccdf_item_get_schema_version(XITEM(group)); xmlNs *ns_xccdf = lookup_xccdf_ns(doc, parent, version_info); /* Handle Attributes */ const char *extends = xccdf_group_get_extends(group); if (extends) xmlNewProp(group_node, BAD_CAST "extends", BAD_CAST extends); if (XITEM(group)->item.defined_flags.selected) { if (xccdf_group_get_selected(group)) xmlNewProp(group_node, BAD_CAST "selected", BAD_CAST "true"); else xmlNewProp(group_node, BAD_CAST "selected", BAD_CAST "false"); } if (XITEM(group)->item.defined_flags.weight) { float weight = xccdf_group_get_weight(group); char *weight_str = oscap_sprintf("%f", weight); xmlNewProp(group_node, BAD_CAST "weight", BAD_CAST weight_str); free(weight_str); } /* Handle Child Nodes */ xccdf_texts_to_dom(xccdf_group_get_rationale(group), group_node, "rationale"); struct oscap_string_iterator *platforms = xccdf_group_get_platforms(group); while (oscap_string_iterator_has_more(platforms)) { const char *platform = oscap_string_iterator_next(platforms); xmlNode * child = xmlNewTextChild(group_node, ns_xccdf, BAD_CAST "platform", BAD_CAST NULL); xmlNewProp(child, BAD_CAST "idref", BAD_CAST platform); } oscap_string_iterator_free(platforms); struct oscap_stringlist_iterator *lists = xccdf_group_get_requires(group); while (oscap_stringlist_iterator_has_more(lists)) { struct oscap_stringlist *list = oscap_stringlist_iterator_next(lists); struct oscap_string_iterator *strings = oscap_stringlist_get_strings(list); while (oscap_string_iterator_has_more(strings)) { const char *requires = oscap_string_iterator_next(strings); xmlNode * child = xmlNewTextChild(group_node, ns_xccdf, BAD_CAST "requires", BAD_CAST NULL); xmlNewProp(child, BAD_CAST "idref", BAD_CAST requires); } oscap_string_iterator_free(strings); } oscap_stringlist_iterator_free(lists); struct oscap_string_iterator *conflicts = xccdf_group_get_conflicts(group); while (oscap_string_iterator_has_more(conflicts)) { const char *conflict = oscap_string_iterator_next(conflicts); xmlNode * child = xmlNewTextChild(group_node, ns_xccdf, BAD_CAST "conflicts", BAD_CAST NULL); xmlNewProp(child, BAD_CAST "idref", BAD_CAST conflict); } oscap_string_iterator_free(conflicts); struct xccdf_value_iterator *values = xccdf_group_get_values(group); while (xccdf_value_iterator_has_more(values)) { struct xccdf_value *value = xccdf_value_iterator_next(values); if (XGROUP(xccdf_value_get_parent(value)) == group) { xccdf_item_to_dom((struct xccdf_item *)value, doc, group_node, version_info); } } xccdf_value_iterator_free(values); struct xccdf_item_iterator *items = xccdf_group_get_content(group); while (xccdf_item_iterator_has_more(items)) { struct xccdf_item *item = xccdf_item_iterator_next(items); if (XGROUP(xccdf_item_get_parent(item)) == group) { xccdf_item_to_dom(item, doc, group_node, version_info); } } xccdf_item_iterator_free(items); }