Blame SOURCES/openscap-1.3.5-fix_testresult_benchmark-PR_1655.patch

8b65ee
From 9b40767967e533bdb340ca4c91f2fd1192694820 Mon Sep 17 00:00:00 2001
8b65ee
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
8b65ee
Date: Wed, 2 Dec 2020 16:45:42 +0100
8b65ee
Subject: [PATCH] Fix TestResult/benchmark/@href attribute
8b65ee
8b65ee
Make the href attribute an URI according to SCAP specification Section
8b65ee
4.5. This should fix SCAPVAL error RES-253-2 which occured when
8b65ee
validating ARFs by SCAPVAL. See #1629 for the problem description.
8b65ee
8b65ee
Also, it fixes a problem that xccdf_benchmark_item_clone didn't create
8b65ee
the clusters_dict hash table.
8b65ee
8b65ee
The existing tests are extended to test this property, the
8b65ee
function test_sds_external_xccdf has been splitted into 2 functions.
8b65ee
8b65ee
Fixes: #1629
8b65ee
---
8b65ee
 src/DS/ds_sds_session.c        | 18 ++++++++++++++++++
8b65ee
 src/DS/ds_sds_session_priv.h   |  1 +
8b65ee
 src/DS/public/ds_sds_session.h |  8 ++++++++
8b65ee
 src/DS/sds.c                   |  3 +++
8b65ee
 src/XCCDF/item.c               |  1 +
8b65ee
 src/XCCDF/xccdf_session.c      | 25 ++++++++++++++++++++-----
8b65ee
 tests/DS/test_ds_misc.sh       | 30 +++++++++++++++++++++++-------
8b65ee
 7 files changed, 74 insertions(+), 12 deletions(-)
8b65ee
8b65ee
diff --git a/src/DS/ds_sds_session.c b/src/DS/ds_sds_session.c
8b65ee
index c03d3d593e..9120ee3243 100644
8b65ee
--- a/src/DS/ds_sds_session.c
8b65ee
+++ b/src/DS/ds_sds_session.c
8b65ee
@@ -50,7 +50,9 @@ struct ds_sds_session {
8b65ee
 	const char *target_dir;                 ///< Target directory for current split
8b65ee
 	const char *datastream_id;              ///< ID of selected datastream
8b65ee
 	const char *checklist_id;               ///< ID of selected checklist
8b65ee
+	const char *checklist_uri;              ///< URI of selected checklist
8b65ee
 	struct oscap_htable *component_sources;	///< oscap_source for parsed components
8b65ee
+	struct oscap_htable *component_uris;    ///< maps component refs to component URIs
8b65ee
 	bool fetch_remote_resources;            ///< Allows loading of external components;
8b65ee
 	download_progress_calllback_t progress;	///< Callback to report progress of download.
8b65ee
 };
8b65ee
@@ -72,6 +74,7 @@ struct ds_sds_session *ds_sds_session_new_from_source(struct oscap_source *sourc
8b65ee
 	struct ds_sds_session *sds_session = (struct ds_sds_session *) calloc(1, sizeof(struct ds_sds_session));
8b65ee
 	sds_session->source = source;
8b65ee
 	sds_session->component_sources = oscap_htable_new();
8b65ee
+	sds_session->component_uris = oscap_htable_new();
8b65ee
 	sds_session->progress = download_progress_empty_calllback;
8b65ee
 	return sds_session;
8b65ee
 }
8b65ee
@@ -84,6 +87,7 @@ void ds_sds_session_free(struct ds_sds_session *sds_session)
8b65ee
 			oscap_acquire_cleanup_dir(&(sds_session->temp_dir));
8b65ee
 		}
8b65ee
 		oscap_htable_free(sds_session->component_sources, (oscap_destruct_func) oscap_source_free);
8b65ee
+		oscap_htable_free(sds_session->component_uris, (oscap_destruct_func) free);
8b65ee
 		free(sds_session);
8b65ee
 	}
8b65ee
 }
8b65ee
@@ -91,10 +95,13 @@ void ds_sds_session_free(struct ds_sds_session *sds_session)
8b65ee
 void ds_sds_session_reset(struct ds_sds_session *session)
8b65ee
 {
8b65ee
 	session->checklist_id = NULL;
8b65ee
+	session->checklist_uri = NULL;
8b65ee
 	session->datastream_id = NULL;
8b65ee
 	session->target_dir = NULL;
8b65ee
 	oscap_htable_free(session->component_sources, (oscap_destruct_func) oscap_source_free);
8b65ee
 	session->component_sources = oscap_htable_new();
8b65ee
+	oscap_htable_free(session->component_uris, (oscap_destruct_func) free);
8b65ee
+	session->component_uris = oscap_htable_new();
8b65ee
 }
8b65ee
 
8b65ee
 struct ds_sds_index *ds_sds_session_get_sds_idx(struct ds_sds_session *session)
8b65ee
@@ -163,11 +170,21 @@ const char *ds_sds_session_get_checklist_id(const struct ds_sds_session *session
8b65ee
 	return session->checklist_id;
8b65ee
 }
8b65ee
 
8b65ee
+const char *ds_sds_session_get_checklist_uri(const struct ds_sds_session *session)
8b65ee
+{
8b65ee
+	return session->checklist_uri;
8b65ee
+}
8b65ee
+
8b65ee
 struct oscap_htable *ds_sds_session_get_component_sources(struct ds_sds_session *session)
8b65ee
 {
8b65ee
 	return session->component_sources;
8b65ee
 }
8b65ee
 
8b65ee
+struct oscap_htable *ds_sds_session_get_component_uris(struct ds_sds_session *session)
8b65ee
+{
8b65ee
+	return session->component_uris;
8b65ee
+}
8b65ee
+
8b65ee
 const char *ds_sds_session_get_readable_origin(const struct ds_sds_session *session)
8b65ee
 {
8b65ee
 	if (session->source == NULL)
8b65ee
@@ -210,6 +227,7 @@ struct oscap_source *ds_sds_session_select_checklist(struct ds_sds_session *sess
8b65ee
 		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not extract %s with all dependencies from datastream.", session->checklist_id);
8b65ee
 		return NULL;
8b65ee
 	}
8b65ee
+	session->checklist_uri = oscap_htable_get(session->component_uris, session->checklist_id);
8b65ee
 	struct oscap_source *xccdf = oscap_htable_get(session->component_sources, session->checklist_id);
8b65ee
 	if (xccdf == NULL) {
8b65ee
 		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Internal error: Could not acquire handle to '%s' source.", session->checklist_id);
8b65ee
diff --git a/src/DS/ds_sds_session_priv.h b/src/DS/ds_sds_session_priv.h
8b65ee
index 4aa559ebb4..f58231dc48 100644
8b65ee
--- a/src/DS/ds_sds_session_priv.h
8b65ee
+++ b/src/DS/ds_sds_session_priv.h
8b65ee
@@ -37,6 +37,7 @@ xmlDoc *ds_sds_session_get_xmlDoc(struct ds_sds_session *session);
8b65ee
 int ds_sds_session_register_component_source(struct ds_sds_session *session, const char *relative_filepath, struct oscap_source *component);
8b65ee
 const char *ds_sds_session_get_target_dir(struct ds_sds_session *session);
8b65ee
 struct oscap_htable *ds_sds_session_get_component_sources(struct ds_sds_session *session);
8b65ee
+struct oscap_htable *ds_sds_session_get_component_uris(struct ds_sds_session *session);
8b65ee
 const char *ds_sds_session_get_readable_origin(const struct ds_sds_session *session);
8b65ee
 bool ds_sds_session_fetch_remote_resources(struct ds_sds_session *session);
8b65ee
 download_progress_calllback_t ds_sds_session_remote_resources_progress(struct ds_sds_session *session);
8b65ee
diff --git a/src/DS/public/ds_sds_session.h b/src/DS/public/ds_sds_session.h
8b65ee
index 1ce692ce21..20a85146cc 100644
8b65ee
--- a/src/DS/public/ds_sds_session.h
8b65ee
+++ b/src/DS/public/ds_sds_session.h
8b65ee
@@ -119,6 +119,14 @@ const char *ds_sds_session_get_datastream_id(const struct ds_sds_sessi
8b65ee
  */
8b65ee
 const char *ds_sds_session_get_checklist_id(const struct ds_sds_session *session);
8b65ee
 
8b65ee
+/**
8b65ee
+ * Return URI of currently selected component representing XCCDF within the DataStream
8b65ee
+ * @memberof ds_sds_session
8b65ee
+ * @param session The Source DataStream session
8b65ee
+ * @returns URI of selected component or NULL
8b65ee
+ */
8b65ee
+const char *ds_sds_session_get_checklist_uri(const struct ds_sds_session *session);
8b65ee
+
8b65ee
 /**
8b65ee
  * Get component from Source DataStream by its href. This assumes that the component
8b65ee
  * has been already cached by the session. You can cache component or its dependencies
8b65ee
diff --git a/src/DS/sds.c b/src/DS/sds.c
8b65ee
index b546ed3e65..20c683a7aa 100644
8b65ee
--- a/src/DS/sds.c
8b65ee
+++ b/src/DS/sds.c
8b65ee
@@ -450,7 +450,10 @@ int ds_sds_dump_component_ref_as(const xmlNodePtr component_ref, struct ds_sds_s
8b65ee
 
8b65ee
 	char* component_id = NULL;
8b65ee
 
8b65ee
+	// make a copy of xlink_href because ds_sds_dump_component_by_href modifies its second argument
8b65ee
+	char *xlink_href_copy = oscap_strdup(xlink_href);
8b65ee
 	int ret = ds_sds_dump_component_by_href(session, xlink_href, target_filename_dirname, relative_filepath, cref_id, &component_id);
8b65ee
+	oscap_htable_add(ds_sds_session_get_component_uris(session), cref_id, xlink_href_copy);
8b65ee
 
8b65ee
 	xmlFree(xlink_href);
8b65ee
 	xmlFree(cref_id);
8b65ee
diff --git a/src/XCCDF/item.c b/src/XCCDF/item.c
8b65ee
index 3657fb461a..295e4a7f00 100644
8b65ee
--- a/src/XCCDF/item.c
8b65ee
+++ b/src/XCCDF/item.c
8b65ee
@@ -1155,6 +1155,7 @@ struct xccdf_benchmark_item * xccdf_benchmark_item_clone(struct xccdf_item *pare
8b65ee
 	clone->items_dict = oscap_htable_new();
8b65ee
 	clone->profiles_dict = oscap_htable_new();
8b65ee
 	clone->results_dict = oscap_htable_new();
8b65ee
+	clone->clusters_dict = oscap_htable_new();
8b65ee
 	clone->notices = oscap_list_clone(item->notices, (oscap_clone_func) xccdf_notice_clone);
8b65ee
 	clone->plain_texts = oscap_list_clone(item->plain_texts, (oscap_clone_func) xccdf_plain_text_clone);
8b65ee
 	
8b65ee
diff --git a/src/XCCDF/xccdf_session.c b/src/XCCDF/xccdf_session.c
8b65ee
index f1b8379591..c88d90be05 100644
8b65ee
--- a/src/XCCDF/xccdf_session.c
8b65ee
+++ b/src/XCCDF/xccdf_session.c
8b65ee
@@ -1374,21 +1374,28 @@ static int _build_xccdf_result_source(struct xccdf_session *session)
8b65ee
 			oscap_seterr(OSCAP_EFAMILY_OSCAP, "No XCCDF results to export.");
8b65ee
 			return 1;
8b65ee
 		}
8b65ee
-		struct xccdf_result* cloned_result = xccdf_result_clone(session->xccdf.result);
8b65ee
-		xccdf_benchmark_add_result(benchmark, cloned_result);
8b65ee
-		session->xccdf.result_source = xccdf_benchmark_export_source(benchmark, session->export.xccdf_file);
8b65ee
 
8b65ee
 		if (session->export.xccdf_file != NULL) {
8b65ee
+			struct xccdf_benchmark *cloned_benchmark = xccdf_benchmark_clone(benchmark);
8b65ee
+			struct xccdf_result *cloned_result = xccdf_result_clone(session->xccdf.result);
8b65ee
+			xccdf_benchmark_add_result(cloned_benchmark, cloned_result);
8b65ee
+			struct oscap_source *xccdf_result_source = xccdf_benchmark_export_source(cloned_benchmark, session->export.xccdf_file);
8b65ee
+			// cloned_result is freed during xccdf_benchmark_free
8b65ee
+			xccdf_benchmark_free(cloned_benchmark);
8b65ee
 			// Export XCCDF result file only when explicitly requested
8b65ee
-			if (oscap_source_save_as(session->xccdf.result_source, NULL) != 0) {
8b65ee
+			if (oscap_source_save_as(xccdf_result_source, NULL) != 0) {
8b65ee
 				oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not save file: %s",
8b65ee
-						oscap_source_readable_origin(session->xccdf.result_source));
8b65ee
+						oscap_source_readable_origin(xccdf_result_source));
8b65ee
+				oscap_source_free(xccdf_result_source);
8b65ee
 				return -1;
8b65ee
 			}
8b65ee
+			oscap_source_free(xccdf_result_source);
8b65ee
 		}
8b65ee
 
8b65ee
 		if (session->export.xccdf_stig_viewer_file != NULL) {
8b65ee
+			struct xccdf_result *cloned_result = xccdf_result_clone(session->xccdf.result);
8b65ee
 			struct oscap_source * stig_result = xccdf_result_stig_viewer_export_source(cloned_result, session->export.xccdf_stig_viewer_file);
8b65ee
+			xccdf_result_free(cloned_result);
8b65ee
 			if (oscap_source_save_as(stig_result, NULL) != 0) {
8b65ee
 				oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not save file: %s",
8b65ee
 						oscap_source_readable_origin(stig_result));
8b65ee
@@ -1398,6 +1405,14 @@ static int _build_xccdf_result_source(struct xccdf_session *session)
8b65ee
 			oscap_source_free(stig_result);
8b65ee
 		}
8b65ee
 
8b65ee
+		struct xccdf_result *cloned_result = xccdf_result_clone(session->xccdf.result);
8b65ee
+		if (xccdf_session_is_sds(session)) {
8b65ee
+			struct ds_sds_session *sds_session = xccdf_session_get_ds_sds_session(session);
8b65ee
+			const char *benchmark_uri = ds_sds_session_get_checklist_uri(sds_session);
8b65ee
+			xccdf_result_set_benchmark_uri(cloned_result, benchmark_uri);
8b65ee
+		}
8b65ee
+		xccdf_benchmark_add_result(benchmark, cloned_result);
8b65ee
+		session->xccdf.result_source = xccdf_benchmark_export_source(benchmark, session->export.xccdf_file);
8b65ee
 		/* validate XCCDF Results */
8b65ee
 		if (session->validate && session->full_validation) {
8b65ee
 			if (oscap_source_validate(session->xccdf.result_source, _reporter, NULL)) {