static int eval_data(const char *type, const char *local_address, unsigned int local_port) { SEXP_t *r0; r0 = SEXP_string_newf("%s", type); if (probe_entobj_cmp(req.protocol_ent, r0) != OVAL_RESULT_TRUE) { SEXP_free(r0); return 0; } SEXP_free(r0); r0 = SEXP_string_newf("%s", local_address); if (probe_entobj_cmp(req.local_address_ent, r0) != OVAL_RESULT_TRUE) { SEXP_free(r0); return 0; } SEXP_free(r0); r0 = SEXP_number_newu_32(local_port); if (probe_entobj_cmp(req.local_port_ent, r0) != OVAL_RESULT_TRUE) { SEXP_free(r0); return 0; } SEXP_free(r0); return 1; }
static SEXP_t *oval_behaviors_to_sexp(struct oval_behavior_iterator *bit) { char *attr_name, *attr_val; SEXP_t *elm_name; SEXP_t *r0; struct oval_behavior *behavior; elm_name = SEXP_list_new(r0 = SEXP_string_newf("behaviors"), NULL); SEXP_free(r0); while (oval_behavior_iterator_has_more(bit)) { behavior = oval_behavior_iterator_next(bit); attr_name = oval_behavior_get_key(behavior); attr_val = oval_behavior_get_value(behavior); SEXP_list_add(elm_name, r0 = SEXP_string_newf(":%s", attr_name)); SEXP_free(r0); if (attr_val != NULL) { SEXP_list_add(elm_name, r0 = SEXP_string_new(attr_val, strlen(attr_val))); SEXP_free(r0); } } r0 = SEXP_list_new(elm_name, NULL); SEXP_free(elm_name); return (r0); }
static SEXP_t *oval_entity_to_sexp(struct oval_entity *ent) { SEXP_t *elm, *elm_name; SEXP_t *r0, *r1, *r2; oval_datatype_t datatype; oval_entity_varref_type_t vr_type; elm_name = SEXP_list_new(r0 = SEXP_string_newf("%s", oval_entity_get_name(ent)), /* operation */ r1 = SEXP_string_new(":operation", 10), r2 = SEXP_number_newu_32(oval_entity_get_operation(ent)), NULL); SEXP_vfree(r0, r1, r2, NULL); if (oval_entity_get_mask(ent)) { SEXP_list_add(elm_name, r0 = SEXP_string_new("mask", 4)); SEXP_free(r0); } elm = SEXP_list_new(NULL); datatype = oval_entity_get_datatype(ent); probe_ent_setdatatype(elm, datatype); vr_type = oval_entity_get_varref_type(ent); if (vr_type == OVAL_ENTITY_VARREF_ATTRIBUTE || vr_type == OVAL_ENTITY_VARREF_ELEMENT) { /* var_ref */ struct oval_variable *var; var = oval_entity_get_variable(ent); SEXP_list_add(elm_name, r0 = SEXP_string_new(":var_ref", 8)); SEXP_list_add(elm_name, r1 = SEXP_string_newf("%s", oval_variable_get_id(var))); SEXP_list_add(elm, elm_name); SEXP_vfree(r0, r1, elm_name, NULL); } else { /* value */ struct oval_value *val; SEXP_list_add(elm, elm_name); SEXP_free(elm_name); val = oval_entity_get_value(ent); if (datatype != OVAL_DATATYPE_RECORD && val != NULL) { SEXP_t *val_sexp; val_sexp = oval_value_to_sexp(val, datatype); if (val_sexp != NULL) { SEXP_list_add(elm, val_sexp); SEXP_free(val_sexp); } } } return (elm); }
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 int read_packet(llist *l, probe_ctx *ctx, oval_schema_version_t over) { int line = 0; FILE *f; char buf[256]; void *s; int refcnt, sk_type, ifindex, running; unsigned long inode; unsigned rmem, uid, proto_num; struct interface_t interface; f = fopen("/proc/net/packet", "rt"); if (f == NULL) { if (errno != ENOENT) return 1; else return 0; } __fsetlocking(f, FSETLOCKING_BYCALLER); while (fgets(buf, sizeof(buf), f)) { if (line == 0) { line++; continue; } /* follow structure from net/packet/af_packet.c */ sscanf(buf, "%p %d %d %04x %d %d %u %u %lu\n", &s, &refcnt, &sk_type, &proto_num, &ifindex, &running, &rmem, &uid, &inode ); if (list_find_inode(l, inode) && get_interface(ifindex, &interface)) { struct result_info r; SEXP_t *r0; dI("Have interface_name: %s, hw_address: %s\n", interface.interface_name, interface.hw_address); r0 = SEXP_string_newf("%s", interface.interface_name); if (probe_entobj_cmp(interface_name_ent, r0) != OVAL_RESULT_TRUE) { SEXP_free(r0); continue; } SEXP_free(r0); r.interface_name = interface.interface_name; r.protocol = oscap_enum_to_string(ProtocolType, proto_num); r.hw_address = interface.hw_address; report_finding(&r, l, ctx, over); } } fclose(f); return 0; }
static SEXP_t *oval_filter_to_sexp(struct oval_filter *filter) { SEXP_t *elm, *attr, *r0, *r1; oval_filter_action_t act; struct oval_state *ste; char *ste_id; act = oval_filter_get_filter_action(filter); ste = oval_filter_get_state(filter); ste_id = oval_state_get_id(ste); attr = probe_attr_creat("action", r0 = SEXP_number_newu(act), NULL); elm = probe_ent_creat1("filter", attr, r1 = SEXP_string_newf("%s", ste_id)); SEXP_vfree(attr, r0, r1, NULL); return (elm); }
SEXP_t *oval_value_to_sexp(struct oval_value *val, oval_datatype_t dtype) { SEXP_t *val_sexp = NULL; char *val_rptr = NULL; switch (dtype) { case OVAL_DATATYPE_EVR_STRING: case OVAL_DATATYPE_DEBIAN_EVR_STRING: case OVAL_DATATYPE_IPV4ADDR: case OVAL_DATATYPE_IPV6ADDR: case OVAL_DATATYPE_STRING: case OVAL_DATATYPE_VERSION: val_rptr = oval_value_get_text (val); if (val_rptr != NULL) { val_sexp = SEXP_string_newf("%s", val_rptr); } break; case OVAL_DATATYPE_FLOAT: val_sexp = SEXP_number_newf(oval_value_get_float(val)); break; case OVAL_DATATYPE_INTEGER: val_sexp = SEXP_number_newi_64(oval_value_get_integer(val)); break; case OVAL_DATATYPE_BOOLEAN: val_sexp = SEXP_number_newb(oval_value_get_boolean(val)); break; case OVAL_DATATYPE_BINARY: case OVAL_DATATYPE_FILESET_REVISION: case OVAL_DATATYPE_IOS_VERSION: // todo: oscap_seterr(OSCAP_EFAMILY_OVAL, "Unsupported datatype: %s.", dtype); val_sexp = NULL; break; default: oscap_seterr(OSCAP_EFAMILY_OVAL, "Unknown datatype: %s.", dtype); val_sexp = NULL; break; } return val_sexp; }
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, 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 (void) { SEXP_t *s_exp; char *s1, *s2; s1 = "Hello, world!"; s2 = "abcdefghijklmnopqrstuvwxyz"; setbuf (stdout, NULL); s_exp = SEXP_string_new (s1, strlen (s1)); SEXP_fprintfa (stdout, s_exp); putc ('\n', stdout); SEXP_free (s_exp); s_exp = SEXP_string_newf ("s2=%s", s2); SEXP_fprintfa (stdout, s_exp); putc ('\n', stdout); SEXP_free (s_exp); return (0); }
static int rpmverify_collect(probe_ctx *ctx, const char *name, oval_operation_t name_op, const char *file, oval_operation_t file_op, SEXP_t *name_ent, SEXP_t *filepath_ent, uint64_t flags, void (*callback)(probe_ctx *, struct rpmverify_res *)) { rpmdbMatchIterator match; rpmVerifyAttrs omit = (rpmVerifyAttrs)(flags & RPMVERIFY_RPMATTRMASK); Header pkgh; pcre *re = NULL; int ret = -1; /* pre-compile regex if needed */ if (file_op == OVAL_OPERATION_PATTERN_MATCH) { const char *errmsg; int erroff; re = pcre_compile(file, PCRE_UTF8, &errmsg, &erroff, NULL); if (re == NULL) { /* TODO */ return (-1); } } RPMVERIFY_LOCK; switch (name_op) { case OVAL_OPERATION_EQUALS: match = rpmtsInitIterator (g_rpm.rpmts, RPMTAG_NAME, (const void *)name, 0); if (match == NULL) { ret = 0; goto ret; } ret = rpmdbGetIteratorCount (match); break; case OVAL_OPERATION_NOT_EQUAL: match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0); if (match == NULL) { ret = 0; goto ret; } if (rpmdbSetIteratorRE (match, RPMTAG_NAME, RPMMIRE_GLOB, "*") != 0) { ret = -1; goto ret; } break; case OVAL_OPERATION_PATTERN_MATCH: match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0); if (match == NULL) { ret = 0; goto ret; } if (rpmdbSetIteratorRE (match, RPMTAG_NAME, RPMMIRE_REGEX, (const char *)name) != 0) { ret = -1; goto ret; } break; default: /* not supported */ dE("package name: operation not supported"); ret = -1; goto ret; } assume_d(RPMTAG_BASENAMES != 0, -1); assume_d(RPMTAG_DIRNAMES != 0, -1); while ((pkgh = rpmdbNextIterator (match)) != NULL) { rpmfi fi; rpmTag tag[2] = { RPMTAG_BASENAMES, RPMTAG_DIRNAMES }; struct rpmverify_res res; errmsg_t rpmerr; int i; SEXP_t *name_sexp; res.name = headerFormat(pkgh, "%{NAME}", &rpmerr); name_sexp = SEXP_string_newf("%s", res.name); if (probe_entobj_cmp(name_ent, name_sexp) != OVAL_RESULT_TRUE) { SEXP_free(name_sexp); continue; } SEXP_free(name_sexp); /* * Inspect package files & directories */ for (i = 0; i < 2; ++i) { fi = rpmfiNew(g_rpm.rpmts, pkgh, tag[i], 1); while (rpmfiNext(fi) != -1) { SEXP_t *filepath_sexp; res.fflags = rpmfiFFlags(fi); res.oflags = omit; if (((res.fflags & RPMFILE_CONFIG) && (flags & RPMVERIFY_SKIP_CONFIG)) || ((res.fflags & RPMFILE_GHOST) && (flags & RPMVERIFY_SKIP_GHOST))) continue; res.file = strdup(rpmfiFN(fi)); filepath_sexp = SEXP_string_newf("%s", res.file); if (probe_entobj_cmp(filepath_ent, filepath_sexp) != OVAL_RESULT_TRUE) { SEXP_free(filepath_sexp); free(res.file); continue; } SEXP_free(filepath_sexp); if (rpmVerifyFile(g_rpm.rpmts, fi, &res.vflags, omit) != 0) res.vflags = RPMVERIFY_FAILURES; callback(ctx, &res); free(res.file); } rpmfiFree(fi); } } match = rpmdbFreeIterator (match); ret = 0; ret: if (re != NULL) pcre_free(re); RPMVERIFY_UNLOCK; return (ret); }
static int read_process(SEXP_t *cmd_ent, probe_ctx *ctx) { int err = 1; DIR *d; struct dirent *ent; d = opendir("/proc"); if (d == NULL) return err; // Get the time tick hertz ticks = (unsigned long)sysconf(_SC_CLK_TCK); get_boot_time(); // Scan the directories while (( ent = readdir(d) )) { int fd, len; char buf[256]; char *tmp, cmd[16], 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; // Skip non-process 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, 0, sizeof(cmd)); sscanf(buf, "%d (%15c", &ppid, cmd); 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; err = 0; // If we get this far, no permission problems dI("Have command: %s\n", cmd); cmd_sexp = SEXP_string_newf("%s", cmd); if (probe_entobj_cmp(cmd_ent, cmd_sexp) == OVAL_RESULT_TRUE) { struct result_info r; unsigned long t = uutime/ticks + ustime/ticks; char tbuf[32], sbuf[32]; 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 = 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; get_uids(pid, &r); report_finding(&r, ctx); } SEXP_free(cmd_sexp); } closedir(d); return err; }
static SEXP_t *oval_set_to_sexp(struct oval_setobject *set) { SEXP_t *elm, *elm_name; SEXP_t *r0, *r1, *r2; elm_name = SEXP_list_new(r0 = SEXP_string_new("set", 3), /* operation */ r1 = SEXP_string_new(":operation", 10), r2 = SEXP_number_newu_32(oval_setobject_get_operation(set)), NULL); SEXP_free(r0); SEXP_free(r1); SEXP_free(r2); elm = SEXP_list_new(elm_name, NULL); SEXP_free(elm_name); switch (oval_setobject_get_type(set)) { case OVAL_SET_AGGREGATE:{ struct oval_setobject_iterator *sit; struct oval_setobject *subset; sit = oval_setobject_get_subsets(set); while (oval_setobject_iterator_has_more(sit)) { subset = oval_setobject_iterator_next(sit); SEXP_list_add(elm, r0 = oval_set_to_sexp(subset)); SEXP_free(r0); } oval_setobject_iterator_free(sit); } break; case OVAL_SET_COLLECTIVE:{ struct oval_object_iterator *oit; struct oval_filter_iterator *fit; struct oval_object *obj; SEXP_t *subelm; oit = oval_setobject_get_objects(set); while (oval_object_iterator_has_more(oit)) { obj = oval_object_iterator_next(oit); subelm = SEXP_list_new(r0 = SEXP_string_new("obj_ref", 7), r1 = SEXP_string_newf("%s", oval_object_get_id(obj)), NULL); SEXP_free(r0); SEXP_free(r1); SEXP_list_add(elm, subelm); SEXP_free(subelm); } oval_object_iterator_free(oit); fit = oval_setobject_get_filters(set); while (oval_filter_iterator_has_more(fit)) { struct oval_filter *fil; fil = oval_filter_iterator_next(fit); subelm = oval_filter_to_sexp(fil); SEXP_list_add(elm, subelm); SEXP_free(subelm); } oval_filter_iterator_free(fit); } break; default: abort(); } return (elm); }
static int oval_varref_attr_to_sexp(void *sess, struct oval_entity *entity, struct oval_syschar *syschar, SEXP_t **out_sexp) { unsigned int val_cnt = 0; SEXP_t *val_lst, *val_sexp, *varref, *id_sexp, *val_cnt_sexp; oval_datatype_t dt; struct oval_variable *var; struct oval_value_iterator *vit; struct oval_value *val; oval_syschar_collection_flag_t flag; char msg[100]; int ret = 0; var = oval_entity_get_variable(entity); if (oval_probe_query_variable(sess, var) != 0) { dE("Can't convert variable reference to SEXP."); return -1; } flag = oval_variable_get_collection_flag(var); switch (flag) { case SYSCHAR_FLAG_COMPLETE: case SYSCHAR_FLAG_INCOMPLETE: vit = oval_variable_get_values(var); if (oval_value_iterator_has_more(vit)) break; oval_value_iterator_free(vit); /* fall through */ case SYSCHAR_FLAG_DOES_NOT_EXIST: snprintf(msg, sizeof(msg), "Referenced variable has no values (%s).", oval_variable_get_id(var)); dI("%s", msg); ret = 1; break; default: snprintf(msg, sizeof(msg), "There was a problem processing referenced variable (%s).", oval_variable_get_id(var)); dW("%s", msg); ret = 1; } if (ret) { oval_syschar_add_new_message(syschar, msg, OVAL_MESSAGE_LEVEL_WARNING); oval_syschar_set_flag(syschar, SYSCHAR_FLAG_DOES_NOT_EXIST); return ret; } val_lst = SEXP_list_new(NULL); while (oval_value_iterator_has_more(vit)) { val = oval_value_iterator_next(vit); dt = oval_entity_get_datatype(entity); val_sexp = oval_value_to_sexp(val, dt); if (val_sexp == NULL) { oval_syschar_add_new_message(syschar, "Failed to convert variable value.", OVAL_MESSAGE_LEVEL_ERROR); oval_syschar_set_flag(syschar, SYSCHAR_FLAG_ERROR); SEXP_free(val_lst); oval_value_iterator_free(vit); return -1; } SEXP_list_add(val_lst, val_sexp); SEXP_free(val_sexp); ++val_cnt; } oval_value_iterator_free(vit); id_sexp = SEXP_string_newf("%s", oval_variable_get_id(var)); val_cnt_sexp = SEXP_number_newu(val_cnt); varref = SEXP_list_new(id_sexp, val_cnt_sexp, val_lst, NULL); SEXP_free(id_sexp); SEXP_free(val_cnt_sexp); SEXP_free(val_lst); *out_sexp = varref; return 0; }
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; }
static int read_environment(SEXP_t *pid_ent, SEXP_t *name_ent, probe_ctx *ctx) { int err = 1, pid, fd; bool empty; size_t env_name_size; SEXP_t *env_name, *env_value, *item, *pid_sexp; DIR *d; struct dirent *d_entry; char *buffer, env_file[256], *null_char; ssize_t buffer_used; size_t buffer_size; d = opendir("/proc"); if (d == NULL) { dE("Can't read /proc: errno=%d, %s.\n", errno, strerror (errno)); return PROBE_EACCESS; } if ((buffer = oscap_realloc(NULL, BUFFER_SIZE)) == NULL) { dE("Can't allocate memory"); closedir(d); return PROBE_EFAULT; } buffer_size = BUFFER_SIZE; while ((d_entry = readdir(d))) { if (strspn(d_entry->d_name, "0123456789") != strlen(d_entry->d_name)) continue; pid = atoi(d_entry->d_name); pid_sexp = SEXP_number_newi_32(pid); if (probe_entobj_cmp(pid_ent, pid_sexp) != OVAL_RESULT_TRUE) { SEXP_free(pid_sexp); continue; } SEXP_free(pid_sexp); sprintf(env_file, "/proc/%d/environ", pid); if ((fd = open(env_file, O_RDONLY)) == -1) { dE("Can't open \"%s\": errno=%d, %s.\n", env_file, errno, strerror (errno)); item = probe_item_create( OVAL_INDEPENDENT_ENVIRONMENT_VARIABLE58, NULL, "pid", OVAL_DATATYPE_INTEGER, (int64_t)pid, NULL ); probe_item_setstatus(item, SYSCHAR_STATUS_ERROR); probe_item_add_msg(item, OVAL_MESSAGE_LEVEL_ERROR, "Can't open \"%s\": errno=%d, %s.", env_file, errno, strerror (errno)); probe_item_collect(ctx, item); continue; } empty = true; if ((buffer_used = read(fd, buffer, buffer_size - 1)) > 0) { empty = false; } while (! empty) { while (! (null_char = memchr(buffer, 0, buffer_used))) { ssize_t s; if ((size_t)buffer_used >= buffer_size) { buffer_size += BUFFER_SIZE; buffer = oscap_realloc(buffer, buffer_size); if (buffer == NULL) { dE("Can't allocate memory"); exit(ENOMEM); } } s = read(fd, buffer + buffer_used, buffer_size - buffer_used); if (s <= 0) { empty = true; buffer[buffer_used++] = 0; } else { buffer_used += s; } } do { char *eq_char = strchr(buffer, '='); if (eq_char == NULL) { /* strange but possible: * $ strings /proc/1218/environ /dev/input/event0 /dev/input/event1 /dev/input/event4 /dev/input/event3 */ buffer_used -= null_char + 1 - buffer; memmove(buffer, null_char + 1, buffer_used); continue; } env_name_size = eq_char - buffer; env_name = SEXP_string_new(buffer, env_name_size); env_value = SEXP_string_newf("%s", buffer + env_name_size + 1); if (probe_entobj_cmp(name_ent, env_name) == OVAL_RESULT_TRUE) { item = probe_item_create( OVAL_INDEPENDENT_ENVIRONMENT_VARIABLE58, NULL, "pid", OVAL_DATATYPE_INTEGER, (int64_t)pid, "name", OVAL_DATATYPE_SEXP, env_name, "value", OVAL_DATATYPE_SEXP, env_value, NULL); probe_item_collect(ctx, item); err = 0; } SEXP_free(env_name); SEXP_free(env_value); buffer_used -= null_char + 1 - buffer; memmove(buffer, null_char + 1, buffer_used); } while ((null_char = memchr(buffer, 0, buffer_used))); } close(fd); } closedir(d); oscap_free(buffer); if (err) { SEXP_t *msg = probe_msg_creatf(OVAL_MESSAGE_LEVEL_ERROR, "Can't find process with requested PID."); probe_cobj_add_msg(probe_ctx_getresult(ctx), msg); SEXP_free(msg); err = 0; } return err; }
int oval_state_to_sexp(void *sess, struct oval_state *state, SEXP_t **out_sexp) { SEXP_t *ste, *ste_name, *ste_ent; SEXP_t *r0, *r1, *r2, *r3, *r4; char buffer[128]; size_t buflen; const char *subtype_name; struct oval_state_content_iterator *contents; subtype_name = oval_subtype_to_str(oval_state_get_subtype(state)); if (subtype_name == NULL) { dI("FAIL: unknown subtype: %d", oval_state_get_subtype(state)); return (-1); } buflen = snprintf(buffer, sizeof buffer, "%s_state", subtype_name); _A(buflen < sizeof buffer); ste_name = SEXP_list_new(r0 = SEXP_string_new(buffer, buflen), r1 = SEXP_string_new(":id", 3), r2 = SEXP_string_newf("%s", oval_state_get_id(state)), r3 = SEXP_string_new(":operator", 9), r4 = SEXP_number_newu(oval_state_get_operator(state)), NULL); ste = SEXP_list_new(ste_name, NULL); SEXP_vfree(r0, r1, r2, r3, r4, ste_name, NULL); contents = oval_state_get_contents(state); while (oval_state_content_iterator_has_more(contents)) { oval_check_t ochk; oval_existence_t oext; oval_entity_varref_type_t vr_type; struct oval_entity *ent; struct oval_state_content *content = oval_state_content_iterator_next(contents); struct oval_record_field_iterator *rf_itr; ent = oval_state_content_get_entity(content); ste_ent = oval_entity_to_sexp(ent); if (ste_ent == NULL) { goto fail; } rf_itr = oval_state_content_get_record_fields(content); while (oval_record_field_iterator_has_more(rf_itr)) { struct oval_record_field *rf; SEXP_t *rf_sexp; rf = oval_record_field_iterator_next(rf_itr); rf_sexp = oval_record_field_STATE_to_sexp(rf); SEXP_list_add(ste_ent, rf_sexp); SEXP_free(rf_sexp); } oval_record_field_iterator_free(rf_itr); ochk = oval_state_content_get_var_check(content); if (ochk != OVAL_CHECK_UNKNOWN) { probe_ent_attr_add(ste_ent, "var_check", r0 = SEXP_number_newu_32(ochk)); SEXP_free(r0); } ochk = oval_state_content_get_ent_check(content); if (ochk != OVAL_CHECK_UNKNOWN) { probe_ent_attr_add(ste_ent, "entity_check", r0 = SEXP_number_newu_32(ochk)); SEXP_free(r0); } oext = oval_state_content_get_check_existence(content); if (oext != OVAL_EXISTENCE_UNKNOWN) { probe_ent_attr_add(ste_ent, "check_existence", r0 = SEXP_number_newu_32(oext)); SEXP_free(r0); } vr_type = oval_entity_get_varref_type(ent); if (vr_type == OVAL_ENTITY_VARREF_ATTRIBUTE || vr_type == OVAL_ENTITY_VARREF_ELEMENT) { SEXP_t *val_lst; struct oval_variable *var; oval_datatype_t dt; var = oval_entity_get_variable(ent); dt = oval_entity_get_datatype(ent); if (oval_varref_elm_to_sexp(sess, var, dt, &val_lst, NULL) != 0) goto fail; SEXP_list_add(ste_ent, val_lst); SEXP_free(val_lst); } SEXP_list_add(ste, ste_ent); SEXP_free(ste_ent); } oval_state_content_iterator_free(contents); *out_sexp = ste; return (0); fail: oval_state_content_iterator_free(contents); SEXP_vfree(ste, ste_ent, NULL); return (-1); }
static int read_process(SEXP_t *cmd_ent, probe_ctx *ctx) { int err = 1; DIR *d; struct dirent *ent; d = opendir("/proc"); if (d == NULL) return err; psinfo_t *psinfo; // Scan the directories while (( ent = readdir(d) )) { int fd, len; char buf[336]; int pid; unsigned sched_policy; SEXP_t *cmd_sexp; // Skip non-process 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/psinfo", pid); fd = open(buf, O_RDONLY, 0); if (fd < 0) continue; len = read(fd, buf, sizeof buf); close(fd); if (len < 336) continue; // The psinfo file contains a psinfo struct; this typecast gets us the struct directly psinfo = (psinfo_t *) buf; err = 0; // If we get this far, no permission problems dI("Have command: %s\n", psinfo->pr_fname); cmd_sexp = SEXP_string_newf("%s", psinfo->pr_fname); if (probe_entobj_cmp(cmd_ent, cmd_sexp) == OVAL_RESULT_TRUE) { struct result_info r; char tbuf[32], sbuf[32]; int tday,tyear; time_t s_time; struct tm *proc, *now; const char *fmt; int fixfmt_year; r.scheduling_class = malloc(PRCLSZ); strncpy(r.scheduling_class, (psinfo->pr_lwp).pr_clname, sizeof(r.scheduling_class)); // Get the start time s_time = time(NULL); now = localtime(&s_time); tyear = now->tm_year; tday = now->tm_yday; // Get current time s_time = psinfo->pr_start.tv_sec; 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 = psinfo->pr_fname; r.exec_time = convert_time(psinfo->pr_time.tv_sec, tbuf, sizeof(tbuf)); r.pid = psinfo->pr_pid; r.ppid = psinfo->pr_ppid; r.priority = (psinfo->pr_lwp).pr_pri; r.ruid = psinfo->pr_uid; r.start_time = sbuf; r.tty = oscap_sprintf("%s", psinfo->pr_ttydev); r.user_id = psinfo->pr_euid; report_finding(&r, ctx); } SEXP_free(cmd_sexp); } closedir(d); return err; }
static int get_runlevel_sysv (struct runlevel_req *req, struct runlevel_rep **rep, bool suse, const char *init_path, const char *rc_path) { const char runlevel_list[] = {'0', '1', '2', '3', '4', '5', '6'}; char pathbuf[PATH_MAX]; DIR *init_dir, *rc_dir; struct dirent *init_dp, *rc_dp; struct stat init_st, rc_st; struct runlevel_rep *rep_lst = NULL; _A(req != NULL); _A(rep != NULL); init_dir = opendir(init_path); if (init_dir == NULL) { dI("Can't open directory \"%s\": errno=%d, %s.", init_path, errno, strerror (errno)); return (-1); } while ((init_dp = readdir(init_dir)) != NULL) { char *service_name; unsigned int i; SEXP_t *r0; // Ensure that we are in the expected directory before // touching relative paths if (fchdir(dirfd(init_dir)) != 0) { dI("Can't fchdir to \"%s\": errno=%d, %s.", init_path, errno, strerror (errno)); closedir(init_dir); return -1; } if (stat(init_dp->d_name, &init_st) != 0) { dI("Can't stat file %s/%s: errno=%d, %s.", init_path, init_dp->d_name, errno, strerror(errno)); continue; } r0 = SEXP_string_newf("%s", init_dp->d_name); if (probe_entobj_cmp(req->service_name_ent, r0) != OVAL_RESULT_TRUE) { SEXP_free(r0); continue; } SEXP_free(r0); service_name = init_dp->d_name; for (i = 0; i < (sizeof (runlevel_list) / sizeof (runlevel_list[0])); ++i) { char runlevel[2] = {'\0', '\0'}; bool start, kill; r0 = SEXP_string_newf("%c", runlevel_list[i]); if (probe_entobj_cmp(req->runlevel_ent, r0) != OVAL_RESULT_TRUE) { SEXP_free(r0); continue; } SEXP_free(r0); runlevel[0] = runlevel_list[i]; snprintf(pathbuf, sizeof (pathbuf), rc_path, runlevel_list[i]); rc_dir = opendir(pathbuf); if (rc_dir == NULL) { dI("Can't open directory \"%s\": errno=%d, %s.", rc_path, errno, strerror (errno)); continue; } if (chdir(pathbuf) != 0) { dI("Can't fchdir to \"%s\": errno=%d, %s.", rc_path, errno, strerror (errno)); closedir(rc_dir); continue; } // On SUSE, the presence of a symbolic link to the init.d/<service> in // a runlevel directory rcx.d implies that the sevice is started on x. if (suse) { start = false; kill = true; } else start = kill = false; while ((rc_dp = readdir(rc_dir)) != NULL) { if (stat(rc_dp->d_name, &rc_st) != 0) { dI("Can't stat file %s/%s: errno=%d, %s.", rc_path, rc_dp->d_name, errno, strerror(errno)); continue; } if (init_st.st_ino == rc_st.st_ino) { if (suse) { if (rc_dp->d_name[0] == 'S') { start = true; kill = false; break; } } else { if (rc_dp->d_name[0] == 'S') { start = true; break; } else if (rc_dp->d_name[0] == 'K') { kill = true; break; } else { dI("Unexpected character in filename: %c, %s/%s.", rc_dp->d_name[0], pathbuf, rc_dp->d_name); } } } } closedir(rc_dir); if (rep_lst == NULL) { rep_lst = *rep = oscap_alloc(sizeof (struct runlevel_rep)); } else { rep_lst->next = oscap_alloc(sizeof (struct runlevel_rep)); rep_lst = rep_lst->next; } rep_lst->service_name = strdup(service_name); rep_lst->runlevel = strdup(runlevel); rep_lst->start = start; rep_lst->kill = kill; rep_lst->next = NULL; } } closedir(init_dir); return (1); }