static int get_all_trustee_names(struct oscap_list *trustees_list) { get_all_well_known_sids(trustees_list); get_all_local_users(trustees_list); struct oscap_list *local_groups_list = oscap_list_new(); get_all_local_groups(local_groups_list); /* Find members of each local group */ struct oscap_iterator *local_groups_it = oscap_iterator_new(local_groups_list); while (oscap_iterator_has_more(local_groups_it)) { WCHAR *group = oscap_iterator_next(local_groups_it); oscap_list_add(trustees_list, wcsdup(group)); expand_group(group, trustees_list, get_local_group_members); } oscap_iterator_free(local_groups_it); oscap_list_free(local_groups_list, free); struct oscap_list *global_groups_list = oscap_list_new(); get_all_global_groups(global_groups_list); /* Find members of each global group */ struct oscap_iterator *global_groups_it = oscap_iterator_new(global_groups_list); while (oscap_iterator_has_more(global_groups_it)) { WCHAR *group = oscap_iterator_next(global_groups_it); oscap_list_add(trustees_list, wcsdup(group)); expand_group(group, trustees_list, get_global_group_members); } oscap_iterator_free(global_groups_it); oscap_list_free(global_groups_list, free); return 0; }
static void oscap_tsort_context_free(struct oscap_tsort_context *ctx) { if (ctx != NULL) { oscap_list_free(ctx->visited, NULL); oscap_list_free(ctx->cur_stack, NULL); oscap_list_free(ctx->result, NULL); oscap_free(ctx); } }
void xccdf_group_free(struct xccdf_item *group) { if (group) { oscap_list_free(group->sub.group.content, (oscap_destruct_func) xccdf_item_free); oscap_list_free(group->sub.group.values, (oscap_destruct_func) xccdf_value_free); oscap_list_free(group->sub.group.requires, (oscap_destruct_func) xccdf_free_strlist); oscap_list_free(group->sub.group.conflicts, free); xccdf_item_release(group); } }
void xccdf_check_free(struct xccdf_check *check) { if (check) { oscap_list_free(check->content_refs, (oscap_destruct_func) xccdf_check_content_ref_free); oscap_list_free(check->imports, (oscap_destruct_func) xccdf_check_import_free); oscap_list_free(check->exports, (oscap_destruct_func) xccdf_check_export_free); oscap_list_free(check->children, (oscap_destruct_func) xccdf_check_free); free(check->id); free(check->system); free(check->selector); free(check->content); free(check); } }
static bool xccdf_item_parse_deps(xmlTextReaderPtr reader, struct xccdf_item *item) { struct oscap_list *conflicts = NULL; struct oscap_list *requires = NULL; xccdf_deps_get(item, &conflicts, &requires); switch (xccdf_element_get(reader)) { case XCCDFE_REQUIRES:{ struct oscap_list *reqs = oscap_list_new(); char *ids = xccdf_attribute_copy(reader, XCCDFA_IDREF), *idsstr = ids, *id; while ((id = strsep(&ids, " ")) != NULL) { if (strcmp(id, "") == 0) continue; oscap_list_add(reqs, oscap_strdup(id)); } if (reqs->itemcount == 0) { oscap_list_free(reqs, NULL); return false; } oscap_list_add(requires, reqs); free(idsstr); break; } case XCCDFE_CONFLICTS: oscap_list_add(conflicts, xccdf_attribute_copy(reader, XCCDFA_IDREF)); break; default: assert(false); } return true; }
/** * Enforce given content with given name to be the only check-content of the check. * This may turn to be usefull,when processing check within rule-result -- * such check may (and in some cases must) refer only to the executed content. */ bool xccdf_check_inject_content_ref(struct xccdf_check *check, const struct xccdf_check_content_ref *content, const char *name) { struct xccdf_check_content_ref *content_clone = xccdf_check_content_ref_clone(content); if (name != NULL) xccdf_check_content_ref_set_name(content_clone, name); oscap_list_free(check->content_refs, (oscap_destruct_func) xccdf_check_content_ref_free); check->content_refs = oscap_list_new(); return oscap_list_add(check->content_refs, content_clone); }
bool xccdf_benchmark_resolve(struct xccdf_benchmark *benchmark) { struct oscap_list *resolve_order = NULL, *root_nodes = oscap_list_new(); oscap_list_add(root_nodes, benchmark); bool ret = false; if (oscap_tsort(root_nodes, &resolve_order, xccdf_benchmark_resolve_dependencies, NULL, NULL)) { OSCAP_FOR(xccdf_item, item, oscap_iterator_new(resolve_order)) xccdf_resolve_item(item, NULL); ret = true; } oscap_list_free(root_nodes, NULL); oscap_list_free(resolve_order, NULL); xccdf_resolve_cleanup(XITEM(benchmark)); return ret; }
void xccdf_tailoring_free(struct xccdf_tailoring *tailoring) { if (tailoring) { oscap_free(tailoring->id); oscap_free(tailoring->benchmark_ref); oscap_free(tailoring->benchmark_ref_version); oscap_list_free(tailoring->statuses, (oscap_destruct_func) xccdf_status_free); oscap_list_free(tailoring->dc_statuses, (oscap_destruct_func) oscap_reference_free); oscap_free(tailoring->version); oscap_free(tailoring->version_update); oscap_free(tailoring->version_time); oscap_list_free(tailoring->metadata, (oscap_destruct_func) oscap_free); oscap_list_free(tailoring->profiles, (oscap_destruct_func) xccdf_profile_free); oscap_free(tailoring); } }
void xccdf_rule_free(struct xccdf_item *rule) { if (rule) { oscap_list_free(rule->sub.rule.idents, (oscap_destruct_func) xccdf_ident_free); oscap_list_free(rule->sub.rule.checks, (oscap_destruct_func) xccdf_check_free); oscap_list_free(rule->sub.rule.profile_notes, (oscap_destruct_func) xccdf_profile_note_free); oscap_list_free(rule->sub.rule.fixes, (oscap_destruct_func) xccdf_fix_free); oscap_list_free(rule->sub.rule.fixtexts, (oscap_destruct_func) xccdf_fixtext_free); oscap_list_free(rule->sub.rule.requires, (oscap_destruct_func) xccdf_free_strlist); oscap_list_free(rule->sub.rule.conflicts, free); xccdf_item_release(rule); } }
static void expand_group(WCHAR *group, struct oscap_list *output_list, int (*get_group_members)(WCHAR *group_name, struct oscap_list *list)) { struct oscap_list *members_list = oscap_list_new(); get_group_members(group, members_list); struct oscap_iterator *members_it = oscap_iterator_new(members_list); while (oscap_iterator_has_more(members_it)) { WCHAR *member = oscap_iterator_next(members_it); /* TODO: implement this using a HashSet instead of linked list */ if (!oscap_list_contains(output_list, member, _members_cmp_func)) { oscap_list_add(output_list, wcsdup(member)); } } oscap_iterator_free(members_it); oscap_list_free(members_list, free); }
int accesstoken_probe_main(probe_ctx *ctx, void *arg) { SEXP_t *probe_in = probe_ctx_getobject(ctx); SEXP_t *behaviors_ent = probe_obj_getent(probe_in, "behaviors", 1); SEXP_t *security_principle_ent = probe_obj_getent(probe_in, "security_principle", 1); SEXP_t *security_principle_val = probe_ent_getval(security_principle_ent); bool include_group = accesstoken_behaviors_get_include_group(behaviors_ent); bool resolve_group = accesstoken_behaviors_get_resolve_group(behaviors_ent); oval_operation_t operation = probe_ent_getoperation(security_principle_ent, OVAL_OPERATION_EQUALS); if (operation == OVAL_OPERATION_EQUALS) { char *security_principle_str = SEXP_string_cstr(security_principle_val); WCHAR *security_principle_wstr = oscap_windows_str_to_wstr(security_principle_str); collect_access_rights(ctx, security_principle_wstr, include_group, resolve_group); free(security_principle_str); free(security_principle_wstr); } else { struct oscap_list *trustees_list = oscap_list_new(); get_all_trustee_names(trustees_list); struct oscap_iterator *it = oscap_iterator_new(trustees_list); while (oscap_iterator_has_more(it)) { WCHAR *trustee_wstr = oscap_iterator_next(it); char *trustee_str = oscap_windows_wstr_to_str(trustee_wstr); SEXP_t *tmp = SEXP_string_new(trustee_str, strlen(trustee_str)); if (probe_entobj_cmp(security_principle_ent, tmp) == OVAL_RESULT_TRUE) { collect_access_rights(ctx, trustee_wstr, include_group, resolve_group); } free(trustee_str); SEXP_free(tmp); } oscap_iterator_free(it); oscap_list_free(trustees_list, free); } SEXP_free(behaviors_ent); SEXP_free(security_principle_ent); SEXP_free(security_principle_val); return 0; }
static bool oscap_tsort_visit(void *node, struct oscap_tsort_context* ctx) { // loop detection if (oscap_list_contains(ctx->cur_stack, node, ctx->cmp_func)) return false; // skip already visited node if (oscap_list_contains(ctx->visited, node, ctx->cmp_func)) return true; // mark as visited & update stack oscap_list_add(ctx->visited, node); oscap_list_push(ctx->cur_stack, node); // visit all next nodes (dependencies) struct oscap_list *next = ctx->edge_func(node, ctx->userdata); bool ret = oscap_tsort_visit_all(next, ctx); oscap_list_free(next, NULL); // update stack & add node to result if (ret) oscap_list_pop(ctx->cur_stack, NULL); oscap_list_add(ctx->result, node); return ret; }
static void xccdf_free_strlist(struct oscap_list *list) { if (list) oscap_list_free(list, free); }
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; }