static void report_finding(struct result_info *res, probe_ctx *ctx) { SEXP_t *item; SEXP_t *se_ruid; if (oval_version_cmp(over, OVAL_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); }
int probe_main(probe_ctx *ctx, void *probe_arg) { SEXP_t *unit_entity, *probe_in, *property_entity; oval_version_t oval_version; probe_in = probe_ctx_getobject(ctx); oval_version = probe_obj_get_schema_version(probe_in); if (oval_version_cmp(oval_version, OVAL_VERSION(5.11)) < 0) { // OVAL 5.10 and less return PROBE_EOPNOTSUPP; } unit_entity = probe_obj_getent(probe_in, "unit", 1); property_entity = probe_obj_getent(probe_in, "property", 1); DBusError dbus_error; DBusConnection *dbus_conn; dbus_error_init(&dbus_error); dbus_conn = connect_dbus(); if (dbus_conn == NULL) { dbus_error_free(&dbus_error); SEXP_free(property_entity); SEXP_free(unit_entity); return PROBE_ESYSTEM; } struct unit_callback_vars vars; vars.dbus_conn = dbus_conn; vars.ctx = ctx; vars.unit_entity = unit_entity; vars.property_entity = property_entity; get_all_systemd_units(dbus_conn, unit_callback, &vars); SEXP_free(unit_entity); SEXP_free(property_entity); dbus_error_free(&dbus_error); disconnect_dbus(dbus_conn); return 0; }
static int collect_item(probe_ctx *ctx, oval_version_t over, struct mntent *mnt_ent) #endif { SEXP_t *item; char *uuid = "", *tok, *save = NULL, **mnt_opts; 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_opts = oscap_alloc(sizeof(char *) * 2); mnt_ocnt = 0; tok = strtok_r(mnt_ent->mnt_opts, ",", &save); do { mnt_opts[++mnt_ocnt - 1] = tok; mnt_opts = oscap_realloc(mnt_opts, sizeof(char *) * (mnt_ocnt + 1)); mnt_opts[mnt_ocnt] = NULL; } while ((tok = strtok_r(NULL, ",", &save)) != NULL); dI("mnt_ocnt = %d, mnt_opts[mnt_ocnt]=%p\n", mnt_ocnt, mnt_opts[mnt_ocnt]); /* * "Correct" the type (this won't be (hopefully) needed in a later version * of OVAL) */ if (oval_version_cmp(over, OVAL_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); oscap_free(mnt_opts); return (0); }
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_result_t ste_ent_res; struct oval_sysent_iterator *item_entities_itr; struct oresults ent_ores; 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_version_t over = oval_state_get_schema_version(state); if (oval_version_cmp(over, OVAL_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); state_entity_operation = oval_entity_get_operation(state_entity); ores_clear(&ent_ores); found_matching_item = false; 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; 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_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_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 read_process(SEXP_t *cmd_ent, SEXP_t *pid_ent, probe_ctx *ctx) { int err = 1, max_cap_id; DIR *d; struct dirent *ent; oval_version_t oval_version; d = opendir("/proc"); if (d == NULL) return err; // Get the time tick hertz ticks = (unsigned long)sysconf(_SC_CLK_TCK); get_boot_time(); oval_version = probe_obj_get_schema_version(probe_ctx_getobject(ctx)); if (oval_version_cmp(oval_version, OVAL_VERSION(5.11)) < 0) { max_cap_id = OVAL_5_8_MAX_CAP_ID; } else { max_cap_id = OVAL_5_11_MAX_CAP_ID; } struct oscap_buffer *cmdline_buffer = oscap_buffer_new(); char cmd_buffer[1 + 15 + 11 + 1]; // Format:" [ cmd:15 ] <defunc>" cmd_buffer[0] = '['; // Scan the directories while (( ent = readdir(d) )) { int fd, len; char buf[256]; char *tmp, state, tty_dev[128]; int pid, ppid, pgrp, session, tty_nr, tpgid; unsigned flags, sched_policy; unsigned long minflt, cminflt, majflt, cmajflt, uutime, ustime; long cutime, cstime, priority, cnice, nthreads, itrealvalue; unsigned long long start; SEXP_t *cmd_sexp = NULL, *pid_sexp = NULL; // Skip non-process58 dir entries if(*ent->d_name<'0' || *ent->d_name>'9') continue; errno = 0; pid = strtol(ent->d_name, NULL, 10); if (errno || pid == 2) // skip err & kthreads continue; // Parse up the stat file for the proc snprintf(buf, 32, "/proc/%d/stat", pid); fd = open(buf, O_RDONLY, 0); if (fd < 0) continue; len = read(fd, buf, sizeof buf - 1); close(fd); if (len < 40) continue; buf[len] = 0; tmp = strrchr(buf, ')'); if (tmp) *tmp = 0; else continue; memset(cmd_buffer + 1, 0, sizeof(cmd_buffer)-1); // clear cmd after starting '[' sscanf(buf, "%d (%15c", &ppid, cmd_buffer + 1); sscanf(tmp+2, "%c %d %d %d %d %d " "%u %lu %lu %lu %lu " "%lu %lu %lu %ld %ld " "%ld %ld %ld %llu", &state, &ppid, &pgrp, &session, &tty_nr, &tpgid, &flags, &minflt, &cminflt, &majflt, &cmajflt, &uutime, &ustime, &cutime, &cstime, &priority, &cnice, &nthreads, &itrealvalue, &start ); // Skip kthreads if (ppid == 2) continue; const char* cmd; if (state == 'Z') { // zombie cmd = make_defunc_str(cmd_buffer); } else { snprintf(buf, 32, "/proc/%d/cmdline", pid); if (get_process_cmdline(buf, cmdline_buffer)) { cmd = oscap_buffer_get_raw(cmdline_buffer); // use full cmdline } else { cmd = cmd_buffer + 1; } } err = 0; // If we get this far, no permission problems dI("Have command: %s\n", cmd); cmd_sexp = SEXP_string_newf("%s", cmd); pid_sexp = SEXP_number_newu_32(pid); if ((cmd_sexp == NULL || probe_entobj_cmp(cmd_ent, cmd_sexp) == OVAL_RESULT_TRUE) && (pid_sexp == NULL || probe_entobj_cmp(pid_ent, pid_sexp) == OVAL_RESULT_TRUE) ) { struct result_info r; unsigned long t = uutime/ticks + ustime/ticks; char tbuf[32], sbuf[32], *selinux_domain_label, **posix_capabilities; int tday,tyear; time_t s_time; struct tm *proc, *now; const char *fmt; // Now get scheduler policy sched_policy = sched_getscheduler(pid); switch (sched_policy) { case SCHED_OTHER: r.scheduling_class = "TS"; break; case SCHED_BATCH: r.scheduling_class = "B"; break; #ifdef SCHED_IDLE case SCHED_IDLE: r.scheduling_class = "#5"; break; #endif case SCHED_FIFO: r.scheduling_class = "FF"; break; case SCHED_RR: r.scheduling_class = "RR"; break; default: r.scheduling_class = "?"; break; } // Calculate the start time s_time = time(NULL); now = localtime(&s_time); tyear = now->tm_year; tday = now->tm_yday; s_time = boot + (start / ticks); proc = localtime(&s_time); // Select format based on how long we've been running // // FROM THE SPEC: // "This is the time of day the process started formatted in HH:MM:SS if // the same day the process started or formatted as MMM_DD (Ex.: Feb_5) // if process started the previous day or further in the past." // if (tday != proc->tm_yday || tyear != proc->tm_year) fmt = "%b_%d"; else fmt = "%H:%M:%S"; strftime(sbuf, sizeof(sbuf), fmt, proc); r.command_line = cmd; r.exec_time = convert_time(t, tbuf, sizeof(tbuf)); r.pid = pid; r.ppid = ppid; r.priority = priority; r.start_time = sbuf; dev_to_tty(tty_dev, sizeof(tty_dev), (dev_t) tty_nr, pid, ABBREV_DEV); r.tty = tty_dev; r.exec_shield = (get_exec_shield_status(pid) > 0); selinux_domain_label = get_selinux_label(pid); r.selinux_domain_label = selinux_domain_label; posix_capabilities = get_posix_capability(pid, max_cap_id); r.posix_capability = posix_capabilities; r.session_id = session; get_uids(pid, &r); report_finding(&r, ctx); if (selinux_domain_label != NULL) free(selinux_domain_label); if (posix_capabilities != NULL) { char **posix_capabilities_p = posix_capabilities; while (*posix_capabilities_p) free(*posix_capabilities_p++); free(posix_capabilities); } } SEXP_free(cmd_sexp); SEXP_free(pid_sexp); } closedir(d); oscap_buffer_free(cmdline_buffer); return err; }