struct cvss_metrics *cvss_metrics_new_from_xml(xmlTextReaderPtr reader) { assert(reader != NULL); int depth = oscap_element_depth(reader); enum cvss_category cat = CVSS_NONE; const char *elname = (const char *) xmlTextReaderConstLocalName(reader); if (oscap_streq(elname, "base_metrics")) cat = CVSS_BASE; if (oscap_streq(elname, "temporal_metrics")) cat = CVSS_TEMPORAL; if (oscap_streq(elname, "environmental_metrics")) cat = CVSS_ENVIRONMENTAL; if (cat == CVSS_NONE) return NULL; struct cvss_metrics *ret = cvss_metrics_new(cat); ret->upgraded_from_version = (char*) xmlTextReaderGetAttribute(reader, BAD_CAST "upgraded-from-version"); xmlTextReaderRead(reader); while (oscap_to_start_element(reader, depth + 1)) { elname = (const char *) xmlTextReaderConstLocalName(reader); if (oscap_streq(elname, "score")) ret->score = atof(oscap_element_string_get(reader)); else if (oscap_streq(elname, "source")) cvss_metrics_set_source(ret, oscap_element_string_get(reader)); else if (oscap_streq(elname, "generated-on-datetime")) cvss_metrics_set_generated_on_datetime(ret, oscap_element_string_get(reader)); else { const struct cvss_valtab_entry *val = cvss_valtab(cvss_keytab(0, elname)->key, 0, NULL, oscap_element_string_get(reader)); if (CVSS_CATEGORY(val->key) == cat) ret->metrics.ANY[CVSS_KEY_IDX(val->key)] = val->value; } xmlTextReaderRead(reader); } return ret; }
struct oscap_reference *oscap_reference_new_parse(xmlTextReaderPtr reader) { assert(reader != NULL); struct oscap_reference *ref = oscap_calloc(1, sizeof(struct oscap_reference)); int depth = oscap_element_depth(reader); xmlNode* ref_node = xmlTextReaderExpand(reader); ref->href = (char*) xmlGetProp(ref_node, BAD_CAST "href"); for (xmlNode* cur = ref_node->children; cur != NULL; cur = cur->next) if (cur->type == XML_ELEMENT_NODE) { ref->is_dublincore = true; break; } if (ref->is_dublincore) { for (xmlNode* cur = ref_node->children; cur != NULL; cur = cur->next) { if (cur->type != XML_ELEMENT_NODE || cur->ns == NULL || !oscap_streq((const char* ) cur->ns->href, (const char *) NS_DUBLINCORE)) continue; DC_DOM_SCAN(title); DC_DOM_SCAN(creator); DC_DOM_SCAN(subject); DC_DOM_SCAN(description); DC_DOM_SCAN(publisher); DC_DOM_SCAN(contributor); DC_DOM_SCAN(date); DC_DOM_SCAN(type); DC_DOM_SCAN(format); DC_DOM_SCAN(identifier); DC_DOM_SCAN(source); DC_DOM_SCAN(language); DC_DOM_SCAN(relation); DC_DOM_SCAN(coverage); DC_DOM_SCAN(rights); } } else { ref->title = (char*) xmlNodeGetContent(ref_node); } if (!oscap_to_start_element(reader, depth)) dW("oscap_to_start_element returned `false'"); return ref; }
struct cvss_impact *cvss_impact_new_from_xml(xmlTextReaderPtr reader) { assert(reader != NULL); int depth = oscap_element_depth(reader); struct cvss_impact *ret = cvss_impact_new(); xmlTextReaderRead(reader); // move to next element while (oscap_to_start_element(reader, depth + 1)) { struct cvss_metrics *mtx = cvss_metrics_new_from_xml(reader); if (mtx) cvss_impact_set_metrics(ret, mtx); // else issue a warning? xmlTextReaderRead(reader); } return ret; }
struct xccdf_item *xccdf_group_parse(xmlTextReaderPtr reader, struct xccdf_item *parent) { XCCDF_ASSERT_ELEMENT(reader, XCCDFE_GROUP); struct xccdf_item *group = xccdf_group_new_internal(parent); if (!xccdf_item_process_attributes(group, reader)) { xccdf_group_free(group); return NULL; } int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { switch (xccdf_element_get(reader)) { case XCCDFE_REQUIRES: case XCCDFE_CONFLICTS: xccdf_item_parse_deps(reader, group); break; case XCCDFE_GROUP: case XCCDFE_RULE: xccdf_content_parse(reader, group); break; case XCCDFE_VALUE: oscap_list_add(group->sub.group.values, xccdf_value_parse(reader, group)); break; default: if (!xccdf_item_process_element(group, reader)) dW("Encountered an unknown element '%s' while parsing XCCDF group.", xmlTextReaderConstLocalName(reader)); } xmlTextReaderRead(reader); } return group; }
struct xccdf_check *xccdf_check_parse(xmlTextReaderPtr reader) { xccdf_element_t el = xccdf_element_get(reader); if (el != XCCDFE_CHECK && el != XCCDFE_COMPLEX_CHECK) return NULL; struct xccdf_check *check = xccdf_check_new(); check->id = xccdf_attribute_copy(reader, XCCDFA_ID); check->system = xccdf_attribute_copy(reader, XCCDFA_SYSTEM); check->selector = xccdf_attribute_copy(reader, XCCDFA_SELECTOR); check->oper = oscap_string_to_enum(XCCDF_BOOLOP_MAP, xccdf_attribute_get(reader, XCCDFA_OPERATOR)); if (xccdf_attribute_has(reader, XCCDFA_MULTICHECK) && el != XCCDFE_COMPLEX_CHECK) { check->flags.def_multicheck = true; check->flags.multicheck = xccdf_attribute_get_bool(reader, XCCDFA_MULTICHECK); } check->flags.def_negate = xccdf_attribute_has(reader, XCCDFA_NEGATE); check->flags.negate = xccdf_attribute_get_bool(reader, XCCDFA_NEGATE); int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { switch (xccdf_element_get(reader)) { case XCCDFE_CHECK: case XCCDFE_COMPLEX_CHECK: if (check->oper == 0) break; oscap_list_add(check->children, xccdf_check_parse(reader)); break; case XCCDFE_CHECK_CONTENT_REF:{ const char *href = xccdf_attribute_get(reader, XCCDFA_HREF); if (href == NULL) break; struct xccdf_check_content_ref *ref = xccdf_check_content_ref_new(); ref->name = xccdf_attribute_copy(reader, XCCDFA_NAME); ref->href = strdup(href); oscap_list_add(check->content_refs, ref); break; } case XCCDFE_CHECK_CONTENT: if (check->content == NULL) check->content = oscap_get_xml(reader); break; case XCCDFE_CHECK_IMPORT:{ const char *name = xccdf_attribute_get(reader, XCCDFA_IMPORT_NAME); const char *xpath = xccdf_attribute_get(reader, XCCDFA_IMPORT_XPATH); if (name == NULL) // @import-name is a required attribute break; struct xccdf_check_import *imp = xccdf_check_import_new(); imp->name = strdup(name); if (xpath) // @import-xpath is just optional imp->xpath = strdup(xpath); imp->content = oscap_element_string_copy(reader); oscap_list_add(check->imports, imp); break; } case XCCDFE_CHECK_EXPORT:{ const char *name = xccdf_attribute_get(reader, XCCDFA_EXPORT_NAME); if (name == NULL) break; struct xccdf_check_export *exp = xccdf_check_export_new(); exp->name = strdup(name); exp->value = xccdf_attribute_copy(reader, XCCDFA_VALUE_ID); oscap_list_add(check->exports, exp); break; } default: break; } xmlTextReaderRead(reader); } return check; }
struct xccdf_item *xccdf_rule_parse(xmlTextReaderPtr reader, struct xccdf_item *parent) { XCCDF_ASSERT_ELEMENT(reader, XCCDFE_RULE); struct xccdf_item *rule = xccdf_rule_new_internal(parent); if (!xccdf_item_process_attributes(rule, reader)) { xccdf_rule_free(rule); return NULL; } if (xccdf_attribute_has(reader, XCCDFA_ROLE)) { rule->sub.rule.role = oscap_string_to_enum(XCCDF_ROLE_MAP, xccdf_attribute_get(reader, XCCDFA_ROLE)); rule->item.defined_flags.role = true; } if (xccdf_attribute_has(reader, XCCDFA_SEVERITY)) { rule->sub.rule.severity = oscap_string_to_enum(XCCDF_LEVEL_MAP, xccdf_attribute_get(reader, XCCDFA_SEVERITY)); rule->item.defined_flags.severity = true; } int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { switch (xccdf_element_get(reader)) { case XCCDFE_REQUIRES: case XCCDFE_CONFLICTS: xccdf_item_parse_deps(reader, rule); break; case XCCDFE_PROFILE_NOTE:{ const char *tag = xccdf_attribute_get(reader, XCCDFA_TAG); if (tag == NULL) break; struct xccdf_profile_note *note = xccdf_profile_note_new(); note->reftag = strdup(tag); note->text = oscap_text_new_parse(XCCDF_TEXT_PROFNOTE, reader); oscap_list_add(rule->sub.rule.profile_notes, note); break; } case XCCDFE_COMPLEX_CHECK: case XCCDFE_CHECK:{ struct xccdf_check *check = xccdf_check_parse(reader); if (check == NULL) break; oscap_list_add(rule->sub.rule.checks, check); break; } case XCCDFE_FIX: oscap_list_add(rule->sub.rule.fixes, xccdf_fix_parse(reader)); break; case XCCDFE_FIXTEXT: oscap_list_add(rule->sub.rule.fixtexts, xccdf_fixtext_parse(reader)); break; case XCCDFE_IDENT: oscap_list_add(rule->sub.rule.idents, xccdf_ident_parse(reader)); break; default: if (!xccdf_item_process_element(rule, reader)) dW("Encountered an unknown element '%s' while parsing XCCDF group.", xmlTextReaderConstLocalName(reader)); } xmlTextReaderRead(reader); } return rule; }
struct xccdf_tailoring *xccdf_tailoring_parse(xmlTextReaderPtr reader, struct xccdf_item *benchmark) { XCCDF_ASSERT_ELEMENT(reader, XCCDFE_TAILORING); struct xccdf_tailoring *tailoring = xccdf_tailoring_new(); const char *id = xccdf_attribute_get(reader, XCCDFA_ID); xccdf_tailoring_set_id(tailoring, id); int depth = oscap_element_depth(reader) + 1; // Read to the inside of Tailoring. xmlTextReaderRead(reader); while (oscap_to_start_element(reader, depth)) { switch (xccdf_element_get(reader)) { case XCCDFE_BENCHMARK_REF: { oscap_free(tailoring->benchmark_ref); tailoring->benchmark_ref = 0; oscap_free(tailoring->benchmark_ref_version); tailoring->benchmark_ref_version = 0; const char *ref = xccdf_attribute_get(reader, XCCDFA_HREF); if (ref) tailoring->benchmark_ref = oscap_strdup(ref); const char *ref_version = xccdf_attribute_get(reader, XCCDFA_VERSION); if (ref_version) tailoring->benchmark_ref_version = oscap_strdup(ref_version); break; } case XCCDFE_STATUS: { const char *date = xccdf_attribute_get(reader, XCCDFA_DATE); char *str = oscap_element_string_copy(reader); struct xccdf_status *status = xccdf_status_new_fill(str, date); oscap_free(str); oscap_list_add(tailoring->statuses, status); break; } case XCCDFE_DC_STATUS: oscap_list_add(tailoring->dc_statuses, oscap_reference_new_parse(reader)); break; case XCCDFE_VERSION: { xmlNode *ver = xmlTextReaderExpand(reader); /* optional attributes */ tailoring->version_time = (char*) xmlGetProp(ver, BAD_CAST "time"); tailoring->version_update = (char*) xmlGetProp(ver, BAD_CAST "update"); /* content */ tailoring->version = (char *) xmlNodeGetContent(ver); if (oscap_streq(tailoring->version, "")) { oscap_free(tailoring->version); tailoring->version = NULL; } break; } case XCCDFE_METADATA: { char* xml = oscap_get_xml(reader); oscap_list_add(tailoring->metadata, oscap_strdup(xml)); oscap_free(xml); break; } case XCCDFE_PROFILE: { struct xccdf_item *item = xccdf_profile_parse(reader, benchmark); if (!xccdf_tailoring_add_profile(tailoring, XPROFILE(item))) { dW("Failed to add profile to tailoring while parsing!"); } break; } default: dW("Encountered an unknown element '%s' while parsing XCCDF Tailoring element.", xmlTextReaderConstLocalName(reader)); } xmlTextReaderRead(reader); } return tailoring; }
bool xccdf_benchmark_parse(struct xccdf_item * benchmark, xmlTextReaderPtr reader) { XCCDF_ASSERT_ELEMENT(reader, XCCDFE_BENCHMARK); assert(benchmark != NULL); if (benchmark->type != XCCDF_BENCHMARK) return false; xccdf_benchmark_set_schema_version(XBENCHMARK(benchmark), xccdf_detect_version_parser(reader)); if (!xccdf_item_process_attributes(benchmark, reader)) { xccdf_benchmark_free(XBENCHMARK(benchmark)); return false; } benchmark->sub.benchmark.style = xccdf_attribute_copy(reader, XCCDFA_STYLE); benchmark->sub.benchmark.style_href = xccdf_attribute_copy(reader, XCCDFA_STYLE_HREF); benchmark->sub.benchmark.lang = (char *) xmlTextReaderXmlLang(reader); if (xccdf_attribute_has(reader, XCCDFA_RESOLVED)) benchmark->item.flags.resolved = xccdf_attribute_get_bool(reader, XCCDFA_RESOLVED); int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { struct xccdf_model *parsed_model; switch (xccdf_element_get(reader)) { case XCCDFE_NOTICE: oscap_list_add(benchmark->sub.benchmark.notices, xccdf_notice_new_parse(reader)); break; case XCCDFE_FRONT_MATTER: oscap_list_add(benchmark->sub.benchmark.front_matter, oscap_text_new_parse(XCCDF_TEXT_HTMLSUB, reader)); break; case XCCDFE_REAR_MATTER: oscap_list_add(benchmark->sub.benchmark.rear_matter, oscap_text_new_parse(XCCDF_TEXT_HTMLSUB, reader)); break; case XCCDFE_PLATFORM: oscap_list_add(benchmark->item.platforms, xccdf_attribute_copy(reader, XCCDFA_IDREF)); break; case XCCDFE_MODEL: parsed_model = xccdf_model_new_xml(reader); // we won't add the implied default scoring model, it is already in the benchmark if (strcmp(xccdf_model_get_system(parsed_model), "urn:xccdf:scoring:default") != 0) assume_ex(xccdf_benchmark_add_model(XBENCHMARK(benchmark), parsed_model), false); else xccdf_model_free(parsed_model); break; case XCCDFE_PLAIN_TEXT:{ const char *id = xccdf_attribute_get(reader, XCCDFA_ID); const char *data = oscap_element_string_get(reader); if (id) oscap_list_add(benchmark->sub.benchmark.plain_texts, xccdf_plain_text_new_fill(id, data == NULL ? "" : data)); break; } case XCCDFE_CPE_LIST:{ struct cpe_parser_ctx *ctx = cpe_parser_ctx_from_reader(reader); xccdf_benchmark_set_cpe_list(XBENCHMARK(benchmark), cpe_dict_model_parse(ctx)); cpe_parser_ctx_free(ctx); break; } case XCCDFE_CPE2_PLATFORMSPEC: xccdf_benchmark_set_cpe_lang_model(XBENCHMARK(benchmark), cpe_lang_model_parse(reader)); break; case XCCDFE_PROFILE: oscap_list_add(benchmark->sub.benchmark.profiles, xccdf_profile_parse(reader, benchmark)); break; case XCCDFE_GROUP: case XCCDFE_RULE: xccdf_content_parse(reader, benchmark); break; case XCCDFE_VALUE: oscap_list_add(benchmark->sub.benchmark.values, xccdf_value_parse(reader, benchmark)); break; case XCCDFE_TESTRESULT: assume_ex(xccdf_benchmark_add_result(XBENCHMARK(benchmark), xccdf_result_new_parse(reader)), false); break; default: if (!xccdf_item_process_element(benchmark, reader)) dW("Encountered an unknown element '%s' while parsing XCCDF benchmark.", xmlTextReaderConstLocalName(reader)); } xmlTextReaderRead(reader); } return true; }