/**
* @file oval_resModel.c
* \brief Open Vulnerability and Assessment Language
*
* See more details at http://oval.mitre.org/
*/
/*
* Copyright 2009--2014 Red Hat Inc., Durham, North Carolina.
* All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* "David Niemoller" <David.Niemoller@g2-inc.com>
* "Peter Vrabec" <pvrabec@redhat.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <time.h>
#include "oval_definitions_impl.h"
#include "oval_agent_api_impl.h"
#include "oval_parser_impl.h"
#include "adt/oval_string_map_impl.h"
#include "oval_system_characteristics_impl.h"
#include "results/oval_results_impl.h"
#if defined(OVAL_PROBES_ENABLED)
# include "oval_probe_impl.h"
#endif
#include "oval_directives_impl.h"
#include "common/util.h"
#include "common/debug_priv.h"
#include "common/_error.h"
#include "common/elements.h"
#include "oscap_source.h"
#include "source/oscap_source_priv.h"
struct oval_results_model {
struct oval_generator *generator;
struct oval_directives_model *directives_model;
struct oval_definition_model *definition_model;
struct oval_collection *systems;
#if defined(OVAL_PROBES_ENABLED)
struct oval_probe_session *probe_session;
#endif
bool export_sys_chars;
};
struct oval_results_model *oval_results_model_new(struct oval_definition_model *definition_model,
struct oval_syschar_model **syschar_models)
{
#if defined(OVAL_PROBES_ENABLED)
return oval_results_model_new_with_probe_session(definition_model, syschar_models, NULL);
}
struct oval_results_model *oval_results_model_new_with_probe_session(struct oval_definition_model *definition_model,
struct oval_syschar_model **syschar_models,
struct oval_probe_session *probe_session)
{
#endif
struct oval_results_model *model = (struct oval_results_model *) malloc(sizeof(struct oval_results_model));
if (model == NULL)
return NULL;
struct oval_generator *generator = oval_definition_model_get_generator(definition_model);
model->generator = oval_generator_clone(generator);
oval_generator_update_timestamp(model->generator);
model->systems = oval_collection_new();
model->definition_model = definition_model;
if (syschar_models) {
struct oval_syschar_model *syschar_model;
for (syschar_model = *syschar_models; syschar_model; syschar_model = *(++syschar_models)) {
oval_result_system_new(model, syschar_model);
}
}
model->directives_model = oval_directives_model_new();
#if defined(OVAL_PROBES_ENABLED)
model->probe_session = probe_session;
#endif
model->export_sys_chars = true;
return model;
}
struct oval_results_model *oval_results_model_clone(struct oval_results_model *old_resmodel)
{
struct oval_definition_model *old_defmodel = oval_results_model_get_definition_model(old_resmodel);
struct oval_results_model *new_resmodel = oval_results_model_new(old_defmodel, NULL);
struct oval_result_system_iterator *old_systems = oval_results_model_get_systems(old_resmodel);
while (oval_result_system_iterator_has_more(old_systems)) {
struct oval_result_system *old_system = oval_result_system_iterator_next(old_systems);
oval_result_system_clone(new_resmodel, old_system);
}
oval_result_system_iterator_free(old_systems);
/* ToDo: Directives Model clone */
return new_resmodel;
}
void oval_results_model_set_export_system_characteristics(struct oval_results_model *model, bool export)
{
model->export_sys_chars = export;
}
bool oval_results_model_get_export_system_characteristics(struct oval_results_model *model)
{
return model->export_sys_chars;
}
void oval_results_model_free(struct oval_results_model *model)
{
__attribute__nonnull__(model);
oval_collection_free_items(model->systems, (oscap_destruct_func) oval_result_system_free);
model->systems = NULL;
model->definition_model = NULL;
oval_generator_free(model->generator);
model->generator=NULL;
oval_directives_model_free(model->directives_model);
model->directives_model=NULL;
free(model);
}
struct oval_generator *oval_results_model_get_generator(struct oval_results_model *model)
{
return model->generator;
}
void oval_results_model_set_generator(struct oval_results_model *model, struct oval_generator *generator)
{
oval_generator_free(model->generator);
model->generator = generator;
}
struct oval_directives_model *oval_results_model_get_directives_model(struct oval_results_model *model) {
__attribute__nonnull__(model);
return model->directives_model;
}
struct oval_definition_model *oval_results_model_get_definition_model(struct oval_results_model *model) {
__attribute__nonnull__(model);
return model->definition_model;
}
struct oval_result_system_iterator *oval_results_model_get_systems(struct oval_results_model *model)
{
__attribute__nonnull__(model);
return (struct oval_result_system_iterator *)
oval_collection_iterator(model->systems);
}
#if defined(OVAL_PROBES_ENABLED)
struct oval_probe_session *oval_results_model_get_probe_session(struct oval_results_model *model)
{
__attribute__nonnull__(model);
return model->probe_session;
}
#endif
void oval_results_model_add_system(struct oval_results_model *model, struct oval_result_system *sys)
{
__attribute__nonnull__(model);
if (sys)
oval_collection_add(model->systems, sys);
}
int oval_results_model_import_source(struct oval_results_model *model, struct oscap_source *source)
{
__attribute__nonnull__(model);
__attribute__nonnull__(source);
int ret = 0;
char *tagname = NULL;
char *namespace = NULL;
/* setup context */
struct oval_parser_context context;
context.reader = oscap_source_get_xmlTextReader(source);
if (context.reader == NULL) {
return -1;
}
context.results_model = model;
context.definition_model = oval_results_model_get_definition_model(model);
context.user_data = NULL;
oscap_setxmlerr(xmlGetLastError());
/* jump into document */
xmlTextReaderRead(context.reader);
/* make sure these are results */
tagname = (char *)xmlTextReaderLocalName(context.reader);
namespace = (char *)xmlTextReaderNamespaceUri(context.reader);
int is_ovalres = strcmp((const char *)OVAL_RESULTS_NAMESPACE, namespace) == 0;
/* star parsing */
if (is_ovalres && (strcmp(tagname, OVAL_ROOT_ELM_RESULTS) == 0)) {
ret = oval_results_model_parse(context.reader, &context);
} else {
oscap_seterr(OSCAP_EFAMILY_OSCAP, "Missing \"oval_results\" element");
ret = -1;
}
free(tagname);
free(namespace);
xmlFreeTextReader(context.reader);
return ret;
}
int oval_results_model_eval(struct oval_results_model *res_model)
{
struct oval_result_system_iterator *systems_itr;
systems_itr = oval_results_model_get_systems(res_model);
while (oval_result_system_iterator_has_more(systems_itr)) {
struct oval_result_system *sys;
sys = oval_result_system_iterator_next(systems_itr);
if( oval_result_system_eval(sys) != 0 ) { /* evaluate each result_system */
oval_result_system_iterator_free(systems_itr);
return -1;
}
}
oval_result_system_iterator_free(systems_itr);
return 0;
}
static xmlNode *oval_results_to_dom(struct oval_results_model *results_model,
struct oval_directives_model *directives_model,
xmlDocPtr doc, xmlNode * parent)
{
xmlNode *root_node;
struct oval_result_directives * dirs;
struct oval_directives_model * dirs_model;
if (parent) {
root_node = xmlNewTextChild(parent, NULL, BAD_CAST OVAL_ROOT_ELM_RESULTS, NULL);
} else {
root_node = xmlNewNode(NULL, BAD_CAST OVAL_ROOT_ELM_RESULTS);
xmlDocSetRootElement(doc, root_node);
}
xmlNewNsProp(root_node, lookup_xsi_ns(doc), BAD_CAST "schemaLocation", BAD_CAST OVAL_RES_SCHEMA_LOCATION);
xmlNs *ns_common = xmlNewNs(root_node, OVAL_COMMON_NAMESPACE, BAD_CAST "oval");
xmlNs *ns_results = xmlNewNs(root_node, OVAL_RESULTS_NAMESPACE, NULL);
xmlSetNs(root_node, ns_common);
xmlSetNs(root_node, ns_results);
/* Report generator */
oval_generator_to_dom(results_model->generator, doc, root_node);
/* Report default directives and class directives from internal or external
* directives model(if provided) */
dirs_model = (directives_model) ? directives_model : results_model->directives_model;
oval_directives_model_to_dom(dirs_model, doc, root_node);
dirs = oval_directives_model_get_defdirs(dirs_model);
/* Report definitions */
if(oval_result_directives_get_included(dirs)) {
struct oval_definition_model *definition_model = oval_results_model_get_definition_model(results_model);
oval_definition_model_to_dom(definition_model, doc, root_node);
}
xmlNode *results_node = xmlNewTextChild(root_node, ns_results, BAD_CAST "results", NULL);
struct oval_result_system_iterator *systems = oval_results_model_get_systems(results_model);
while (oval_result_system_iterator_has_more(systems)) {
struct oval_result_system *sys = oval_result_system_iterator_next(systems);
oval_result_system_to_dom(sys, results_model, dirs_model, doc, results_node);
}
oval_result_system_iterator_free(systems);
return root_node;
}
struct oscap_source *oval_results_model_export_source(struct oval_results_model *results_model, struct oval_directives_model *directives_model, const char *name)
{
__attribute__nonnull__(results_model);
xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
if (doc == NULL) {
oscap_setxmlerr(xmlGetLastError());
return NULL;
}
oval_results_to_dom(results_model, directives_model, doc, NULL);
return oscap_source_new_from_xmlDoc(doc, name);
}
int oval_results_model_export(struct oval_results_model *results_model,
struct oval_directives_model *directives_model,
const char *file)
{
struct oscap_source *source = oval_results_model_export_source(results_model, directives_model, file);
if (source == NULL) {
return -1;
}
int ret = oscap_source_save_as(source, NULL);
oscap_source_free(source);
return ret;
}
int oval_results_model_parse(xmlTextReaderPtr reader, struct oval_parser_context *context) {
int depth = xmlTextReaderDepth(reader);
int ret = 0;
xmlTextReaderRead(reader);
while ((xmlTextReaderDepth(reader) > depth) && (ret != -1 )) {
if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
char *tagname = (char *)xmlTextReaderLocalName(reader);
char *namespace = (char *)xmlTextReaderNamespaceUri(reader);
int is_ovalres = strcmp((const char *)OVAL_RESULTS_NAMESPACE, namespace) == 0;
int is_ovaldef = (is_ovalres) ? false : (strcmp((const char *)OVAL_DEFINITIONS_NAMESPACE, namespace) == 0);
if (is_ovalres && (strcmp(tagname, "generator") == 0)) {
struct oval_generator *gen;
gen = oval_results_model_get_generator(context->results_model);
ret = oval_parser_parse_tag(reader, context, &oval_generator_parse_tag, gen);
} else if (is_ovalres && (strcmp(tagname, "directives") == 0)) {
struct oval_result_directives *def_dirs;
bool val;
def_dirs = oval_directives_model_get_defdirs(context->results_model->directives_model);
val = oval_parser_boolean_attribute(reader, "include_source_definitions", 1);
oval_result_directives_set_included(def_dirs, val);
ret = oval_parser_parse_tag(reader, context, &oval_result_directives_parse_tag, def_dirs);
} else if (is_ovalres && (strcmp(tagname, "class_directives") == 0)) {
struct oval_result_directives *class_dir;
oval_definition_class_t class_type;
char *class_str = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "class");
class_type = oval_definition_class_enum(class_str);
class_dir = oval_directives_model_get_new_classdir(context->results_model->directives_model, class_type);
ret = oval_parser_parse_tag(reader, context, &oval_result_directives_parse_tag, class_dir);
free(class_str);
} else if (is_ovaldef && (strcmp(tagname, OVAL_ROOT_ELM_DEFINITIONS) == 0)) {
ret = oval_definition_model_parse(reader, context);
} else if (is_ovalres && (strcmp(tagname, "results") == 0)) {
ret = oval_parser_parse_tag(reader, context, &oval_result_system_parse_tag , NULL);
} else {
dW("Unprocessed tag: <%s:%s>.", namespace, tagname);
oval_parser_skip_tag(reader, context);
}
free(tagname);
free(namespace);
} else {
if (xmlTextReaderRead(reader) != 1) {
ret = -1;
break;
}
}
}
return ret;
}