Skip to content

Commit c2a737a

Browse files
authored
Merge pull request #1319 from maltek/stig-viewer-handle-multiple-rules
improve --stig-viewer output when there is no 1:1 connection between rules
2 parents 5501753 + 97ea3d5 commit c2a737a

File tree

2 files changed

+76
-19
lines changed

2 files changed

+76
-19
lines changed

src/XCCDF/result.c

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,13 +1065,68 @@ void xccdf_result_to_dom(struct xccdf_result *result, xmlNode *result_node, xmlD
10651065
}
10661066
xccdf_setvalue_iterator_free(setvalues);
10671067

1068+
struct oscap_htable *nodes_by_rule_id = oscap_htable_new();
1069+
10681070
struct xccdf_rule_result_iterator *rule_results = xccdf_result_get_rule_results(result);
1071+
if (use_stig_rule_id) {
1072+
while (xccdf_rule_result_iterator_has_more(rule_results)) {
1073+
struct xccdf_rule_result *rule_result = xccdf_rule_result_iterator_next(rule_results);
1074+
1075+
const char *idref = xccdf_rule_result_get_idref(rule_result);
1076+
if (!idref)
1077+
continue;
1078+
1079+
xccdf_test_result_type_t test_res = xccdf_rule_result_get_result(rule_result);
1080+
1081+
const struct xccdf_item *item = xccdf_benchmark_get_member(associated_benchmark, XCCDF_RULE, idref);
1082+
if (!item)
1083+
continue;
1084+
1085+
struct oscap_reference_iterator *references = xccdf_item_get_references(item);
1086+
while (oscap_reference_iterator_has_more(references)) {
1087+
struct oscap_reference *ref = oscap_reference_iterator_next(references);
1088+
if (strcmp(oscap_reference_get_href(ref), DISA_STIG_VIEWER_HREF) == 0) {
1089+
const char *stig_rule_id = oscap_reference_get_title(ref);
1090+
1091+
xccdf_test_result_type_t other_res = (xccdf_test_result_type_t)oscap_htable_detach(nodes_by_rule_id, stig_rule_id);
1092+
xccdf_test_result_type_t wanted_res;
1093+
if (other_res == 0) {
1094+
wanted_res = test_res;
1095+
} else {
1096+
// if one test passed, and the other didn't, the other one should win
1097+
if (test_res == XCCDF_RESULT_PASS) {
1098+
wanted_res = other_res;
1099+
} else if (other_res == XCCDF_RESULT_PASS) {
1100+
wanted_res = test_res;
1101+
// if one had an error, that should win
1102+
} else if (test_res == XCCDF_RESULT_ERROR || other_res == XCCDF_RESULT_ERROR) {
1103+
wanted_res = XCCDF_RESULT_ERROR;
1104+
// next prio: failures
1105+
} else if (test_res == XCCDF_RESULT_FAIL || other_res == XCCDF_RESULT_FAIL) {
1106+
wanted_res = XCCDF_RESULT_FAIL;
1107+
// next prio: unknown
1108+
} else if (test_res == XCCDF_RESULT_UNKNOWN || other_res == XCCDF_RESULT_UNKNOWN) {
1109+
wanted_res = XCCDF_RESULT_UNKNOWN;
1110+
// otherwise, just pick the lower one (more or less arbitrarily)
1111+
} else {
1112+
wanted_res = (test_res < other_res) ? test_res : other_res;
1113+
}
1114+
}
1115+
oscap_htable_add(nodes_by_rule_id, stig_rule_id, (void*)wanted_res);
1116+
}
1117+
}
1118+
oscap_reference_iterator_free(references);
1119+
}
1120+
xccdf_rule_result_iterator_reset(rule_results);
1121+
}
10691122
while (xccdf_rule_result_iterator_has_more(rule_results)) {
10701123
struct xccdf_rule_result *rule_result = xccdf_rule_result_iterator_next(rule_results);
1071-
xccdf_rule_result_to_dom(rule_result, doc, result_node, version_info, associated_benchmark, use_stig_rule_id);
1124+
xccdf_rule_result_to_dom(rule_result, doc, result_node, version_info, associated_benchmark, use_stig_rule_id, nodes_by_rule_id);
10721125
}
10731126
xccdf_rule_result_iterator_free(rule_results);
10741127

1128+
oscap_htable_free0(nodes_by_rule_id);
1129+
10751130
struct xccdf_score_iterator *scores = xccdf_result_get_scores(result);
10761131
while (xccdf_score_iterator_has_more(scores)) {
10771132
struct xccdf_score *score = xccdf_score_iterator_next(scores);
@@ -1221,36 +1276,39 @@ xmlNode *xccdf_target_identifier_to_dom(const struct xccdf_target_identifier *ti
12211276
return target_idref_node;
12221277
}
12231278
}
1224-
1225-
xmlNode *xccdf_rule_result_to_dom(struct xccdf_rule_result *result, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info, struct xccdf_benchmark *benchmark, bool use_stig_rule_id)
1279+
static void _xccdf_rule_result_to_dom_idref(struct xccdf_rule_result *result, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info, struct xccdf_benchmark *benchmark, const char *idref);
1280+
void xccdf_rule_result_to_dom(struct xccdf_rule_result *result, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info, struct xccdf_benchmark *benchmark, bool use_stig_rule_id, struct oscap_htable *nodes_by_rule_id)
12261281
{
12271282
const char *idref = xccdf_rule_result_get_idref(result);
12281283
if (use_stig_rule_id) {
12291284
// Don't output rules with no stig ids
12301285
if (!idref || !benchmark)
1231-
return NULL;
1286+
return;
12321287

1233-
struct xccdf_item *item = xccdf_benchmark_get_member(benchmark, XCCDF_RULE, idref);
1288+
const struct xccdf_item *item = xccdf_benchmark_get_member(benchmark, XCCDF_RULE, idref);
12341289
if (!item)
1235-
return NULL;
1290+
return;
12361291

1237-
const char *stig_rule_id = NULL;
1238-
struct oscap_reference_iterator *references = xccdf_item_get_references(XRULE(item));
1292+
struct oscap_reference_iterator *references = xccdf_item_get_references(item);
12391293
while (oscap_reference_iterator_has_more(references)) {
12401294
struct oscap_reference *ref = oscap_reference_iterator_next(references);
12411295
if (strcmp(oscap_reference_get_href(ref), DISA_STIG_VIEWER_HREF) == 0) {
1242-
stig_rule_id = oscap_reference_get_title(ref);
1243-
break;
1296+
const char *stig_rule_id = oscap_reference_get_title(ref);
1297+
1298+
xccdf_test_result_type_t expected_res = (xccdf_test_result_type_t)oscap_htable_get(nodes_by_rule_id, stig_rule_id);
1299+
xccdf_test_result_type_t test_res = xccdf_rule_result_get_result(result);
1300+
if (expected_res == test_res) {
1301+
oscap_htable_detach(nodes_by_rule_id, stig_rule_id);
1302+
_xccdf_rule_result_to_dom_idref(result, doc, parent, version_info, benchmark, stig_rule_id);
1303+
}
12441304
}
12451305
}
12461306
oscap_reference_iterator_free(references);
1247-
1248-
if (!stig_rule_id)
1249-
return NULL;
1250-
1251-
idref = stig_rule_id;
1307+
} else {
1308+
_xccdf_rule_result_to_dom_idref(result, doc, parent, version_info, benchmark, idref);
12521309
}
1253-
1310+
}
1311+
static void _xccdf_rule_result_to_dom_idref(struct xccdf_rule_result *result, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info, struct xccdf_benchmark *benchmark, const char *idref) {
12541312
xmlNs *ns_xccdf = lookup_xccdf_ns(doc, parent, version_info);
12551313

12561314
xmlNode *result_node = xmlNewTextChild(parent, ns_xccdf, BAD_CAST "rule-result", NULL);
@@ -1343,8 +1401,6 @@ xmlNode *xccdf_rule_result_to_dom(struct xccdf_rule_result *result, xmlDoc *doc,
13431401
xccdf_check_to_dom(check, doc, result_node, version_info);
13441402
}
13451403
xccdf_check_iterator_free(checks);
1346-
1347-
return result_node;
13481404
}
13491405

13501406
bool xccdf_rule_result_override(struct xccdf_rule_result *rule_result, xccdf_test_result_type_t new_result, const char *waiver_time, const char *authority, struct oscap_text *remark)

src/XCCDF/xccdf_impl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <public/xccdf_benchmark.h>
2828
#include <common/util.h>
2929
#include <libxml/xmlreader.h>
30+
#include <common/list.h>
3031

3132

3233
#define XCCDF_DC_NAMESPACE BAD_CAST "http://purl.org/dc/elements/1.1/"
@@ -48,7 +49,7 @@ void xccdf_group_to_dom(struct xccdf_group *group, xmlNode *group_node, xmlDoc *
4849
void xccdf_profile_to_dom(struct xccdf_profile *profile, xmlNode *profile_node, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info *version_info);
4950
void xccdf_result_to_dom(struct xccdf_result *result, xmlNode *result_node, xmlDoc *doc, xmlNode *parent, bool use_stig_rule_id);
5051
xmlNode *xccdf_target_identifier_to_dom(const struct xccdf_target_identifier *ti, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info);
51-
xmlNode *xccdf_rule_result_to_dom(struct xccdf_rule_result *result, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info, struct xccdf_benchmark *benchmark, bool use_stig_rule_id);
52+
void xccdf_rule_result_to_dom(struct xccdf_rule_result *result, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info, struct xccdf_benchmark *benchmark, bool use_stig_rule_id, struct oscap_htable *nodes_by_rule_id);
5253
xmlNode *xccdf_ident_to_dom(struct xccdf_ident *ident, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info);
5354
xmlNode *xccdf_setvalue_to_dom(struct xccdf_setvalue *setvalue, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info);
5455
xmlNode *xccdf_override_to_dom(struct xccdf_override *override, xmlDoc *doc, xmlNode *parent, const struct xccdf_version_info* version_info);

0 commit comments

Comments
 (0)