int probe_main (probe_ctx *ctx, void *arg) { SEXP_t *object; struct runlevel_req request_st; struct runlevel_rep *reply_st = NULL; object = probe_ctx_getobject(ctx); request_st.service_name_ent = probe_obj_getent(object, "service_name", 1); if (request_st.service_name_ent == NULL) { dI("%s: element not found", "service_name"); return PROBE_ENOELM; } request_st.runlevel_ent = probe_obj_getent(object, "runlevel", 1); if (request_st.runlevel_ent == NULL) { SEXP_free(request_st.service_name_ent); dI("%s: element not found", "runlevel"); return PROBE_ENOELM; } if (get_runlevel(&request_st, &reply_st) == -1) { SEXP_t *msg; msg = probe_msg_creat(OVAL_MESSAGE_LEVEL_ERROR, "get_runlevel failed."); probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); } else { struct runlevel_rep *next_rep; SEXP_t *item; while (reply_st != NULL) { dI("get_runlevel: [0]=\"%s\", [1]=\"%s\", [2]=\"%d\", [3]=\"%d\"", reply_st->service_name, reply_st->runlevel, reply_st->start, reply_st->kill); item = probe_item_create(OVAL_UNIX_RUNLEVEL, NULL, "service_name", OVAL_DATATYPE_STRING, reply_st->service_name, "runlevel", OVAL_DATATYPE_STRING, reply_st->runlevel, "start", OVAL_DATATYPE_BOOLEAN, reply_st->start, "kill", OVAL_DATATYPE_BOOLEAN, reply_st->kill, NULL); probe_item_collect(ctx, item); next_rep = reply_st->next; oscap_free(reply_st->service_name); oscap_free(reply_st->runlevel); oscap_free(reply_st); reply_st = next_rep; } } SEXP_free(request_st.runlevel_ent); SEXP_free(request_st.service_name_ent); return 0; }
int probe_main(probe_ctx *ctx, void *unused) { (void)unused; probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_NOT_APPLICABLE); return (0); }
/** * Collect an item * This function adds an item the collected object assosiated * with the given probe context. * * Returns: * 0 ... the item was succesfully added to the collected object * 1 ... the item was filtered out * 2 ... the item was not added because of memory constraints * and the collected object was flagged as incomplete *-1 ... unexpected/internal error * * The caller must not free the item, it's freed automatically * by this function or by the icache worker thread. */ int probe_item_collect(struct probe_ctx *ctx, SEXP_t *item) { SEXP_t *cobj_content; size_t cobj_itemcnt; assume_d(ctx != NULL, -1); assume_d(ctx->probe_out != NULL, -1); assume_d(item != NULL, -1); cobj_content = SEXP_listref_nth(ctx->probe_out, 3); cobj_itemcnt = SEXP_list_length(cobj_content); SEXP_free(cobj_content); if (probe_cobj_memcheck(cobj_itemcnt) != 0) { /* * Don't set the message again if the collected object is * already flagged as incomplete. */ if (probe_cobj_get_flag(ctx->probe_out) != SYSCHAR_FLAG_INCOMPLETE) { SEXP_t *msg; /* * Sync with the icache thread before modifying the * collected object. */ if (probe_icache_nop(ctx->icache) != 0) return -1; msg = probe_msg_creat(OVAL_MESSAGE_LEVEL_WARNING, "Object is incomplete due to memory constraints."); probe_cobj_add_msg(ctx->probe_out, msg); probe_cobj_set_flag(ctx->probe_out, SYSCHAR_FLAG_INCOMPLETE); SEXP_free(msg); } return 2; } if (ctx->filters != NULL && probe_item_filtered(item, ctx->filters)) { SEXP_free(item); return (1); } if (probe_icache_add(ctx->icache, ctx->probe_out, item) != 0) { dE("Can't add item (%p) to the item cache (%p)", item, ctx->icache); SEXP_free(item); return (-1); } return (0); }
int probe_main (probe_ctx *ctx, void *arg) { SEXP_t *probe_in, *name_ent, *file_ent, *bh_ent; char file[PATH_MAX]; size_t file_len = sizeof file; char name[64]; size_t name_len = sizeof name; oval_operation_t name_op, file_op; uint64_t collect_flags = 0; unsigned int i; // If probe_init() failed it's because there was no rpm config files if (arg == NULL) { probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_NOT_APPLICABLE); return 0; } /* * Get refs to object entities */ probe_in = probe_ctx_getobject(ctx); name_ent = probe_obj_getent(probe_in, "name", 1); file_ent = probe_obj_getent(probe_in, "filepath", 1); if (name_ent == NULL || file_ent == NULL) { dE("Missing \"name\" (%p) or \"filepath\" (%p) entity", name_ent, file_ent); SEXP_free(name_ent); SEXP_free(file_ent); return (PROBE_ENOENT); } /* * Extract the requested operation for each entity */ name_op = probe_ent_getoperation(name_ent, OVAL_OPERATION_EQUALS); file_op = probe_ent_getoperation(file_ent, OVAL_OPERATION_EQUALS); if (name_op == OVAL_OPERATION_UNKNOWN || file_op == OVAL_OPERATION_UNKNOWN) { SEXP_free(name_ent); SEXP_free(file_ent); return (PROBE_EINVAL); } /* * Extract entity values */ PROBE_ENT_STRVAL(name_ent, name, name_len, /* void */, strcpy(name, ""););
static int get_selinuxboolean(SEXP_t *ut_ent, probe_ctx *ctx) { int err = 1, active, pending, len, i; SEXP_t *boolean, *item; char **booleans; if ( ! is_selinux_enabled()) { probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_NOT_APPLICABLE); return 0; } if (security_get_boolean_names(&booleans, &len) == -1) { probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); return err; } for (i = 0; i < len; i++) { boolean = SEXP_string_new(booleans[i], strlen(booleans[i])); if (probe_entobj_cmp(ut_ent, boolean) == OVAL_RESULT_TRUE) { active = security_get_boolean_active(booleans[i]); pending = security_get_boolean_pending(booleans[i]); item = probe_item_create( OVAL_LINUX_SELINUXBOOLEAN, NULL, "name", OVAL_DATATYPE_SEXP, boolean, "current_status", OVAL_DATATYPE_BOOLEAN, active, "pending_status", OVAL_DATATYPE_BOOLEAN, pending, NULL); probe_item_collect(ctx, item); } SEXP_free(boolean); } for (i = 0; i < len; i++) free(booleans[i]); free(booleans); return 0; }
int probe_main(probe_ctx *ctx, void *arg) { SEXP_t *object; int err; llist ll; oval_schema_version_t over; object = probe_ctx_getobject(ctx); over = probe_obj_get_platform_schema_version(object); interface_name_ent = probe_obj_getent(object, "interface_name", 1); if (interface_name_ent == NULL) { err = PROBE_ENOVAL; goto cleanup; } // Now start collecting the info list_create(&ll); if (collect_process_info(&ll) || perm_warn) { SEXP_t *msg; msg = probe_msg_creat(OVAL_MESSAGE_LEVEL_ERROR, "Permission error."); probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); err = 0; goto cleanup; } read_packet(&ll, ctx, over); list_clear(&ll); err = 0; cleanup: SEXP_vfree(interface_name_ent, NULL); return err; }
int probe_main(probe_ctx *ctx, void *arg) { SEXP_t *path_ent, *file_ent, *inst_ent, *bh_ent, *patt_ent, *filepath_ent, *probe_in; SEXP_t *r0; /* char *i_val, *m_val, *s_val; */ bool val; struct pfdata pfd; int ret = 0; #if defined USE_REGEX_PCRE int errorffset = -1; const char *error; #elif defined USE_REGEX_POSIX regex_t _re; pfd.compiled_regex = &_re; int err; #endif OVAL_FTS *ofts; OVAL_FTSENT *ofts_ent; (void)arg; memset(&pfd, 0, sizeof(pfd)); probe_in = probe_ctx_getobject(ctx); over = probe_obj_get_platform_schema_version(probe_in); path_ent = probe_obj_getent(probe_in, "path", 1); file_ent = probe_obj_getent(probe_in, "filename", 1); inst_ent = probe_obj_getent(probe_in, "instance", 1); patt_ent = probe_obj_getent(probe_in, "pattern", 1); filepath_ent = probe_obj_getent(probe_in, "filepath", 1); bh_ent = probe_obj_getent(probe_in, "behaviors", 1); /* we want (path+filename or filepath) + instance + pattern*/ if ( ((path_ent == NULL || file_ent == NULL) && filepath_ent==NULL) || inst_ent==NULL || patt_ent==NULL) { SEXP_free (patt_ent); ret = PROBE_ENOELM; goto cleanup; } /* get pattern from SEXP */ SEXP_t *ent_val; ent_val = probe_ent_getval(patt_ent); pfd.pattern = SEXP_string_cstr(ent_val); assume_d(pfd.pattern != NULL, -1); SEXP_free(patt_ent); SEXP_free(ent_val); /* wtf? i_val = s_val = "0"; m_val = "1"; */ /* reset filebehavior attributes if 'filepath' entity is used */ if (filepath_ent != NULL && bh_ent != NULL) { SEXP_t *r1, *r2, *r3; r1 = probe_ent_getattrval(bh_ent, "ignore_case"); r2 = probe_ent_getattrval(bh_ent, "multiline"); r3 = probe_ent_getattrval(bh_ent, "singleline"); r0 = probe_attr_creat("ignore_case", r1, "multiline", r2, "singleline", r3, NULL); SEXP_free(bh_ent); bh_ent = probe_ent_creat1("behaviors", r0, NULL); SEXP_vfree(r0, r1, r2, r3, NULL); } probe_tfc54behaviors_canonicalize(&bh_ent); pfd.instance_ent = inst_ent; pfd.ctx = ctx; #if defined USE_REGEX_PCRE pfd.re_opts = PCRE_UTF8; r0 = probe_ent_getattrval(bh_ent, "ignore_case"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= PCRE_CASELESS; } r0 = probe_ent_getattrval(bh_ent, "multiline"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= PCRE_MULTILINE; } r0 = probe_ent_getattrval(bh_ent, "singleline"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= PCRE_DOTALL; } pfd.compiled_regex = pcre_compile(pfd.pattern, pfd.re_opts, &error, &errorffset, NULL); if (pfd.compiled_regex == NULL) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "pcre_compile() '%s' %s.", pfd.pattern, error); probe_cobj_add_msg(probe_ctx_getresult(pfd.ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd.ctx), SYSCHAR_FLAG_ERROR); goto cleanup; } #elif defined USE_REGEX_POSIX pfd.re_opts = REG_EXTENDED | REG_NEWLINE; r0 = probe_ent_getattrval(bh_ent, "ignore_case"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= REG_ICASE; } if ((err = regcomp(pfd.compiled_regex, pfd.pattern, pfd.re_opts)) != 0) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "regcomp() '%s' returned %d.", pfd.pattern, err); probe_cobj_add_msg(probe_ctx_getresult(pfd.ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd.ctx), SYSCHAR_FLAG_ERROR); goto cleanup; } #endif if ((ofts = oval_fts_open(path_ent, file_ent, filepath_ent, bh_ent)) != NULL) { while ((ofts_ent = oval_fts_read(ofts)) != NULL) { if (ofts_ent->fts_info == FTS_F || ofts_ent->fts_info == FTS_SL) { // todo: handle return code process_file(ofts_ent->path, ofts_ent->file, &pfd); } oval_ftsent_free(ofts_ent); } oval_fts_close(ofts); } cleanup: SEXP_free(file_ent); SEXP_free(path_ent); SEXP_free(inst_ent); SEXP_free(bh_ent); SEXP_free(filepath_ent); if (pfd.pattern != NULL) oscap_free(pfd.pattern); #if defined USE_REGEX_PCRE if (pfd.compiled_regex != NULL) pcre_free(pfd.compiled_regex); #elif defined USE_REGEX_POSIX regfree(&_re); #endif return ret; }
static int process_file(const char *path, const char *file, void *arg) { struct pfdata *pfd = (struct pfdata *) arg; int ret = 0, path_len, file_len, cur_inst = 0, fd = -1, substr_cnt, buf_size = 0, buf_used = 0, ofs = 0, buf_inc = 4096; char *whole_path = NULL, *buf = NULL; SEXP_t *next_inst = NULL; struct stat st; if (file == NULL) goto cleanup; path_len = strlen(path); file_len = strlen(file); whole_path = oscap_alloc(path_len + file_len + 2); memcpy(whole_path, path, path_len); if (whole_path[path_len - 1] != FILE_SEPARATOR) { whole_path[path_len] = FILE_SEPARATOR; ++path_len; } memcpy(whole_path + path_len, file, file_len + 1); /* * If stat() fails, don't report an error and just skip the file. * This is an expected situation, because the fts_*() functions * are called with the 'FTS_PHYSICAL' option. Normally, stumbling * upon a symlink without a target would cause fts_read() to return * the 'FTS_SLNONE' flag, but the 'FTS_PHYSICAL' option causes it * to return 'FTS_SL' and the presence of a valid target has to * be determined with stat(). */ if (stat(whole_path, &st) == -1) goto cleanup; if (!S_ISREG(st.st_mode)) goto cleanup; fd = open(whole_path, O_RDONLY); if (fd == -1) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "open(): '%s' %s.", whole_path, strerror(errno)); probe_cobj_add_msg(probe_ctx_getresult(pfd->ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd->ctx), SYSCHAR_FLAG_ERROR); ret = -1; goto cleanup; } do { buf_size += buf_inc; buf = oscap_realloc(buf, buf_size); ret = read(fd, buf + buf_used, buf_inc); if (ret == -1) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "read(): '%s' %s.", whole_path, strerror(errno)); probe_cobj_add_msg(probe_ctx_getresult(pfd->ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd->ctx), SYSCHAR_FLAG_ERROR); ret = -2; goto cleanup; } buf_used += ret; } while (ret == buf_inc); if (buf_used == buf_size) buf = realloc(buf, ++buf_size); buf[buf_used++] = '\0'; do { char **substrs; int want_instance; next_inst = SEXP_number_newi_32(cur_inst + 1); if (probe_entobj_cmp(pfd->instance_ent, next_inst) == OVAL_RESULT_TRUE) want_instance = 1; else want_instance = 0; SEXP_free(next_inst); substr_cnt = get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs); if (substr_cnt > 0) { ++cur_inst; if (want_instance) { int k; SEXP_t *item; item = create_item(path, file, pfd->pattern, cur_inst, substrs, substr_cnt); probe_item_collect(pfd->ctx, item); for (k = 0; k < substr_cnt; ++k) oscap_free(substrs[k]); oscap_free(substrs); } } } while (substr_cnt > 0 && ofs < buf_used); cleanup: if (fd != -1) close(fd); oscap_free(buf); if (whole_path != NULL) oscap_free(whole_path); return ret; }
int probe_main(probe_ctx *ctx, void *arg) { SEXP_t *path_ent, *file_ent, *inst_ent, *bh_ent, *patt_ent, *filepath_ent, *probe_in; SEXP_t *r0; /* char *i_val, *m_val, *s_val; */ bool val; struct pfdata pfd; int ret = 0; int errorffset = -1; const char *error; OVAL_FTS *ofts; OVAL_FTSENT *ofts_ent; char path_with_root[PATH_MAX + 1]; unsigned int root_len = 0; (void)arg; memset(&pfd, 0, sizeof(pfd)); probe_in = probe_ctx_getobject(ctx); over = probe_obj_get_platform_schema_version(probe_in); path_ent = probe_obj_getent(probe_in, "path", 1); file_ent = probe_obj_getent(probe_in, "filename", 1); inst_ent = probe_obj_getent(probe_in, "instance", 1); patt_ent = probe_obj_getent(probe_in, "pattern", 1); filepath_ent = probe_obj_getent(probe_in, "filepath", 1); bh_ent = probe_obj_getent(probe_in, "behaviors", 1); /* we want (path+filename or filepath) + instance + pattern*/ if ( ((path_ent == NULL || file_ent == NULL) && filepath_ent==NULL) || inst_ent==NULL || patt_ent==NULL) { SEXP_free (patt_ent); ret = PROBE_ENOELM; goto cleanup; } /* get pattern from SEXP */ SEXP_t *ent_val; ent_val = probe_ent_getval(patt_ent); pfd.pattern = SEXP_string_cstr(ent_val); assume_d(pfd.pattern != NULL, -1); SEXP_free(patt_ent); SEXP_free(ent_val); /* wtf? i_val = s_val = "0"; m_val = "1"; */ /* reset filebehavior attributes if 'filepath' entity is used */ if (filepath_ent != NULL && bh_ent != NULL) { SEXP_t *r1, *r2, *r3; r1 = r2 = r3 = NULL; if (probe_ent_attrexists(bh_ent, "ignore_case")) { r1 = probe_ent_getattrval(bh_ent, "ignore_case"); } if (probe_ent_attrexists(bh_ent, "multiline")) { r2 = probe_ent_getattrval(bh_ent, "multiline"); } if (probe_ent_attrexists(bh_ent, "singleline")) { r3 = probe_ent_getattrval(bh_ent, "singleline"); } r0 = SEXP_list_new(NULL); SEXP_free(bh_ent); bh_ent = probe_ent_creat1("behaviors", r0, NULL); SEXP_free(r0); if (r1) { probe_ent_attr_add(bh_ent, "ignore_case", r1); SEXP_free(r1); } if (r2) { probe_ent_attr_add(bh_ent, "multiline", r2); SEXP_free(r2); } if (r3) { probe_ent_attr_add(bh_ent, "singleline", r3); SEXP_free(r3); } } probe_tfc54behaviors_canonicalize(&bh_ent); pfd.instance_ent = inst_ent; pfd.ctx = ctx; pfd.re_opts = PCRE_UTF8; r0 = probe_ent_getattrval(bh_ent, "ignore_case"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= PCRE_CASELESS; } r0 = probe_ent_getattrval(bh_ent, "multiline"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= PCRE_MULTILINE; } r0 = probe_ent_getattrval(bh_ent, "singleline"); if (r0) { val = SEXP_string_getb(r0); SEXP_free(r0); if (val) pfd.re_opts |= PCRE_DOTALL; } pfd.compiled_regex = pcre_compile(pfd.pattern, pfd.re_opts, &error, &errorffset, NULL); if (pfd.compiled_regex == NULL) { SEXP_t *msg; msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "pcre_compile() '%s' %s.", pfd.pattern, error); probe_cobj_add_msg(probe_ctx_getresult(pfd.ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(pfd.ctx), SYSCHAR_FLAG_ERROR); goto cleanup; } path_with_root[PATH_MAX] = '\0'; if (OSCAP_GSYM(offline_mode) & PROBE_OFFLINE_OWN) { strncpy(path_with_root, getenv("OSCAP_PROBE_ROOT"), PATH_MAX); root_len = strlen(path_with_root); if (path_with_root[root_len - 1] == FILE_SEPARATOR) --root_len; } if ((ofts = oval_fts_open(path_ent, file_ent, filepath_ent, bh_ent, probe_ctx_getresult(ctx))) != NULL) { while ((ofts_ent = oval_fts_read(ofts)) != NULL) { if (ofts_ent->fts_info == FTS_F || ofts_ent->fts_info == FTS_SL) { strncpy(path_with_root + root_len, ofts_ent->path, PATH_MAX - root_len); // todo: handle return code process_file(path_with_root, ofts_ent->file, &pfd); } oval_ftsent_free(ofts_ent); } oval_fts_close(ofts); } cleanup: SEXP_free(file_ent); SEXP_free(path_ent); SEXP_free(inst_ent); SEXP_free(bh_ent); SEXP_free(filepath_ent); if (pfd.pattern != NULL) free(pfd.pattern); if (pfd.compiled_regex != NULL) pcre_free(pfd.compiled_regex); return ret; }
int probe_main(probe_ctx *ctx, void *arg) { SEXP_t *object; int err; llist ll; object = probe_ctx_getobject(ctx); req.protocol_ent = probe_obj_getent(object, "protocol", 1); if (req.protocol_ent == NULL) { err = PROBE_ENOVAL; goto cleanup; } req.local_address_ent = probe_obj_getent(object, "local_address", 1); if (req.local_address_ent == NULL) { err = PROBE_ENOVAL; goto cleanup; } req.local_port_ent = probe_obj_getent(object, "local_port", 1); if (req.local_port_ent == NULL) { err = PROBE_ENOVAL; goto cleanup; } // Now start collecting the info list_create(&ll); if (collect_process_info(&ll)) { SEXP_t *msg; msg = probe_msg_creat(OVAL_MESSAGE_LEVEL_ERROR, "Permission error."); probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); SEXP_free(msg); probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR); err = 0; goto cleanup; } // Now we check the tcp socket list... read_tcp("/proc/net/tcp", "tcp", &ll, ctx); read_tcp("/proc/net/tcp6", "tcp", &ll, ctx); // Next udp sockets... read_udp("/proc/net/udp", "udp", &ll, ctx); read_udp("/proc/net/udp6", "udp", &ll, ctx); // Next, raw sockets...not exactly part of standard yet. They // can be used to send datagrams, so we will pretend they are udp read_raw("/proc/net/raw", "udp", &ll, ctx); read_raw("/proc/net/raw6", "udp", &ll, ctx); list_clear(&ll); err = 0; cleanup: SEXP_vfree(req.protocol_ent, req.local_address_ent, req.local_port_ent, NULL); return err; }