int app_xccdf_resolve(const struct oscap_action *action) { int ret = OSCAP_ERROR; struct xccdf_benchmark *bench = NULL; if (!action->f_xccdf) { fprintf(stderr, "No input document specified!\n"); return OSCAP_ERROR; } if (!action->f_results) { fprintf(stderr, "No output document filename specified!\n"); return OSCAP_ERROR; } struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf); /* validate input */ if (action->validate) { if (oscap_source_validate(source, reporter, (void *) action) != 0) { oscap_source_free(source); goto cleanup; } } bench = xccdf_benchmark_import_source(source); oscap_source_free(source); if (!bench) goto cleanup; if (action->force) xccdf_benchmark_set_resolved(bench, false); if (xccdf_benchmark_get_resolved(bench)) fprintf(stderr, "Benchmark is already resolved!\n"); else { if (!xccdf_benchmark_resolve(bench)) fprintf(stderr, "Benchmark resolving failure (probably a dependency loop)!\n"); else { if (xccdf_benchmark_export(bench, action->f_results) == 0) { ret = OSCAP_OK; /* validate exported results */ const char* full_validation = getenv("OSCAP_FULL_VALIDATION"); if (action->validate && full_validation) { struct oscap_source *result_source = oscap_source_new_from_file(action->f_results); if (oscap_source_validate(result_source, reporter, (void *) action) != 0) { ret = OSCAP_ERROR; } else fprintf(stdout, "Resolved XCCDF has been exported correctly.\n"); oscap_source_free(result_source); } } } } cleanup: oscap_print_error(); if (bench) xccdf_benchmark_free(bench); return ret; }
static void xccdf_resolve_item(struct xccdf_item *item, struct xccdf_tailoring *tailoring) { assert(item != NULL); if (xccdf_item_get_type(item) == XCCDF_BENCHMARK) { xccdf_benchmark_set_resolved(xccdf_item_to_benchmark(item), true); return; // benchmark has no extends } assert(!xccdf_item_get_extends(item) || xccdf_item_get_type(item) & (XCCDF_PROFILE | XCCDF_ITEM)); struct xccdf_item *parent = NULL; if (xccdf_item_get_type(item) == XCCDF_PROFILE && tailoring != NULL) { parent = XITEM(_xccdf_tailoring_profile_get_real_parent(tailoring, XPROFILE(item))); } else { parent = xccdf_benchmark_get_member(xccdf_item_get_benchmark(item), xccdf_item_get_type(item), xccdf_item_get_extends(item)); } if (parent == NULL) return; if (xccdf_item_get_type(item) != xccdf_item_get_type(parent)) return; if (xccdf_item_get_type(item) == XCCDF_GROUP && xccdf_version_cmp(xccdf_item_get_schema_version(item), "1.2") >= 0) return; // Group/@extends= has been obsoleted in XCCDF 1.2 // resolve flags XCCDF_RESOLVE_FLAG(item, parent, selected); XCCDF_RESOLVE_FLAG(item, parent, hidden); XCCDF_RESOLVE_FLAG(item, parent, prohibit_changes); XCCDF_RESOLVE_FLAG(item, parent, interactive); XCCDF_RESOLVE_FLAG(item, parent, multiple); // resolve weight & version if (!item->item.defined_flags.weight) xccdf_item_set_weight(item, xccdf_item_get_weight(parent)); if (xccdf_item_get_version(item) == NULL) { xccdf_item_set_version(item, xccdf_item_get_version(parent)); xccdf_item_set_version_update(item, xccdf_item_get_version_update(parent)); xccdf_item_set_version_time(item, xccdf_item_get_version_time(parent)); } // resolve textual elements xccdf_resolve_textlist(item->item.title, parent->item.title, NULL); xccdf_resolve_textlist(item->item.description, parent->item.description, NULL); xccdf_resolve_textlist(item->item.question, parent->item.question, NULL); xccdf_resolve_textlist(item->item.rationale, parent->item.rationale, NULL); xccdf_resolve_textlist(item->item.warnings, parent->item.warnings, xccdf_resolve_warning); xccdf_resolve_textlist(item->item.references, parent->item.references, NULL); // resolve platforms OSCAP_FOR_STR(platform, xccdf_item_get_platforms(parent)) xccdf_item_add_platform(item, platform); // resolve properties specific to particular item type switch (xccdf_item_get_type(item)) { case XCCDF_PROFILE: xccdf_resolve_profile(item, parent); break; case XCCDF_GROUP: xccdf_resolve_group(item, parent); break; case XCCDF_RULE: xccdf_resolve_rule(item, parent); break; case XCCDF_VALUE: xccdf_resolve_value(item, parent); break; default: assert(false); } // item resolved -> it no longer has a parent xccdf_item_set_extends(item, NULL); }
int app_xccdf_resolve(const struct oscap_action *action) { char *doc_version = NULL; int ret = OSCAP_ERROR; struct xccdf_benchmark *bench = NULL; if (!action->f_xccdf) { fprintf(stderr, "No input document specified!\n"); return OSCAP_ERROR; } if (!action->f_results) { fprintf(stderr, "No output document filename specified!\n"); return OSCAP_ERROR; } /* validate input */ if (action->validate) { doc_version = xccdf_detect_version(action->f_xccdf); if (!doc_version) { return OSCAP_ERROR; } if (oscap_validate_document(action->f_xccdf, OSCAP_DOCUMENT_XCCDF, doc_version, reporter, (void*) action) != 0) { validation_failed(action->f_xccdf, OSCAP_DOCUMENT_XCCDF, doc_version); goto cleanup; } } bench = xccdf_benchmark_import(action->f_xccdf); if (!bench) goto cleanup; if (action->force) xccdf_benchmark_set_resolved(bench, false); if (xccdf_benchmark_get_resolved(bench)) fprintf(stderr, "Benchmark is already resolved!\n"); else { if (!xccdf_benchmark_resolve(bench)) fprintf(stderr, "Benchmark resolving failure (probably a dependency loop)!\n"); else { if (xccdf_benchmark_export(bench, action->f_results)) { ret = OSCAP_OK; /* validate exported results */ const char* full_validation = getenv("OSCAP_FULL_VALIDATION"); if (action->validate && full_validation) { /* reuse doc_version from unresolved document it should be same in resolved one */ if (oscap_validate_document(action->f_results, OSCAP_DOCUMENT_XCCDF, doc_version, reporter, (void*)action)) { validation_failed(action->f_results, OSCAP_DOCUMENT_XCCDF, doc_version); ret = OSCAP_ERROR; } else fprintf(stdout, "Resolved XCCDF has been exported correctly.\n"); } } } } cleanup: oscap_print_error(); if (bench) xccdf_benchmark_free(bench); if (doc_version) free(doc_version); return ret; }