Exemple #1
0
static xmlNodePtr ds_sds_get_component_root_by_id(xmlDoc *doc, const char* component_id)
{
	xmlNodePtr component;
	if (component_id == NULL) {
		component = (xmlNodePtr)doc;
	} else {
		component = _lookup_component_in_collection(doc, component_id);
		if (component == NULL)
		{
			oscap_seterr(OSCAP_EFAMILY_XML, "Component of given id '%s' was not found in the document.", component_id);
			return NULL;
		}
	}

	return node_get_child_element(component, NULL);
}
Exemple #2
0
static int ds_sds_dump_component(const char* component_id, struct ds_sds_session *session, const char *target_filename_dirname, const char *relative_filepath)
{
	xmlDoc *doc = ds_sds_session_get_xmlDoc(session);
	xmlNodePtr component = _lookup_component_in_collection(doc, component_id);
	if (component == NULL)
	{
		oscap_seterr(OSCAP_EFAMILY_XML, "Component of given id '%s' was not found in the document.", component_id);
		return -1;
	}

	xmlNodePtr inner_root = node_get_child_element(component, NULL);

	if (inner_root == NULL)
	{
		oscap_seterr(OSCAP_EFAMILY_XML, "Found component (id='%s') but it has no element contents, nothing to dump, skipping...", component_id);
		return -1;
	}

	// If the inner root is script, we have to treat it in a special way
	if (strcmp((const char*)inner_root->name, "script") == 0) {
		// the cast is safe to do because we are using the GNU basename, it doesn't
		// modify the string
		const char* file_basename = basename((char*)relative_filepath);
		const char* sce_filename = oscap_sprintf("%s/%s/%s",ds_sds_session_get_target_dir(session), target_filename_dirname, file_basename);
		int ret = ds_sds_dump_component_sce(inner_root->children, component_id, sce_filename);
		oscap_free(sce_filename);
		if (ret != 0) {
			return ret;
		}
	}
	// Otherwise we create a new XML doc we will dump the contents to.
	// We can't just dump node "innerXML" because namespaces have to be
	// handled.
	else {
		xmlDoc *new_doc = ds_doc_from_foreign_node(inner_root, doc);
		if (new_doc == NULL) {
			return -1;
		}
		struct oscap_source *source = oscap_source_new_from_xmlDoc(new_doc, relative_filepath);
		ds_sds_session_register_component_source(session, relative_filepath, source);
	}

	return 0;
}
Exemple #3
0
int ds_sds_compose_add_component_with_ref(xmlDocPtr doc, xmlNodePtr datastream, const char* filepath, const char* cref_id)
{
	xmlNsPtr ds_ns = xmlSearchNsByHref(doc, datastream, BAD_CAST datastream_ns_uri);
	xmlNsPtr xlink_ns = xmlSearchNsByHref(doc, datastream, BAD_CAST xlink_ns_uri);
	xmlNsPtr cat_ns = xmlSearchNsByHref(doc, datastream, BAD_CAST cat_ns_uri);

	// In case we already have this component we just return, no need to add
	// it twice. We will typically have many references to OVAL files, adding
	// component for each reference would create unnecessarily huge datastreams
	int result = ds_sds_compose_has_component_ref(doc, datastream, filepath, cref_id);
	if (result == 0)
	{
		return 0;
	}

	if (result == -1)
	{
		// no need to free anything
		// oscap_seterr has already been called
		return -1;
	}

	xmlNodePtr cref_catalog = xmlNewNode(cat_ns, BAD_CAST "catalog");
	xmlNodePtr cref_parent;

	bool extended_component = false;

	struct oscap_source *component_source = oscap_source_new_from_file(filepath);
	oscap_document_type_t doc_type = oscap_source_get_scap_type(component_source);
	if (doc_type == OSCAP_DOCUMENT_XCCDF)
	{
		cref_parent = node_get_child_element(datastream, "checklists");
		if (ds_sds_compose_add_component_dependencies(doc, datastream, component_source, cref_catalog, doc_type) != 0)
		{
			// oscap_seterr has already been called
			oscap_source_free(component_source);
			return -1;
		}
	}
	else if (doc_type == OSCAP_DOCUMENT_CPE_DICTIONARY || doc_type == OSCAP_DOCUMENT_CPE_LANGUAGE)
	{
		cref_parent = node_get_child_element(datastream, "dictionaries");
		if (cref_parent == NULL) {
			cref_parent = xmlNewNode(ds_ns, BAD_CAST "dictionaries");
			// The <ds:dictionaries element must as the first child of the datastream
			xmlNodePtr first_child = datastream->xmlChildrenNode;
			xmlNodePtr new_node = (first_child == NULL) ?
				xmlAddChild(datastream, cref_parent) : xmlAddPrevSibling(first_child, cref_parent);
			if (new_node == NULL) {
				oscap_seterr(OSCAP_EFAMILY_XML, "Failed to add dictionaries element to the DataStream.");
				xmlFreeNode(cref_parent);
				cref_parent = NULL;
			}
		}
		if (ds_sds_compose_add_component_dependencies(doc, datastream, component_source, cref_catalog, doc_type) != 0) {
			oscap_source_free(component_source);
			return -1;
		}
	}
	else if (doc_type == OSCAP_DOCUMENT_OVAL_DEFINITIONS || doc_type == OSCAP_DOCUMENT_OCIL)
	{
		cref_parent = node_get_child_element(datastream, "checks");
	}
	else
	{
		// not an XCCDF file, not an OVAL file, not a dict/lang, assume it goes into extended components
		extended_component = true;
		cref_parent = node_get_child_element(datastream, "extended-components");
	}
	oscap_source_free(component_source);

	char* mangled_filepath = ds_sds_mangle_filepath(filepath);
	// extended components (sadly :-/) use a different ID scheme and have
	// a different element name than "normal" components
	char* comp_id = oscap_sprintf("scap_org.open-scap_%scomp_%s",
		extended_component ? "e" : "", mangled_filepath);

	int counter = 0;
	while (_lookup_component_in_collection(doc, comp_id) != NULL) {
		// While a component of the given ID already exists, generate a new one
		oscap_free(comp_id);
		comp_id = oscap_sprintf("scap_org.open-scap_%scomp_%s%03d",
			extended_component ? "e" : "", mangled_filepath, counter++);
	}

	oscap_free(mangled_filepath);

	result = ds_sds_compose_add_component_internal(doc, datastream, filepath, comp_id, extended_component);
	if (result == 0) {
		xmlNodePtr cref = xmlNewNode(ds_ns, BAD_CAST "component-ref");
		xmlAddChild(cref, cref_catalog);
		xmlSetProp(cref, BAD_CAST "id", BAD_CAST cref_id);

		const char* xlink_href = oscap_sprintf("#%s", comp_id);
		xmlSetNsProp(cref, xlink_ns, BAD_CAST "href", BAD_CAST xlink_href);
		oscap_free(xlink_href);

		if (xmlAddChild(cref_parent, cref) == NULL) {
			oscap_seterr(OSCAP_EFAMILY_XML, "Failed to add component-ref/@id='%s' to the DataStream.", cref_id);
			result = 1;
		}
	}

	oscap_free(comp_id);
	// the source data stream XSD requires either no catalog or a non-empty one
	if (cref_catalog->children == NULL)
	{
		xmlUnlinkNode(cref_catalog);
		xmlFreeNode(cref_catalog);
	}

	return result;
}