static oval_result_t _oval_result_test_evaluate_items(struct oval_test *test, struct oval_syschar *syschar_object, void **args) { struct oval_sysitem_iterator *collected_items_itr; oval_result_t result; int exists_cnt, error_cnt; bool hasstate; oval_check_t test_check; oval_existence_t test_check_existence; struct oval_state_iterator *ste_itr; exists_cnt = error_cnt = 0; collected_items_itr = oval_syschar_get_sysitem(syschar_object); while (oval_sysitem_iterator_has_more(collected_items_itr)) { struct oval_sysitem *item; char *item_id; oval_syschar_status_t item_status; struct oval_result_item *ritem; item = oval_sysitem_iterator_next(collected_items_itr); if (item == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "Iterator returned null."); oval_sysitem_iterator_free(collected_items_itr); return OVAL_RESULT_ERROR; } item_status = oval_sysitem_get_status(item); if (item_status == SYSCHAR_STATUS_EXISTS) exists_cnt++; if (item_status == SYSCHAR_STATUS_ERROR) error_cnt++; item_id = oval_sysitem_get_id(item); ritem = oval_result_item_new(SYSTEM, item_id); oval_result_item_set_result(ritem, OVAL_RESULT_NOT_EVALUATED); _oval_test_item_consumer(ritem, args); } oval_sysitem_iterator_free(collected_items_itr); test_check = oval_test_get_check(test); test_check_existence = oval_test_get_existence(test); ste_itr = oval_test_get_states(test); hasstate = oval_state_iterator_has_more(ste_itr); oval_state_iterator_free(ste_itr); switch (oval_syschar_get_flag(syschar_object)) { case SYSCHAR_FLAG_ERROR: if (test_check_existence == OVAL_ANY_EXIST && !hasstate) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_ERROR; } break; case SYSCHAR_FLAG_NOT_COLLECTED: if (test_check_existence == OVAL_ANY_EXIST && !hasstate) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_UNKNOWN; } break; case SYSCHAR_FLAG_NOT_APPLICABLE: if (test_check_existence == OVAL_ANY_EXIST && !hasstate) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_NOT_APPLICABLE; } break; case SYSCHAR_FLAG_DOES_NOT_EXIST: if (test_check_existence == OVAL_NONE_EXIST || test_check_existence == OVAL_ANY_EXIST) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_FALSE; } break; case SYSCHAR_FLAG_COMPLETE: result = eval_check_existence(test_check_existence, exists_cnt, error_cnt); if (result == OVAL_RESULT_TRUE && hasstate) { result = eval_check_state(test, args); } break; case SYSCHAR_FLAG_INCOMPLETE: if (test_check_existence == OVAL_ANY_EXIST) { result = OVAL_RESULT_TRUE; } else if (test_check_existence == OVAL_AT_LEAST_ONE_EXISTS && exists_cnt > 0) { result = OVAL_RESULT_TRUE; } else if (test_check_existence == OVAL_NONE_EXIST && exists_cnt > 0) { result = OVAL_RESULT_FALSE; } else if (test_check_existence == OVAL_ONLY_ONE_EXISTS && exists_cnt > 1) { result = OVAL_RESULT_FALSE; } else { result = OVAL_RESULT_UNKNOWN; } if (result == OVAL_RESULT_TRUE && hasstate) { result = eval_check_state(test, args); if (result == OVAL_RESULT_TRUE) { if (test_check != OVAL_CHECK_AT_LEAST_ONE) { result = OVAL_RESULT_UNKNOWN; } } else if (result != OVAL_RESULT_FALSE) { result = OVAL_RESULT_UNKNOWN; } } break; default: { const char *object_id = oval_syschar_get_object(syschar_object) ? oval_object_get_id(oval_syschar_get_object(syschar_object)) : "<UNKNOWN>"; oscap_seterr(OSCAP_EFAMILY_OVAL, "Unknown syschar flag: '%d' when evaluating object: '%s' from test: '%s' ", oval_syschar_get_flag(syschar_object), object_id, oval_test_get_id(test)); return OVAL_RESULT_ERROR; } } return result; }
int oval_object_to_sexp(void *sess, const char *typestr, struct oval_syschar *syschar, SEXP_t **out_sexp) { unsigned int ent_cnt, varref_cnt; int ret; SEXP_t *obj_sexp, *elm, *varrefs, *ent_lst, *lst, *stmp; SEXP_t *r0, *r1, *r2, *obj_attr, sm0, sm1; struct oval_object *object; struct oval_object_content_iterator *cit; struct oval_behavior_iterator *bit; struct oval_object_content *content; struct oval_entity *entity; char obj_name[128]; const char *obj_id; object = oval_syschar_get_object(syschar); /* * Object name & attributes (id) */ ret = snprintf(obj_name, sizeof obj_name, "%s_object", typestr); if (ret<0 || (unsigned int) ret > sizeof obj_name) { dE("obj_name length too short"); return -1; } // even though it returns const char* it has to be freed :-( char *obj_over = (char*)oval_schema_version_to_cstr(oval_object_get_platform_schema_version(object)); obj_id = oval_object_get_id(object); obj_attr = probe_attr_creat("id", SEXP_string_new_r(&sm0, obj_id, strlen(obj_id)), "oval_version", SEXP_string_new_r(&sm1, obj_over, strlen(obj_over)), NULL); free(obj_over); obj_sexp = probe_obj_new(obj_name, obj_attr); SEXP_free_r(&sm0); SEXP_free_r(&sm1); SEXP_free(obj_attr); /* * Object content */ ent_lst = SEXP_list_new(NULL); varrefs = NULL; ent_cnt = varref_cnt = 0; cit = oval_object_get_object_contents(object); while (oval_object_content_iterator_has_more(cit)) { oval_check_t ochk; oval_entity_varref_type_t vr_type; content = oval_object_content_iterator_next(cit); elm = NULL; lst = ent_lst; switch (oval_object_content_get_type(content)) { case OVAL_OBJECTCONTENT_ENTITY: entity = oval_object_content_get_entity(content); elm = oval_entity_to_sexp(entity); if (elm == NULL) break; ochk = oval_object_content_get_varCheck(content); if (ochk != OVAL_CHECK_UNKNOWN) { probe_ent_attr_add(elm, "var_check", r0 = SEXP_number_newu_32(ochk)); SEXP_free(r0); } ret = 0; vr_type = oval_entity_get_varref_type(entity); if (vr_type == OVAL_ENTITY_VARREF_ATTRIBUTE) { const char *var_id = oval_variable_get_id(oval_entity_get_variable(entity)); const char *field_name = oval_object_content_get_field_name(content); dI("Object '%s' references variable '%s' in '%s' field.", obj_id, var_id, field_name); ret = oval_varref_attr_to_sexp(sess, entity, syschar, &stmp); if (ret == 0) { if (varrefs == NULL) varrefs = SEXP_list_new(NULL); SEXP_list_add(varrefs, stmp); SEXP_free(stmp); // todo: don't add duplicates ++varref_cnt; lst = obj_sexp; ++ent_cnt; } } else if (vr_type == OVAL_ENTITY_VARREF_ELEMENT) { SEXP_t *val_lst; struct oval_variable *var; oval_datatype_t dt; var = oval_entity_get_variable(entity); dt = oval_entity_get_datatype(entity); ret = oval_varref_elm_to_sexp(sess, var, dt, &val_lst, syschar); if (ret == 0) { SEXP_list_add(elm, val_lst); SEXP_free(val_lst); } } if (ret != 0) { SEXP_t s_flag; SEXP_number_newi_32_r(&s_flag, SYSCHAR_FLAG_DOES_NOT_EXIST); probe_item_attr_add(obj_sexp, "skip_eval", &s_flag); SEXP_free_r(&s_flag); SEXP_free(elm); SEXP_free(ent_lst); if (varrefs != NULL) SEXP_free(varrefs); oval_object_content_iterator_free(cit); *out_sexp = obj_sexp; return (0); } break; case OVAL_OBJECTCONTENT_SET: elm = oval_set_to_sexp(oval_object_content_get_setobject(content)); break; case OVAL_OBJECTCONTENT_FILTER: { struct oval_filter *filter = oval_object_content_get_filter(content); struct oval_state *ste = oval_filter_get_state(filter); const char *ste_id = oval_state_get_id(ste); oval_filter_action_t action = oval_filter_get_filter_action(filter); const char *action_text = oval_filter_action_get_text(action); dI("Object '%s' has a filter that %ss items conforming to state '%s'.", obj_id, action_text, ste_id); elm = oval_filter_to_sexp(filter); } break; case OVAL_OBJECTCONTENT_UNKNOWN: break; } if (elm == NULL) { SEXP_free(obj_sexp); SEXP_free(ent_lst); if (varrefs != NULL) SEXP_free(varrefs); oval_object_content_iterator_free(cit); return -1; } SEXP_list_add(lst, elm); SEXP_free(elm); } if (varrefs != NULL) { // todo: SEXP_list_push() stmp = SEXP_list_new(r0 = SEXP_string_new("varrefs", 7), r1 = SEXP_number_newu(varref_cnt), r2 = SEXP_number_newu(ent_cnt), NULL); SEXP_vfree(r0, r1, r2, NULL); r0 = SEXP_list_join(stmp, varrefs); SEXP_list_add(obj_sexp, r0); SEXP_vfree(stmp, varrefs, r0, NULL); } stmp = SEXP_list_join(obj_sexp, ent_lst); SEXP_free(obj_sexp); SEXP_free(ent_lst); obj_sexp = stmp; oval_object_content_iterator_free(cit); /* * Object behaviors */ bit = oval_object_get_behaviors(object); if (oval_behavior_iterator_has_more(bit)) { elm = oval_behaviors_to_sexp(bit); SEXP_list_add(obj_sexp, elm); SEXP_free(elm); } oval_behavior_iterator_free(bit); *out_sexp = obj_sexp; return (0); }
static oval_result_t _oval_result_test_evaluate_items(struct oval_test *test, struct oval_syschar *syschar_object, void **args) { struct oval_sysitem_iterator *collected_items_itr; oval_result_t result; int exists_cnt, error_cnt; bool hasstate; const char *test_id, *object_id, *flag_text; oval_check_t test_check; oval_existence_t test_check_existence; struct oval_state_iterator *ste_itr; oval_syschar_collection_flag_t flag; struct oval_object *object; exists_cnt = error_cnt = 0; test_id = oval_test_get_id(test); collected_items_itr = oval_syschar_get_sysitem(syschar_object); while (oval_sysitem_iterator_has_more(collected_items_itr)) { struct oval_sysitem *item; char *item_id; oval_syschar_status_t item_status; struct oval_result_item *ritem; item = oval_sysitem_iterator_next(collected_items_itr); if (item == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "Iterator returned null."); oval_sysitem_iterator_free(collected_items_itr); return OVAL_RESULT_ERROR; } item_status = oval_sysitem_get_status(item); if (item_status == SYSCHAR_STATUS_EXISTS) exists_cnt++; if (item_status == SYSCHAR_STATUS_ERROR) error_cnt++; item_id = oval_sysitem_get_id(item); ritem = oval_result_item_new(SYSTEM, item_id); oval_result_item_set_result(ritem, OVAL_RESULT_NOT_EVALUATED); _oval_test_item_consumer(ritem, args); } oval_sysitem_iterator_free(collected_items_itr); test_check = oval_test_get_check(test); test_check_existence = oval_test_get_existence(test); ste_itr = oval_test_get_states(test); hasstate = oval_state_iterator_has_more(ste_itr); oval_state_iterator_free(ste_itr); object = oval_syschar_get_object(syschar_object); object_id = object ? oval_object_get_id(object) : "<UNKNOWN>"; switch (test_check_existence) { case OVAL_ALL_EXIST: dI("Test '%s' requires that every object defined by '%s' exists on the system.", test_id, object_id); break; case OVAL_ANY_EXIST: dI("Test '%s' requires that zero or more objects defined by '%s' exist on the system.", test_id, object_id); break; case OVAL_AT_LEAST_ONE_EXISTS: dI("Test '%s' requires that at least one object defined by '%s' exists on the system.", test_id, object_id); break; case OVAL_NONE_EXIST: dI("Test '%s' requires that none of the objects defined by '%s' exist on the system.", test_id, object_id); break; case OVAL_ONLY_ONE_EXISTS: dI("Test '%s' requires that only one object defined by '%s' exists on the system.", test_id, object_id); break; default: oscap_seterr(OSCAP_EFAMILY_OVAL, "Check_existence parameter of test '%s' is unknown. This may indicate a bug in OpenSCAP.", test_id); } dI("%d objects defined by '%s' exist on the system.", exists_cnt, object_id); if (!hasstate) { dI("Test '%s' does not contain any state to compare object with.", test_id); } flag = oval_syschar_get_flag(syschar_object); flag_text = oval_syschar_collection_flag_get_text(flag); switch (flag) { case SYSCHAR_FLAG_ERROR: dI("An error occured while collecting items matching object '%s'. (flag=%s)", object_id, flag_text); if (test_check_existence == OVAL_ANY_EXIST && !hasstate) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_ERROR; } break; case SYSCHAR_FLAG_NOT_COLLECTED: dI("No attempt was made to collect items matching object '%s'. (flag=%s)", object_id, flag_text); if (test_check_existence == OVAL_ANY_EXIST && !hasstate) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_UNKNOWN; } break; case SYSCHAR_FLAG_NOT_APPLICABLE: dI("Object '%s' is not applicable to the system. (flag=%s)", object_id, flag_text); if (test_check_existence == OVAL_ANY_EXIST && !hasstate) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_NOT_APPLICABLE; } break; case SYSCHAR_FLAG_DOES_NOT_EXIST: dI("No item matching object '%s' was found on the system. (flag=%s)", object_id, flag_text); if (test_check_existence == OVAL_NONE_EXIST || test_check_existence == OVAL_ANY_EXIST) { result = OVAL_RESULT_TRUE; } else { result = OVAL_RESULT_FALSE; } break; case SYSCHAR_FLAG_COMPLETE: dI("All items matching object '%s' were collected. (flag=%s)", object_id, flag_text); result = eval_check_existence(test_check_existence, exists_cnt, error_cnt); if (result == OVAL_RESULT_TRUE && hasstate) { result = eval_check_state(test, args); } break; case SYSCHAR_FLAG_INCOMPLETE: dI("Only some of items matching object '%s' have been collected from the system. It is unknown if other matching items also exist. (flag=%s)", object_id, flag_text); if (test_check_existence == OVAL_ANY_EXIST) { result = OVAL_RESULT_TRUE; } else if (test_check_existence == OVAL_AT_LEAST_ONE_EXISTS && exists_cnt > 0) { result = OVAL_RESULT_TRUE; } else if (test_check_existence == OVAL_NONE_EXIST && exists_cnt > 0) { result = OVAL_RESULT_FALSE; } else if (test_check_existence == OVAL_ONLY_ONE_EXISTS && exists_cnt > 1) { result = OVAL_RESULT_FALSE; } else { result = OVAL_RESULT_UNKNOWN; } if (result == OVAL_RESULT_TRUE && hasstate) { result = eval_check_state(test, args); if (result == OVAL_RESULT_TRUE) { if (test_check != OVAL_CHECK_AT_LEAST_ONE) { result = OVAL_RESULT_UNKNOWN; } } else if (result != OVAL_RESULT_FALSE) { result = OVAL_RESULT_UNKNOWN; } } break; default: { oscap_seterr(OSCAP_EFAMILY_OVAL, "Item corresponding to object '%s' from test '%s' has an unknown flag. This may indicate a bug in OpenSCAP.", object_id, test_id); return OVAL_RESULT_ERROR; } } return result; }
static int oval_probe_variable_eval(oval_probe_session_t *sess, struct oval_syschar *syschar) { struct oval_value_iterator *vit; struct oval_variable *var; struct oval_object *obj; oval_syschar_collection_flag_t flag = SYSCHAR_FLAG_ERROR; int ret = 0; obj = oval_syschar_get_object(syschar); var = oval_probe_variable_objgetvar(obj); if (var == NULL) { oval_syschar_set_flag(syschar, SYSCHAR_FLAG_ERROR); return(-1); } if (oval_probe_query_variable(sess, var) != 0) { oval_syschar_set_flag(syschar, SYSCHAR_FLAG_ERROR); return(-1); } flag = oval_variable_get_collection_flag(var); switch (flag) { case SYSCHAR_FLAG_COMPLETE: case SYSCHAR_FLAG_INCOMPLETE: break; default: { char msg[100]; snprintf(msg, sizeof(msg), "There was a problem processing referenced variable (%s).", oval_variable_get_id(var)); dW("%s\n", msg); oval_syschar_add_new_message(syschar, msg, OVAL_MESSAGE_LEVEL_WARNING); oval_syschar_set_flag(syschar, SYSCHAR_FLAG_ERROR); return(1); } } vit = oval_variable_get_values(var); if (vit == NULL) { flag = SYSCHAR_FLAG_ERROR; oval_syschar_set_flag(syschar, SYSCHAR_FLAG_ERROR); return(1); } else { SEXP_t *r0, *item, *cobj, *vrent, *val_sexp, *valent; char *var_ref; cobj = probe_cobj_new(SYSCHAR_FLAG_UNKNOWN, NULL, NULL); /* Create shared entity */ var_ref = oval_variable_get_id(var); vrent = probe_ent_creat1("var_ref", NULL, r0 = SEXP_string_new(var_ref, strlen(var_ref))); SEXP_free(r0); while (oval_value_iterator_has_more(vit)) { oval_datatype_t dtype; struct oval_value *val; val = oval_value_iterator_next(vit); oval_value_cast(val, OVAL_DATATYPE_STRING); dtype = oval_value_get_datatype(val); val_sexp = oval_value_to_sexp(val, dtype); assume_d(val_sexp != NULL, -1); valent = probe_ent_creat1("value", NULL, val_sexp); item = probe_item_creat("variable_item", NULL, NULL); /* temporary workaround to generate ids */ _gen_item_id(item); /* Add shared var_ref entity */ SEXP_list_add(item, vrent); /* Add value entity */ SEXP_list_add(item, valent); /* Add item to the item list */ probe_cobj_add_item(cobj, item); SEXP_vfree(item, valent, val_sexp, NULL); } oval_value_iterator_free(vit); probe_cobj_compute_flag(cobj); ret = oval_sexp2sysch(cobj, syschar); SEXP_vfree(cobj, vrent, NULL); } return(ret); }