bool xccdf_group_add_requires(struct xccdf_group* group, struct oscap_stringlist* requires) { oscap_list_add(XITEM(group)->sub.group.requires, requires); return true; }
bool xccdf_rule_add_requires(struct xccdf_rule* rule, struct oscap_stringlist* requires) { oscap_list_add(XITEM(rule)->sub.rule.requires, requires); return true; }
struct xccdf_check *xccdf_check_parse(xmlTextReaderPtr reader) { xccdf_element_t el = xccdf_element_get(reader); if (el != XCCDFE_CHECK && el != XCCDFE_COMPLEX_CHECK) return NULL; struct xccdf_check *check = xccdf_check_new(); check->id = xccdf_attribute_copy(reader, XCCDFA_ID); check->system = xccdf_attribute_copy(reader, XCCDFA_SYSTEM); check->selector = xccdf_attribute_copy(reader, XCCDFA_SELECTOR); check->oper = oscap_string_to_enum(XCCDF_BOOLOP_MAP, xccdf_attribute_get(reader, XCCDFA_OPERATOR)); if (xccdf_attribute_has(reader, XCCDFA_MULTICHECK) && el != XCCDFE_COMPLEX_CHECK) { check->flags.def_multicheck = true; check->flags.multicheck = xccdf_attribute_get_bool(reader, XCCDFA_MULTICHECK); } check->flags.def_negate = xccdf_attribute_has(reader, XCCDFA_NEGATE); check->flags.negate = xccdf_attribute_get_bool(reader, XCCDFA_NEGATE); int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { switch (xccdf_element_get(reader)) { case XCCDFE_CHECK: case XCCDFE_COMPLEX_CHECK: if (check->oper == 0) break; oscap_list_add(check->children, xccdf_check_parse(reader)); break; case XCCDFE_CHECK_CONTENT_REF:{ const char *href = xccdf_attribute_get(reader, XCCDFA_HREF); if (href == NULL) break; struct xccdf_check_content_ref *ref = xccdf_check_content_ref_new(); ref->name = xccdf_attribute_copy(reader, XCCDFA_NAME); ref->href = strdup(href); oscap_list_add(check->content_refs, ref); break; } case XCCDFE_CHECK_CONTENT: if (check->content == NULL) check->content = oscap_get_xml(reader); break; case XCCDFE_CHECK_IMPORT:{ const char *name = xccdf_attribute_get(reader, XCCDFA_IMPORT_NAME); const char *xpath = xccdf_attribute_get(reader, XCCDFA_IMPORT_XPATH); if (name == NULL) // @import-name is a required attribute break; struct xccdf_check_import *imp = xccdf_check_import_new(); imp->name = strdup(name); if (xpath) // @import-xpath is just optional imp->xpath = strdup(xpath); imp->content = oscap_element_string_copy(reader); oscap_list_add(check->imports, imp); break; } case XCCDFE_CHECK_EXPORT:{ const char *name = xccdf_attribute_get(reader, XCCDFA_EXPORT_NAME); if (name == NULL) break; struct xccdf_check_export *exp = xccdf_check_export_new(); exp->name = strdup(name); exp->value = xccdf_attribute_copy(reader, XCCDFA_VALUE_ID); oscap_list_add(check->exports, exp); break; } default: break; } xmlTextReaderRead(reader); } return check; }
struct xccdf_item *xccdf_rule_parse(xmlTextReaderPtr reader, struct xccdf_item *parent) { XCCDF_ASSERT_ELEMENT(reader, XCCDFE_RULE); struct xccdf_item *rule = xccdf_rule_new_internal(parent); if (!xccdf_item_process_attributes(rule, reader)) { xccdf_rule_free(rule); return NULL; } if (xccdf_attribute_has(reader, XCCDFA_ROLE)) { rule->sub.rule.role = oscap_string_to_enum(XCCDF_ROLE_MAP, xccdf_attribute_get(reader, XCCDFA_ROLE)); rule->item.defined_flags.role = true; } if (xccdf_attribute_has(reader, XCCDFA_SEVERITY)) { rule->sub.rule.severity = oscap_string_to_enum(XCCDF_LEVEL_MAP, xccdf_attribute_get(reader, XCCDFA_SEVERITY)); rule->item.defined_flags.severity = true; } int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { switch (xccdf_element_get(reader)) { case XCCDFE_REQUIRES: case XCCDFE_CONFLICTS: xccdf_item_parse_deps(reader, rule); break; case XCCDFE_PROFILE_NOTE:{ const char *tag = xccdf_attribute_get(reader, XCCDFA_TAG); if (tag == NULL) break; struct xccdf_profile_note *note = xccdf_profile_note_new(); note->reftag = strdup(tag); note->text = oscap_text_new_parse(XCCDF_TEXT_PROFNOTE, reader); oscap_list_add(rule->sub.rule.profile_notes, note); break; } case XCCDFE_COMPLEX_CHECK: case XCCDFE_CHECK:{ struct xccdf_check *check = xccdf_check_parse(reader); if (check == NULL) break; oscap_list_add(rule->sub.rule.checks, check); break; } case XCCDFE_FIX: oscap_list_add(rule->sub.rule.fixes, xccdf_fix_parse(reader)); break; case XCCDFE_FIXTEXT: oscap_list_add(rule->sub.rule.fixtexts, xccdf_fixtext_parse(reader)); break; case XCCDFE_IDENT: oscap_list_add(rule->sub.rule.idents, xccdf_ident_parse(reader)); break; default: if (!xccdf_item_process_element(rule, reader)) dW("Encountered an unknown element '%s' while parsing XCCDF group.", xmlTextReaderConstLocalName(reader)); } xmlTextReaderRead(reader); } return rule; }
bool xccdf_benchmark_parse(struct xccdf_item * benchmark, xmlTextReaderPtr reader) { XCCDF_ASSERT_ELEMENT(reader, XCCDFE_BENCHMARK); assert(benchmark != NULL); if (benchmark->type != XCCDF_BENCHMARK) return false; xccdf_benchmark_set_schema_version(XBENCHMARK(benchmark), xccdf_detect_version_parser(reader)); if (!xccdf_item_process_attributes(benchmark, reader)) { xccdf_benchmark_free(XBENCHMARK(benchmark)); return false; } benchmark->sub.benchmark.style = xccdf_attribute_copy(reader, XCCDFA_STYLE); benchmark->sub.benchmark.style_href = xccdf_attribute_copy(reader, XCCDFA_STYLE_HREF); benchmark->sub.benchmark.lang = (char *) xmlTextReaderXmlLang(reader); if (xccdf_attribute_has(reader, XCCDFA_RESOLVED)) benchmark->item.flags.resolved = xccdf_attribute_get_bool(reader, XCCDFA_RESOLVED); int depth = oscap_element_depth(reader) + 1; while (oscap_to_start_element(reader, depth)) { struct xccdf_model *parsed_model; switch (xccdf_element_get(reader)) { case XCCDFE_NOTICE: oscap_list_add(benchmark->sub.benchmark.notices, xccdf_notice_new_parse(reader)); break; case XCCDFE_FRONT_MATTER: oscap_list_add(benchmark->sub.benchmark.front_matter, oscap_text_new_parse(XCCDF_TEXT_HTMLSUB, reader)); break; case XCCDFE_REAR_MATTER: oscap_list_add(benchmark->sub.benchmark.rear_matter, oscap_text_new_parse(XCCDF_TEXT_HTMLSUB, reader)); break; case XCCDFE_PLATFORM: oscap_list_add(benchmark->item.platforms, xccdf_attribute_copy(reader, XCCDFA_IDREF)); break; case XCCDFE_MODEL: parsed_model = xccdf_model_new_xml(reader); // we won't add the implied default scoring model, it is already in the benchmark if (strcmp(xccdf_model_get_system(parsed_model), "urn:xccdf:scoring:default") != 0) assume_ex(xccdf_benchmark_add_model(XBENCHMARK(benchmark), parsed_model), false); else xccdf_model_free(parsed_model); break; case XCCDFE_PLAIN_TEXT:{ const char *id = xccdf_attribute_get(reader, XCCDFA_ID); char *data = (char *)xmlTextReaderReadInnerXml(reader); if (id) oscap_list_add(benchmark->sub.benchmark.plain_texts, xccdf_plain_text_new_fill(id, data == NULL ? "" : data)); xmlFree(data); break; } case XCCDFE_CPE_LIST:{ struct cpe_parser_ctx *ctx = cpe_parser_ctx_from_reader(reader); xccdf_benchmark_set_cpe_list(XBENCHMARK(benchmark), cpe_dict_model_parse(ctx)); cpe_parser_ctx_free(ctx); break; } case XCCDFE_CPE2_PLATFORMSPEC: xccdf_benchmark_set_cpe_lang_model(XBENCHMARK(benchmark), cpe_lang_model_parse(reader)); break; case XCCDFE_PROFILE: oscap_list_add(benchmark->sub.benchmark.profiles, xccdf_profile_parse(reader, benchmark)); break; case XCCDFE_GROUP: case XCCDFE_RULE: xccdf_content_parse(reader, benchmark); break; case XCCDFE_VALUE: oscap_list_add(benchmark->sub.benchmark.values, xccdf_value_parse(reader, benchmark)); break; case XCCDFE_TESTRESULT: assume_ex(xccdf_benchmark_add_result(XBENCHMARK(benchmark), xccdf_result_new_parse(reader)), false); break; default: if (!xccdf_item_process_element(benchmark, reader)) dW("Encountered an unknown element '%s' while parsing XCCDF benchmark.", xmlTextReaderConstLocalName(reader)); } xmlTextReaderRead(reader); } return true; }
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; }