int ds_sds_session_register_component_with_dependencies(struct ds_sds_session *session, const char *container_name, const char *component_id, const char *target_filename) { xmlNode *datastream = ds_sds_session_get_selected_datastream(session); if (!datastream) { return -1; } xmlNodePtr container = node_get_child_element(datastream, container_name); if (!container) { if (ds_sds_session_get_datastream_id(session) == NULL) oscap_seterr(OSCAP_EFAMILY_XML, "No '%s' container element found in file '%s' in the first datastream.", container_name, oscap_source_readable_origin(session->source)); else oscap_seterr(OSCAP_EFAMILY_XML, "No '%s' container element found in file '%s' in datastream of id '%s'.", container_name, oscap_source_readable_origin(session->source), ds_sds_session_get_datastream_id(session)); return -1; } int res = -1; xmlNode *component_ref = containter_get_component_ref_by_id(container, component_id); if (component_ref != NULL) { if (target_filename == NULL) { res = ds_sds_dump_component_ref(component_ref, session); } else { res = ds_sds_dump_component_ref_as(component_ref, session, "." , target_filename); } } else { oscap_seterr(OSCAP_EFAMILY_XML, "No '%s' component ref found in file '%s' in datastream of id '%s'.", component_id, oscap_source_readable_origin(session->source), ds_sds_session_get_datastream_id(session)); return -1; } return res; }
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; }
const char *ds_sds_session_get_readable_origin(const struct ds_sds_session *session) { if (session->source == NULL) return NULL; return oscap_source_readable_origin(session->source); }
int ds_rds_session_register_component_source(struct ds_rds_session *session, const char *content_id, struct oscap_source *component) { if (!oscap_htable_add(session->component_sources, content_id, component)) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Content '%s' has already been register with Result DataStream session: %s", content_id, oscap_source_readable_origin(session->source)); return -1; } return 0; }
int ds_sds_session_register_component_source(struct ds_sds_session *session, const char *relative_filepath, struct oscap_source *component) { if (!oscap_htable_add(session->component_sources, relative_filepath, component)) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "File %s has already been register with Source DataStream session: %s", relative_filepath, oscap_source_readable_origin(session->source)); return -1; } return 0; }
int ds_dump_component_sources(struct oscap_htable *component_sources, const char *target_dir) { struct oscap_htable_iterator *hit = oscap_htable_iterator_new(component_sources); while (oscap_htable_iterator_has_more(hit)) { struct oscap_source *s = oscap_htable_iterator_next_value(hit); char *filename = target_dir == NULL ? oscap_strdup(oscap_source_readable_origin(s)) : oscap_sprintf("%s/%s", target_dir, oscap_source_readable_origin(s)); int ret = oscap_acquire_ensure_parent_dir(filename); if (ret != 0) { oscap_htable_iterator_free(hit); return ret; } ret = oscap_source_save_as(s, filename); free(filename); if (ret != 0) { oscap_htable_iterator_free(hit); return ret; } } oscap_htable_iterator_free(hit); return 0; }
struct cpe_lang_model *cpe_lang_model_import_source(struct oscap_source *source) { xmlTextReaderPtr reader = oscap_source_get_xmlTextReader(source); struct cpe_lang_model *ret = NULL; if (reader != NULL) { xmlTextReaderNextNode(reader); ret = cpe_lang_model_parse(reader); if (ret != NULL) { cpe_lang_model_set_origin_file(ret, oscap_source_readable_origin(source)); } } xmlFreeTextReader(reader); return ret; }
int oscap_source_validate_priv(struct oscap_source *source, oscap_document_type_t doc_type, const char *version, xml_reporter reporter, void *user) { if (version == NULL) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not determine version for file: %s", oscap_source_readable_origin(source)); return -1; } /* find a right schema file */ for (struct oscap_schema_table_entry *entry = OSCAP_SCHEMAS_TABLE; entry->doc_type != 0; ++entry) { if (entry->doc_type != doc_type || strcmp(entry->schema_version, version)) continue; return oscap_validate_xml(source, entry->schema_path, reporter, user); } oscap_seterr(OSCAP_EFAMILY_OSCAP, "Schema file not found when trying to validate '%s'", oscap_source_readable_origin(source)); return -1; }
static inline int oscap_validate_xml(struct oscap_source *source, const char *schemafile, xml_reporter reporter, void *arg) { int result = -1; xmlSchemaParserCtxtPtr parser_ctxt = NULL; xmlSchemaPtr schema = NULL; xmlSchemaValidCtxtPtr ctxt = NULL; xmlDocPtr doc = NULL; struct ctxt context = { reporter, arg, (void*) oscap_source_readable_origin(source)}; if (schemafile == NULL) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "'schemafile' == NULL"); return -1; } char * schemapath = oscap_sprintf("%s%s%s", oscap_path_to_schemas(), "/", schemafile); if (access(schemapath, R_OK)) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Schema file '%s' not found in path '%s' when trying to validate '%s'", schemafile, oscap_path_to_schemas(), oscap_source_readable_origin(source)); goto cleanup; } parser_ctxt = xmlSchemaNewParserCtxt(schemapath); if (parser_ctxt == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Could not create parser context for validation"); goto cleanup; } xmlSchemaSetParserStructuredErrors(parser_ctxt, oscap_xml_validity_handler, &context); schema = xmlSchemaParse(parser_ctxt); if (schema == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Could not parse XML schema"); goto cleanup; } ctxt = xmlSchemaNewValidCtxt(schema); if (ctxt == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Could not create validation context"); goto cleanup; } xmlSchemaSetValidStructuredErrors(ctxt, oscap_xml_validity_handler, &context); doc = oscap_source_get_xmlDoc(source); if (!doc) goto cleanup; result = xmlSchemaValidateDoc(ctxt, doc); /* * xmlSchemaValidateFile() returns "-1" if document is not well formed * thefore we ignore libxml internal errors here and map return code to * either pass or fail. */ if (result != 0) result = 1; /* This would be nicer * if (result == -1) * oscap_setxmlerr(xmlGetLastError()); */ cleanup: if (ctxt) xmlSchemaFreeValidCtxt(ctxt); if (schema) xmlSchemaFree(schema); if (parser_ctxt) xmlSchemaFreeParserCtxt(parser_ctxt); oscap_free(schemapath); return result; }
static int ds_sds_compose_add_component_dependencies(xmlDocPtr doc, xmlNodePtr datastream, struct oscap_source *component_source, xmlNodePtr catalog, int component_type) { xmlDocPtr component_doc = oscap_source_get_xmlDoc(component_source); if (component_doc == NULL) { return -1; } xmlXPathContextPtr xpathCtx = xmlXPathNewContext(component_doc); if (xpathCtx == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Error: unable to create new XPath context."); return -1; } xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( // we want robustness and support for future versions, this expression // retrieves check-content-refs from any namespace BAD_CAST _get_dep_xpath_for_type(component_type), xpathCtx); if (xpathObj == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Error: Unable to evalute XPath expression."); xmlXPathFreeContext(xpathCtx); return -1; } xmlNsPtr cat_ns = xmlSearchNsByHref(doc, datastream, BAD_CAST cat_ns_uri); xmlNodeSetPtr nodeset = xpathObj->nodesetval; if (nodeset != NULL) { struct oscap_htable *exported = oscap_htable_new(); char* filepath_cpy = oscap_strdup(oscap_source_readable_origin(component_source)); const char* dir = dirname(filepath_cpy); for (int i = 0; i < nodeset->nodeNr; i++) { xmlNodePtr node = nodeset->nodeTab[i]; if (node->type != XML_ELEMENT_NODE) continue; if (xmlHasProp(node, BAD_CAST "href")) { char* href = (char*)xmlGetProp(node, BAD_CAST "href"); if (oscap_htable_get(exported, href) != NULL) { // This path has been already exported. Do not export duplicate. xmlFree(href); continue; } oscap_htable_add(exported, href, ""); if (oscap_acquire_url_is_supported(href)) { /* If the referenced component is remote one, do not include * it within the DataStream. Such component shall only be * downloaded once the scan is run. */ xmlFree(href); continue; } char* real_path = (strcmp(dir, "") == 0 || strcmp(dir, ".") == 0) ? oscap_strdup(href) : oscap_sprintf("%s/%s", dir, href); char* mangled_path = ds_sds_mangle_filepath(real_path); char* cref_id = oscap_sprintf("scap_org.open-scap_cref_%s", mangled_path); int counter = 0; while (ds_sds_find_component_ref(datastream, cref_id) != NULL) { // While the given component ID already exists in the document. oscap_free(cref_id); cref_id = oscap_sprintf("scap_org.open-scap_cref_%s%03d", mangled_path, counter++); } oscap_free(mangled_path); char* uri = oscap_sprintf("#%s", cref_id); // we don't want duplicated uri elements in the catalog if (ds_sds_compose_catalog_has_uri(doc, catalog, uri) == 0) { oscap_free(uri); oscap_free(cref_id); oscap_free(real_path); xmlFree(href); continue; } int ret = ds_sds_compose_add_component_with_ref(doc, datastream, real_path, cref_id); if (ret == 0) { xmlNodePtr catalog_uri = xmlNewNode(cat_ns, BAD_CAST "uri"); xmlSetProp(catalog_uri, BAD_CAST "name", BAD_CAST href); xmlSetProp(catalog_uri, BAD_CAST "uri", BAD_CAST uri); xmlAddChild(catalog, catalog_uri); } oscap_free(cref_id); oscap_free(uri); oscap_free(real_path); xmlFree(href); if (ret < 0) { // oscap_seterr has already been called oscap_htable_free0(exported); return -1; } } } oscap_htable_free0(exported); oscap_free(filepath_cpy); } xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); return 0; }