static SEXP_t *create_item(const char *path, const char *filename, char *pattern, int instance, char **substrs, int substr_cnt, oval_schema_version_t over) { int i; SEXP_t *item; SEXP_t *r0; SEXP_t *se_instance, *se_filepath; char *text; if (strlen(path) + strlen(filename) + 1 > PATH_MAX) { dE("path+filename too long"); return (NULL); } if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.4)) < 0) { pattern = text = NULL; se_instance = NULL; } else { text = substrs[0]; se_instance = SEXP_number_newu_64((int64_t) instance); } if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.6)) < 0) { se_filepath = NULL; } else { const size_t path_len = strlen(path); /* Avoid 2 slashes */ if (path_len >= 1 && path[path_len - 1] == FILE_SEPARATOR) { se_filepath = SEXP_string_newf("%s%s", path, filename); } else { se_filepath = SEXP_string_newf("%s%c%s", path, FILE_SEPARATOR, filename); } } item = probe_item_create(OVAL_INDEPENDENT_TEXT_FILE_CONTENT, NULL, "filepath", OVAL_DATATYPE_SEXP, se_filepath, "path", OVAL_DATATYPE_STRING, path, "filename", OVAL_DATATYPE_STRING, filename, "pattern", OVAL_DATATYPE_STRING, pattern, "instance", OVAL_DATATYPE_SEXP, se_instance, "line", OVAL_DATATYPE_STRING, pattern, "text", OVAL_DATATYPE_STRING, substrs[0], NULL); for (i = 1; i < substr_cnt; ++i) { probe_item_ent_add (item, "subexpression", NULL, r0 = SEXP_string_new (substrs[i], strlen (substrs[i]))); SEXP_free (r0); } return item; }
static void report_finding(struct result_info *res, probe_ctx *ctx) { SEXP_t *item; SEXP_t *se_ruid; if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.8)) < 0) { se_ruid = NULL; } else { se_ruid = SEXP_number_newu_64(res->ruid); } item = probe_item_create(OVAL_UNIX_PROCESS, NULL, "command", OVAL_DATATYPE_STRING, res->command, "exec_time", OVAL_DATATYPE_STRING, res->exec_time, "pid", OVAL_DATATYPE_INTEGER, (int64_t)res->pid, "ppid", OVAL_DATATYPE_INTEGER, (int64_t)res->ppid, "priority", OVAL_DATATYPE_INTEGER, (int64_t)res->priority, "ruid", OVAL_DATATYPE_SEXP, se_ruid, "scheduling_class", OVAL_DATATYPE_STRING, res->scheduling_class, "start_time", OVAL_DATATYPE_STRING, res->start_time, "tty", OVAL_DATATYPE_STRING, res->tty, "user_id", OVAL_DATATYPE_INTEGER, (int64_t)res->user_id, NULL); probe_item_collect(ctx, item); }
//typedef void (*oval_entity_consumer)(struct oval_entity_node*, void*); int oval_entity_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context, oscap_consumer_func consumer, void *user) { __attribute__nonnull__(context); struct oval_entity *entity = oval_entity_new(context->definition_model); int return_code = 0; oval_datatype_t datatype = oval_datatype_parse(reader, "datatype", OVAL_DATATYPE_STRING); oval_operation_t operation = oval_operation_parse(reader, "operation", OVAL_OPERATION_EQUALS); int mask = oval_parser_boolean_attribute(reader, "mask", 0); char *nil_attr = (char *) xmlTextReaderGetAttributeNs(reader, BAD_CAST "nil", OSCAP_XMLNS_XSI); int xsi_nil = oscap_streq(nil_attr, "true") != 0; xmlFree(nil_attr); oval_entity_type_t type = OVAL_ENTITY_TYPE_UNKNOWN; //The value of the type field vs. the complexity of extracting type is arguable char *varref = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "var_ref"); struct oval_value *value = NULL; struct oval_variable *variable; char *name = (char *)xmlTextReaderLocalName(reader); oval_entity_varref_type_t varref_type; if (strcmp(name, "var_ref") == 0) { //special case for <var_ref> if (varref == NULL) { struct oval_definition_model *model = context->definition_model; varref_type = OVAL_ENTITY_VARREF_ELEMENT; struct oval_consume_varref_context ctx = {.model = model, .variable = &variable, .value = &value}; return_code = oscap_parser_text_value(reader, &oval_consume_varref, &ctx); } else { varref_type = OVAL_ENTITY_VARREF_ATTRIBUTE; struct oval_definition_model *model = context->definition_model; oval_schema_version_t version = oval_definition_model_get_core_schema_version(model); if (oval_schema_version_cmp(version, OVAL_SCHEMA_VERSION(5.6)) > 0) { oscap_seterr(OSCAP_EFAMILY_OVAL, "The var_ref attribute for the var_ref entity " "of a variable_object is prohibited since OVAL 5.6. Use plain " "var_ref instead."); } variable = oval_definition_model_get_variable(model, varref); if (variable == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "Could not found variable '%s' referenced by var_ref element.", varref); return_code = 1; } else { oscap_free(varref); varref = NULL; value = NULL; } } } else if (varref == NULL) {
xmlNode *oval_state_content_to_dom(struct oval_state_content * content, xmlDoc * doc, xmlNode * parent) { __attribute__nonnull__(content); struct oval_record_field_iterator *rf_itr; bool parent_mask; xmlNode *content_node = oval_entity_to_dom(content->entity, doc, parent); parent_mask = oval_entity_get_mask(content->entity); rf_itr = oval_state_content_get_record_fields(content); if (oval_record_field_iterator_has_more(rf_itr)) { xmlNsPtr field_ns = NULL; field_ns = xmlSearchNsByHref(doc, xmlDocGetRootElement(doc), OVAL_DEFINITIONS_NAMESPACE); if (field_ns == NULL) { field_ns = xmlNewNs(xmlDocGetRootElement(doc), OVAL_DEFINITIONS_NAMESPACE, BAD_CAST "oval-def"); } while (oval_record_field_iterator_has_more(rf_itr)) { struct oval_record_field *rf; rf = oval_record_field_iterator_next(rf_itr); oval_record_field_to_dom(rf, parent_mask, doc, content_node, field_ns); } } oval_record_field_iterator_free(rf_itr); oval_check_t var_check = oval_state_content_get_var_check(content); if (var_check != OVAL_CHECK_ALL || xmlHasProp(content_node, BAD_CAST "var_ref")) xmlNewProp(content_node, BAD_CAST "var_check", BAD_CAST oval_check_get_text(var_check)); oval_check_t ent_check = oval_state_content_get_ent_check(content); if (ent_check != OVAL_CHECK_ALL) xmlNewProp(content_node, BAD_CAST "entity_check", BAD_CAST oval_check_get_text(ent_check)); oval_schema_version_t ver = oval_definition_model_get_core_schema_version(content->model); if (oval_schema_version_cmp(ver, OVAL_SCHEMA_VERSION(5.11.1)) >= 0) { oval_existence_t check_existence = oval_state_content_get_check_existence(content); if (check_existence != OVAL_AT_LEAST_ONE_EXISTS) { // at_least_one_exists is default value xmlNewProp(content_node, BAD_CAST "check_existence", BAD_CAST oval_existence_get_text(check_existence)); } } return content_node; }
static int read_password(SEXP_t *un_ent, probe_ctx *ctx, oval_schema_version_t over) { struct passwd *pw; while ((pw = getpwent())) { SEXP_t *un; dI("Have user: %s", pw->pw_name); un = SEXP_string_newf("%s", pw->pw_name); if (probe_entobj_cmp(un_ent, un) == OVAL_RESULT_TRUE) { struct result_info r; r.username = pw->pw_name; r.password = pw->pw_passwd; r.user_id = pw->pw_uid; r.group_id = pw->pw_gid; r.gcos = pw->pw_gecos; r.home_dir = pw->pw_dir; r.login_shell = pw->pw_shell; r.last_login = -1; if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.10)) >= 0) { FILE *ll_fp = fopen(_PATH_LASTLOG, "r"); if (ll_fp != NULL) { struct lastlog ll; if (fseeko(ll_fp, (off_t)pw->pw_uid * sizeof(ll), SEEK_SET) == 0) if (fread((char *)&ll, sizeof(ll), 1, ll_fp) == 1) r.last_login = (int64_t)ll.ll_time; fclose(ll_fp); } } report_finding(&r, ctx, over); } SEXP_free(un); } endpwent(); return 0; }
static void report_finding(struct result_info *res, probe_ctx *ctx, oval_schema_version_t over) { SEXP_t *item; item = probe_item_create(OVAL_UNIX_PASSWORD, NULL, "username", OVAL_DATATYPE_STRING, res->username, "password", OVAL_DATATYPE_STRING, res->password, "user_id", OVAL_DATATYPE_INTEGER, (int64_t)res->user_id, "group_id", OVAL_DATATYPE_INTEGER, (int64_t)res->group_id, "gcos", OVAL_DATATYPE_STRING, res->gcos, "home_dir", OVAL_DATATYPE_STRING, res->home_dir, "login_shell", OVAL_DATATYPE_STRING, res->login_shell, NULL); if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.10)) >= 0) { SEXP_t last_login; SEXP_number_newi_64_r(&last_login, res->last_login); probe_item_ent_add(item, "last_login", NULL, &last_login); SEXP_free_r(&last_login); } probe_item_collect(ctx, item); }
static void report_finding(struct result_info *res, llist *l, probe_ctx *ctx, oval_schema_version_t over) { SEXP_t *item, *user_id; lnode *n = list_get_cur(l); if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.10)) < 0) user_id = SEXP_string_newf("%d", n->uid); else user_id = SEXP_number_newi_64((int64_t)n->uid); item = probe_item_create(OVAL_LINUX_IFLISTENERS, NULL, "interface_name", OVAL_DATATYPE_STRING, res->interface_name, "protocol", OVAL_DATATYPE_STRING, res->protocol, "hw_address", OVAL_DATATYPE_STRING, res->hw_address, "program_name", OVAL_DATATYPE_STRING, n->cmd, "pid", OVAL_DATATYPE_INTEGER, (int64_t)n->pid, "user_id", OVAL_DATATYPE_SEXP, user_id, NULL); probe_item_collect(ctx, item); SEXP_free(user_id); }
int main(int argc, char **argv) { if (argc != 4) { printf("Not enough arguments\n"); return 1; } const char *v1_str = argv[1]; const char *v2_str = argv[2]; int expected_result = atoi(argv[3]); oval_schema_version_t v1 = oval_schema_version_from_cstr(v1_str); oval_schema_version_t v2 = oval_schema_version_from_cstr(v2_str); int cmp = oval_schema_version_cmp(v1, v2); int retval; if (cmp == expected_result) { retval = 0; printf("\tPASS\t%s %s %s\n", v1_str, cmp_to_cstr(cmp), v2_str); } else { retval = 1; printf("\tFAIL\t%s %s %s but expected result is '%s'\n", v1_str, cmp_to_cstr(cmp), v2_str, cmp_to_cstr(expected_result)); } return retval; }
static oval_result_t eval_item(struct oval_syschar_model *syschar_model, struct oval_sysitem *cur_sysitem, struct oval_state *state) { struct oval_state_content_iterator *state_contents_itr; struct oresults ste_ores; oval_operator_t operator; oval_result_t result = OVAL_RESULT_ERROR; ores_clear(&ste_ores); state_contents_itr = oval_state_get_contents(state); while (oval_state_content_iterator_has_more(state_contents_itr)) { struct oval_state_content *content; struct oval_entity *state_entity; char *state_entity_name; oval_operation_t state_entity_operation; oval_check_t entity_check; oval_existence_t check_existence; oval_result_t ste_ent_res; struct oval_sysent_iterator *item_entities_itr; struct oresults ent_ores; struct oval_status_counter counter; bool found_matching_item; if ((content = oval_state_content_iterator_next(state_contents_itr)) == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL state content"); goto fail; } if ((state_entity = oval_state_content_get_entity(content)) == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL entity"); goto fail; } if ((state_entity_name = oval_entity_get_name(state_entity)) == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL entity name"); goto fail; } if (oscap_streq(state_entity_name, "line") && oval_state_get_subtype(state) == (oval_subtype_t) OVAL_INDEPENDENT_TEXT_FILE_CONTENT) { /* Hack: textfilecontent_state/line shall be compared against textfilecontent_item/text. * * textfilecontent_test and textfilecontent54_test share the same syschar * (textfilecontent_item). In OVAL 5.3 and below this syschar did not hold any usable * information ('text' ent). In OVAL 5.4 textfilecontent_test was deprecated. But the * 'text' ent has been added to textfilecontent_item, making it potentially usable. */ oval_schema_version_t over = oval_state_get_platform_schema_version(state); if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.4)) >= 0) { /* The OVAL-5.3 does not have textfilecontent_item/text */ state_entity_name = "text"; } } entity_check = oval_state_content_get_ent_check(content); check_existence = oval_state_content_get_check_existence(content); state_entity_operation = oval_entity_get_operation(state_entity); ores_clear(&ent_ores); found_matching_item = false; oval_status_counter_clear(&counter); item_entities_itr = oval_sysitem_get_sysents(cur_sysitem); while (oval_sysent_iterator_has_more(item_entities_itr)) { struct oval_sysent *item_entity; oval_result_t ent_val_res; char *item_entity_name; oval_syschar_status_t item_status; item_entity = oval_sysent_iterator_next(item_entities_itr); if (item_entity == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "OVAL internal error: found NULL sysent"); oval_sysent_iterator_free(item_entities_itr); goto fail; } item_status = oval_sysent_get_status(item_entity); oval_status_counter_add_status(&counter, item_status); item_entity_name = oval_sysent_get_name(item_entity); if (strcmp(item_entity_name, state_entity_name)) continue; found_matching_item = true; /* copy mask attribute from state to item */ if (oval_entity_get_mask(state_entity)) oval_sysent_set_mask(item_entity,1); ent_val_res = _evaluate_sysent(syschar_model, item_entity, state_entity, state_entity_operation, content); if (((signed) ent_val_res) == -1) { oval_sysent_iterator_free(item_entities_itr); goto fail; } ores_add_res(&ent_ores, ent_val_res); } oval_sysent_iterator_free(item_entities_itr); if (!found_matching_item) dW("Entity name '%s' from state (id: '%s') not found in item (id: '%s').\n", state_entity_name, oval_state_get_id(state), oval_sysitem_get_id(cur_sysitem)); ste_ent_res = ores_get_result_bychk(&ent_ores, entity_check); ores_add_res(&ste_ores, ste_ent_res); oval_result_t cres = oval_status_counter_get_result(&counter, check_existence); ores_add_res(&ste_ores, cres); } oval_state_content_iterator_free(state_contents_itr); operator = oval_state_get_operator(state); result = ores_get_result_byopr(&ste_ores, operator); return result; fail: oval_state_content_iterator_free(state_contents_itr); return OVAL_RESULT_ERROR; }
static int collect_item(probe_ctx *ctx, oval_schema_version_t over, struct mntent *mnt_ent) #endif { SEXP_t *item; char *uuid = "", *tok, *save = NULL, **mnt_opts = NULL; uint8_t mnt_ocnt; struct statvfs stvfs; /* * Get FS stats */ if (statvfs(mnt_ent->mnt_dir, &stvfs) != 0) return (-1); /* * Get UUID */ #if defined(HAVE_BLKID_GET_TAG_VALUE) uuid = blkid_get_tag_value(blkcache, "UUID", mnt_ent->mnt_fsname); if (uuid == NULL) { uuid = ""; } #endif /* * Create a NULL-terminated array from the mount options */ mnt_ocnt = 0; tok = strtok_r(mnt_ent->mnt_opts, ",", &save); do { add_mnt_opt(&mnt_opts, ++mnt_ocnt, tok); } while ((tok = strtok_r(NULL, ",", &save)) != NULL); /* * Check for "remount", "bind" and "move" mount options * These options can't be found in /proc/mounts, * we must use flags got by statvfs(). */ if (stvfs.f_flag & MS_REMOUNT) { add_mnt_opt(&mnt_opts, ++mnt_ocnt, "remount"); } if (stvfs.f_flag & MS_BIND) { add_mnt_opt(&mnt_opts, ++mnt_ocnt, "bind"); } if (stvfs.f_flag & MS_MOVE) { add_mnt_opt(&mnt_opts, ++mnt_ocnt, "move"); } dI("mnt_ocnt = %d, mnt_opts[mnt_ocnt]=%p", mnt_ocnt, mnt_opts[mnt_ocnt]); /* * "Correct" the type (this won't be (hopefully) needed in a later version * of OVAL) */ if (oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.10)) < 0) mnt_ent->mnt_type = (char *)correct_fstype(mnt_ent->mnt_type); /* * Create the item */ item = probe_item_create(OVAL_LINUX_PARTITION, NULL, "mount_point", OVAL_DATATYPE_STRING, mnt_ent->mnt_dir, "device", OVAL_DATATYPE_STRING, mnt_ent->mnt_fsname, "uuid", OVAL_DATATYPE_STRING, uuid, "fs_type", OVAL_DATATYPE_STRING, mnt_ent->mnt_type, "mount_options", OVAL_DATATYPE_STRING_M, mnt_opts, "total_space", OVAL_DATATYPE_INTEGER, (int64_t)stvfs.f_blocks, "space_used", OVAL_DATATYPE_INTEGER, (int64_t)(stvfs.f_blocks - stvfs.f_bfree), "space_left", OVAL_DATATYPE_INTEGER, (int64_t)stvfs.f_bfree, NULL); #if defined(HAVE_BLKID_GET_TAG_VALUE) /* * If the partition doesn't have an UUID assigned, set the uuid entity status to * "does not exist" which means that the value was collected but does not exist * on the system. */ if (strcmp(uuid, "") == 0) { probe_itement_setstatus(item, "uuid", 1, SYSCHAR_STATUS_DOES_NOT_EXIST); } #else /* Compiled without blkid library, we don't collect UUID */ probe_itement_setstatus(item, "uuid", 1, SYSCHAR_STATUS_NOT_COLLECTED); #endif /* HAVE_BLKID_GET_TAG_VALUE */ probe_item_collect(ctx, item); free(mnt_opts); return (0); }
static int filehash_cb (const char *p, const char *f, probe_ctx *ctx, oval_schema_version_t over) { SEXP_t *itm; char pbuf[PATH_MAX+1]; size_t plen, flen; bool include_filepath; int fd; if (f == NULL) return (0); /* * Prepare path */ plen = strlen (p); flen = strlen (f); if (plen + flen + 1 > PATH_MAX) return (-1); memcpy (pbuf, p, sizeof (char) * plen); if (p[plen - 1] != FILE_SEPARATOR) { pbuf[plen] = FILE_SEPARATOR; ++plen; } memcpy (pbuf + plen, f, sizeof (char) * flen); pbuf[plen+flen] = '\0'; include_filepath = oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.6)) >= 0; /* * Open the file */ fd = open (pbuf, O_RDONLY); if (fd < 0) { strerror_r (errno, pbuf, PATH_MAX); pbuf[PATH_MAX] = '\0'; itm = probe_item_create(OVAL_INDEPENDENT_FILE_HASH, NULL, "filepath", OVAL_DATATYPE_STRING, include_filepath ? pbuf : NULL, "path", OVAL_DATATYPE_STRING, p, "filename", OVAL_DATATYPE_STRING, f, NULL ); probe_item_add_msg(itm, OVAL_MESSAGE_LEVEL_ERROR, "Can't open \"%s\": errno=%d, %s.", pbuf, errno, strerror (errno)); probe_item_setstatus(itm, SYSCHAR_STATUS_ERROR); } else { uint8_t md5_dst[16]; size_t md5_dstlen = sizeof md5_dst; char md5_str[(sizeof md5_dst * 2) + 1]; uint8_t sha1_dst[20]; size_t sha1_dstlen = sizeof sha1_dst; char sha1_str[(sizeof sha1_dst * 2) + 1]; /* * Compute hash values */ if (crapi_mdigest_fd (fd, 2, CRAPI_DIGEST_MD5, md5_dst, &md5_dstlen, CRAPI_DIGEST_SHA1, sha1_dst, &sha1_dstlen) != 0) { close (fd); return (-1); } close (fd); md5_str[0] = '\0'; sha1_str[0] = '\0'; mem2hex (md5_dst, md5_dstlen, md5_str, sizeof md5_str); mem2hex (sha1_dst, sha1_dstlen, sha1_str, sizeof sha1_str); /* * Create and add the item */ itm = probe_item_create(OVAL_INDEPENDENT_FILE_HASH, NULL, "filepath", OVAL_DATATYPE_STRING, include_filepath ? pbuf : NULL, "path", OVAL_DATATYPE_STRING, p, "filename", OVAL_DATATYPE_STRING, f, "md5", OVAL_DATATYPE_STRING, md5_str, "sha1", OVAL_DATATYPE_STRING, sha1_str, NULL); if (md5_dstlen == 0 || sha1_dstlen == 0) probe_item_setstatus(itm, SYSCHAR_STATUS_ERROR); if (md5_dstlen == 0) probe_item_add_msg(itm, OVAL_MESSAGE_LEVEL_ERROR, "Unable to compute md5 hash value of \"%s\".", pbuf); if (sha1_dstlen == 0) probe_item_add_msg(itm, OVAL_MESSAGE_LEVEL_ERROR, "Unable to compute sha1 hash value of \"%s\".", pbuf); } probe_item_collect(ctx, itm); return (0); }