diff --git a/schemas/oval/5.11.3/independent-definitions-schema.xsd b/schemas/oval/5.11.3/independent-definitions-schema.xsd index 53e67e1..d9a891d 100644 --- a/schemas/oval/5.11.3/independent-definitions-schema.xsd +++ b/schemas/oval/5.11.3/independent-definitions-schema.xsd @@ -2115,7 +2115,7 @@ - Specifies an YAML Path expression to evaluate against the YAML file specified by the filename entity. This YAML Path expression must evaluate to a list of zero or more scalar values which will be accessible in OVAL via instances of the value_of entity. Any results from evaluating the YAML Path expression other than a list of scalar values (e.g., a hash or list of lists) is considered an error. The intention is that the scalar values be drawn from instances of a single, uniquely named element. However, an OVAL interpreter is not required to verify this, so the author should define the YAML Path expression carefully. Note that "equals" is the only valid operator for the yamlpath entity. + Specifies an YAML Path expression to evaluate against the YAML file specified by the filename entity. This YAML Path expression must evaluate to a sequence or a map (part of a map) of scalar values which will be accessible in OVAL via instances of the value entity. Any results from evaluating the YAML Path expression other than a sequence (or a map) of scalar values (e.g. sequence of sequences, sequence of maps, map of maps etc.) are considered as incorrect, so the author should define the YAML Path expression carefully. Note that "equals" is the only valid operator for the yamlpath entity. @@ -2158,13 +2158,24 @@ - Specifies an YAML Path expression to evaluate against the YAML file specified by the filename entity. This YAML Path expression must evaluate to a list of zero or more text values which will be accessible in OVAL via instances of the value_of entity. Any results from evaluating the YAML Path expression other than a list of text strings (e.g., a nodes set) is considered an error. The intention is that the text values be drawn from instances of a single, uniquely named element or attribute. However, an OVAL interpreter is not required to verify this, so the author should define the YAML Path expression carefully. Note that "equals" is the only valid operator for the yamlpath entity. + Specifies an YAML Path expression to evaluate against the YAML file specified by the filename entity. Note that "equals" is the only valid operator for the yamlpath entity. - + - The value_of element checks the value(s) of the text node(s) or attribute(s) found. + The value entity specifies how to test objects in the value set of the specified YAML Path. To define tests for a single scalar value or a list of scalar values (where there is no key to associate), set the name attribute of the field element to '#'. Due to the limitation of the record type field names could not contain uppercase letters, they should be converted to the lowercase and escaped using the '^' symbol (the '^' symbol should be escaped as well). For example, to check a value associated with 'myCamelCase^Key' set the name attribute of the field to 'my^camel^case^^^key'. The check is entirely controlled by operator attributes of the field element. + + + + - datatype attribute for the value entity of a yamlfile_state must be 'record' + + + + + + + diff --git a/schemas/oval/5.11.3/independent-system-characteristics-schema.xsd b/schemas/oval/5.11.3/independent-system-characteristics-schema.xsd index 19c6a24..c2a2aab 100644 --- a/schemas/oval/5.11.3/independent-system-characteristics-schema.xsd +++ b/schemas/oval/5.11.3/independent-system-characteristics-schema.xsd @@ -606,12 +606,19 @@ - Specifies an YAML Path expression to evaluate against the YAML file specified by the filename entity. This YAML Path expression must evaluate to a list of zero or more scalar values which will be accessible in OVAL via instances of the value_of entity. Any results from evaluating the YAML Path expression other than a list of scalar values (e.g., a hash or list of lists) is considered an error. The intention is that the scalar values be drawn from instances of a single, uniquely named element. However, an OVAL interpreter is not required to verify this, so the author should define the YAML Path expression carefully. Note that "equals" is the only valid operator for the yamlpath entity. + Specifies an YAML Path expression to evaluate against the YAML file specified by the filename entity. Note that "equals" is the only valid operator for the yamlpath entity. - + - The value_of element checks the value(s) of the text node(s) or attribute(s) found. How this is used is entirely controlled by operator attributes. + The value entity holds the target(s) of the specified YAML Path. A single scalar value or a list of scalar values (where there is no key to associate) would have the name attribute of the field element set to '#'. Due to the limitation of the record type field names could not contain uppercase letters, they will be converted to the lowercase and escaped using the '^' symbol (the '^' symbol would be escaped as well). For example 'myCamelCase^Key' would be collected as 'my^camel^case^^^key'. + + + + - datatype attribute for the value entity of a yamlfile_item must be 'record' + + + diff --git a/src/OVAL/oval_recordField.c b/src/OVAL/oval_recordField.c index a0c8a6a..dd76509 100644 --- a/src/OVAL/oval_recordField.c +++ b/src/OVAL/oval_recordField.c @@ -208,7 +208,7 @@ void oval_record_field_set_mask(struct oval_record_field *rf, int mask) void oval_record_field_set_operation(struct oval_record_field *rf, oval_operation_t operation) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (set operation): %d.", rf->record_field_type); return; } @@ -218,7 +218,7 @@ void oval_record_field_set_operation(struct oval_record_field *rf, oval_operatio void oval_record_field_set_variable(struct oval_record_field *rf, struct oval_variable *var) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (set variable): %d.", rf->record_field_type); return; } @@ -228,7 +228,7 @@ void oval_record_field_set_variable(struct oval_record_field *rf, struct oval_va void oval_record_field_set_var_check(struct oval_record_field *rf, oval_check_t var_check) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (set var_check): %d.", rf->record_field_type); return; } @@ -238,7 +238,7 @@ void oval_record_field_set_var_check(struct oval_record_field *rf, oval_check_t void oval_record_field_set_ent_check(struct oval_record_field *rf, oval_check_t ent_check) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (set ent_check): %d.", rf->record_field_type); return; } @@ -248,7 +248,7 @@ void oval_record_field_set_ent_check(struct oval_record_field *rf, oval_check_t void oval_record_field_set_status(struct oval_record_field *rf, oval_syschar_status_t status) { if (rf->record_field_type != OVAL_RECORD_FIELD_ITEM) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (set status): %d.", rf->record_field_type); return; } @@ -283,7 +283,7 @@ int oval_record_field_get_mask(struct oval_record_field *rf) oval_operation_t oval_record_field_get_operation(struct oval_record_field *rf) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (get operation): %d.", rf->record_field_type); return OVAL_OPERATION_UNKNOWN; } @@ -293,7 +293,7 @@ oval_operation_t oval_record_field_get_operation(struct oval_record_field *rf) struct oval_variable *oval_record_field_get_variable(struct oval_record_field *rf) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (get variable): %d.", rf->record_field_type); return NULL; } @@ -303,7 +303,7 @@ struct oval_variable *oval_record_field_get_variable(struct oval_record_field *r oval_check_t oval_record_field_get_var_check(struct oval_record_field *rf) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (get var_check): %d.", rf->record_field_type); return OVAL_CHECK_UNKNOWN; } @@ -313,7 +313,7 @@ oval_check_t oval_record_field_get_var_check(struct oval_record_field *rf) oval_check_t oval_record_field_get_ent_check(struct oval_record_field *rf) { if (rf->record_field_type != OVAL_RECORD_FIELD_STATE) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (get ent_check): %d.", rf->record_field_type); return OVAL_CHECK_UNKNOWN; } @@ -323,7 +323,7 @@ oval_check_t oval_record_field_get_ent_check(struct oval_record_field *rf) oval_syschar_status_t oval_record_field_get_status(struct oval_record_field *rf) { if (rf->record_field_type != OVAL_RECORD_FIELD_ITEM) { - dE("Wrong record field type: %d.", rf->record_field_type); + dE("Wrong record field type (get status): %d.", rf->record_field_type); return SYSCHAR_STATUS_UNKNOWN; } diff --git a/src/OVAL/probes/independent/yamlfilecontent_probe.c b/src/OVAL/probes/independent/yamlfilecontent_probe.c index b8a3793..1e3c62f 100644 --- a/src/OVAL/probes/independent/yamlfilecontent_probe.c +++ b/src/OVAL/probes/independent/yamlfilecontent_probe.c @@ -72,7 +72,7 @@ static SEXP_t *yaml_scalar_event_to_sexp(yaml_event_t *event) char *tag = (char *) event->data.scalar.tag; char *value = (char *) event->data.scalar.value; - /* nodes lacking an explicit tag are given a non-specific tag: + /* Nodes lacking an explicit tag are given a non-specific tag: * “!” for non-plain scalars, and “?” for all other nodes */ if (tag == NULL) { @@ -138,30 +138,63 @@ static SEXP_t *yaml_scalar_event_to_sexp(yaml_event_t *event) return SEXP_string_new(value, strlen(value)); } +static char *escape_key(char *key) +{ + if (key == NULL) + return NULL; + + size_t cap_letters = 0; + size_t key_len = strlen(key); + for (size_t i = 0; i < key_len; i++) + if ((key[i] >= 'A' && key[i] <= 'Z') || key[i] == '^') + cap_letters++; + + if (cap_letters == 0) + return key; + + char *new_key = realloc(key, key_len + 1 + cap_letters); + if (new_key == NULL) + return key; + new_key[key_len + cap_letters] = '\0'; + + for (ssize_t i = key_len; i >= 0; i--) { + if ((new_key[i] >= 'A' && new_key[i] <= 'Z') || new_key[i] == '^') { + if (new_key[i] != '^') + new_key[i] += 32; + memmove(new_key + i + cap_letters, new_key + i, key_len - i); + new_key[i + cap_letters - 1] = '^'; + cap_letters--; + key_len = i; + } + } + + return new_key; +} + +#define result_error(fmt, args...) \ +do { \ + SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, fmt, args); \ + probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); \ + SEXP_free(msg); \ + probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); \ + ret = -1; \ +} while (0) + static int yaml_path_query(const char *filepath, const char *yaml_path_cstr, struct oscap_list *values, probe_ctx *ctx) { int ret = 0; FILE *yaml_file = fopen(filepath, "r"); if (yaml_file == NULL) { - SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, - "Unable to open file '%s': %s", filepath, strerror(errno)); - probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); - SEXP_free(msg); - probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); - return -1; + result_error("Unable to open file '%s': %s", filepath, strerror(errno)); + return ret; } yaml_path_t *yaml_path = yaml_path_create(); if (yaml_path_parse(yaml_path, (char *) yaml_path_cstr)) { - SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, - "Invalid YAML path '%s' (%s)\n", yaml_path_cstr, - yaml_path_error_get(yaml_path)->message); - probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); - SEXP_free(msg); - probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); + result_error("Invalid YAML path '%s': %s", yaml_path_cstr, yaml_path_error_get(yaml_path)->message); yaml_path_destroy(yaml_path); fclose(yaml_file); - return -1; + return ret; }; yaml_parser_t parser; @@ -171,71 +204,98 @@ static int yaml_path_query(const char *filepath, const char *yaml_path_cstr, str yaml_event_t event; yaml_event_type_t event_type; bool sequence = false; + bool mapping = false; + int index = 0; + char *key = strdup("#"); + + struct oscap_htable *record = NULL; do { if (!yaml_parser_parse(&parser, &event)) { - SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, - "YAML parser error: yaml_parse_parse returned 0: %s", - parser.problem); - probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); - SEXP_free(msg); - probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); - ret = -1; + result_error("YAML parser error: %s", parser.problem); goto cleanup; } - - event_type = event.type; - if (!yaml_path_filter_event(yaml_path, &parser, &event, - YAML_PATH_FILTER_RETURN_ALL)) { + if (yaml_path_filter_event(yaml_path, &parser, &event) == YAML_PATH_FILTER_RESULT_OUT) { goto next; } + + event_type = event.type; + if (sequence) { if (event_type == YAML_SEQUENCE_END_EVENT) { sequence = false; - } else if (event_type != YAML_SCALAR_EVENT) { - SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, - "YAML path '%s' contains non-scalar in a sequence.", - yaml_path_cstr); - probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); - SEXP_free(msg); - probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); - ret = -1; + } else if (event_type == YAML_SEQUENCE_START_EVENT) { + result_error("YAML path '%s' points to a multi-dimensional structure (sequence containing another sequence)", yaml_path_cstr); goto cleanup; } } else { if (event_type == YAML_SEQUENCE_START_EVENT) { sequence = true; } - if (event_type == YAML_MAPPING_START_EVENT) { - SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, - "YAML path '%s' matches a mapping.", - yaml_path_cstr); - probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); - SEXP_free(msg); - probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); - ret = -1; + } + + if (mapping) { + if (event_type == YAML_MAPPING_END_EVENT) { + mapping = false; + if (record->itemcount > 0) { + oscap_list_add(values, record); + } else { + // Do not collect empty records + oscap_htable_free0(record); + } + record = NULL; + } else if (event_type == YAML_MAPPING_START_EVENT) { + result_error("YAML path '%s' points to a multi-dimensional structure (map containing another map)", yaml_path_cstr); goto cleanup; } + } else { + if (event_type == YAML_MAPPING_START_EVENT) { + if (record) { + result_error("YAML path '%s' points to an invalid structure (map containing another map)", yaml_path_cstr); + goto cleanup; + } + mapping = true; + sequence = false; + index = 0; + record = oscap_htable_new(); + } } + if (event_type == YAML_SCALAR_EVENT) { + if (mapping) { + if (!sequence) { + if (index++ % 2 == 0) { + free(key); + key = escape_key(strdup((const char *) event.data.scalar.value)); + goto next; + } + } + } + SEXP_t *sexp = yaml_scalar_event_to_sexp(&event); if (sexp == NULL) { - SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, - "Can't convert '%s %s' to SEXP", event.data.scalar.tag, - event.data.scalar.value); - probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); - SEXP_free(msg); - probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); - ret = -1; + result_error("Can't convert '%s %s' to SEXP", event.data.scalar.tag, event.data.scalar.value); goto cleanup; } - oscap_list_add(values, sexp); + + if (!record) + record = oscap_htable_new(); + struct oscap_list *field = oscap_htable_get(record, key); + if (!field) { + field = oscap_list_new(); + oscap_htable_add(record, key, field); + } + + oscap_list_add(field, sexp); } next: yaml_event_delete(&event); } while (event_type != YAML_STREAM_END_EVENT); cleanup: + if (record) + oscap_list_add(values, record); + free(key); yaml_parser_delete(&parser); yaml_path_destroy(yaml_path); fclose(yaml_file); @@ -243,6 +303,16 @@ cleanup: return ret; } +static void record_free(struct oscap_list *items) +{ + oscap_list_free(items, (oscap_destruct_func) SEXP_free); +} + +static void values_free(struct oscap_htable *record) +{ + oscap_htable_free(record, (oscap_destruct_func) record_free); +} + static int process_yaml_file(const char *prefix, const char *path, const char *filename, const char *yamlpath, probe_ctx *ctx) { int ret = 0; @@ -264,21 +334,38 @@ static int process_yaml_file(const char *prefix, const char *path, const char *f "path", OVAL_DATATYPE_STRING, path, "filename", OVAL_DATATYPE_STRING, filename, "yamlpath", OVAL_DATATYPE_STRING, yamlpath, - /* - "windows_view", - */ + // TODO: Implement "windows_view", NULL ); while (oscap_iterator_has_more(values_it)) { - SEXP_t *value_sexp = oscap_iterator_next(values_it); - probe_item_ent_add(item, "value_of", NULL, value_sexp); + SEXP_t *result_ent = probe_ent_creat1("value", NULL, NULL); + probe_ent_setdatatype(result_ent, OVAL_DATATYPE_RECORD); + struct oscap_htable *record = oscap_iterator_next(values_it); + struct oscap_htable_iterator *record_it = oscap_htable_iterator_new(record); + while(oscap_htable_iterator_has_more(record_it)) { + const struct oscap_htable_item *record_item = oscap_htable_iterator_next(record_it); + struct oscap_iterator *item_value_it = oscap_iterator_new(record_item->value); + SEXP_t se_tmp_mem; + SEXP_t *key = SEXP_string_new_r(&se_tmp_mem, record_item->key, strlen(record_item->key)); + while(oscap_iterator_has_more(item_value_it)) { + SEXP_t *value_sexp = oscap_iterator_next(item_value_it); + SEXP_t *field = probe_ent_creat1("field", NULL, value_sexp); + probe_item_attr_add(field, "name", key); + SEXP_list_add(result_ent, field); + } + oscap_iterator_free(item_value_it); + SEXP_free_r(&se_tmp_mem); + } + oscap_htable_iterator_free(record_it); + SEXP_list_add(item, result_ent); + SEXP_free(result_ent); } probe_item_collect(ctx, item); } oscap_iterator_free(values_it); cleanup: - oscap_list_free(values, (oscap_destruct_func) SEXP_free); + oscap_list_free(values, (oscap_destruct_func) values_free); free(filepath_with_prefix); free(filepath); return ret; diff --git a/src/OVAL/results/oval_cmp.c b/src/OVAL/results/oval_cmp.c index 24a5e55..a9549ba 100644 --- a/src/OVAL/results/oval_cmp.c +++ b/src/OVAL/results/oval_cmp.c @@ -161,9 +161,3 @@ oval_result_t oval_str_cmp_str(char *state_data, oval_datatype_t state_data_type oscap_seterr(OSCAP_EFAMILY_OVAL, "Invalid OVAL data type: %d.", state_data_type); return OVAL_RESULT_ERROR; } - -oval_result_t oval_ent_cmp_str(char *state_data, oval_datatype_t state_data_type, struct oval_sysent *sysent, oval_operation_t operation) -{ - const char *sys_data = oval_sysent_get_value(sysent); - return oval_str_cmp_str(state_data, state_data_type, sys_data, operation); -} diff --git a/src/OVAL/results/oval_cmp_impl.h b/src/OVAL/results/oval_cmp_impl.h index 4e38810..0101476 100644 --- a/src/OVAL/results/oval_cmp_impl.h +++ b/src/OVAL/results/oval_cmp_impl.h @@ -30,16 +30,6 @@ /** - * Compare state entity (or variable/value) to sysent object collected from system. - * This function does not support @datatype="record". - * @param state_value Value defined within state/entity/value or variable/value - * @param sysent Value collected from system - * @operation Comparison type operation - * @returns OVAL Result of comparison - */ -oval_result_t oval_ent_cmp_str(char *state_data, oval_datatype_t state_data_type, struct oval_sysent *sysent, oval_operation_t operation); - -/** * Compare state entity (or variable/value) to data collected from system. * This function does not support @datatype="record". * @param state_data Value defined within state/entity/value or variable/value diff --git a/src/OVAL/results/oval_resultTest.c b/src/OVAL/results/oval_resultTest.c index c906b99..60d1039 100644 --- a/src/OVAL/results/oval_resultTest.c +++ b/src/OVAL/results/oval_resultTest.c @@ -381,17 +381,11 @@ oval_result_t ores_get_result_byopr(struct oresults *ores, oval_operator_t op) return result; } -static inline oval_result_t _evaluate_sysent_with_variable(struct oval_syschar_model *syschar_model, struct oval_entity *state_entity, struct oval_sysent *item_entity, oval_operation_t state_entity_operation, struct oval_state_content *content) +static inline oval_result_t _evaluate_sysent_with_variable(struct oval_syschar_model *syschar_model, struct oval_variable *state_entity_var, const char *sys_data, oval_operation_t state_entity_operation, oval_check_t var_check) { oval_syschar_collection_flag_t flag; oval_result_t ent_val_res; - struct oval_variable *state_entity_var; - if ((state_entity_var = oval_entity_get_variable(state_entity)) == NULL) { - oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL variable"); - return -1; - } - if (0 != oval_syschar_model_compute_variable(syschar_model, state_entity_var)) { return -1; } @@ -420,16 +414,15 @@ static inline oval_result_t _evaluate_sysent_with_variable(struct oval_syschar_m } oval_datatype_t state_entity_val_datatype = oval_value_get_datatype(var_val); - var_val_res = oval_ent_cmp_str(state_entity_val_text, state_entity_val_datatype, item_entity, state_entity_operation); + var_val_res = oval_str_cmp_str(state_entity_val_text, state_entity_val_datatype, sys_data, state_entity_operation); if (var_val_res == OVAL_RESULT_ERROR) { dE("Error occured when comparing a variable '%s' value '%s' with collected item entity = '%s'", - oval_variable_get_id(state_entity_var), state_entity_val_text, oval_sysent_get_value(item_entity)); + oval_variable_get_id(state_entity_var), state_entity_val_text, sys_data); } ores_add_res(&var_ores, var_val_res); } oval_value_iterator_free(val_itr); - oval_check_t var_check = oval_state_content_get_var_check(content); ent_val_res = ores_get_result_bychk(&var_ores, var_check); } break; case SYSCHAR_FLAG_ERROR: @@ -450,6 +443,9 @@ struct record_field_instance { char *value; oval_datatype_t data_type; oval_check_t ent_check; + oval_operation_t operation; + struct oval_variable *var; + oval_check_t var_check; }; static struct record_field_instance _oval_record_field_iterator_next_instance(struct oval_record_field_iterator *iterator) @@ -461,11 +457,14 @@ static struct record_field_instance _oval_record_field_iterator_next_instance(st instance.data_type = oval_record_field_get_datatype(rf); if (oval_record_field_get_type(rf) == OVAL_RECORD_FIELD_STATE) { instance.ent_check = oval_record_field_get_ent_check(rf); + instance.operation = oval_record_field_get_operation(rf); + instance.var = oval_record_field_get_variable(rf); + instance.var_check = oval_record_field_get_var_check(rf); } return instance; } -static oval_result_t _evaluate_sysent_record(struct oval_state_content *state_content, struct oval_sysent *item_entity) +static oval_result_t _evaluate_sysent_record(struct oval_syschar_model *syschar_model, struct oval_state_content *state_content, struct oval_sysent *item_entity) { struct oresults record_ores; ores_clear(&record_ores); @@ -485,7 +484,12 @@ static oval_result_t _evaluate_sysent_record(struct oval_state_content *state_co struct record_field_instance item_rf = _oval_record_field_iterator_next_instance(item_it); if (strcmp(state_rf.name, item_rf.name) == 0) { field_found = true; - oval_result_t fields_comparison_result = oval_str_cmp_str(state_rf.value, state_rf.data_type, item_rf.value, OVAL_OPERATION_EQUALS); + oval_result_t fields_comparison_result; + if (state_rf.var != NULL) { + fields_comparison_result = _evaluate_sysent_with_variable(syschar_model, state_rf.var, item_rf.value, state_rf.operation, state_rf.var_check); + } else { + fields_comparison_result = oval_str_cmp_str(state_rf.value, state_rf.data_type, item_rf.value, state_rf.operation); + } ores_add_res(&field_ores, fields_comparison_result); } } @@ -510,10 +514,17 @@ static inline oval_result_t _evaluate_sysent(struct oval_syschar_model *syschar_ if (oval_sysent_get_status(item_entity) == SYSCHAR_STATUS_DOES_NOT_EXIST) { return OVAL_RESULT_FALSE; } else if (oval_entity_get_varref_type(state_entity) == OVAL_ENTITY_VARREF_ATTRIBUTE) { + struct oval_variable *state_entity_var; + if ((state_entity_var = oval_entity_get_variable(state_entity)) == NULL) { + oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL variable"); + return -1; + } + const char *sys_data = oval_sysent_get_value(item_entity); + oval_check_t var_check = oval_state_content_get_var_check(content); return _evaluate_sysent_with_variable(syschar_model, - state_entity, item_entity, - state_entity_operation, content); + state_entity_var, sys_data, + state_entity_operation, var_check); } else { struct oval_value *state_entity_val; char *state_entity_val_text; @@ -525,7 +536,7 @@ static inline oval_result_t _evaluate_sysent(struct oval_syschar_model *syschar_ dE("The only allowed operation for comparing record types is 'equals'."); return OVAL_RESULT_ERROR; } - return _evaluate_sysent_record(content, item_entity); + return _evaluate_sysent_record(syschar_model, content, item_entity); } else { if ((state_entity_val = oval_entity_get_value(state_entity)) == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL entity value"); @@ -537,7 +548,8 @@ static inline oval_result_t _evaluate_sysent(struct oval_syschar_model *syschar_ } state_entity_val_datatype = oval_value_get_datatype(state_entity_val); - return oval_ent_cmp_str(state_entity_val_text, state_entity_val_datatype, item_entity, state_entity_operation); + const char *sys_data = oval_sysent_get_value(item_entity); + return oval_str_cmp_str(state_entity_val_text, state_entity_val_datatype, sys_data, state_entity_operation); } } } diff --git a/tests/probes/yamlfilecontent/openshift-logging.yaml b/tests/probes/yamlfilecontent/openshift-logging.yaml index a89e709..fb6a9d8 100644 --- a/tests/probes/yamlfilecontent/openshift-logging.yaml +++ b/tests/probes/yamlfilecontent/openshift-logging.yaml @@ -38,3 +38,31 @@ spec: inputSource: logs.audit outputRefs: - secureforward-offcluster +status: + conditions: + - lastTransitionTime: "2020-06-08T04:54:58Z" + reason: AsExpected + status: "False" + type: Degraded + - lastTransitionTime: "2020-06-08T06:34:00Z" + reason: AsExpected + status: "False" + type: Progressing + - lastTransitionTime: "2020-06-08T04:51:08Z" + reason: AsExpected + status: "True" + type: Available + - lastTransitionTime: "2020-06-08T04:45:45Z" + reason: AsExpected + status: "True" + type: Upgradeable + extension: null + relatedObjects: + - group: operator.openshift.io + name: cluster + resource: openshiftapiservers + versions: + - name: operator + version: 4.5.0-0.nightly-2020-06-04-214605 + - name: openshift-apiserver + version: 4.5.0-0.nightly-2020-06-04-214605 diff --git a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_array.xml b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_array.xml index 768b0b4..c05c5fb 100644 --- a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_array.xml +++ b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_array.xml @@ -62,7 +62,7 @@ /tmp openshift-logging.yaml - .spec.outputs[0:2].name + .spec.outputs[:].name @@ -76,11 +76,15 @@ - secureforward-offcluster + + secureforward-offcluster + - + + + diff --git a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.sh b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.sh index 300c1b4..fc1e0ae 100755 --- a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.sh +++ b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.sh @@ -19,7 +19,7 @@ function test_probes_yamlfilecontent_key { $OSCAP oval eval --results $RF $DF if [ -f $RF ]; then - verify_results "def" $DF $RF 3 && verify_results "tst" $DF $RF 4 + verify_results "def" $DF $RF 6 && verify_results "tst" $DF $RF 7 ret_val=$? else ret_val=1 diff --git a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.xml b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.xml index f055bb6..05757d0 100644 --- a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.xml +++ b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_key.xml @@ -21,7 +21,7 @@ - + @@ -41,6 +41,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -55,7 +94,7 @@ - + @@ -63,6 +102,23 @@ + + + + + + + + + + + + + + + + + @@ -91,16 +147,59 @@ .doesnt.exist + + /tmp + openshift-logging.yaml + .status.conditions[:]['status','type'] + + + + /tmp + openshift-logging.yaml + .status.conditions[:] + + + + /tmp + openshift-logging.yaml + .status.conditions[:]['nonexistent','dummy'] + + + + /tmp + openshift-logging.yaml + .spec.outputs + - LogForwarding + + LogForwarding + - openshift-logging + + openshift-logging + + + + + + True + Upgradeable + + + + + + True + AsExpected + Upgradeable + ^\d+-\d+-.*Z$ + diff --git a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_offline_mode.xml b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_offline_mode.xml index 675f528..35a6466 100644 --- a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_offline_mode.xml +++ b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_offline_mode.xml @@ -85,15 +85,21 @@ - instance + + instance + - outstance + + outstance + - instance + + instance + diff --git a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_types.sh b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_types.sh index 97bb33d..4f110f6 100755 --- a/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_types.sh +++ b/tests/probes/yamlfilecontent/test_probes_yamlfilecontent_types.sh @@ -24,51 +24,49 @@ function test_probes_yamlfilecontent_types { sd='/oval_results/results/system/oval_system_characteristics/system_data' - assert_exists 8 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="boolean"]' - assert_exists 4 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="boolean" and text()="true"]' - assert_exists 4 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="boolean" and text()="false"]' + assert_exists 8 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="boolean"]' + assert_exists 4 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="boolean" and text()="true"]' + assert_exists 4 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="boolean" and text()="false"]' - assert_exists 5 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="int"]' + assert_exists 5 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="int"]' # int_10: 42 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="int" and text()="42"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="int" and text()="42"]' # int_10_neg: -17 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="int" and text()="-17"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="int" and text()="-17"]' # int_8: 0o33 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="int" and text()="27"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="int" and text()="27"]' # int_16: 0xFF - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="int" and text()="255"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="int" and text()="255"]' # int_cast: !!int "369" - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="int" and text()="369"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="int" and text()="369"]' - assert_exists 7 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float"]' + assert_exists 7 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float"]' # float: 7.4 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="7.400000"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="7.400000"]' # float_neg: -0.3 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="-0.300000"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="-0.300000"]' # float_exp: +12e03 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="12000.000000"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="12000.000000"]' # float_exp_neg: -43e-4 - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="-0.004300"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="-0.004300"]' # float: .inf - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="inf"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="inf"]' # float: .NAN - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="nan"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="nan"]' # float_cast: !!float "978.65" - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype="float" and text()="978.650000"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype="float" and text()="978.650000"]' # string_true - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype!="boolean" and text()="true"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype!="boolean" and text()="true"]' # string_number - assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value_of[@datatype!="int" and text()="81"]' + assert_exists 1 $sd'/ind-sys:yamlfilecontent_item/ind-sys:value/field[@name="#" and @datatype!="int" and text()="81"]' # bool_error_cast, int_error_cast, float_error_cast co='/oval_results/results/system/oval_system_characteristics/collected_objects' assert_exists 3 $co'/object[@flag="error"]' assert_exists 3 $co'/object[@flag="error"]/message' - rm -f $result rm -f $YAML_FILE - } test_probes_yamlfilecontent_types