|
Packit |
517ee8 |
/*
|
|
Packit |
517ee8 |
* Copyright 2010--2014 Red Hat Inc., Durham, North Carolina.
|
|
Packit |
517ee8 |
* All Rights Reserved.
|
|
Packit |
517ee8 |
*
|
|
Packit |
517ee8 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
517ee8 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
517ee8 |
* License as published by the Free Software Foundation; either
|
|
Packit |
517ee8 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
517ee8 |
*
|
|
Packit |
517ee8 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
517ee8 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
517ee8 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
517ee8 |
* Lesser General Public License for more details.
|
|
Packit |
517ee8 |
*
|
|
Packit |
517ee8 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
517ee8 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
517ee8 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
517ee8 |
*
|
|
Packit |
517ee8 |
* Authors:
|
|
Packit |
517ee8 |
* Peter Vrabec <pvrabec@redhat.com>
|
|
Packit |
517ee8 |
*/
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
517ee8 |
#include <config.h>
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#if defined(OVAL_PROBES_ENABLED)
|
|
Packit |
517ee8 |
# include <oval_probe.h>
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
#include <oval_agent_api.h>
|
|
Packit |
517ee8 |
#include <oval_agent_xccdf_api.h>
|
|
Packit |
517ee8 |
#include <oval_results.h>
|
|
Packit |
517ee8 |
#include <oval_variables.h>
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#include <scap_ds.h>
|
|
Packit |
517ee8 |
#include <xccdf_benchmark.h>
|
|
Packit |
517ee8 |
#include <xccdf_policy.h>
|
|
Packit |
517ee8 |
#include <xccdf_session.h>
|
|
Packit |
517ee8 |
#include <ds_rds_session.h>
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#include <sys/types.h>
|
|
Packit |
517ee8 |
#include <sys/stat.h>
|
|
Packit |
517ee8 |
#include <fcntl.h>
|
|
Packit |
517ee8 |
#include <errno.h>
|
|
Packit |
517ee8 |
#include <assert.h>
|
|
Packit |
517ee8 |
#include <limits.h>
|
|
Packit |
517ee8 |
#ifdef HAVE_GETOPT_H
|
|
Packit |
517ee8 |
#include <getopt.h>
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#ifdef OS_WINDOWS
|
|
Packit |
517ee8 |
#include <io.h>
|
|
Packit |
517ee8 |
#include <windows.h>
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
#include <unistd.h>
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
#if defined(HAVE_SYSLOG_H)
|
|
Packit |
517ee8 |
#include <syslog.h>
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#include "oscap-tool.h"
|
|
Packit |
517ee8 |
#include "oscap.h"
|
|
Packit |
517ee8 |
#include "oscap_source.h"
|
|
Packit |
517ee8 |
#include <oscap_debug.h>
|
|
Packit |
517ee8 |
#include "oscap_helpers.h"
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#ifndef O_NOFOLLOW
|
|
Packit |
517ee8 |
#define O_NOFOLLOW 0
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static int app_evaluate_xccdf(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_xccdf_validate(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_xccdf_resolve(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_xccdf_export_oval_variables(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_xccdf_remediate(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static bool getopt_xccdf(int argc, char **argv, struct oscap_action *action);
|
|
Packit |
517ee8 |
static bool getopt_generate(int argc, char **argv, struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_xccdf_xslt(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_generate_fix(const struct oscap_action *action);
|
|
Packit |
517ee8 |
static int app_generate_guide(const struct oscap_action *action);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#define XCCDF_SUBMODULES_NUM 7
|
|
Packit |
517ee8 |
#define XCCDF_GEN_SUBMODULES_NUM 5 /* See actual arrays
|
|
Packit |
517ee8 |
initialization below. */
|
|
Packit |
517ee8 |
static struct oscap_module* XCCDF_SUBMODULES[XCCDF_SUBMODULES_NUM];
|
|
Packit |
517ee8 |
static struct oscap_module* XCCDF_GEN_SUBMODULES[XCCDF_GEN_SUBMODULES_NUM];
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
struct oscap_module OSCAP_XCCDF_MODULE = {
|
|
Packit |
517ee8 |
.name = "xccdf",
|
|
Packit |
517ee8 |
.parent = &OSCAP_ROOT_MODULE,
|
|
Packit |
517ee8 |
.summary = "eXtensible Configuration Checklist Description Format",
|
|
Packit |
517ee8 |
.usage_extra = "command [command-specific-options]",
|
|
Packit |
517ee8 |
.submodules = XCCDF_SUBMODULES
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_RESOLVE = {
|
|
Packit |
517ee8 |
.name = "resolve",
|
|
Packit |
517ee8 |
.parent = &OSCAP_XCCDF_MODULE,
|
|
Packit |
517ee8 |
.summary = "Resolve an XCCDF document",
|
|
Packit |
517ee8 |
.usage = "[options] -o output-xccdf.xml input-xccdf.xml",
|
|
Packit |
517ee8 |
.help =
|
|
Packit |
517ee8 |
"Options:\n"
|
|
Packit |
517ee8 |
" --force - Force resolving XCCDF document even if it is aleready marked as resolved.",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.func = app_xccdf_resolve
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_VALIDATE = {
|
|
Packit |
517ee8 |
.name = "validate",
|
|
Packit |
517ee8 |
.parent = &OSCAP_XCCDF_MODULE,
|
|
Packit |
517ee8 |
.summary = "Validate XCCDF XML content",
|
|
Packit |
517ee8 |
.usage = "xccdf-file.xml",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.func = app_xccdf_validate,
|
|
Packit |
517ee8 |
.help = "Options:\n"
|
|
Packit |
517ee8 |
" --schematron - Use schematron-based validation in addition to XML Schema\n"
|
|
Packit |
517ee8 |
,
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_EXPORT_OVAL_VARIABLES = {
|
|
Packit |
517ee8 |
.name = "export-oval-variables",
|
|
Packit |
517ee8 |
.parent = &OSCAP_XCCDF_MODULE,
|
|
Packit |
517ee8 |
.summary = "Export XCCDF values as OVAL external-variables document(s)",
|
|
Packit |
517ee8 |
.usage = "[options] <xccdf benchmark file> [oval definitions files]",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.func = app_xccdf_export_oval_variables,
|
|
Packit |
517ee8 |
.help = "Options:\n"
|
|
Packit |
517ee8 |
" --profile <name> - The name of Profile to be evaluated.\n"
|
|
Packit |
517ee8 |
" --skip-valid - Skip validation.\n"
|
|
Packit |
517ee8 |
" --fetch-remote-resources - Download remote content referenced by XCCDF.\n"
|
|
Packit |
517ee8 |
" --datastream-id <id> - ID of the datastream in the collection to use.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --xccdf-id <id> - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --benchmark-id <id> - ID of XCCDF Benchmark in some component in the datastream that should be evaluated.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" (only applicable when datastream-id AND xccdf-id are not specified)\n"
|
|
Packit |
517ee8 |
" --cpe <name> - Use given CPE dictionary or language (autodetected)\n"
|
|
Packit |
517ee8 |
" for applicability checks.\n"
|
|
Packit |
517ee8 |
,
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_EVAL = {
|
|
Packit |
517ee8 |
.name = "eval",
|
|
Packit |
517ee8 |
.parent = &OSCAP_XCCDF_MODULE,
|
|
Packit |
517ee8 |
.summary = "Perform evaluation driven by XCCDF file and use OVAL as checking engine",
|
|
Packit |
517ee8 |
.usage = "[options] INPUT_FILE [oval-definitions-files]",
|
|
Packit |
517ee8 |
.help =
|
|
Packit |
517ee8 |
"INPUT_FILE - XCCDF file or a source data stream file\n\n"
|
|
Packit |
517ee8 |
"Options:\n"
|
|
Packit |
517ee8 |
" --profile <name> - The name of Profile to be evaluated.\n"
|
|
Packit |
517ee8 |
" --rule <name> - The name of a single rule to be evaluated.\n"
|
|
Packit |
517ee8 |
" --tailoring-file <file> - Use given XCCDF Tailoring file.\n"
|
|
Packit |
517ee8 |
" --tailoring-id <component-id> - Use given DS component as XCCDF Tailoring file.\n"
|
|
Packit |
517ee8 |
" --cpe <name> - Use given CPE dictionary or language (autodetected)\n"
|
|
Packit |
517ee8 |
" for applicability checks.\n"
|
|
Packit |
517ee8 |
" --oval-results - Save OVAL results as well.\n"
|
|
Packit |
517ee8 |
" --check-engine-results - Save results from check engines loaded from plugins as well.\n"
|
|
Packit |
517ee8 |
" --export-variables - Export OVAL external variables provided by XCCDF.\n"
|
|
Packit |
517ee8 |
" --results <file> - Write XCCDF Results into file.\n"
|
|
Packit |
517ee8 |
" --results-arf <file> - Write ARF (result data stream) into file.\n"
|
|
Packit |
517ee8 |
" --stig-viewer <file> - Writes XCCDF results into FILE in a format readable by DISA STIG Viewer\n"
|
|
Packit |
517ee8 |
" --thin-results - Thin Results provides only minimal amount of information in OVAL/ARF results.\n"
|
|
Packit |
517ee8 |
" The option --without-syschar is automatically enabled when you use Thin Results.\n"
|
|
Packit |
517ee8 |
" --without-syschar - Don't provide system characteristic in OVAL/ARF result files.\n"
|
|
Packit |
517ee8 |
" --report <file> - Write HTML report into file.\n"
|
|
Packit |
517ee8 |
" --skip-valid - Skip validation.\n"
|
|
Packit |
517ee8 |
" --fetch-remote-resources - Download remote content referenced by XCCDF.\n"
|
|
Packit |
517ee8 |
" --progress - Switch to sparse output suitable for progress reporting.\n"
|
|
Packit |
517ee8 |
" Format is \"$rule_id:$result\\n\".\n"
|
|
Packit |
517ee8 |
" --datastream-id <id> - ID of the datastream in the collection to use.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --xccdf-id <id> - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --benchmark-id <id> - ID of XCCDF Benchmark in some component in the datastream that should be evaluated.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" (only applicable when datastream-id AND xccdf-id are not specified)\n"
|
|
Packit |
517ee8 |
" --remediate - Automatically execute XCCDF fix elements for failed rules.\n"
|
|
Packit |
517ee8 |
" Use of this option is always at your own risk.\n",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.func = app_evaluate_xccdf
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_REMEDIATE = {
|
|
Packit |
517ee8 |
.name = "remediate",
|
|
Packit |
517ee8 |
.parent = &OSCAP_XCCDF_MODULE,
|
|
Packit |
517ee8 |
.summary = "Perform remediation driven by XCCDF TestResult file or ARF.",
|
|
Packit |
517ee8 |
.usage = "[options] INPUT_FILE [oval-definitions-files]",
|
|
Packit |
517ee8 |
.help = "INPUT_FILE - XCCDF TestResult file or ARF\n\n"
|
|
Packit |
517ee8 |
"Options:\n"
|
|
Packit |
517ee8 |
" --result-id - TestResult ID to be processed. Default is the most recent one.\n"
|
|
Packit |
517ee8 |
" --skip-valid - Skip validation.\n"
|
|
Packit |
517ee8 |
" --cpe <name> - Use given CPE dictionary or language (autodetected)\n"
|
|
Packit |
517ee8 |
" for applicability checks.\n"
|
|
Packit |
517ee8 |
" --fetch-remote-resources - Download remote content referenced by XCCDF.\n"
|
|
Packit |
517ee8 |
" --results <file> - Write XCCDF Results into file.\n"
|
|
Packit |
517ee8 |
" --results-arf <file> - Write ARF (result data stream) into file.\n"
|
|
Packit |
517ee8 |
" --stig-viewer <file> - Writes XCCDF results into FILE in a format readable by DISA STIG Viewer\n"
|
|
Packit |
517ee8 |
" --report <file> - Write HTML report into file.\n"
|
|
Packit |
517ee8 |
" --oval-results - Save OVAL results.\n"
|
|
Packit |
517ee8 |
" --export-variables - Export OVAL external variables provided by XCCDF.\n"
|
|
Packit |
517ee8 |
" --check-engine-results - Save results from check engines loaded from plugins as well.\n"
|
|
Packit |
517ee8 |
" --progress - Switch to sparse output suitable for progress reporting.\n"
|
|
Packit |
517ee8 |
" Format is \"$rule_id:$result\\n\".\n"
|
|
Packit |
517ee8 |
,
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.func = app_xccdf_remediate
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#define GEN_OPTS \
|
|
Packit |
517ee8 |
"Generate options:\n" \
|
|
Packit |
517ee8 |
" --profile <profile-id> - Apply profile with given ID to the Benchmark before further processing takes place.\n"
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_GENERATE = {
|
|
Packit |
517ee8 |
.name = "generate",
|
|
Packit |
517ee8 |
.parent = &OSCAP_XCCDF_MODULE,
|
|
Packit |
517ee8 |
.summary = "Convert XCCDF Benchmark to other formats",
|
|
Packit |
517ee8 |
.usage = "[options]",
|
|
Packit |
517ee8 |
.usage_extra = "<subcommand> [sub-options] benchmark-file.xml",
|
|
Packit |
517ee8 |
.help = GEN_OPTS,
|
|
Packit |
517ee8 |
.opt_parser = getopt_generate,
|
|
Packit |
517ee8 |
.submodules = XCCDF_GEN_SUBMODULES
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_GEN_REPORT = {
|
|
Packit |
517ee8 |
.name = "report",
|
|
Packit |
517ee8 |
.parent = &XCCDF_GENERATE,
|
|
Packit |
517ee8 |
.summary = "Generate results report",
|
|
Packit |
517ee8 |
.usage = "[options] xccdf-file.xml",
|
|
Packit |
517ee8 |
.help = GEN_OPTS
|
|
Packit |
517ee8 |
"\nReport Options:\n"
|
|
Packit |
517ee8 |
" --result-id <id> - TestResult ID to be processed. Default is the most recent one.\n"
|
|
Packit |
517ee8 |
" --output <file> - Write the document into file.\n"
|
|
Packit |
517ee8 |
" --oval-template <template-string> - Template which will be used to obtain OVAL result files.\n",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.user = "xccdf-report.xsl",
|
|
Packit |
517ee8 |
.func = app_xccdf_xslt
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_GEN_GUIDE = {
|
|
Packit |
517ee8 |
.name = "guide",
|
|
Packit |
517ee8 |
.parent = &XCCDF_GENERATE,
|
|
Packit |
517ee8 |
.summary = "Generate security guide",
|
|
Packit |
517ee8 |
.usage = "[options] xccdf-file.xml",
|
|
Packit |
517ee8 |
.help = GEN_OPTS
|
|
Packit |
517ee8 |
"\nGuide Options:\n"
|
|
Packit |
517ee8 |
" --output <file> - Write the document into file.\n"
|
|
Packit |
517ee8 |
" --hide-profile-info - This option has no effect.\n"
|
|
Packit |
517ee8 |
" --benchmark-id <id> - ID of XCCDF Benchmark in some component in the datastream that should be used.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --xccdf-id <id> - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --tailoring-file <file> - Use given XCCDF Tailoring file.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --tailoring-id <component-id> - Use given DS component as XCCDF Tailoring file.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.user = NULL,
|
|
Packit |
517ee8 |
.func = app_generate_guide
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_GEN_FIX = {
|
|
Packit |
517ee8 |
.name = "fix",
|
|
Packit |
517ee8 |
.parent = &XCCDF_GENERATE,
|
|
Packit |
517ee8 |
.summary = "Generate a fix script from an XCCDF file",
|
|
Packit |
517ee8 |
.usage = "[options] xccdf-file.xml",
|
|
Packit |
517ee8 |
.help = GEN_OPTS
|
|
Packit |
517ee8 |
"\nFix Options:\n"
|
|
Packit |
517ee8 |
" --fix-type <type> - Fix type. Should be one of: bash, ansible, puppet, anaconda (default: bash).\n"
|
|
Packit |
517ee8 |
" --output <file> - Write the script into file.\n"
|
|
Packit |
517ee8 |
" --result-id <id> - Fixes will be generated for failed rule-results of the specified TestResult.\n"
|
|
Packit |
517ee8 |
" --template <id|filename> - Fix template. (default: bash)\n"
|
|
Packit |
517ee8 |
" --benchmark-id <id> - ID of XCCDF Benchmark in some component in the datastream that should be used.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --xccdf-id <id> - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --tailoring-file <file> - Use given XCCDF Tailoring file.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n"
|
|
Packit |
517ee8 |
" --tailoring-id <component-id> - Use given DS component as XCCDF Tailoring file.\n"
|
|
Packit |
517ee8 |
" (only applicable for source datastreams)\n",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.user = "legacy-fix.xsl",
|
|
Packit |
517ee8 |
.func = app_generate_fix
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module XCCDF_GEN_CUSTOM = {
|
|
Packit |
517ee8 |
.name = "custom",
|
|
Packit |
517ee8 |
.parent = &XCCDF_GENERATE,
|
|
Packit |
517ee8 |
.summary = "Generate a custom output (depending on given XSLT file) from an XCCDF file",
|
|
Packit |
517ee8 |
.usage = "--stylesheet <file> [--output <file>] xccdf-file.xml",
|
|
Packit |
517ee8 |
.help = GEN_OPTS
|
|
Packit |
517ee8 |
"\nCustom Options:\n"
|
|
Packit |
517ee8 |
" --stylesheet <file> - Specify an absolute path to a custom stylesheet to format the output.\n"
|
|
Packit |
517ee8 |
" --output <file> - Write the document into file.\n",
|
|
Packit |
517ee8 |
.opt_parser = getopt_xccdf,
|
|
Packit |
517ee8 |
.user = NULL,
|
|
Packit |
517ee8 |
.func = app_xccdf_xslt
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module* XCCDF_GEN_SUBMODULES[XCCDF_GEN_SUBMODULES_NUM] = {
|
|
Packit |
517ee8 |
&XCCDF_GEN_REPORT,
|
|
Packit |
517ee8 |
&XCCDF_GEN_GUIDE,
|
|
Packit |
517ee8 |
&XCCDF_GEN_FIX,
|
|
Packit |
517ee8 |
&XCCDF_GEN_CUSTOM,
|
|
Packit |
517ee8 |
NULL
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static struct oscap_module* XCCDF_SUBMODULES[XCCDF_SUBMODULES_NUM] = {
|
|
Packit |
517ee8 |
&XCCDF_EVAL,
|
|
Packit |
517ee8 |
&XCCDF_RESOLVE,
|
|
Packit |
517ee8 |
&XCCDF_VALIDATE,
|
|
Packit |
517ee8 |
&XCCDF_EXPORT_OVAL_VARIABLES,
|
|
Packit |
517ee8 |
&XCCDF_GENERATE,
|
|
Packit |
517ee8 |
&XCCDF_REMEDIATE,
|
|
Packit |
517ee8 |
NULL
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/**
|
|
Packit |
517ee8 |
* XCCDF Result Colors:
|
|
Packit |
517ee8 |
* PASS:green(32), FAIL:red(31), ERROR:lred(1;31), UNKNOWN:grey(1;30), NOT_APPLICABLE:default bold(1), NOT_CHECKED:default bold(1),
|
|
Packit |
517ee8 |
* NOT_SELECTED:default dim(2), INFORMATIONAL:blue(34), FIXED:yellow(1;33)
|
|
Packit |
517ee8 |
*/
|
|
Packit |
517ee8 |
#if defined(OS_WINDOWS)
|
|
Packit |
517ee8 |
int RESULT_COLORS[] = {0, 10, 12, 12, 8, 15, 15, 15, 9, 14};
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
static const char * RESULT_COLORS[] = {"", "32", "31", "1;31", "1;30", "1", "1", "2", "34", "1;33" };
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static char custom_stylesheet_path[PATH_MAX];
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static int callback_scr_rule(struct xccdf_rule *rule, void *arg)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
const char * rule_id = xccdf_rule_get_id(rule);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* is rule selected? we print only selected rules */
|
|
Packit |
517ee8 |
const bool selected = xccdf_policy_is_item_selected((struct xccdf_policy *) arg, rule_id);
|
|
Packit |
517ee8 |
if (!selected)
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
const char *title = xccdf_policy_get_readable_item_title((struct xccdf_policy *)arg, (struct xccdf_item *) rule, NULL);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* print */
|
|
Packit |
517ee8 |
if (isatty(1)) {
|
|
Packit |
517ee8 |
#if defined(OS_WINDOWS)
|
|
Packit |
517ee8 |
HANDLE console;
|
|
Packit |
517ee8 |
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
Packit |
517ee8 |
printf("Title");
|
|
Packit |
517ee8 |
SetConsoleTextAttribute(console, 15);
|
|
Packit |
517ee8 |
printf("\t%s\n", title);
|
|
Packit |
517ee8 |
SetConsoleTextAttribute(console, 7);
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
printf("Title\r\t\033[1m%s\033[0;0m\n", title);
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
} else
|
|
Packit |
517ee8 |
printf("Title\r\t%s\n", title);
|
|
Packit |
517ee8 |
free((char *)title);
|
|
Packit |
517ee8 |
#if defined(OS_WINDOWS)
|
|
Packit |
517ee8 |
printf("Rule\t%s\n", rule_id);
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
printf("Rule\r\t%s\n", rule_id);
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
struct xccdf_ident_iterator *idents = xccdf_rule_get_idents(rule);
|
|
Packit |
517ee8 |
while (xccdf_ident_iterator_has_more(idents)) {
|
|
Packit |
517ee8 |
const struct xccdf_ident *ident = xccdf_ident_iterator_next(idents);
|
|
Packit |
517ee8 |
const char *ident_id = xccdf_ident_get_id(ident);
|
|
Packit |
517ee8 |
#if defined(OS_WINDOWS)
|
|
Packit |
517ee8 |
printf("Ident\t%s\n", ident_id);
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
printf("Ident\r\t%s\n", ident_id);
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
xccdf_ident_iterator_free(idents);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
fflush(stdout);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static int callback_scr_result(struct xccdf_rule_result *rule_result, void *arg)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
xccdf_test_result_type_t result = xccdf_rule_result_get_result(rule_result);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* is result from selected rule? we print only selected rules */
|
|
Packit |
517ee8 |
if (result == XCCDF_RESULT_NOT_SELECTED)
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* print result */
|
|
Packit |
517ee8 |
#if defined(OS_WINDOWS)
|
|
Packit |
517ee8 |
printf("Result\t");
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
printf("Result\r\t");
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
const char * result_str = xccdf_test_result_type_get_text(result);
|
|
Packit |
517ee8 |
if (isatty(1)) {
|
|
Packit |
517ee8 |
#if defined(OS_WINDOWS)
|
|
Packit |
517ee8 |
HANDLE console;
|
|
Packit |
517ee8 |
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
Packit |
517ee8 |
SetConsoleTextAttribute(console, RESULT_COLORS[result]);
|
|
Packit |
517ee8 |
printf("%s", result_str);
|
|
Packit |
517ee8 |
SetConsoleTextAttribute(console, 7);
|
|
Packit |
517ee8 |
printf("\n\n");
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
printf("\033[%sm%s\033[0m\n\n", RESULT_COLORS[result], result_str);
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
} else
|
|
Packit |
517ee8 |
printf("%s\n\n", result_str);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static int callback_scr_result_progress(struct xccdf_rule_result *rule_result, void *arg)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
xccdf_test_result_type_t result = xccdf_rule_result_get_result(rule_result);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* is result from selected rule? we print only selected rules */
|
|
Packit |
517ee8 |
if (result == XCCDF_RESULT_NOT_SELECTED)
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* print result */
|
|
Packit |
517ee8 |
const char *rule_id = xccdf_rule_result_get_idref(rule_result);
|
|
Packit |
517ee8 |
const char *result_str = xccdf_test_result_type_get_text(result);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
printf("%s:%s\n", rule_id, result_str);
|
|
Packit |
517ee8 |
fflush(stdout);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static int callback_scr_multicheck(struct oval_definition *definition, void *arg)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
printf("OVAL Definition ID\t%s\n", oval_definition_get_id(definition));
|
|
Packit |
517ee8 |
printf("OVAL Definition Title\t%s\n", oval_definition_get_title(definition));
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/*
|
|
Packit |
517ee8 |
* Send XCCDF Rule Results info message to syslog
|
|
Packit |
517ee8 |
*
|
|
Packit |
517ee8 |
static int callback_syslog_result(struct xccdf_rule_result *rule_result, void *arg)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
xccdf_test_result_type_t result = xccdf_rule_result_get_result(rule_result);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
// do we log it?
|
|
Packit |
517ee8 |
if ((result != XCCDF_RESULT_FAIL) && (result != XCCDF_RESULT_UNKNOWN))
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
// yes we do
|
|
Packit |
517ee8 |
const char * result_str = xccdf_test_result_type_get_text(result);
|
|
Packit |
517ee8 |
const char * ident_id = NULL;
|
|
Packit |
517ee8 |
int priority = LOG_NOTICE;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
// get ident
|
|
Packit |
517ee8 |
struct xccdf_ident_iterator *idents = xccdf_rule_result_get_idents(rule_result);
|
|
Packit |
517ee8 |
if (xccdf_ident_iterator_has_more(idents)) {
|
|
Packit |
517ee8 |
const struct xccdf_ident *ident = xccdf_ident_iterator_next(idents);
|
|
Packit |
517ee8 |
ident_id = xccdf_ident_get_id(ident);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
xccdf_ident_iterator_free(idents);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
// emit the message
|
|
Packit |
517ee8 |
syslog(priority, "Rule: %s, Ident: %s, Result: %s.", xccdf_rule_result_get_idref(rule_result), ident_id, result_str);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return 0;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
*/
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static void _register_progress_callback(struct xccdf_session *session, bool progress)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
struct xccdf_policy_model *policy_model = xccdf_session_get_policy_model(session);
|
|
Packit |
517ee8 |
if (progress) {
|
|
Packit |
517ee8 |
xccdf_policy_model_register_output_callback(policy_model, callback_scr_result_progress, NULL);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
else {
|
|
Packit |
517ee8 |
xccdf_policy_model_register_start_callback(policy_model, callback_scr_rule,
|
|
Packit |
517ee8 |
(void *) xccdf_session_get_xccdf_policy(session));
|
|
Packit |
517ee8 |
xccdf_policy_model_register_output_callback(policy_model, callback_scr_result, NULL);
|
|
Packit |
517ee8 |
xccdf_policy_model_register_multicheck_callback(policy_model, callback_scr_multicheck, NULL);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
/* xccdf_policy_model_register_output_callback(policy_model, callback_syslog_result, NULL); */
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
void report_missing_profile(const char *profile_suffix, const char *source_file)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
fprintf(stderr,
|
|
Packit |
517ee8 |
"No profile matching suffix \"%s\" was found. Get available profiles using:\n"
|
|
Packit |
517ee8 |
"$ oscap info \"%s\"\n", profile_suffix, source_file);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
void report_multiple_profile_matches(const char *profile_suffix, const char *source_file)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
fprintf(stderr,
|
|
Packit |
517ee8 |
"At least two profiles matched suffix \"%s\". Use a more specific suffix "
|
|
Packit |
517ee8 |
"to get an exact match. Get list of profiles using:\n"
|
|
Packit |
517ee8 |
"$ oscap info \"%s\"\n", profile_suffix, source_file);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int evaluate_suffix_match_result_with_custom_reports(int suffix_match_result, const char *profile_suffix, const char *source_file,
|
|
Packit |
517ee8 |
void (* report_missing)(const char *, const char *), void (* report_multiple)(const char *, const char *))
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
if (suffix_match_result == OSCAP_PROFILE_NO_MATCH) {
|
|
Packit |
517ee8 |
if (report_missing)
|
|
Packit |
517ee8 |
report_missing(profile_suffix, source_file);
|
|
Packit |
517ee8 |
return OSCAP_ERROR;
|
|
Packit |
517ee8 |
} else if (suffix_match_result == OSCAP_PROFILE_MULTIPLE_MATCHES) {
|
|
Packit |
517ee8 |
if (report_multiple)
|
|
Packit |
517ee8 |
report_multiple(profile_suffix, source_file);
|
|
Packit |
517ee8 |
return OSCAP_ERROR;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
return OSCAP_OK;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int evaluate_suffix_match_result(int suffix_match_result, const char *profile_suffix, const char *source_file)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
return evaluate_suffix_match_result_with_custom_reports(suffix_match_result, profile_suffix, source_file, &report_missing_profile, &report_multiple_profile_matches);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int xccdf_set_profile_or_report_bad_id(struct xccdf_session *session, const char *profile_id, const char *source_file)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
const int suffix_match_result = xccdf_session_set_profile_id_by_suffix(session, profile_id);
|
|
Packit |
517ee8 |
int return_code = evaluate_suffix_match_result(suffix_match_result, profile_id, source_file);
|
|
Packit |
517ee8 |
return return_code;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/**
|
|
Packit |
517ee8 |
* XCCDF Processing fucntion
|
|
Packit |
517ee8 |
* @param action OSCAP Action structure
|
|
Packit |
517ee8 |
* @param sess OVAL Agent Session
|
|
Packit |
517ee8 |
*/
|
|
Packit |
517ee8 |
int app_evaluate_xccdf(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
struct xccdf_session *session = NULL;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int result = OSCAP_ERROR;
|
|
Packit |
517ee8 |
#if defined(HAVE_SYSLOG_H)
|
|
Packit |
517ee8 |
int priority = LOG_NOTICE;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* syslog message */
|
|
Packit |
517ee8 |
syslog(priority, "Evaluation started. Content: %s, Profile: %s.", action->f_xccdf, action->profile);
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
session = xccdf_session_new(action->f_xccdf);
|
|
Packit |
517ee8 |
if (session == NULL)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
|
|
Packit |
517ee8 |
if (action->thin_results) {
|
|
Packit |
517ee8 |
xccdf_session_set_thin_results(session, true);
|
|
Packit |
517ee8 |
xccdf_session_set_without_sys_chars_export(session, true);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
if (xccdf_session_is_sds(session)) {
|
|
Packit |
517ee8 |
xccdf_session_set_datastream_id(session, action->f_datastream_id);
|
|
Packit |
517ee8 |
xccdf_session_set_component_id(session, action->f_xccdf_id);
|
|
Packit |
517ee8 |
xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
xccdf_session_set_user_cpe(session, action->cpe);
|
|
Packit |
517ee8 |
// The tailoring_file may be NULL but the tailoring file may have been
|
|
Packit |
517ee8 |
// autonegotiated from the input file, we don't want to lose that.
|
|
Packit |
517ee8 |
if (action->tailoring_file != NULL)
|
|
Packit |
517ee8 |
xccdf_session_set_user_tailoring_file(session, action->tailoring_file);
|
|
Packit |
517ee8 |
xccdf_session_set_user_tailoring_cid(session, action->tailoring_id);
|
|
Packit |
517ee8 |
xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
|
|
Packit |
517ee8 |
xccdf_session_set_custom_oval_files(session, action->f_ovals);
|
|
Packit |
517ee8 |
xccdf_session_set_product_cpe(session, OSCAP_PRODUCTNAME);
|
|
Packit |
517ee8 |
xccdf_session_set_rule(session, action->rule);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_load(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* Select profile */
|
|
Packit |
517ee8 |
if (!xccdf_session_set_profile_id(session, action->profile)) {
|
|
Packit |
517ee8 |
if (action->profile != NULL) {
|
|
Packit |
517ee8 |
if (xccdf_set_profile_or_report_bad_id(session, action->profile, action->f_xccdf) == OSCAP_ERROR)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
fprintf(stderr, "No Policy was found for default profile.\n");
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
_register_progress_callback(session, action->progress);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* Perform evaluation */
|
|
Packit |
517ee8 |
if (xccdf_session_evaluate(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_without_sys_chars_export(session, action->without_sys_chars);
|
|
Packit |
517ee8 |
xccdf_session_set_oval_results_export(session, action->oval_results);
|
|
Packit |
517ee8 |
xccdf_session_set_oval_variables_export(session, action->export_variables);
|
|
Packit |
517ee8 |
xccdf_session_set_arf_export(session, action->f_results_arf);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_export_oval(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
else if (action->validate && getenv("OSCAP_FULL_VALIDATION") != NULL &&
|
|
Packit |
517ee8 |
(action->oval_results == true || action->f_results_arf))
|
|
Packit |
517ee8 |
fprintf(stdout, "OVAL Results are exported correctly.\n");
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_check_engine_plugins_results_export(session, action->check_engine_results);
|
|
Packit |
517ee8 |
if (xccdf_session_export_check_engine_plugins(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->remediate) {
|
|
Packit |
517ee8 |
if (!action->progress)
|
|
Packit |
517ee8 |
printf("\n --- Starting Remediation ---\n");
|
|
Packit |
517ee8 |
xccdf_session_remediate(session);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit Service |
deda86 |
/* Get the result from TestResult model and decide if end with error or with correct return code */
|
|
Packit Service |
deda86 |
int evaluation_result = xccdf_session_contains_fail_result(session) ? OSCAP_FAIL : OSCAP_OK;
|
|
Packit Service |
deda86 |
|
|
Packit Service |
deda86 |
/* syslog message */
|
|
Packit Service |
deda86 |
#if defined(HAVE_SYSLOG_H)
|
|
Packit Service |
4277b7 |
syslog(priority, "Evaluation finished. Return code: %d, Base score %f.", evaluation_result, xccdf_session_get_base_score(session));
|
|
Packit Service |
deda86 |
#endif
|
|
Packit Service |
deda86 |
|
|
Packit |
517ee8 |
xccdf_session_set_xccdf_export(session, action->f_results);
|
|
Packit |
517ee8 |
xccdf_session_set_xccdf_stig_viewer_export(session, action->f_results_stig);
|
|
Packit |
517ee8 |
xccdf_session_set_report_export(session, action->f_report);
|
|
Packit Service |
deda86 |
if (xccdf_session_export_all(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit Service |
deda86 |
|
|
Packit Service |
deda86 |
if (action->validate && getenv("OSCAP_FULL_VALIDATION") != NULL &&
|
|
Packit |
517ee8 |
(action->f_results || action->f_report || action->f_results_arf || action->f_results_stig))
|
|
Packit |
517ee8 |
fprintf(stdout, "XCCDF Results are exported correctly.\n");
|
|
Packit |
517ee8 |
|
|
Packit Service |
deda86 |
if (action->f_results_arf && getenv("OSCAP_FULL_VALIDATION") != NULL)
|
|
Packit |
517ee8 |
fprintf(stdout, "Result DataStream exported correctly.\n");
|
|
Packit |
517ee8 |
|
|
Packit Service |
deda86 |
result = evaluation_result;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit Service |
deda86 |
xccdf_session_free(session);
|
|
Packit |
517ee8 |
oscap_print_error();
|
|
Packit |
517ee8 |
return result;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static xccdf_test_result_type_t resolve_variables_wrapper(struct xccdf_policy *policy, const char *rule_id,
|
|
Packit |
517ee8 |
const char *id, const char *href, struct xccdf_value_binding_iterator *bnd_itr,
|
|
Packit |
517ee8 |
struct xccdf_check_import_iterator *check_import_it, void *usr)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
if (0 != oval_agent_resolve_variables((struct oval_agent_session *) usr, bnd_itr))
|
|
Packit |
517ee8 |
return XCCDF_RESULT_UNKNOWN;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return XCCDF_RESULT_PASS;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static int app_xccdf_export_oval_variables(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
struct xccdf_policy *policy = NULL;
|
|
Packit |
517ee8 |
struct xccdf_result *xres;
|
|
Packit |
517ee8 |
int result = OSCAP_ERROR;
|
|
Packit |
517ee8 |
struct xccdf_session *session = NULL;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
session = xccdf_session_new(action->f_xccdf);
|
|
Packit |
517ee8 |
if (session == NULL)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_is_sds(session)) {
|
|
Packit |
517ee8 |
xccdf_session_set_datastream_id(session, action->f_datastream_id);
|
|
Packit |
517ee8 |
xccdf_session_set_component_id(session, action->f_xccdf_id);
|
|
Packit |
517ee8 |
xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
xccdf_session_set_user_cpe(session, action->cpe);
|
|
Packit |
517ee8 |
xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
|
|
Packit |
517ee8 |
xccdf_session_set_custom_oval_files(session, action->f_ovals);
|
|
Packit |
517ee8 |
xccdf_session_set_custom_oval_eval_fn(session, resolve_variables_wrapper);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_load(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* select a profile */
|
|
Packit |
517ee8 |
policy = xccdf_policy_model_get_policy_by_id(xccdf_session_get_policy_model(session), action->profile);
|
|
Packit |
517ee8 |
if (policy == NULL) {
|
|
Packit |
517ee8 |
if (action->profile != NULL)
|
|
Packit |
517ee8 |
report_missing_profile(action->profile, action->f_xccdf);
|
|
Packit |
517ee8 |
else
|
|
Packit |
517ee8 |
fprintf(stderr, "No Policy was found for default profile.\n");
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* perform evaluation */
|
|
Packit |
517ee8 |
xres = xccdf_policy_evaluate(policy);
|
|
Packit |
517ee8 |
if (xres == NULL)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_oval_variables_export(session, true);
|
|
Packit |
517ee8 |
if (xccdf_session_export_oval(session) == 0)
|
|
Packit |
517ee8 |
result = OSCAP_OK;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit |
517ee8 |
oscap_print_error();
|
|
Packit |
517ee8 |
if (session != NULL)
|
|
Packit |
517ee8 |
xccdf_session_free(session);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return result;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int app_xccdf_remediate(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
struct xccdf_session *session = NULL;
|
|
Packit |
517ee8 |
int result = OSCAP_ERROR;
|
|
Packit |
517ee8 |
session = xccdf_session_new(action->f_xccdf);
|
|
Packit |
517ee8 |
if (session == NULL)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
|
|
Packit |
517ee8 |
xccdf_session_set_user_cpe(session, action->cpe);
|
|
Packit |
517ee8 |
xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
|
|
Packit |
517ee8 |
xccdf_session_set_custom_oval_files(session, action->f_ovals);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_load(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_build_policy_from_testresult(session, action->id) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
_register_progress_callback(session, action->progress);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_remediate(session);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_oval_results_export(session, action->oval_results);
|
|
Packit |
517ee8 |
xccdf_session_set_oval_variables_export(session, action->export_variables);
|
|
Packit |
517ee8 |
xccdf_session_set_arf_export(session, action->f_results_arf);
|
|
Packit |
517ee8 |
xccdf_session_set_xccdf_export(session, action->f_results);
|
|
Packit |
517ee8 |
xccdf_session_set_xccdf_stig_viewer_export(session, action->f_results_stig);
|
|
Packit |
517ee8 |
xccdf_session_set_report_export(session, action->f_report);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_export_oval(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_check_engine_plugins_results_export(session, action->check_engine_results);
|
|
Packit |
517ee8 |
if (xccdf_session_export_check_engine_plugins(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit Service |
deda86 |
/* Get the result from TestResult model and decide if end with error or with correct return code */
|
|
Packit Service |
deda86 |
int evaluation_result = xccdf_session_contains_fail_result(session) ? OSCAP_FAIL : OSCAP_OK;
|
|
Packit Service |
deda86 |
|
|
Packit Service |
deda86 |
if (xccdf_session_export_all(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit Service |
deda86 |
result = evaluation_result;
|
|
Packit Service |
deda86 |
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit |
517ee8 |
xccdf_session_free(session);
|
|
Packit Service |
deda86 |
oscap_print_error();
|
|
Packit |
517ee8 |
return result;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int app_xccdf_resolve(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
int ret = OSCAP_ERROR;
|
|
Packit |
517ee8 |
struct xccdf_benchmark *bench = NULL;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (!action->f_xccdf) {
|
|
Packit |
517ee8 |
fprintf(stderr, "No input document specified!\n");
|
|
Packit |
517ee8 |
return OSCAP_ERROR;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
if (!action->f_results) {
|
|
Packit |
517ee8 |
fprintf(stderr, "No output document filename specified!\n");
|
|
Packit |
517ee8 |
return OSCAP_ERROR;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
|
|
Packit |
517ee8 |
/* validate input */
|
|
Packit |
517ee8 |
if (action->validate) {
|
|
Packit |
517ee8 |
if (oscap_source_validate(source, reporter, (void *) action) != 0) {
|
|
Packit |
517ee8 |
oscap_source_free(source);
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
bench = xccdf_benchmark_import_source(source);
|
|
Packit |
517ee8 |
oscap_source_free(source);
|
|
Packit |
517ee8 |
if (!bench)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->force)
|
|
Packit |
517ee8 |
xccdf_benchmark_set_resolved(bench, false);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_benchmark_get_resolved(bench))
|
|
Packit |
517ee8 |
fprintf(stderr, "Benchmark is already resolved!\n");
|
|
Packit |
517ee8 |
else {
|
|
Packit |
517ee8 |
if (!xccdf_benchmark_resolve(bench))
|
|
Packit |
517ee8 |
fprintf(stderr, "Benchmark resolving failure (probably a dependency loop)!\n");
|
|
Packit |
517ee8 |
else
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
if (xccdf_benchmark_export(bench, action->f_results) == 0) {
|
|
Packit |
517ee8 |
ret = OSCAP_OK;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* validate exported results */
|
|
Packit |
517ee8 |
const char* full_validation = getenv("OSCAP_FULL_VALIDATION");
|
|
Packit |
517ee8 |
if (action->validate && full_validation) {
|
|
Packit |
517ee8 |
struct oscap_source *result_source = oscap_source_new_from_file(action->f_results);
|
|
Packit |
517ee8 |
if (oscap_source_validate(result_source, reporter, (void *) action) != 0) {
|
|
Packit |
517ee8 |
ret = OSCAP_ERROR;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
else
|
|
Packit |
517ee8 |
fprintf(stdout, "Resolved XCCDF has been exported correctly.\n");
|
|
Packit |
517ee8 |
oscap_source_free(result_source);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit |
517ee8 |
oscap_print_error();
|
|
Packit |
517ee8 |
if (bench)
|
|
Packit |
517ee8 |
xccdf_benchmark_free(bench);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return ret;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
static bool _some_result_exists(struct oscap_source *xccdf_source, const char *namespace)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
struct xccdf_benchmark *benchmark = NULL;
|
|
Packit |
517ee8 |
struct xccdf_policy_model *policy_model = NULL;
|
|
Packit |
517ee8 |
struct oscap_file_entry_list *files = NULL;
|
|
Packit |
517ee8 |
struct oscap_file_entry_iterator *files_it = NULL;
|
|
Packit |
517ee8 |
char *oval_result = NULL;
|
|
Packit |
517ee8 |
bool result = false;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
benchmark = xccdf_benchmark_import_source(xccdf_source);
|
|
Packit |
517ee8 |
if (benchmark == NULL)
|
|
Packit |
517ee8 |
return false;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
policy_model = xccdf_policy_model_new(benchmark);
|
|
Packit |
517ee8 |
files = xccdf_policy_model_get_systems_and_files(policy_model);
|
|
Packit |
517ee8 |
files_it = oscap_file_entry_list_get_files(files);
|
|
Packit |
517ee8 |
oval_result = malloc(PATH_MAX * sizeof(char));
|
|
Packit |
517ee8 |
while (oscap_file_entry_iterator_has_more(files_it)) {
|
|
Packit |
517ee8 |
struct oscap_file_entry *file_entry = (struct oscap_file_entry *) oscap_file_entry_iterator_next(files_it);;
|
|
Packit |
517ee8 |
struct stat sb;
|
|
Packit |
517ee8 |
if (strcmp(oscap_file_entry_get_system(file_entry), namespace))
|
|
Packit |
517ee8 |
continue;
|
|
Packit |
517ee8 |
snprintf(oval_result, PATH_MAX, "./%s.result.xml", oscap_file_entry_get_file(file_entry));
|
|
Packit |
517ee8 |
if (stat(oval_result, &sb) == 0) {
|
|
Packit |
517ee8 |
result = true;
|
|
Packit |
517ee8 |
break;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
free(oval_result);
|
|
Packit |
517ee8 |
oscap_file_entry_iterator_free(files_it);
|
|
Packit |
517ee8 |
oscap_file_entry_list_free(files);
|
|
Packit |
517ee8 |
xccdf_policy_model_free(policy_model);
|
|
Packit |
517ee8 |
return result;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int app_generate_fix(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
struct xccdf_session *session = NULL;
|
|
Packit |
517ee8 |
struct ds_rds_session *arf_session = NULL;
|
|
Packit |
517ee8 |
const char *template = NULL;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->fix_type != NULL && action->tmpl != NULL) {
|
|
Packit |
517ee8 |
/* Avoid undefined situations, eg.:
|
|
Packit |
517ee8 |
* oscap xccdf generate fix --fix-type ansible --template urn:xccdf:fix:scipt:sh
|
|
Packit |
517ee8 |
*/
|
|
Packit |
517ee8 |
fprintf(stderr,
|
|
Packit |
517ee8 |
"Option '--fix-type' is mutually exclusive with '--template'.\n"
|
|
Packit |
517ee8 |
"Please provide only one of them.\n");
|
|
Packit |
517ee8 |
return OSCAP_ERROR;
|
|
Packit |
517ee8 |
} else if (action->fix_type != NULL) {
|
|
Packit |
517ee8 |
if (strcmp(action->fix_type, "bash") == 0) {
|
|
Packit |
517ee8 |
template = "urn:xccdf:fix:script:sh";
|
|
Packit |
517ee8 |
} else if (strcmp(action->fix_type, "ansible") == 0) {
|
|
Packit |
517ee8 |
template = "urn:xccdf:fix:script:ansible";
|
|
Packit |
517ee8 |
} else if (strcmp(action->fix_type, "puppet") == 0) {
|
|
Packit |
517ee8 |
template = "urn:xccdf:fix:script:puppet";
|
|
Packit |
517ee8 |
} else if (strcmp(action->fix_type, "anaconda") == 0) {
|
|
Packit |
517ee8 |
template = "urn:redhat:anaconda:pre";
|
|
Packit |
517ee8 |
} else if (strcmp(action->fix_type, "ignition") == 0) {
|
|
Packit |
517ee8 |
template = "urn:xccdf:fix:script:ignition";
|
|
Packit |
517ee8 |
} else if (strcmp(action->fix_type, "kubernetes") == 0) {
|
|
Packit |
517ee8 |
template = "urn:xccdf:fix:script:kubernetes";
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
fprintf(stderr,
|
|
Packit |
517ee8 |
"Unknown fix type '%s'.\n"
|
|
Packit |
517ee8 |
"Please provide one of: bash, ansible, puppet, anaconda, ignition, kubernetes.\n"
|
|
Packit |
517ee8 |
"Or provide a custom template using '--template' instead.\n",
|
|
Packit |
517ee8 |
action->fix_type);
|
|
Packit |
517ee8 |
return OSCAP_ERROR;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
} else if (action->tmpl != NULL) {
|
|
Packit |
517ee8 |
template = action->tmpl;
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
template = "urn:xccdf:fix:script:sh";
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int ret = OSCAP_ERROR;
|
|
Packit |
517ee8 |
struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
|
|
Packit |
517ee8 |
oscap_document_type_t document_type = oscap_source_get_scap_type(source);
|
|
Packit |
517ee8 |
if (document_type == OSCAP_DOCUMENT_ARF) {
|
|
Packit |
517ee8 |
arf_session = ds_rds_session_new_from_source(source);
|
|
Packit |
517ee8 |
if (arf_session == NULL) {
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
struct oscap_source *report_source = ds_rds_session_select_report(arf_session, NULL);
|
|
Packit |
517ee8 |
if (report_source == NULL) {
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
struct oscap_source *report_request_source = ds_rds_session_select_report_request(arf_session, NULL);
|
|
Packit |
517ee8 |
if (report_request_source == NULL) {
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
session = xccdf_session_new_from_source(oscap_source_clone(report_request_source));
|
|
Packit |
517ee8 |
if (action->id != NULL) {
|
|
Packit |
517ee8 |
if (xccdf_session_add_report_from_source(session, oscap_source_clone(report_source))) {
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
oscap_source_free(source);
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
session = xccdf_session_new_from_source(source);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
if (session == NULL)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
|
|
Packit |
517ee8 |
xccdf_session_set_user_cpe(session, action->cpe);
|
|
Packit |
517ee8 |
xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
|
|
Packit |
517ee8 |
xccdf_session_set_custom_oval_files(session, action->f_ovals);
|
|
Packit |
517ee8 |
xccdf_session_set_user_tailoring_file(session, action->tailoring_file);
|
|
Packit |
517ee8 |
xccdf_session_set_user_tailoring_cid(session, action->tailoring_id);
|
|
Packit |
517ee8 |
if (xccdf_session_is_sds(session)) {
|
|
Packit |
517ee8 |
xccdf_session_set_component_id(session, action->f_xccdf_id);
|
|
Packit |
517ee8 |
xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
xccdf_session_set_loading_flags(session, XCCDF_SESSION_LOAD_XCCDF);
|
|
Packit |
517ee8 |
if (xccdf_session_load(session) != 0)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#ifdef OS_WINDOWS
|
|
Packit |
517ee8 |
int output_fd = _fileno(stdout);
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
int output_fd = STDOUT_FILENO;
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
if (action->f_results != NULL) {
|
|
Packit |
517ee8 |
if ((output_fd = open(action->f_results, O_CREAT|O_TRUNC|O_NOFOLLOW|O_WRONLY, 0700)) < 0) {
|
|
Packit |
517ee8 |
fprintf(stderr, "Could not open %s: %s", action->f_results, strerror(errno));
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->id != NULL) {
|
|
Packit |
517ee8 |
/* Result-oriented fixes */
|
|
Packit |
517ee8 |
if (xccdf_session_build_policy_from_testresult(session, action->id) != 0)
|
|
Packit |
517ee8 |
goto cleanup2;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
|
|
Packit |
517ee8 |
struct xccdf_result *result = xccdf_policy_get_result_by_id(policy, xccdf_session_get_result_id(session));
|
|
Packit |
517ee8 |
if (xccdf_policy_generate_fix(policy, result, template, output_fd) == 0)
|
|
Packit |
517ee8 |
ret = OSCAP_OK;
|
|
Packit |
517ee8 |
} else { // Fallback to profile if result id is missing
|
|
Packit |
517ee8 |
/* Profile-oriented fixes */
|
|
Packit |
517ee8 |
if (!xccdf_session_set_profile_id(session, action->profile)) {
|
|
Packit |
517ee8 |
if (action->profile != NULL) {
|
|
Packit |
517ee8 |
if (xccdf_set_profile_or_report_bad_id(session, action->profile, action->f_xccdf) == OSCAP_ERROR)
|
|
Packit |
517ee8 |
goto cleanup2;
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
fprintf(stderr, "No Policy was found for default profile.\n");
|
|
Packit |
517ee8 |
goto cleanup2;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
|
|
Packit |
517ee8 |
if (xccdf_policy_generate_fix(policy, NULL, template, output_fd) == 0)
|
|
Packit |
517ee8 |
ret = OSCAP_OK;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
cleanup2:
|
|
Packit |
517ee8 |
#ifdef OS_WINDOWS
|
|
Packit |
517ee8 |
if (output_fd != _fileno(stdout))
|
|
Packit |
517ee8 |
#else
|
|
Packit |
517ee8 |
if (output_fd != STDOUT_FILENO)
|
|
Packit |
517ee8 |
#endif
|
|
Packit |
517ee8 |
close(output_fd);
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit |
517ee8 |
ds_rds_session_free(arf_session);
|
|
Packit |
517ee8 |
xccdf_session_free(session);
|
|
Packit |
517ee8 |
oscap_print_error();
|
|
Packit |
517ee8 |
return ret;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int app_generate_guide(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
int ret = OSCAP_ERROR;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
|
|
Packit |
517ee8 |
struct xccdf_session *session = xccdf_session_new_from_source(source);
|
|
Packit |
517ee8 |
if (session == NULL) {
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
|
|
Packit |
517ee8 |
xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
|
|
Packit |
517ee8 |
xccdf_session_set_user_tailoring_file(session, action->tailoring_file);
|
|
Packit |
517ee8 |
xccdf_session_set_user_tailoring_cid(session, action->tailoring_id);
|
|
Packit |
517ee8 |
if (xccdf_session_is_sds(session)) {
|
|
Packit |
517ee8 |
xccdf_session_set_component_id(session, action->f_xccdf_id);
|
|
Packit |
517ee8 |
xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
xccdf_session_set_loading_flags(session, XCCDF_SESSION_LOAD_XCCDF);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_load(session) != 0) {
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (!xccdf_session_set_profile_id(session, action->profile)) {
|
|
Packit |
517ee8 |
if (action->profile != NULL) {
|
|
Packit |
517ee8 |
if (xccdf_set_profile_or_report_bad_id(session, action->profile, action->f_xccdf) == OSCAP_ERROR)
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
fprintf(stderr, "No Policy was found for default profile.\n");
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (xccdf_session_generate_guide(session, action->f_results) == 0) {
|
|
Packit |
517ee8 |
ret = OSCAP_OK;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit |
517ee8 |
xccdf_session_free(session);
|
|
Packit |
517ee8 |
oscap_print_error();
|
|
Packit |
517ee8 |
return ret;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int app_xccdf_xslt(const struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
const char *oval_template = action->oval_template;
|
|
Packit |
517ee8 |
const char *sce_template = action->sce_template;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->module == &XCCDF_GEN_REPORT && (oval_template == NULL || sce_template == NULL)) {
|
|
Packit |
517ee8 |
/* If generating the report and the option is missing -> use defaults */
|
|
Packit |
517ee8 |
struct oscap_source *xccdf_source = oscap_source_new_from_file(action->f_xccdf);
|
|
Packit |
517ee8 |
/* We want to define default template because we strive to serve user the
|
|
Packit |
517ee8 |
* best. However, we must not offer a template, if there is a risk it might
|
|
Packit |
517ee8 |
* be incorrect. Otherwise, libxml2 will throw a lot of misleading messages
|
|
Packit |
517ee8 |
* to stderr. */
|
|
Packit |
517ee8 |
if (oval_template == NULL && _some_result_exists(xccdf_source, "http://oval.mitre.org/XMLSchema/oval-definitions-5")) {
|
|
Packit |
517ee8 |
oval_template = "%.result.xml";
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
if (sce_template == NULL && _some_result_exists(xccdf_source, "http://open-scap.org/page/SCE")) {
|
|
Packit |
517ee8 |
sce_template = "%.result.xml";
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
oscap_source_free(xccdf_source);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->module == &XCCDF_GEN_CUSTOM) {
|
|
Packit |
517ee8 |
action->module->user = (void*)action->stylesheet;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
const char *params[] = {
|
|
Packit |
517ee8 |
"result-id", action->id,
|
|
Packit |
517ee8 |
"benchmark_id", action->f_benchmark_id,
|
|
Packit |
517ee8 |
"profile_id", action->profile,
|
|
Packit |
517ee8 |
"template", action->tmpl,
|
|
Packit |
517ee8 |
"oval-template", oval_template,
|
|
Packit |
517ee8 |
"sce-template", sce_template,
|
|
Packit |
517ee8 |
"verbosity", "",
|
|
Packit |
517ee8 |
"hide-profile-info", action->hide_profile_info ? "yes" : NULL,
|
|
Packit |
517ee8 |
NULL
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int ret = app_xslt(action->f_xccdf, action->module->user, action->f_results, params);
|
|
Packit |
517ee8 |
return ret;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
bool getopt_generate(int argc, char **argv, struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
static const struct option long_options[] = {
|
|
Packit |
517ee8 |
{"profile", 1, 0, 3},
|
|
Packit |
517ee8 |
{0, 0, 0, 0}
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int c;
|
|
Packit |
517ee8 |
while ((c = getopt_long(argc, argv, "+", long_options, NULL)) != -1) {
|
|
Packit |
517ee8 |
switch (c) {
|
|
Packit |
517ee8 |
case 3: action->profile = optarg; break;
|
|
Packit |
517ee8 |
default: return oscap_module_usage(action->module, stderr, NULL);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
return true;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
enum oval_opt {
|
|
Packit |
517ee8 |
XCCDF_OPT_RESULT_FILE = 1,
|
|
Packit |
517ee8 |
XCCDF_OPT_RESULT_FILE_STIG,
|
|
Packit |
517ee8 |
XCCDF_OPT_RESULT_FILE_ARF,
|
|
Packit |
517ee8 |
XCCDF_OPT_DATASTREAM_ID,
|
|
Packit |
517ee8 |
XCCDF_OPT_XCCDF_ID,
|
|
Packit |
517ee8 |
XCCDF_OPT_BENCHMARK_ID,
|
|
Packit |
517ee8 |
XCCDF_OPT_PROFILE,
|
|
Packit |
517ee8 |
XCCDF_OPT_RULE,
|
|
Packit |
517ee8 |
XCCDF_OPT_REPORT_FILE,
|
|
Packit |
517ee8 |
XCCDF_OPT_TEMPLATE,
|
|
Packit |
517ee8 |
XCCDF_OPT_FORMAT,
|
|
Packit |
517ee8 |
XCCDF_OPT_OVAL_TEMPLATE,
|
|
Packit |
517ee8 |
XCCDF_OPT_STYLESHEET_FILE,
|
|
Packit |
517ee8 |
XCCDF_OPT_SCE_TEMPLATE,
|
|
Packit |
517ee8 |
XCCDF_OPT_FILE_VERSION,
|
|
Packit |
517ee8 |
XCCDF_OPT_TAILORING_FILE,
|
|
Packit |
517ee8 |
XCCDF_OPT_TAILORING_ID,
|
|
Packit |
517ee8 |
XCCDF_OPT_CPE,
|
|
Packit |
517ee8 |
XCCDF_OPT_CPE_DICT,
|
|
Packit |
517ee8 |
XCCDF_OPT_OUTPUT = 'o',
|
|
Packit |
517ee8 |
XCCDF_OPT_RESULT_ID = 'i',
|
|
Packit |
517ee8 |
XCCDF_OPT_FIX_TYPE
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
bool getopt_xccdf(int argc, char **argv, struct oscap_action *action)
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
assert(action != NULL);
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
action->doctype = OSCAP_DOCUMENT_XCCDF;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
/* Command-options */
|
|
Packit |
517ee8 |
const struct option long_options[] = {
|
|
Packit |
517ee8 |
// options
|
|
Packit |
517ee8 |
{"output", required_argument, NULL, XCCDF_OPT_OUTPUT},
|
|
Packit |
517ee8 |
{"results", required_argument, NULL, XCCDF_OPT_RESULT_FILE},
|
|
Packit |
517ee8 |
{"results-arf", required_argument, NULL, XCCDF_OPT_RESULT_FILE_ARF},
|
|
Packit |
517ee8 |
{"stig-viewer", required_argument, NULL, XCCDF_OPT_RESULT_FILE_STIG},
|
|
Packit |
517ee8 |
{"datastream-id", required_argument, NULL, XCCDF_OPT_DATASTREAM_ID},
|
|
Packit |
517ee8 |
{"xccdf-id", required_argument, NULL, XCCDF_OPT_XCCDF_ID},
|
|
Packit |
517ee8 |
{"benchmark-id", required_argument, NULL, XCCDF_OPT_BENCHMARK_ID},
|
|
Packit |
517ee8 |
{"profile", required_argument, NULL, XCCDF_OPT_PROFILE},
|
|
Packit |
517ee8 |
{"rule", required_argument, NULL, XCCDF_OPT_RULE},
|
|
Packit |
517ee8 |
{"result-id", required_argument, NULL, XCCDF_OPT_RESULT_ID},
|
|
Packit |
517ee8 |
{"report", required_argument, NULL, XCCDF_OPT_REPORT_FILE},
|
|
Packit |
517ee8 |
{"template", required_argument, NULL, XCCDF_OPT_TEMPLATE},
|
|
Packit |
517ee8 |
{"oval-template", required_argument, NULL, XCCDF_OPT_OVAL_TEMPLATE},
|
|
Packit |
517ee8 |
{"stylesheet", required_argument, NULL, XCCDF_OPT_STYLESHEET_FILE},
|
|
Packit |
517ee8 |
{"tailoring-file", required_argument, NULL, XCCDF_OPT_TAILORING_FILE},
|
|
Packit |
517ee8 |
{"tailoring-id", required_argument, NULL, XCCDF_OPT_TAILORING_ID},
|
|
Packit |
517ee8 |
{"cpe", required_argument, NULL, XCCDF_OPT_CPE},
|
|
Packit |
517ee8 |
{"cpe-dict", required_argument, NULL, XCCDF_OPT_CPE_DICT}, // DEPRECATED!
|
|
Packit |
517ee8 |
{"sce-template", required_argument, NULL, XCCDF_OPT_SCE_TEMPLATE},
|
|
Packit |
517ee8 |
{"fix-type", required_argument, NULL, XCCDF_OPT_FIX_TYPE},
|
|
Packit |
517ee8 |
// flags
|
|
Packit |
517ee8 |
{"force", no_argument, &action->force, 1},
|
|
Packit |
517ee8 |
{"oval-results", no_argument, &action->oval_results, 1},
|
|
Packit |
517ee8 |
{"check-engine-results", no_argument, &action->check_engine_results, 1},
|
|
Packit |
517ee8 |
{"skip-valid", no_argument, &action->validate, 0},
|
|
Packit |
517ee8 |
{"fetch-remote-resources", no_argument, &action->remote_resources, 1},
|
|
Packit |
517ee8 |
{"progress", no_argument, &action->progress, 1},
|
|
Packit |
517ee8 |
{"remediate", no_argument, &action->remediate, 1},
|
|
Packit |
517ee8 |
{"hide-profile-info", no_argument, &action->hide_profile_info, 1},
|
|
Packit |
517ee8 |
{"export-variables", no_argument, &action->export_variables, 1},
|
|
Packit |
517ee8 |
{"schematron", no_argument, &action->schematron, 1},
|
|
Packit |
517ee8 |
{"without-syschar", no_argument, &action->without_sys_chars, 1},
|
|
Packit |
517ee8 |
{"thin-results", no_argument, &action->thin_results, 1},
|
|
Packit |
517ee8 |
// end
|
|
Packit |
517ee8 |
{0, 0, 0, 0}
|
|
Packit |
517ee8 |
};
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int c;
|
|
Packit |
517ee8 |
while ((c = getopt_long(argc, argv, "o:i:", long_options, NULL)) != -1) {
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
switch (c) {
|
|
Packit |
517ee8 |
case XCCDF_OPT_OUTPUT:
|
|
Packit |
517ee8 |
case XCCDF_OPT_RESULT_FILE: action->f_results = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_RESULT_FILE_STIG: action->f_results_stig = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_RESULT_FILE_ARF: action->f_results_arf = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_DATASTREAM_ID: action->f_datastream_id = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_XCCDF_ID: action->f_xccdf_id = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_BENCHMARK_ID: action->f_benchmark_id = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_PROFILE: action->profile = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_RULE: action->rule = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_RESULT_ID: action->id = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_REPORT_FILE: action->f_report = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_TEMPLATE: action->tmpl = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_OVAL_TEMPLATE: action->oval_template = optarg; break;
|
|
Packit |
517ee8 |
/* we use realpath to get an absolute path to given XSLT to prevent openscap from looking
|
|
Packit |
517ee8 |
into /usr/share/openscap/xsl instead of CWD */
|
|
Packit |
517ee8 |
case XCCDF_OPT_STYLESHEET_FILE: oscap_realpath(optarg, custom_stylesheet_path); action->stylesheet = custom_stylesheet_path; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_TAILORING_FILE: action->tailoring_file = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_TAILORING_ID: action->tailoring_id = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_CPE: action->cpe = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_CPE_DICT:
|
|
Packit |
517ee8 |
{
|
|
Packit |
517ee8 |
fprintf(stdout, "Warning: --cpe-dict is a deprecated option. Please use --cpe instead!\n\n");
|
|
Packit |
517ee8 |
action->cpe = optarg; break;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
case XCCDF_OPT_SCE_TEMPLATE: action->sce_template = optarg; break;
|
|
Packit |
517ee8 |
case XCCDF_OPT_FIX_TYPE:
|
|
Packit |
517ee8 |
action->fix_type = optarg;
|
|
Packit |
517ee8 |
break;
|
|
Packit |
517ee8 |
case 0: break;
|
|
Packit |
517ee8 |
default: return oscap_module_usage(action->module, stderr, NULL);
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->module == &XCCDF_EVAL) {
|
|
Packit |
517ee8 |
/* We should have XCCDF file here */
|
|
Packit |
517ee8 |
if (optind >= argc) {
|
|
Packit |
517ee8 |
/* TODO */
|
|
Packit |
517ee8 |
return oscap_module_usage(action->module, stderr, "XCCDF file need to be specified!");
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
action->f_xccdf = argv[optind];
|
|
Packit |
517ee8 |
if (argc > (optind+1)) {
|
|
Packit |
517ee8 |
action->f_ovals = malloc((argc-(optind+1)+1) * sizeof(char *));
|
|
Packit |
517ee8 |
int i = 1;
|
|
Packit |
517ee8 |
while (argc > (optind+i)) {
|
|
Packit |
517ee8 |
action->f_ovals[i-1] = argv[optind + i];
|
|
Packit |
517ee8 |
i++;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
action->f_ovals[i-1] = NULL;
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
action->f_ovals = NULL;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
} else if (action->module == &XCCDF_GEN_CUSTOM) {
|
|
Packit |
517ee8 |
if (!action->stylesheet) {
|
|
Packit |
517ee8 |
return oscap_module_usage(action->module, stderr, "XSLT Stylesheet needs to be specified!");
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (optind >= argc)
|
|
Packit |
517ee8 |
return oscap_module_usage(action->module, stderr, "XCCDF file needs to be specified!");
|
|
Packit |
517ee8 |
action->f_xccdf = argv[optind];
|
|
Packit |
517ee8 |
} else {
|
|
Packit |
517ee8 |
if (optind >= argc)
|
|
Packit |
517ee8 |
return oscap_module_usage(action->module, stderr, "XCCDF file needs to be specified!");
|
|
Packit |
517ee8 |
action->f_xccdf = argv[optind];
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return true;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
int app_xccdf_validate(const struct oscap_action *action) {
|
|
Packit |
517ee8 |
int ret;
|
|
Packit |
517ee8 |
int result;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
|
|
Packit |
517ee8 |
ret = oscap_source_validate(source, reporter, (void *) action);
|
|
Packit |
517ee8 |
if (ret==-1) {
|
|
Packit |
517ee8 |
result=OSCAP_ERROR;
|
|
Packit |
517ee8 |
goto cleanup;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
else if (ret==1) {
|
|
Packit |
517ee8 |
result=OSCAP_FAIL;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
else
|
|
Packit |
517ee8 |
result=OSCAP_OK;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if (action->schematron) {
|
|
Packit |
517ee8 |
ret = oscap_source_validate_schematron(source, NULL);
|
|
Packit |
517ee8 |
if (ret == -1) {
|
|
Packit |
517ee8 |
result = OSCAP_ERROR;
|
|
Packit |
517ee8 |
} else if (ret > 0) {
|
|
Packit |
517ee8 |
result = OSCAP_FAIL;
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
cleanup:
|
|
Packit |
517ee8 |
oscap_source_free(source);
|
|
Packit |
517ee8 |
oscap_print_error();
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return result;
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
}
|