static int collect_item(struct route_info *rt, probe_ctx *ctx) { SEXP_t *item, *rt_dst; oval_datatype_t addr_type; rt_dst = SEXP_string_new(rt->ip_dst, strlen(rt->ip_dst)); if (probe_entobj_cmp(rt->ip_dst_ent, rt_dst) != OVAL_RESULT_TRUE) { SEXP_free(rt_dst); return 0; } addr_type = rt->ip_version == 4 ? OVAL_DATATYPE_IPV4ADDR : OVAL_DATATYPE_IPV6ADDR; /* create the item */ item = probe_item_create(OVAL_UNIX_ROUTINGTABLE, NULL, "destination", addr_type, rt->ip_dst, "gateway", addr_type, rt->ip_gw, "flags", OVAL_DATATYPE_STRING_M, rt->rt_flags, "interface_name", OVAL_DATATYPE_STRING, rt->if_name, NULL); SEXP_free(rt_dst); return probe_item_collect(ctx, item) == 2 ? 1 : 0; }
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; }
static void rpmverify_additem(probe_ctx *ctx, struct rpmverify_res *res) { SEXP_t *item; #define VF_RESULT(f) (res->oflags & (f) ? "not performed" : (res->vflags & RPMVERIFY_FAILURES ? "not performed" : (res->vflags & (f) ? "fail" : "pass"))) #define FF_RESULT(f) (res->fflags & (f) ? true : false) item = probe_item_create(OVAL_LINUX_RPMVERIFY, NULL, "name", OVAL_DATATYPE_STRING, res->name, "filepath", OVAL_DATATYPE_STRING, res->file, "size_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_FILESIZE), "mode_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_MODE), "md5_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_MD5), "device_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_RDEV), "link_mismatch", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_LINKTO), "ownership_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_USER), "group_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_GROUP), "mtime_differs", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_MTIME), #ifndef HAVE_LIBRPM44 "capabilities_differ", OVAL_DATATYPE_STRING, VF_RESULT(RPMVERIFY_CAPS), #endif "configuration_file", OVAL_DATATYPE_BOOLEAN, FF_RESULT(RPMFILE_CONFIG), "documentation_file", OVAL_DATATYPE_BOOLEAN, FF_RESULT(RPMFILE_DOC), "ghost_file", OVAL_DATATYPE_BOOLEAN, FF_RESULT(RPMFILE_GHOST), "license_file", OVAL_DATATYPE_BOOLEAN, FF_RESULT(RPMFILE_LICENSE), "readme_file", OVAL_DATATYPE_BOOLEAN, FF_RESULT(RPMFILE_README), NULL); probe_item_collect(ctx, item); }
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); }
static void report_finding(struct result_info *res, llist *l, probe_ctx *ctx) { SEXP_t *item; SEXP_t se_lport_mem, se_rport_mem, se_lfull_mem, se_ffull_mem, *se_uid_mem = NULL; lnode *n = NULL; if (l) { n = list_get_cur(l); } if (n) { item = probe_item_create(OVAL_LINUX_INET_LISTENING_SERVER, NULL, "protocol", OVAL_DATATYPE_STRING, res->proto, "local_address", OVAL_DATATYPE_STRING, res->laddr, "local_port", OVAL_DATATYPE_SEXP, SEXP_number_newu_64_r(&se_lport_mem, res->lport), "local_full_address", OVAL_DATATYPE_SEXP, SEXP_string_newf_r(&se_lfull_mem, "%s:%u", res->laddr, res->lport), "program_name", OVAL_DATATYPE_STRING, n->cmd, "foreign_address", OVAL_DATATYPE_STRING, res->raddr, "foreign_port", OVAL_DATATYPE_SEXP, SEXP_number_newu_64_r(&se_rport_mem, res->rport), "foreign_full_address", OVAL_DATATYPE_SEXP, SEXP_string_newf_r(&se_ffull_mem, "%s:%u", res->raddr, res->rport), "pid", OVAL_DATATYPE_INTEGER, (int64_t)n->pid, "user_id", OVAL_DATATYPE_SEXP, se_uid_mem = SEXP_number_newu_64(n->uid), NULL); } else { item = probe_item_create(OVAL_LINUX_INET_LISTENING_SERVER, NULL, "protocol", OVAL_DATATYPE_STRING, res->proto, "local_address", OVAL_DATATYPE_STRING, res->laddr, "local_port", OVAL_DATATYPE_SEXP, SEXP_number_newu_64_r(&se_lport_mem, res->lport), "local_full_address", OVAL_DATATYPE_SEXP, SEXP_string_newf_r(&se_lfull_mem, "%s:%u", res->laddr, res->lport), "foreign_address", OVAL_DATATYPE_STRING, res->raddr, "foreign_port", OVAL_DATATYPE_SEXP, SEXP_number_newu_64_r(&se_rport_mem, res->rport), "foreign_full_address", OVAL_DATATYPE_SEXP, SEXP_string_newf_r(&se_ffull_mem, "%s:%u", res->raddr, res->rport), NULL); } probe_item_collect(ctx, item); SEXP_free_r(&se_lport_mem); SEXP_free_r(&se_rport_mem); SEXP_free_r(&se_lfull_mem); SEXP_free_r(&se_ffull_mem); SEXP_free(se_uid_mem); }
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 property_callback(const char *property, const char *value, void *cbarg) { struct unit_callback_vars *vars = (struct unit_callback_vars *)cbarg; if (vars->se_property != NULL) { // // Compare the previously matched entity to the current one // If they are the same, continue to fill the current item // with property values. If not, collect the item and create // a new one for the current property. // if (SEXP_strcmp(vars->se_property, property) == 0) { SEXP_t *se_value = SEXP_string_new(value, strlen(value)); probe_item_ent_add(vars->item, "value", NULL, se_value); SEXP_free(se_value); return 0; } else { probe_item_collect(vars->ctx, vars->item); vars->item = NULL; SEXP_free(vars->se_property); vars->se_property = NULL; } } SEXP_t *se_property = SEXP_string_new(property, strlen(property)); if (probe_entobj_cmp(vars->property_entity, se_property) != OVAL_RESULT_TRUE) { SEXP_free(se_property); return 0; } vars->se_property = se_property; vars->item = probe_item_create(OVAL_LINUX_SYSTEMDUNITPROPERTY, NULL, "unit", OVAL_DATATYPE_SEXP, vars->se_unit, "property", OVAL_DATATYPE_SEXP, vars->se_property, "value", OVAL_DATATYPE_STRING, value, NULL); return 0; }
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; }
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); }
static void report_finding(struct result_info *res, probe_ctx *ctx) { SEXP_t *item; item = probe_item_create(OVAL_UNIX_PROCESS58, NULL, "command_line", OVAL_DATATYPE_STRING, res->command_line, "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_INTEGER, (int64_t) res->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, "exec_shield", OVAL_DATATYPE_BOOLEAN, (bool)res->exec_shield, "loginuid", OVAL_DATATYPE_INTEGER, (int64_t)res->loginuid, "posix_capability", OVAL_DATATYPE_STRING_M, res->posix_capability, "selinux_domain_label", OVAL_DATATYPE_STRING, res->selinux_domain_label, "session_id", OVAL_DATATYPE_INTEGER, (int64_t)res->session_id, NULL); probe_item_collect(ctx, item); }
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 file_cb (const char *p, const char *f, void *ptr) { char path_buffer[PATH_MAX]; SEXP_t *item, xattr_name; struct cbargs *args = (struct cbargs *) ptr; const char *st_path; ssize_t xattr_count = -1; char *xattr_buf = NULL; size_t xattr_buflen = 0, i; if (f == NULL) { st_path = p; } else { snprintf (path_buffer, sizeof path_buffer, "%s/%s", p, f); st_path = path_buffer; } SEXP_init(&xattr_name); do { /* estimate the size of the buffer */ xattr_count = llistxattr(st_path, NULL, 0); if (xattr_count == 0) return (0); if (xattr_count < 0) { dI("FAIL: llistxattr(%s, %p, %zu): errno=%u, %s.", errno, strerror(errno)); return 0; } /* allocate space for xattr names */ xattr_buflen = xattr_count; xattr_buf = oscap_realloc(xattr_buf, sizeof(char) * xattr_buflen); /* fill the buffer */ xattr_count = llistxattr(st_path, xattr_buf, xattr_buflen); /* check & retry if needed */ } while (errno == ERANGE); if (xattr_count < 0) { dI("FAIL: llistxattr(%s, %p, %zu): errno=%u, %s.", errno, strerror(errno)); oscap_free(xattr_buf); } /* update lastpath if needed */ if (!SEXP_emptyp(&gr_lastpath)) { if (SEXP_strcmp(&gr_lastpath, p) != 0) { SEXP_free_r(&gr_lastpath); SEXP_string_new_r(&gr_lastpath, p, strlen(p)); } } else SEXP_string_new_r(&gr_lastpath, p, strlen(p)); i = 0; /* collect */ do { SEXP_string_new_r(&xattr_name, xattr_buf + i, strlen(xattr_buf +i)); if (probe_entobj_cmp(args->attr_ent, &xattr_name) == OVAL_RESULT_TRUE) { ssize_t xattr_vallen = -1; char *xattr_val = NULL; xattr_vallen = lgetxattr(st_path, xattr_buf + i, NULL, 0); retry_value: if (xattr_vallen >= 0) { // Check possible buffer overflow if (sizeof(char) * (xattr_vallen + 1) <= sizeof(char) * xattr_vallen) { dE("Attribute is too long."); abort(); } // Allocate buffer, '+1' is for trailing '\0' xattr_val = oscap_realloc(xattr_val, sizeof(char) * (xattr_vallen + 1)); // we don't want to override space for '\0' by call of 'lgetxattr' // we pass only 'xattr_vallen' instead of 'xattr_vallen + 1' xattr_vallen = lgetxattr(st_path, xattr_buf + i, xattr_val, xattr_vallen); if (xattr_vallen < 0 || errno == ERANGE) goto retry_value; xattr_val[xattr_vallen] = '\0'; item = probe_item_create(OVAL_UNIX_FILEEXTENDEDATTRIBUTE, NULL, "filepath", OVAL_DATATYPE_STRING, f == NULL ? NULL : st_path, "path", OVAL_DATATYPE_SEXP, &gr_lastpath, "filename", OVAL_DATATYPE_STRING, f == NULL ? "" : f, "attribute_name", OVAL_DATATYPE_SEXP, &xattr_name, "value", OVAL_DATATYPE_STRING, xattr_val, NULL); oscap_free(xattr_val); } else { dI("FAIL: lgetxattr(%s, %s, NULL, 0): errno=%u, %s.", errno, strerror(errno)); item = probe_item_create(OVAL_UNIX_FILEEXTENDEDATTRIBUTE, NULL, NULL); probe_item_setstatus(item, SYSCHAR_STATUS_ERROR); if (xattr_val != NULL) oscap_free(xattr_val); } probe_item_collect(args->ctx, item); /* XXX: handle ENOMEM */ } SEXP_free_r(&xattr_name); /* skip to next name */ while (i < xattr_buflen && xattr_buf[i] != '\0') ++i; ++i; } while (xattr_buf + i < xattr_buf + xattr_buflen - 1); oscap_free(xattr_buf); 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); }
static int filehash_cb (const char *p, const char *f, void *ptr, const SEXP_t *filters) { SEXP_t *itm, *r0, *r1; SEXP_t *cobj = (SEXP_t *) ptr; char pbuf[PATH_MAX+1]; size_t plen, flen; 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'; /* * Open the file */ fd = open (pbuf, O_RDONLY); if (fd < 0) { itm = probe_item_create(OVAL_INDEPENDENT_FILE_MD5, NULL, "filepath", OVAL_DATATYPE_STRING, pbuf, "path", OVAL_DATATYPE_STRING, p, "filename", OVAL_DATATYPE_STRING, f, NULL); probe_item_add_msg(itm, OVAL_MESSAGE_LEVEL_ERROR, "Can't get context for %s: %s\n", pbuf, 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[32+1]; /* * Compute hash values */ if (crapi_digest_fd (fd, CRAPI_DIGEST_MD5, &md5_dst, &md5_dstlen) != 0) { close (fd); return (-1); } close (fd); mem2hex (md5_dst, sizeof md5_dst, md5_str, sizeof md5_str); /* * Create and add the item */ itm = probe_item_create(OVAL_INDEPENDENT_FILE_MD5, NULL, "filepath", OVAL_DATATYPE_STRING, pbuf, "path", OVAL_DATATYPE_STRING, p, "filename", OVAL_DATATYPE_STRING, f, "md5", OVAL_DATATYPE_STRING, md5_str, NULL); } probe_cobj_add_item(cobj, itm, filters); SEXP_free (itm); return (0); }
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 probe_main(probe_ctx *ctx, void *mutex) { LDAP *ldp; LDAPMessage *ldpres, *entry; SEXP_t *se_ldap_behaviors = NULL, *se_relative_dn = NULL; SEXP_t *se_suffix = NULL, *se_attribute = NULL; SEXP_t *sa_scope, *sv_op; SEXP_t *item; SEXP_t *probe_in; char *relative_dn = NULL; char *suffix = NULL, *xattribute = NULL; char *uri_list, *uri, *uri_save, *attr; int scope; char base[2048]; char *attrs[3]; bool a_pattern_match = false, rdn_pattern_match = false; /* runtime */ #if defined(PROBE_LDAP_MUTEX) assume_r(mutex != NULL, PROBE_EINIT); #endif probe_in = probe_ctx_getobject(ctx); se_ldap_behaviors = probe_obj_getent(probe_in, "behaviors", 1); if (se_ldap_behaviors != NULL) { sa_scope = probe_ent_getattrval(se_ldap_behaviors, "scope"); SEXP_free(se_ldap_behaviors); if (sa_scope == NULL) { dE("Atrribute `scope' is missing!"); return (PROBE_ENOATTR); } if (!SEXP_stringp(sa_scope)) { dE("Invalid value type of the `scope' attribute."); SEXP_free(sa_scope); return (PROBE_EINVAL); } if (SEXP_strcmp(sa_scope, "ONE") == 0) scope = LDAP_SCOPE_ONELEVEL; else if (SEXP_strcmp(sa_scope, "BASE") == 0) scope = LDAP_SCOPE_BASE; else if (SEXP_strcmp(sa_scope, "SUBTREE") == 0) scope = LDAP_SCOPE_SUBTREE; else { dE("Invalid value of the `scope' attribute."); SEXP_free(sa_scope); return (PROBE_EINVAL); } SEXP_free(sa_scope); } else scope = LDAP_SCOPE_BASE; #define get_string(dst, se_dst, obj, ent_name) \ do { \ SEXP_t *__sval; \ \ __sval = probe_obj_getentval (obj, ent_name, 1); \ \ if (__sval != NULL) { \ (dst) = SEXP_string_cstr (__sval); \ \ if ((dst) == NULL) { \ SEXP_free(__sval); \ return (PROBE_EINVAL); \ } \ \ (se_dst) = __sval; \ } else { \ return (PROBE_ENOATTR); \ } \ } while (0) get_string(suffix, se_suffix, probe_in, "suffix"); get_string(relative_dn, se_relative_dn, probe_in, "relative_dn"); get_string(xattribute, se_attribute, probe_in, "attribute"); if ((sv_op = probe_ent_getattrval(se_relative_dn, "operation")) != NULL) { if (SEXP_number_geti_32(sv_op) == OVAL_OPERATION_PATTERN_MATCH) rdn_pattern_match = true; SEXP_free(sv_op); } if ((sv_op = probe_ent_getattrval(se_attribute, "operation")) != NULL) { if (SEXP_number_geti_32(sv_op) == OVAL_OPERATION_PATTERN_MATCH) a_pattern_match = true; SEXP_free(sv_op); } /* * Construct the attribute array for ldap_search_* * * nil -> "1.1" * .* -> "*" * "foo" -> "foo" */ attrs[0] = "objectClass"; if (xattribute == NULL) attrs[1] = strdup("1.1"); /* no attibutes */ else if (a_pattern_match) attrs[1] = strdup("*"); /* collect all, we'll filter them afterwards */ else attrs[1] = xattribute; /* no pattern match, use the string directly */ attrs[2] = NULL; /* * Construct `base' */ assume_r(((relative_dn ? strlen(relative_dn) : 0) + ( suffix ? strlen(suffix) : 0) + 2) < (sizeof base/sizeof(char)), PROBE_ERANGE); if (relative_dn != NULL) { strcpy(base, relative_dn); strcat(base, ","); strcat(base, suffix); } else strcpy(base, suffix); /* * Get URIs */ if (ldap_get_option(NULL, LDAP_OPT_URI, &uri_list) != LDAP_OPT_SUCCESS) { item = probe_item_creat("ldap57_item", NULL, NULL); probe_item_setstatus(item, SYSCHAR_STATUS_ERROR); probe_item_collect(ctx, item); dE("ldap_get_option failed"); goto fail0; } /* * Query each URI */ for (;;) { char *entry_dn = NULL; if ((uri = strtok_r(uri_list, " ,", &uri_save)) == NULL) break; ldp = NULL; if (ldap_initialize(&ldp, uri) != LDAP_SUCCESS) continue; if (ldap_search_ext_s(ldp, base, scope, NULL, attrs, 0, NULL /* serverctrls */, NULL /* clientctrls */, NULL /* timeout */, 0, &ldpres) != LDAP_SUCCESS) { item = probe_item_creat("ldap57_item", NULL, NULL); probe_item_setstatus(item, SYSCHAR_STATUS_ERROR); probe_item_collect(ctx, item); dE("ldap_search_ext_s failed"); goto fail0; } entry = ldap_first_entry(ldp, ldpres); entry_dn = ldap_get_dn(ldp, entry); while (entry != NULL) { BerElement *berelm = NULL; attr = ldap_first_attribute(ldp, entry, &berelm); /* XXX: pattern match filter */ while (attr != NULL) { SEXP_t *se_value = NULL; ber_tag_t bertag = LBER_DEFAULT; ber_len_t berlen = 0; Sockbuf *berbuf = NULL; SEXP_t se_tmp_mem; berbuf = ber_sockbuf_alloc(); /* * Prepare the value (record) entity. Collect only * primitive (i.e. simple) types. */ se_value = probe_ent_creat1("value", NULL, NULL); probe_ent_setdatatype(se_value, OVAL_DATATYPE_RECORD); /* * XXX: does ber_get_next() return LBER_ERROR after the last value? */ while ((bertag = ber_get_next(berbuf, &berlen, berelm)) != LBER_ERROR) { SEXP_t *field = NULL; oval_datatype_t field_type = OVAL_DATATYPE_UNKNOWN; switch(bertag & LBER_ENCODING_MASK) { case LBER_PRIMITIVE: dI("Found primitive value, bertag = %u", bertag); break; case LBER_CONSTRUCTED: dW("Don't know how to handle LBER_CONSTRUCTED values"); /* FALLTHROUGH */ default: dW("Skipping attribute value, bertag = %u", bertag); continue; } assume_d(bertag & LBER_PRIMITIVE, NULL); switch(bertag & LBER_BIG_TAG_MASK) { case LBER_BOOLEAN: { /* LDAPTYPE_BOOLEAN */ ber_int_t val = -1; if (ber_get_boolean(berelm, &val) == LBER_ERROR) { dW("ber_get_boolean: LBER_ERROR"); /* XXX: set error status on field */ continue; } assume_d(val != -1, NULL); field = probe_ent_creat1("field", NULL, SEXP_number_newb_r(&se_tmp_mem, (bool)val)); field_type = OVAL_DATATYPE_BOOLEAN; SEXP_free_r(&se_tmp_mem); } break; case LBER_INTEGER: { /* LDAPTYPE_INTEGER */ ber_int_t val = -1; if (ber_get_int(berelm, &val) == LBER_ERROR) { dW("ber_get_int: LBER_ERROR"); /* XXX: set error status on field */ continue; } field = probe_ent_creat1("field", NULL, SEXP_number_newi_r(&se_tmp_mem, (int)val)); field_type = OVAL_DATATYPE_INTEGER; SEXP_free_r(&se_tmp_mem); } break; case LBER_BITSTRING: /* LDAPTYPE_BIT_STRING */ dW("LBER_BITSTRING: not implemented"); continue; case LBER_OCTETSTRING: { /* * LDAPTYPE_PRINTABLE_STRING * LDAPTYPE_NUMERIC_STRING * LDAPTYPE_DN_STRING * LDAPTYPE_BINARY (?) */ char *val = NULL; if (ber_get_stringa(berelm, &val) == LBER_ERROR) { dW("ber_get_stringa: LBER_ERROR"); /* XXX: set error status on field */ continue; } assume_d(val != NULL, NULL); field = probe_ent_creat1("field", NULL, SEXP_string_new_r(&se_tmp_mem, val, strlen(val))); field_type = OVAL_DATATYPE_STRING; SEXP_free_r(&se_tmp_mem); ber_memfree(val); } break; case LBER_NULL: /* XXX: no equivalent LDAPTYPE_? or empty */ dI("LBER_NULL: skipped"); continue; case LBER_ENUMERATED: /* XXX: no equivalent LDAPTYPE_? */ dW("Don't know how to handle LBER_ENUMERATED type"); continue; default: dW("Unknown attribute value type, bertag = %u", bertag); continue; } if (field != NULL) { assume_d(field_type != OVAL_DATATYPE_UNKNOWN, NULL); probe_ent_setdatatype(field, field_type); probe_ent_attr_add(field, "name", SEXP_string_new_r(&se_tmp_mem, attr, strlen(attr))); SEXP_list_add(se_value, field); SEXP_free_r(&se_tmp_mem); SEXP_free(field); } } ber_sockbuf_free(berbuf); /* * Create the item */ item = probe_item_create(OVAL_INDEPENDENT_LDAP57, NULL, "suffix", OVAL_DATATYPE_STRING, suffix, "relative_dn", OVAL_DATATYPE_STRING, relative_dn, /* XXX: pattern match */ "attribute", OVAL_DATATYPE_STRING, attr, "object_class", OVAL_DATATYPE_STRING, "", "ldaptype", OVAL_DATATYPE_STRING, "", NULL); SEXP_list_add(item, se_value); SEXP_free(se_value); probe_item_collect(ctx, item); attr = ldap_next_attribute(ldp, entry, berelm); } ber_free(berelm, 0); ldap_memfree(entry_dn); entry = ldap_next_entry(ldp, entry); entry_dn = ldap_get_dn(ldp, entry); } /* * Close the LDAP connection and free resources */ ldap_unbind_ext_s(ldp, NULL, NULL); } ldap_memfree(uri_list); fail0: SEXP_free(se_suffix); SEXP_free(se_relative_dn); SEXP_free(se_attribute); free(suffix); free(relative_dn); free(attrs[1]); /* attribute */ return (0); }
static int filehash58_cb (const char *p, const char *f, const char *h, probe_ctx *ctx) { SEXP_t *itm; char pbuf[PATH_MAX+1]; size_t plen, flen; 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'; /* * 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_HASH58, NULL, "filepath", OVAL_DATATYPE_STRING, pbuf, "path", OVAL_DATATYPE_STRING, p, "filename", OVAL_DATATYPE_STRING, f, "hash_type",OVAL_DATATYPE_STRING, h, 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 hash_dst[1025]; size_t hash_dstlen = sizeof hash_dst; char hash_str[2051]; crapi_alg_t hash_type; hash_type = oscap_string_to_enum(CRAPI_ALG_MAP, h); hash_dstlen = oscap_string_to_enum(CRAPI_ALG_MAP_SIZE, h); /* * Compute hash value */ if (crapi_mdigest_fd (fd, 1, hash_type, hash_dst, &hash_dstlen) != 0) { close (fd); return (-1); } close (fd); hash_str[0] = '\0'; mem2hex (hash_dst, hash_dstlen, hash_str, sizeof hash_str); /* * Create and add the item */ itm = probe_item_create(OVAL_INDEPENDENT_FILE_HASH58, NULL, "filepath", OVAL_DATATYPE_STRING, pbuf, "path", OVAL_DATATYPE_STRING, p, "filename", OVAL_DATATYPE_STRING, f, "hash_type",OVAL_DATATYPE_STRING, h, "hash", OVAL_DATATYPE_STRING, hash_str, NULL); if (hash_dstlen == 0) { probe_item_add_msg(itm, OVAL_MESSAGE_LEVEL_ERROR, "Unable to compute %s hash value of \"%s\".", h, pbuf); probe_item_setstatus(itm, SYSCHAR_STATUS_ERROR); } } probe_item_collect(ctx, itm); return (0); }
static int collect_access_rights(probe_ctx *ctx, WCHAR *security_principle, bool include_group, bool resolve_group) { char *security_principle_str = oscap_windows_wstr_to_str(security_principle); LSA_OBJECT_ATTRIBUTES object_attributes; ZeroMemory(&object_attributes, sizeof(LSA_OBJECT_ATTRIBUTES)); LSA_HANDLE lsa_policy_handle; NTSTATUS status = LsaOpenPolicy(NULL, &object_attributes, POLICY_LOOKUP_NAMES, &lsa_policy_handle); if (status != STATUS_SUCCESS) { DWORD err = LsaNtStatusToWinError(status); char *error_message = oscap_windows_error_message(err); dD("LsaOpenPolicy failed for principle '%s': %s", security_principle_str, error_message); free(error_message); free(security_principle_str); return 1; } /* Convert the value of the security_principle element to a SID. */ DWORD sid_len = 0; DWORD domain_name_len = 0; SID_NAME_USE sid_type; LookupAccountNameW(NULL, security_principle, NULL, &sid_len, NULL, &domain_name_len, &sid_type); SID *sid = malloc(sid_len); WCHAR *domain_name = malloc(domain_name_len * sizeof(WCHAR)); if (!LookupAccountNameW(NULL, security_principle, sid, &sid_len, domain_name, &domain_name_len, &sid_type)) { DWORD err = GetLastError(); char *error_message = oscap_windows_error_message(err); dD("LookupAccountNameW failed for '%s': %s", security_principle_str, error_message); free(error_message); free(security_principle_str); free(sid); free(domain_name); return 1; } /* Is it a group? */ if (sid_type == SidTypeGroup || sid_type == SidTypeWellKnownGroup || sid_type == SidTypeAlias) { if (resolve_group) { struct oscap_list *group_members_list = oscap_list_new(); get_local_group_members(security_principle, group_members_list); get_global_group_members(security_principle, group_members_list); struct oscap_iterator *group_members_it = oscap_iterator_new(group_members_list); while (oscap_iterator_has_more(group_members_it)) { WCHAR *group_member = oscap_iterator_next(group_members_it); collect_access_rights(ctx, group_member, include_group, resolve_group); } oscap_iterator_free(group_members_it); oscap_list_free(group_members_list, free); } if (!include_group) { free(sid); free(domain_name); free(security_principle_str); return 0; } } /* Users and groups can inherit their privileges from their parents */ struct oscap_list *every_rights_sources = oscap_list_new(); oscap_list_add(every_rights_sources, wcsdup(security_principle)); get_user_local_groups(security_principle, every_rights_sources); get_user_global_groups(security_principle, every_rights_sources); /* Iterate over the items */ bool privileges_enabled[OVAL_PRIVILEGES_COUNT] = { false }; struct oscap_iterator *it = oscap_iterator_new(every_rights_sources); while (oscap_iterator_has_more(it)) { WCHAR *account_name = oscap_iterator_next(it); DWORD account_sid_len = 0; DWORD account_domain_name_len = 0; SID_NAME_USE account_sid_type; LookupAccountNameW(NULL, account_name, NULL, &account_sid_len, NULL, &account_domain_name_len, &account_sid_type); SID *account_sid = malloc(account_sid_len); WCHAR *account_domain_name = malloc(account_domain_name_len * sizeof(WCHAR)); if (!LookupAccountNameW(NULL, account_name, account_sid, &account_sid_len, account_domain_name, &account_domain_name_len, &account_sid_type)) { free(account_sid); free(account_domain_name); DWORD err = GetLastError(); char *error_message = oscap_windows_error_message(err); dD("LookupAccountNameW failed for '%s': %s", security_principle_str, error_message); free(error_message); free(security_principle_str); return 1; } LSA_UNICODE_STRING *granted_rights = NULL; ULONG granted_rights_count = 0; status = LsaEnumerateAccountRights(lsa_policy_handle, account_sid, &granted_rights, &granted_rights_count); if (status != STATUS_SUCCESS) { free(account_sid); free(account_domain_name); DWORD err = LsaNtStatusToWinError(status); char *error_message = oscap_windows_error_message(err); dD("LsaEnumerateAccountRights failed for '%s': %s", security_principle_str, error_message); free(error_message); /* We should not exit here, because when LsaEnumerateAccountRights * failed it can mean that the entity simply doesn't have any specific * privileges, it only inhertis privileges form its parent group(s). */ continue; } for (int i = 0; i < OVAL_PRIVILEGES_COUNT; i++) { if (!privileges_enabled[i]) { for (ULONG j = 0; j < granted_rights_count; j++) { if (wcscmp(granted_rights[j].Buffer, privileges_texts[i]) == 0) { privileges_enabled[i] = true; break; } } } } LsaFreeMemory(granted_rights); free(account_sid); free(account_domain_name); } oscap_iterator_free(it); oscap_list_free(every_rights_sources, free); /* Collect the OVAL item */ SEXP_t *item = probe_item_create(OVAL_WINDOWS_ACCESS_TOKEN, NULL, "security_principle", OVAL_DATATYPE_STRING, strdup(security_principle_str), NULL); for (int i = 0; i < OVAL_PRIVILEGES_COUNT; i++) { char *privilege_name = oscap_windows_wstr_to_str(privileges_texts[i]); /* Convert the element name to lowercase */ for (char *p = privilege_name; *p; p++) { *p = tolower(*p); } SEXP_t *privilege_value = SEXP_number_newb(privileges_enabled[i]); probe_item_ent_add(item, privilege_name, NULL, privilege_value); free(privilege_name); SEXP_free(privilege_value); } probe_item_collect(ctx, item); free(security_principle_str); return 0; }