Skip to content

Commit 43a3ba0

Browse files
authored
Merge pull request #1426 from jan-cerny/multi_check_results
Show check identifiers at multi-check rules
2 parents 02c7831 + 10d17e8 commit 43a3ba0

11 files changed

+333
-216
lines changed

src/OVAL/oval_agent.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -630,19 +630,34 @@ _oval_agent_list_definitions(void *usr, xccdf_policy_engine_query_t query_type,
630630
{
631631
__attribute__nonnull__(usr);
632632
struct oval_agent_session *sess = (struct oval_agent_session *) usr;
633-
if (query_type != POLICY_ENGINE_QUERY_NAMES_FOR_HREF || (query_data != NULL && strcmp(sess->filename, (const char *) query_data)))
633+
if (query_data != NULL && strcmp(sess->filename, (const char *) query_data)) {
634634
return NULL;
635-
struct oval_definition_iterator *iterator = oval_definition_model_get_definitions(sess->def_model);
636-
struct oscap_stringlist *result = oscap_stringlist_new();
637-
struct oval_definition *oval_def;
638-
639-
while (oval_definition_iterator_has_more(iterator)) {
640-
oval_def = oval_definition_iterator_next(iterator);
641-
oscap_stringlist_add_string(result, oval_definition_get_id(oval_def));
642635
}
636+
if (query_type == POLICY_ENGINE_QUERY_NAMES_FOR_HREF) {
637+
struct oval_definition_iterator *iterator = oval_definition_model_get_definitions(sess->def_model);
638+
struct oscap_stringlist *result = oscap_stringlist_new();
639+
640+
while (oval_definition_iterator_has_more(iterator)) {
641+
struct oval_definition *oval_def = oval_definition_iterator_next(iterator);
642+
oscap_stringlist_add_string(result, oval_definition_get_id(oval_def));
643+
}
644+
645+
oval_definition_iterator_free(iterator);
646+
return result;
647+
} else if (query_type == POLICY_ENGINE_QUERY_OVAL_DEFS_FOR_HREF) {
648+
struct oval_definition_iterator *iterator = oval_definition_model_get_definitions(sess->def_model);
649+
struct oscap_list *result = oscap_list_new();
643650

644-
oval_definition_iterator_free(iterator);
645-
return result;
651+
while (oval_definition_iterator_has_more(iterator)) {
652+
struct oval_definition *oval_def = oval_definition_iterator_next(iterator);
653+
oscap_list_add(result, oval_def);
654+
}
655+
656+
oval_definition_iterator_free(iterator);
657+
return result;
658+
} else {
659+
return NULL;
660+
}
646661
}
647662

648663
bool xccdf_policy_model_register_engine_oval(struct xccdf_policy_model * model, struct oval_agent_session * usr)

src/XCCDF_POLICY/public/xccdf_policy.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <time.h>
3737
#include <oscap.h>
3838
#include "oscap_export.h"
39+
#include "oval_definitions.h"
3940

4041
/**
4142
* @struct xccdf_policy_model
@@ -70,6 +71,7 @@ struct xccdf_policy_iterator;
7071
*/
7172
typedef enum {
7273
POLICY_ENGINE_QUERY_NAMES_FOR_HREF = 1, /// Considering xccdf:check-content-ref, what are possible @name attributes for given href?
74+
POLICY_ENGINE_QUERY_OVAL_DEFS_FOR_HREF = 2, /// Considering xccdf:check-content-ref, what are OVAL definitions for given href?
7375
} xccdf_policy_engine_query_t;
7476

7577
/**
@@ -81,9 +83,11 @@ typedef enum {
8183
* is always user data as registered. Second argument defines the query. Third argument is
8284
* dependent on query and defined as follows:
8385
* - (const char *)href -- for POLICY_ENGINE_QUERY_NAMES_FOR_HREF
86+
* - (const char *)href -- for POLICY_ENGINE_QUERY_OVAL_DEFS_FOR_HREF
8487
*
8588
* Expected return type depends also on query as follows:
86-
* - (struct oscap_stringlists *) -- for POLICY_ENGINE_QUERY_NAMES_FOR_HREF
89+
* - (struct oscap_stringlist *) -- for POLICY_ENGINE_QUERY_NAMES_FOR_HREF
90+
* - (struct oscap_list *) -- for POLICY_ENGINE_QUERY_OVAL_DEFS_FOR_HREF
8791
* - NULL shall be returned if the function doesn't understand the query.
8892
*/
8993
typedef void *(*xccdf_policy_engine_query_fn) (void *, xccdf_policy_engine_query_t, void *);
@@ -259,6 +263,18 @@ typedef int (*policy_reporter_start)(struct xccdf_rule *, void *);
259263
*/
260264
OSCAP_API bool xccdf_policy_model_register_start_callback(struct xccdf_policy_model * model, policy_reporter_start func, void * usr);
261265

266+
typedef int (*policy_reporter_multicheck)(struct oval_definition*, void *);
267+
/**
268+
* Function to register callback for checking system that will be called
269+
* DURING each rule evaluation if rule sets multi-check="true".
270+
* @param model XCCDF Policy Model
271+
* @param func Callback - pointer to function called by XCCDF Policy system when rule parsed
272+
* @param usr optional parameter for passing user data to callback
273+
* @memberof xccdf_policy_model
274+
* @return true if callback registered successfully, false otherwise
275+
*/
276+
OSCAP_API bool xccdf_policy_model_register_multicheck_callback(struct xccdf_policy_model *model, policy_reporter_multicheck func, void *usr);
277+
262278
/************************************************************/
263279
/**
264280
* @name Getters

src/XCCDF_POLICY/xccdf_policy.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,20 +378,19 @@ xccdf_policy_evaluate_cb(struct xccdf_policy * policy, const char * sysname, con
378378
}
379379

380380
/**
381-
* Find all posible names for given check-content-ref/@href, considering also the check/@system.
382-
* This is usefull for multi-check="true" feature.
383-
* @return list of names (even empty) if the given href found, NULL otherwise.
381+
* Find all possible names for given check-content-ref/@href, considering also the check/@system.
382+
* This is useful for multi-check="true" feature.
383+
* @return list of OVAL definitions if the given href found, NULL otherwise.
384384
*/
385-
static struct oscap_stringlist *
386-
_xccdf_policy_get_namesfor_href(struct xccdf_policy *policy, const char *sysname, const char *href)
385+
static struct oscap_list *_xccdf_policy_get_oval_definitions_for_href(struct xccdf_policy *policy, const char *sysname, const char *href)
387386
{
388387
struct oscap_iterator *cb_it = _xccdf_policy_get_engines_by_sysname(policy, sysname);
389-
struct oscap_stringlist *result = NULL;
388+
struct oscap_list *result = NULL;
390389
while (oscap_iterator_has_more(cb_it) && result == NULL) {
391390
struct xccdf_policy_engine *engine = (struct xccdf_policy_engine *) oscap_iterator_next(cb_it);
392391
if (engine == NULL)
393392
break;
394-
result = xccdf_policy_engine_query(engine, POLICY_ENGINE_QUERY_NAMES_FOR_HREF, (void *) href);
393+
result = xccdf_policy_engine_query(engine, POLICY_ENGINE_QUERY_OVAL_DEFS_FOR_HREF, (void *) href);
395394
}
396395
oscap_iterator_free(cb_it);
397396
return result;
@@ -1048,24 +1047,27 @@ _xccdf_policy_rule_evaluate(struct xccdf_policy * policy, const struct xccdf_rul
10481047

10491048
if (content_name == NULL && xccdf_check_get_multicheck(check)) {
10501049
// parent element is Rule, @multi-check is required
1051-
struct oscap_stringlist *names = _xccdf_policy_get_namesfor_href(policy, system_name, href);
1052-
if (names != NULL) {
1050+
struct oscap_list *oval_definition_list = _xccdf_policy_get_oval_definitions_for_href(policy, system_name, href);
1051+
if (oval_definition_list != NULL) {
10531052
// multi-check is supported by checking-engine
1054-
struct oscap_string_iterator *name_it = oscap_stringlist_get_strings(names);
1055-
if (!oscap_string_iterator_has_more(name_it)) {
1053+
struct oscap_iterator *oval_definition_iterator = oscap_iterator_new(oval_definition_list);
1054+
if (!oscap_iterator_has_more(oval_definition_iterator)) {
10561055
// Super special case when oval file contains no definitions
10571056
// thus multi-check shall yield zero rule-results.
10581057
report = _xccdf_policy_report_rule_result(policy, result, rule, check, XCCDF_RESULT_UNKNOWN, "No definitions found for @multi-check.");
1059-
oscap_string_iterator_free(name_it);
1060-
oscap_stringlist_free(names);
1058+
oscap_iterator_free(oval_definition_iterator);
1059+
oscap_list_free(oval_definition_list, NULL);
10611060
xccdf_check_content_ref_iterator_free(content_it);
10621061
oscap_list_free(bindings, (oscap_destruct_func) xccdf_value_binding_free);
10631062
return report;
10641063
}
1065-
while (oscap_string_iterator_has_more(name_it)) {
1066-
const char *name = oscap_string_iterator_next(name_it);
1064+
while (oscap_iterator_has_more(oval_definition_iterator)) {
1065+
struct oval_definition *oval_definition = oscap_iterator_next(oval_definition_iterator);
1066+
if ((report = xccdf_policy_report_cb(policy, XCCDF_POLICY_OUTCB_MULTICHECK, (void *) oval_definition)) != 0) {
1067+
break;
1068+
}
10671069
struct xccdf_check *cloned_check = xccdf_check_clone(check);
1068-
xccdf_check_inject_content_ref(cloned_check, content, name);
1070+
xccdf_check_inject_content_ref(cloned_check, content, oval_definition_get_id(oval_definition));
10691071
int inner_ret = xccdf_policy_check_evaluate(policy, cloned_check);
10701072
if (inner_ret == -1) {
10711073
xccdf_check_free(cloned_check);
@@ -1074,12 +1076,13 @@ _xccdf_policy_rule_evaluate(struct xccdf_policy * policy, const struct xccdf_rul
10741076
}
10751077
if ((report = _xccdf_policy_report_rule_result(policy, result, rule, cloned_check, inner_ret, NULL)) != 0)
10761078
break;
1077-
if (oscap_string_iterator_has_more(name_it))
1079+
if (oscap_iterator_has_more(oval_definition_iterator)) {
10781080
if ((report = xccdf_policy_report_cb(policy, XCCDF_POLICY_OUTCB_START, (void *) rule)) != 0)
10791081
break;
1082+
}
10801083
}
1081-
oscap_string_iterator_free(name_it);
1082-
oscap_stringlist_free(names);
1084+
oscap_iterator_free(oval_definition_iterator);
1085+
oscap_list_free(oval_definition_list, NULL);
10831086
xccdf_check_content_ref_iterator_free(content_it);
10841087
oscap_list_free(bindings, (oscap_destruct_func) xccdf_value_binding_free);
10851088
xccdf_check_free(check);
@@ -1596,6 +1599,13 @@ bool xccdf_policy_model_register_output_callback(struct xccdf_policy_model * mod
15961599
return oscap_list_add(model->callbacks, reporter);
15971600
}
15981601

1602+
bool xccdf_policy_model_register_multicheck_callback(struct xccdf_policy_model *model, policy_reporter_multicheck func, void *usr)
1603+
{
1604+
__attribute__nonnull__(model);
1605+
struct reporter *reporter = reporter_new(XCCDF_POLICY_OUTCB_MULTICHECK, func, usr);
1606+
return oscap_list_add(model->callbacks, reporter);
1607+
}
1608+
15991609
struct xccdf_result * xccdf_policy_get_result_by_id(struct xccdf_policy * policy, const char * id) {
16001610

16011611
struct xccdf_result_iterator * result_it;

src/XCCDF_POLICY/xccdf_policy_engine.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ xccdf_test_result_type_t xccdf_policy_engine_eval(struct xccdf_policy_engine *en
6969
return ret;
7070
}
7171

72-
struct oscap_stringlist *xccdf_policy_engine_query(struct xccdf_policy_engine *engine, xccdf_policy_engine_query_t query_type, void *query_data)
72+
struct oscap_list *xccdf_policy_engine_query(struct xccdf_policy_engine *engine, xccdf_policy_engine_query_t query_type, void *query_data)
7373
{
7474
if (engine->query_fn == NULL)
7575
return NULL;
76-
return (struct oscap_stringlist *) engine->query_fn(engine->usr, query_type, query_data);
76+
return (struct oscap_list *) engine->query_fn(engine->usr, query_type, query_data);
7777
}

src/XCCDF_POLICY/xccdf_policy_engine_priv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ xccdf_test_result_type_t xccdf_policy_engine_eval(struct xccdf_policy_engine *en
7474
* @param query_data Additional data for the checking engine query.
7575
* @returns list of query results
7676
*/
77-
struct oscap_stringlist *xccdf_policy_engine_query(struct xccdf_policy_engine *engine, xccdf_policy_engine_query_t query_type, void *query_data);
77+
struct oscap_list *xccdf_policy_engine_query(struct xccdf_policy_engine *engine, xccdf_policy_engine_query_t query_type, void *query_data);
7878

7979

8080
#endif

src/XCCDF_POLICY/xccdf_policy_model_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#define XCCDF_POLICY_OUTCB_START "urn:xccdf:system:callback:start"
3434
#define XCCDF_POLICY_OUTCB_END "urn:xccdf:system:callback:output"
35+
#define XCCDF_POLICY_OUTCB_MULTICHECK "urn:xccdf:system:callback:multicheck"
3536

3637
/**
3738
* Remove checking engines with given system from xccdf_policy_model

tests/API/XCCDF/unittests/test_xccdf_check_content_ref_without_name_attr.oval.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
</generator>
1818
<definitions>
1919
<definition class="compliance" id="oval:moc.elpmaxe.www:def:1" version="1">
20-
<metadata><title>PASS</title><description>Bla.</description></metadata>
20+
<metadata><title>DEFINITION_1_TITLE_EXPECTED_PASS</title><description>Bla.</description></metadata>
2121
<criteria><criterion test_ref="oval:moc.elpmaxe.www:tst:1" comment="Is executable"/></criteria>
2222
</definition>
2323
<definition class="compliance" id="oval:moc.elpmaxe.www:def:2" version="1">
24-
<metadata><title>FAIL</title><description>Bla.</description></metadata>
24+
<metadata><title>DEFINITION_2_TITLE_EXPECTED_FAIL</title><description>Bla.</description></metadata>
2525
<criteria><criterion test_ref="oval:moc.elpmaxe.www:tst:2" comment="Is not executable"/></criteria>
2626
</definition>
2727
</definitions>

tests/API/XCCDF/unittests/test_xccdf_check_multi_check2.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ echo "Result file = $result"
2020
[ -f $stderr ]; [ ! -s $stderr ]; rm $stderr
2121
grep '^Result.*pass$' $stdout
2222
grep '^Result.*fail$' $stdout
23+
[ $(grep -c '^Rule.*xccdf_moc.elpmaxe.www_rule_1' $stdout) == 2 ]
24+
[ $(grep -c '^Title.*The only rule in this benchmark' $stdout) == 2 ]
25+
grep '^OVAL Definition ID.*oval:moc.elpmaxe.www:def:1$' $stdout
26+
grep '^OVAL Definition Title.*DEFINITION_1_TITLE_EXPECTED_PASS$' $stdout
27+
grep '^OVAL Definition ID.*oval:moc.elpmaxe.www:def:2$' $stdout
28+
grep '^OVAL Definition Title.*DEFINITION_2_TITLE_EXPECTED_FAIL$' $stdout
2329
rm $stdout
2430

2531
$OSCAP xccdf validate $result

tests/API/XCCDF/unittests/test_xccdf_check_multi_check2.xccdf.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<status>incomplete</status>
44
<version>1.0</version>
55
<Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_1">
6+
<title>The only rule in this benchmark</title>
67
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" multi-check="true">
78
<check-content-ref href="test_xccdf_check_content_ref_without_name_attr.oval.xml"/>
89
</check>

utils/oscap-xccdf.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,13 @@ static int callback_scr_result_progress(struct xccdf_rule_result *rule_result, v
420420
return 0;
421421
}
422422

423+
static int callback_scr_multicheck(struct oval_definition *definition, void *arg)
424+
{
425+
printf("OVAL Definition ID\t%s\n", oval_definition_get_id(definition));
426+
printf("OVAL Definition Title\t%s\n", oval_definition_get_title(definition));
427+
return 0;
428+
}
429+
423430
/*
424431
* Send XCCDF Rule Results info message to syslog
425432
*
@@ -462,6 +469,7 @@ static void _register_progress_callback(struct xccdf_session *session, bool prog
462469
xccdf_policy_model_register_start_callback(policy_model, callback_scr_rule,
463470
(void *) xccdf_session_get_xccdf_policy(session));
464471
xccdf_policy_model_register_output_callback(policy_model, callback_scr_result, NULL);
472+
xccdf_policy_model_register_multicheck_callback(policy_model, callback_scr_multicheck, NULL);
465473
}
466474
/* xccdf_policy_model_register_output_callback(policy_model, callback_syslog_result, NULL); */
467475
}

0 commit comments

Comments
 (0)