Exemple #1
0
xmlDoc *ds_doc_from_foreign_node(xmlNode *node, xmlDoc *parent)
{
	xmlDOMWrapCtxtPtr wrap_ctxt = xmlDOMWrapNewCtxt();
	xmlDocPtr new_doc = xmlNewDoc(BAD_CAST "1.0");
	xmlNodePtr res_node = NULL;
	if (xmlDOMWrapCloneNode(wrap_ctxt, parent, node, &res_node, new_doc, NULL, 1, 0) != 0)
	{
		oscap_seterr(OSCAP_EFAMILY_XML, "Error when cloning node '%s' while dumping component "
				"from DataStream", node->name);
			xmlFreeDoc(new_doc);
			xmlDOMWrapFreeCtxt(wrap_ctxt);
			return NULL;
	}
	xmlDocSetRootElement(new_doc, res_node);
	if (xmlDOMWrapReconcileNamespaces(wrap_ctxt, res_node, 0) != 0)
	{
		oscap_seterr(OSCAP_EFAMILY_XML, "Internal libxml error when reconciling namespaces "
				"for node '%s' while dumping component.", node->name);
		xmlFreeDoc(new_doc);
		xmlDOMWrapFreeCtxt(wrap_ctxt);
		return NULL;
	}
	xmlDOMWrapFreeCtxt(wrap_ctxt);
	return new_doc;
}
Exemple #2
0
xmlNodePtr ds_rds_create_report(xmlDocPtr target_doc, xmlNodePtr reports_node, xmlDocPtr source_doc, const char* report_id)
{
	xmlNsPtr arf_ns = xmlSearchNsByHref(target_doc, xmlDocGetRootElement(target_doc), BAD_CAST arf_ns_uri);

	xmlNodePtr report = xmlNewNode(arf_ns, BAD_CAST "report");
	xmlSetProp(report, BAD_CAST "id", BAD_CAST report_id);

	xmlNodePtr report_content = xmlNewNode(arf_ns, BAD_CAST "content");
	xmlAddChild(report, report_content);

	xmlDOMWrapCtxtPtr wrap_ctxt = xmlDOMWrapNewCtxt();
	xmlNodePtr res_node = NULL;
	xmlDOMWrapCloneNode(wrap_ctxt, source_doc, xmlDocGetRootElement(source_doc),
			&res_node, target_doc, NULL, 1, 0);
	xmlAddChild(report_content, res_node);
	xmlDOMWrapReconcileNamespaces(wrap_ctxt, res_node, 0);
	xmlDOMWrapFreeCtxt(wrap_ctxt);

	xmlAddChild(reports_node, report);

	return report;
}
Exemple #3
0
static int ds_rds_create_from_dom(xmlDocPtr* ret, xmlDocPtr sds_doc, xmlDocPtr xccdf_result_file_doc, struct oscap_htable* oval_result_sources)
{
	*ret = NULL;

	xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
	xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "asset-report-collection");
	xmlDocSetRootElement(doc, root);

	xmlNsPtr arf_ns = xmlNewNs(root, BAD_CAST arf_ns_uri, BAD_CAST "arf");
	xmlSetNs(root, arf_ns);

	xmlNsPtr core_ns = xmlNewNs(root, BAD_CAST core_ns_uri, BAD_CAST "core");
	xmlNewNs(root, BAD_CAST ai_ns_uri, BAD_CAST "ai");

	xmlNodePtr relationships = xmlNewNode(core_ns, BAD_CAST "relationships");
	xmlNewNs(relationships, BAD_CAST arfvocab_ns_uri, BAD_CAST "arfvocab");
	xmlNewNs(relationships, BAD_CAST arfrel_ns_uri, BAD_CAST "arfrel");
	xmlAddChild(root, relationships);

	xmlNodePtr report_requests = xmlNewNode(arf_ns, BAD_CAST "report-requests");
	xmlAddChild(root, report_requests);

	xmlNodePtr assets = xmlNewNode(arf_ns, BAD_CAST "assets");
	xmlAddChild(root, assets);

	xmlNodePtr report_request = xmlNewNode(arf_ns, BAD_CAST "report-request");
	xmlSetProp(report_request, BAD_CAST "id", BAD_CAST "collection1");

	xmlNodePtr arf_content = xmlNewNode(arf_ns, BAD_CAST "content");

	xmlDOMWrapCtxtPtr sds_wrap_ctxt = xmlDOMWrapNewCtxt();
	xmlNodePtr sds_res_node = NULL;
	xmlDOMWrapCloneNode(sds_wrap_ctxt, sds_doc, xmlDocGetRootElement(sds_doc),
			&sds_res_node, doc, NULL, 1, 0);
	xmlAddChild(arf_content, sds_res_node);
	xmlDOMWrapReconcileNamespaces(sds_wrap_ctxt, sds_res_node, 0);
	xmlDOMWrapFreeCtxt(sds_wrap_ctxt);

	xmlAddChild(report_request, arf_content);

	xmlAddChild(report_requests, report_request);

	xmlNodePtr reports = xmlNewNode(arf_ns, BAD_CAST "reports");

	ds_rds_add_xccdf_test_results(doc, reports, xccdf_result_file_doc,
			relationships, assets, "collection1");

	unsigned int oval_report_suffix = 2;
	struct oscap_htable_iterator *hit = oscap_htable_iterator_new(oval_result_sources);
	while (oscap_htable_iterator_has_more(hit)) {
		struct oscap_source *oval_source = oscap_htable_iterator_next_value(hit);
		xmlDoc *oval_result_doc = oscap_source_get_xmlDoc(oval_source);

		char* report_id = oscap_sprintf("oval%i", oval_report_suffix++);
		ds_rds_create_report(doc, reports, oval_result_doc, report_id);
		oscap_free(report_id);
	}
	oscap_htable_iterator_free(hit);

	xmlAddChild(root, reports);

	*ret = doc;
	return 0;
}
Exemple #4
0
static void ds_rds_add_xccdf_test_results(xmlDocPtr doc, xmlNodePtr reports,
		xmlDocPtr xccdf_result_file_doc, xmlNodePtr relationships, xmlNodePtr assets,
		const char* report_request_id)
{
	xmlNodePtr root_element = xmlDocGetRootElement(xccdf_result_file_doc);

	// There are 2 possible scenarios here:

	// 1) root element of given xccdf result file doc is a TestResult element
	// This is the easier scenario, we will just use ds_rds_create_report and
	// be done with it.
	if (strcmp((const char*)root_element->name, "TestResult") == 0)
	{
		xmlNodePtr report = ds_rds_create_report(doc, reports, xccdf_result_file_doc, "xccdf1");
		ds_rds_add_relationship(doc, relationships, "arfvocab:createdFor",
				"xccdf1", report_request_id);

		xmlNodePtr asset = ds_rds_add_ai_from_xccdf_results(doc, assets, xccdf_result_file_doc);
		char* asset_id = (char*)xmlGetProp(asset, BAD_CAST "id");
		ds_rds_add_relationship(doc, relationships, "arfrel:isAbout",
				"xccdf1", asset_id);

		// We deliberately don't act on errors in inject refs as
		// these aren't fatal errors.
		ds_rds_report_inject_refs(doc, report, asset_id);

		xmlFree(asset_id);
	}

	// 2) the root element is a Benchmark, TestResults are embedded within
	// We will have to walk through all elements, wrap each TestResult
	// in a xmlDoc and add them separately
	else if (strcmp((const char*)root_element->name, "Benchmark") == 0)
	{
		unsigned int report_suffix = 1;

		xmlNodePtr candidate_result = root_element->children;

		for (; candidate_result != NULL; candidate_result = candidate_result->next)
		{
			if (candidate_result->type != XML_ELEMENT_NODE)
				continue;

			if (strcmp((const char*)(candidate_result->name), "TestResult") != 0)
				continue;

			xmlDocPtr wrap_doc = xmlNewDoc(BAD_CAST "1.0");

			xmlDOMWrapCtxtPtr wrap_ctxt = xmlDOMWrapNewCtxt();
			xmlNodePtr res_node = NULL;
			xmlDOMWrapCloneNode(wrap_ctxt, xccdf_result_file_doc, candidate_result,
					&res_node, wrap_doc, NULL, 1, 0);
			xmlDocSetRootElement(wrap_doc, res_node);
			xmlDOMWrapReconcileNamespaces(wrap_ctxt, res_node, 0);
			xmlDOMWrapFreeCtxt(wrap_ctxt);

			char* report_id = oscap_sprintf("xccdf%i", report_suffix++);
			xmlNodePtr report = ds_rds_create_report(doc, reports, wrap_doc, report_id);
			ds_rds_add_relationship(doc, relationships, "arfvocab:createdFor",
					report_id, report_request_id);

			xmlNodePtr asset = ds_rds_add_ai_from_xccdf_results(doc, assets, wrap_doc);
			char* asset_id = (char*)xmlGetProp(asset, BAD_CAST "id");
			ds_rds_add_relationship(doc, relationships, "arfrel:isAbout",
					report_id, asset_id);

			// We deliberately don't act on errors in inject ref as
			// these aren't fatal errors.
			ds_rds_report_inject_refs(doc, report, asset_id);

			xmlFree(asset_id);

			oscap_free(report_id);

			xmlFreeDoc(wrap_doc);
		}
	}

	else
	{
		char* error = oscap_sprintf(
				"Unknown root element '%s' in given XCCDF result document, expected TestResult or Benchmark.",
				(const char*)root_element->name);

		oscap_seterr(OSCAP_EFAMILY_XML, 0, error);
		oscap_free(error);
	}
}
Exemple #5
0
static int ds_sds_compose_add_component_internal(xmlDocPtr doc, xmlNodePtr datastream, const char* filepath, const char* comp_id, bool extended)
{
	xmlNsPtr ds_ns = xmlSearchNsByHref(doc, datastream, BAD_CAST datastream_ns_uri);
	if (!ds_ns)
	{
		oscap_seterr(OSCAP_EFAMILY_GLIBC,
				"Unable to find namespace '%s' in the XML DOM tree when create "
				"source datastream. This is most likely an internal error!",
				datastream_ns_uri);
		return -1;
	}

	char file_timestamp[32];
	strcpy(file_timestamp, "0000-00-00T00:00:00");

	struct stat file_stat;
	if (stat(filepath, &file_stat) == 0)
		strftime(file_timestamp, 32, "%Y-%m-%dT%H:%M:%S", localtime(&file_stat.st_mtime));
	else {
		oscap_seterr(OSCAP_EFAMILY_GLIBC, "Could not find file %s: %s.", filepath, strerror(errno));
		// Return positive number, indicating less severe problem.
		// Rationale: When an OVAL file is missing during a scan it it not considered
		// to be deal breaker (it shall have 'notchecked' result), thus we shall allow
		// DataStreams with missing OVAL.
		return 1;
	}

	xmlNodePtr component = xmlNewNode(ds_ns, BAD_CAST (extended ? "extended-component" : "component"));
	xmlSetProp(component, BAD_CAST "id", BAD_CAST comp_id);
	xmlSetProp(component, BAD_CAST "timestamp", BAD_CAST file_timestamp);

	xmlNodePtr doc_root = xmlDocGetRootElement(doc);

	if (extended) {
		if (ds_sds_compose_component_add_script_content(component, filepath) == -1) {
			xmlFreeNode(component);
			return -1;
		}
		// extended components always go at the end
		xmlAddChild(doc_root, component);
	} else {
		struct oscap_source *component_source = oscap_source_new_from_file(filepath);
		xmlDoc *component_doc = oscap_source_get_xmlDoc(component_source);
		if (!component_doc) {
			oscap_seterr(OSCAP_EFAMILY_XML, "Could not read/parse XML of given input file at path '%s'.", filepath);
			xmlFreeNode(component);
			oscap_source_free(component_source);
			return -1;
		}

		xmlNodePtr component_root = xmlDocGetRootElement(component_doc);

		xmlDOMWrapCtxtPtr wrap_ctxt = xmlDOMWrapNewCtxt();

		xmlNodePtr res_component_root = NULL;
		if (xmlDOMWrapCloneNode(wrap_ctxt, component_doc, component_root, &res_component_root, doc, NULL, 1, 0) != 0)
		{
			oscap_seterr(OSCAP_EFAMILY_XML,
					"Cannot clone node when adding component from file '%s' with id '%s' while "
					"creating source datastream.", filepath, comp_id);

			xmlDOMWrapFreeCtxt(wrap_ctxt);
			oscap_source_free(component_source);
			xmlFreeNode(component);

			return -1;
		}
		if (xmlDOMWrapReconcileNamespaces(wrap_ctxt, res_component_root, 0) != 0)
		{
			oscap_seterr(OSCAP_EFAMILY_XML,
					"Cannot reconcile namespaces when adding component from file '%s' with id '%s' while "
					"creating source datastream.", filepath, comp_id);

			xmlDOMWrapFreeCtxt(wrap_ctxt);
			oscap_source_free(component_source);
			xmlFreeNode(component);

			return -1;
		}

		xmlAddChild(component, res_component_root);

		xmlDOMWrapFreeCtxt(wrap_ctxt);

		// this component is not extended, we have to figure out if there
		// already is an extended-component and if so, add it right before
		// that component

		xmlNodePtr first_extended_component = node_get_child_element(doc_root, "extended-component");
		if (first_extended_component == NULL)
		{
			// no extended component yet, add to the end
			xmlAddChild(doc_root, component);
		}
		else
		{
			xmlAddPrevSibling(first_extended_component, component);
		}
		oscap_source_free(component_source);
	}

	return 0;
}