struct xccdf_benchmark *xccdf_benchmark_import_source(struct oscap_source *source) { xmlTextReader *reader = oscap_source_get_xmlTextReader(source); while (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) ; struct xccdf_benchmark *benchmark = xccdf_benchmark_new(); const bool parse_result = xccdf_benchmark_parse(XITEM(benchmark), reader); xmlFreeTextReader(reader); if (!parse_result) { // parsing fatal error oscap_seterr(OSCAP_EFAMILY_XML, "Failed to import XCCDF content from '%s'.", oscap_source_readable_origin(source)); xccdf_benchmark_free(benchmark); return NULL; } // This is sadly the only place where we can pass origin file information // to the CPE1 embedded dictionary (if any). It is necessary to figure out // proper paths to OVAL files referenced from CPE1 dictionaries. // FIXME: Refactor and move this somewhere else struct cpe_dict_model* embedded_dict = xccdf_benchmark_get_cpe_list(benchmark); if (embedded_dict != NULL) { cpe_dict_model_set_origin_file(embedded_dict, oscap_source_readable_origin(source)); } // same situation with embedded CPE2 lang model // FIXME: Refactor and move this somewhere else struct cpe_lang_model* embedded_lang_model = xccdf_benchmark_get_cpe_lang_model(benchmark); if (embedded_lang_model != NULL) { cpe_lang_model_set_origin_file(embedded_lang_model, oscap_source_readable_origin(source)); } return benchmark; }
struct xccdf_benchmark *xccdf_benchmark_import(const char *file) { xmlTextReaderPtr reader = xmlReaderForFile(file, NULL, 0); if (!reader) { oscap_seterr(OSCAP_EFAMILY_GLIBC, "Unable to open file: '%s'", file); return NULL; } xmlTextReaderSetErrorHandler(reader, &libxml_error_handler, NULL); while (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) ; struct xccdf_benchmark *benchmark = xccdf_benchmark_new(); const bool parse_result = xccdf_benchmark_parse(XITEM(benchmark), reader); xmlFreeTextReader(reader); if (!parse_result) { // parsing fatal error oscap_seterr(OSCAP_EFAMILY_XML, "Failed to parse '%s'.", file); xccdf_benchmark_free(benchmark); return NULL; } // This is sadly the only place where we can pass origin file information // to the CPE1 embedded dictionary (if any). It is necessary to figure out // proper paths to OVAL files referenced from CPE1 dictionaries. // FIXME: Refactor and move this somewhere else struct cpe_dict_model* embedded_dict = xccdf_benchmark_get_cpe_list(benchmark); if (embedded_dict != NULL) { cpe_dict_model_set_origin_file(embedded_dict, file); } // same situation with embedded CPE2 lang model // FIXME: Refactor and move this somewhere else struct cpe_lang_model* embedded_lang_model = xccdf_benchmark_get_cpe_lang_model(benchmark); if (embedded_lang_model != NULL) { cpe_lang_model_set_origin_file(embedded_lang_model, file); } return benchmark; }
int main(int argc, char **argv) { if (argc < 2) return 1; if (strcmp(argv[1], "--export") == 0) { if (argc != 4) return 1; struct oscap_source *source = oscap_source_new_from_file(argv[2]); struct xccdf_benchmark *bench = xccdf_benchmark_import_source(source); oscap_source_free(source); if (bench == NULL) return 1; xccdf_benchmark_export(bench, argv[3]); xccdf_benchmark_free(bench); oscap_cleanup(); return 0; } else if (strcmp(argv[1], "--validate") == 0) { if (argc != 4) { fprintf(stderr, "Usage: %s --validate ver xccdf\n", argv[0]); return 1; } struct oscap_source *source = oscap_source_new_from_file(argv[3]); if (oscap_source_validate(source, NULL, stdout)) { fprintf(stderr, "ERROR: %s\n", oscap_err_desc()); oscap_source_free(source); return 1; } oscap_source_free(source); return 0; } else { fprintf(stderr, "Unknown mode: %s\n", argv[1]); } return 1; }
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); const char *data = oscap_element_string_get(reader); if (id) oscap_list_add(benchmark->sub.benchmark.plain_texts, xccdf_plain_text_new_fill(id, data == NULL ? "" : 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; }
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; }
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; }