Blame SOURCES/openscap-1.3.3-generate-guide-tailoring.patch

0b628f
diff --git a/src/XCCDF/benchmark.c b/src/XCCDF/benchmark.c
0b628f
index f561736d4..d6560b7c9 100644
0b628f
--- a/src/XCCDF/benchmark.c
0b628f
+++ b/src/XCCDF/benchmark.c
0b628f
@@ -866,6 +866,19 @@ xccdf_benchmark_find_target_htable(const struct xccdf_benchmark *benchmark, xccd
0b628f
 	return XITEM(benchmark)->sub.benchmark.items_dict;
0b628f
 }
0b628f
 
0b628f
+int xccdf_benchmark_include_tailored_profiles(struct xccdf_benchmark *benchmark)
0b628f
+{
0b628f
+	struct oscap_list *profiles = XITEM(benchmark)->sub.benchmark.profiles;
0b628f
+	struct oscap_htable_iterator *it = oscap_htable_iterator_new(XITEM(benchmark)->sub.benchmark.profiles_dict);
0b628f
+	while(oscap_htable_iterator_has_more(it)) {
0b628f
+		struct xccdf_profile *profile = oscap_htable_iterator_next_value(it);
0b628f
+		if (xccdf_profile_get_tailoring(profile)) {
0b628f
+			oscap_list_add(profiles, xccdf_profile_clone(profile));
0b628f
+		}
0b628f
+	}
0b628f
+	oscap_htable_iterator_free(it);
0b628f
+	return 0;
0b628f
+}
0b628f
 
0b628f
 struct xccdf_plain_text *xccdf_plain_text_new(void)
0b628f
 {
0b628f
diff --git a/src/XCCDF/item.h b/src/XCCDF/item.h
0b628f
index 35204744f..da76f854d 100644
0b628f
--- a/src/XCCDF/item.h
0b628f
+++ b/src/XCCDF/item.h
0b628f
@@ -437,6 +437,7 @@ void xccdf_item_dump(struct xccdf_item *item, int depth);
0b628f
 struct xccdf_item* xccdf_item_get_benchmark_internal(struct xccdf_item* item);
0b628f
 bool xccdf_benchmark_parse(struct xccdf_item *benchmark, xmlTextReaderPtr reader);
0b628f
 void xccdf_benchmark_dump(struct xccdf_benchmark *benchmark);
0b628f
+int xccdf_benchmark_include_tailored_profiles(struct xccdf_benchmark *benchmark);
0b628f
 struct oscap_htable_iterator *xccdf_benchmark_get_cluster_items(struct xccdf_benchmark *benchmark, const char *cluster_id);
0b628f
 bool xccdf_benchmark_register_item(struct xccdf_benchmark *benchmark, struct xccdf_item *item);
0b628f
 bool xccdf_benchmark_unregister_item(struct xccdf_item *item);
0b628f
diff --git a/src/XCCDF/public/xccdf_session.h b/src/XCCDF/public/xccdf_session.h
0b628f
index ac96e2036..026432693 100644
0b628f
--- a/src/XCCDF/public/xccdf_session.h
0b628f
+++ b/src/XCCDF/public/xccdf_session.h
0b628f
@@ -558,6 +558,14 @@ OSCAP_API int xccdf_session_build_policy_from_testresult(struct xccdf_session *s
0b628f
  */
0b628f
 OSCAP_API int xccdf_session_add_report_from_source(struct xccdf_session *session, struct oscap_source *report_source);
0b628f
 
0b628f
+/**
0b628f
+ * Generate HTML guide form a loaded XCCDF session
0b628f
+ * @param session XCCDF Session
0b628f
+ * @param outfile path to the output file
0b628f
+ * @returns zero on success
0b628f
+ */
0b628f
+OSCAP_API int xccdf_session_generate_guide(struct xccdf_session *session, const char *outfile);
0b628f
+
0b628f
 /// @}
0b628f
 /// @}
0b628f
 #endif
0b628f
diff --git a/src/XCCDF/xccdf_session.c b/src/XCCDF/xccdf_session.c
0b628f
index 1005a030a..d38905f77 100644
0b628f
--- a/src/XCCDF/xccdf_session.c
0b628f
+++ b/src/XCCDF/xccdf_session.c
0b628f
@@ -1746,3 +1746,44 @@ int xccdf_session_add_report_from_source(struct xccdf_session *session, struct o
0b628f
 	session->xccdf.result = result;
0b628f
 	return 0;
0b628f
 }
0b628f
+
0b628f
+int xccdf_session_generate_guide(struct xccdf_session *session, const char *outfile)
0b628f
+{
0b628f
+	struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
0b628f
+	if (policy == NULL) {
0b628f
+		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF policy.");
0b628f
+		return 1;
0b628f
+	}
0b628f
+	struct xccdf_policy_model *model = xccdf_policy_get_model(policy);
0b628f
+	if (model == NULL) {
0b628f
+		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF policy model.");
0b628f
+		return 1;
0b628f
+	}
0b628f
+	struct xccdf_benchmark *benchmark = xccdf_policy_model_get_benchmark(model);
0b628f
+	if (benchmark == NULL) {
0b628f
+		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF benchmark.");
0b628f
+		return 1;
0b628f
+	}
0b628f
+	xccdf_benchmark_include_tailored_profiles(benchmark);
0b628f
+	const char *params[] = {
0b628f
+		"oscap-version",     oscap_get_version(),
0b628f
+		"benchmark_id",      xccdf_benchmark_get_id(benchmark),
0b628f
+		"profile_id",        xccdf_session_get_profile_id(session),
0b628f
+		NULL
0b628f
+	};
0b628f
+	struct oscap_source *benchmark_source = xccdf_benchmark_export_source(benchmark, NULL);
0b628f
+	if (benchmark_source == NULL) {
0b628f
+		oscap_seterr(OSCAP_EFAMILY_OSCAP,
0b628f
+			"Failed to export source from XCCDF benchmark %s.",
0b628f
+			xccdf_benchmark_get_id(benchmark));
0b628f
+		return 1;
0b628f
+	}
0b628f
+	int ret = oscap_source_apply_xslt_path(benchmark_source,
0b628f
+		"xccdf-guide.xsl", outfile, params, oscap_path_to_xslt());
0b628f
+	oscap_source_free(benchmark_source);
0b628f
+	if (ret < 0) {
0b628f
+		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not apply XSLT.");
0b628f
+		return 1;
0b628f
+	}
0b628f
+	return 0;
0b628f
+}
0b628f
\ No newline at end of file
0b628f
diff --git a/tests/API/XCCDF/tailoring/all.sh b/tests/API/XCCDF/tailoring/all.sh
0b628f
index dbed97a87..fc2ccd743 100755
0b628f
--- a/tests/API/XCCDF/tailoring/all.sh
0b628f
+++ b/tests/API/XCCDF/tailoring/all.sh
0b628f
@@ -134,6 +134,21 @@ function test_api_xccdf_tailoring_profile_generate_fix {
0b628f
     rm -f $tailoring_result $fix_result
0b628f
 }
0b628f
 
0b628f
+function test_api_xccdf_tailoring_profile_generate_guide {
0b628f
+    local INPUT=$srcdir/$1
0b628f
+    local TAILORING=$srcdir/$2
0b628f
+
0b628f
+    guide=`mktemp`
0b628f
+    # tailoring profile only with "always fail" rule and generate HTML guide
0b628f
+    $OSCAP xccdf generate guide --tailoring-file $TAILORING --profile "xccdf_com.example.www_profile_customized" --output $guide $INPUT
0b628f
+
0b628f
+    grep -q "Baseline Testing Profile 1 \[CUSTOMIZED\]" $guide
0b628f
+    # profile 'customized' selects first rule and deselects the second
0b628f
+    grep -q "xccdf_com.example.www_rule_first" $guide
0b628f
+    grep -v "xccdf_com.example.www_rule_second" $guide
0b628f
+    rm -f $guide
0b628f
+}
0b628f
+
0b628f
 # Testing.
0b628f
 
0b628f
 test_init "test_api_xccdf_tailoring.log"
0b628f
@@ -154,6 +169,7 @@ test_run "test_api_xccdf_tailoring_autonegotiation" test_api_xccdf_tailoring_aut
0b628f
 test_run "test_api_xccdf_tailoring_simple_include_in_arf" test_api_xccdf_tailoring_simple_include_in_arf simple-xccdf.xml simple-tailoring.xml
0b628f
 test_run "test_api_xccdf_tailoring_profile_include_in_arf" test_api_xccdf_tailoring_profile_include_in_arf baseline.xccdf.xml baseline.tailoring.xml
0b628f
 test_run "test_api_xccdf_tailoring_profile_generate_fix" test_api_xccdf_tailoring_profile_generate_fix baseline.xccdf.xml baseline.tailoring.xml
0b628f
+test_run "test_api_xccdf_tailoring_profile_generate_guide" test_api_xccdf_tailoring_profile_generate_guide baseline.xccdf.xml baseline.tailoring.xml
0b628f
 
0b628f
 
0b628f
 test_exit
0b628f
diff --git a/utils/oscap-xccdf.c b/utils/oscap-xccdf.c
0b628f
index 472a2cc6f..87a0c7ad1 100644
0b628f
--- a/utils/oscap-xccdf.c
0b628f
+++ b/utils/oscap-xccdf.c
0b628f
@@ -77,6 +77,7 @@ static bool getopt_xccdf(int argc, char **argv, struct oscap_action *action);
0b628f
 static bool getopt_generate(int argc, char **argv, struct oscap_action *action);
0b628f
 static int app_xccdf_xslt(const struct oscap_action *action);
0b628f
 static int app_generate_fix(const struct oscap_action *action);
0b628f
+static int app_generate_guide(const struct oscap_action *action);
0b628f
 
0b628f
 #define XCCDF_SUBMODULES_NUM		7
0b628f
 #define XCCDF_GEN_SUBMODULES_NUM	5 /* See actual arrays
0b628f
@@ -244,12 +245,18 @@ static struct oscap_module XCCDF_GEN_GUIDE = {
0b628f
     .help = GEN_OPTS
0b628f
 		"\nGuide Options:\n"
0b628f
 		"   --output <file>               - Write the document into file.\n"
0b628f
-		"   --hide-profile-info           - Do not output additional information about selected profile.\n"
0b628f
+		"   --hide-profile-info           - This option has no effect.\n"
0b628f
 		"   --benchmark-id <id>           - ID of XCCDF Benchmark in some component in the datastream that should be used.\n"
0b628f
+		"                                   (only applicable for source datastreams)\n"
0b628f
+		"   --xccdf-id <id>               - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
0b628f
+		"                                   (only applicable for source datastreams)\n"
0b628f
+		"   --tailoring-file <file>       - Use given XCCDF Tailoring file.\n"
0b628f
+		"                                   (only applicable for source datastreams)\n"
0b628f
+		"   --tailoring-id <component-id> - Use given DS component as XCCDF Tailoring file.\n"
0b628f
 		"                                   (only applicable for source datastreams)\n",
0b628f
     .opt_parser = getopt_xccdf,
0b628f
-    .user = "xccdf-guide.xsl",
0b628f
-    .func = app_xccdf_xslt
0b628f
+    .user = NULL,
0b628f
+    .func = app_generate_guide
0b628f
 };
0b628f
 
0b628f
 static struct oscap_module XCCDF_GEN_FIX = {
0b628f
@@ -973,6 +980,50 @@ int app_generate_fix(const struct oscap_action *action)
0b628f
 	return ret;
0b628f
 }
0b628f
 
0b628f
+int app_generate_guide(const struct oscap_action *action)
0b628f
+{
0b628f
+	int ret = OSCAP_ERROR;
0b628f
+
0b628f
+	struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
0b628f
+	struct xccdf_session *session = xccdf_session_new_from_source(source);
0b628f
+	if (session == NULL) {
0b628f
+		goto cleanup;
0b628f
+	}
0b628f
+
0b628f
+	xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
0b628f
+	xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
0b628f
+	xccdf_session_set_user_tailoring_file(session, action->tailoring_file);
0b628f
+	xccdf_session_set_user_tailoring_cid(session, action->tailoring_id);
0b628f
+	if (xccdf_session_is_sds(session)) {
0b628f
+		xccdf_session_set_component_id(session, action->f_xccdf_id);
0b628f
+		xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
0b628f
+	}
0b628f
+	xccdf_session_set_loading_flags(session, XCCDF_SESSION_LOAD_XCCDF);
0b628f
+
0b628f
+	if (xccdf_session_load(session) != 0) {
0b628f
+		goto cleanup;
0b628f
+	}
0b628f
+
0b628f
+	if (!xccdf_session_set_profile_id(session, action->profile)) {
0b628f
+		if (action->profile != NULL) {
0b628f
+			if (xccdf_set_profile_or_report_bad_id(session, action->profile, action->f_xccdf) == OSCAP_ERROR)
0b628f
+				goto cleanup;
0b628f
+		} else {
0b628f
+			fprintf(stderr, "No Policy was found for default profile.\n");
0b628f
+			goto cleanup;
0b628f
+		}
0b628f
+	}
0b628f
+
0b628f
+	if (xccdf_session_generate_guide(session, action->f_results) == 0) {
0b628f
+		ret = OSCAP_OK;
0b628f
+	}
0b628f
+
0b628f
+cleanup:
0b628f
+	xccdf_session_free(session);
0b628f
+	oscap_print_error();
0b628f
+	return ret;
0b628f
+}
0b628f
+
0b628f
 int app_xccdf_xslt(const struct oscap_action *action)
0b628f
 {
0b628f
 	const char *oval_template = action->oval_template;
0b628f
diff --git a/utils/oscap.8 b/utils/oscap.8
0b628f
index 1b05f8c9e..3a50d1df5 100644
0b628f
--- a/utils/oscap.8
0b628f
+++ b/utils/oscap.8
0b628f
@@ -331,10 +331,19 @@ Generate a HTML document containing a security guide from an XCCDF Benchmark. Un
0b628f
 Write the guide to this file instead of standard output.
0b628f
 .TP
0b628f
 \fB\-\-hide-profile-info\fR
0b628f
-Information on chosen profile (e.g. rules selected by the profile) will be excluded from the document.
0b628f
+This option has no effect and is kept only for backward compatibility purposes.
0b628f
 .TP
0b628f
 \fB\-\-benchmark-id ID\fR
0b628f
 Selects a component ref from any datastream that references a component with XCCDF Benchmark such that its @id attribute matches given string exactly.
0b628f
+.TP
0b628f
+\fB\-\-xccdf-id ID\fR
0b628f
+Takes component ref with given ID from checklists. This allows to select a particular XCCDF component even in cases where there are 2 XCCDFs in one datastream. If none is given, the first component from the checklists element is used.
0b628f
+.TP
0b628f
+\fB\-\-tailoring-file TAILORING_FILE\fR
0b628f
+Use given file for XCCDF tailoring. Select profile from tailoring file to apply using --profile. If both --tailoring-file and --tailoring-id are specified, --tailoring-file takes priority.
0b628f
+.TP
0b628f
+\fB\-\-tailoring-id COMPONENT_REF_ID\fR
0b628f
+Use tailoring component in input source datastream for XCCDF tailoring. The tailoring component must be specified by its Ref-ID (value of component-ref/@id attribute in input source datastream). Select profile from tailoring component to apply using --profile. If both --tailoring-file and --tailoring-id are specified, --tailoring-file takes priority.
0b628f
 .RE
0b628f
 .TP
0b628f
 .B \fBreport\fR  [\fIoptions\fR] xccdf-file