Пример #1
0
xmlNs *lookup_xccdf_ns(xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info *version_info)
{
	assert(parent != NULL);

	xmlNs *ns_xccdf = xmlSearchNsByHref(doc, parent,
		(const xmlChar *)xccdf_version_info_get_namespace_uri(version_info));
	if (ns_xccdf == NULL) {
		ns_xccdf = xmlNewNs(parent,
			(const xmlChar *) xccdf_version_info_get_namespace_uri(version_info), NULL);
	}
	return ns_xccdf;
}
Пример #2
0
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;
}
Пример #3
0
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));
	}