/**
* @file oval_definition.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>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "oval_definitions_impl.h"
#include "adt/oval_collection_impl.h"
#include "adt/oval_string_map_impl.h"
#include "oval_agent_api_impl.h"
#include "common/util.h"
#include "common/debug_priv.h"
#include "common/elements.h"
#include "common/_error.h"
/***************************************************************************/
/* Variable definitions
* */
typedef struct oval_definition {
struct oval_definition_model *model;
char *id;
int version;
oval_definition_class_t class;
int deprecated;
char *title;
char *description;
struct oval_collection *affected;
struct oval_collection *reference;
struct oval_collection *notes;
char *anyxml;
struct oval_criteria_node *criteria;
} oval_definition_t;
/* End of variable definitions
* */
/***************************************************************************/
char *oval_definition_get_id(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->id;
}
int oval_definition_get_version(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->version;
}
oval_definition_class_t oval_definition_get_class(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->class;
}
bool oval_definition_get_deprecated(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->deprecated;
}
char *oval_definition_get_title(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->title;
}
char *oval_definition_get_description(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->description;
}
struct oval_affected_iterator *oval_definition_get_affected(struct oval_definition
*definition)
{
__attribute__nonnull__(definition);
return (struct oval_affected_iterator *)
oval_collection_iterator(definition->affected);
}
struct oval_reference_iterator *oval_definition_get_references(struct oval_definition
*definition)
{
__attribute__nonnull__(definition);
return (struct oval_reference_iterator *)
oval_collection_iterator(definition->reference);
}
struct oval_string_iterator *oval_definition_get_notes(struct oval_definition *definition) {
__attribute__nonnull__(definition);
return (struct oval_string_iterator *)
oval_collection_iterator(definition->notes);
}
struct oval_criteria_node *oval_definition_get_criteria(struct oval_definition
*definition)
{
__attribute__nonnull__(definition);
return ((struct oval_definition *)definition)->criteria;
}
struct oval_definition *oval_definition_new(struct oval_definition_model *model, const char *id)
{
__attribute__nonnull__(model);
struct oval_definition *definition = (struct oval_definition *)malloc(sizeof(oval_definition_t));
definition->id = oscap_strdup(id);
definition->version = 0;
definition->class = OVAL_CLASS_UNKNOWN;
definition->deprecated = 0;
definition->title = NULL;
definition->description = NULL;
definition->affected = oval_collection_new();
definition->reference = oval_collection_new();
definition->notes = oval_collection_new();
definition->anyxml = NULL;
definition->criteria = NULL;
definition->model = model;
oval_definition_model_add_definition(model, definition);
return definition;
}
struct oval_definition *oval_definition_clone
(struct oval_definition_model *new_model, struct oval_definition *old_definition) {
__attribute__nonnull__(old_definition);
struct oval_definition *new_definition = oval_definition_model_get_definition(new_model, old_definition->id);
if (new_definition == NULL) {
new_definition = oval_definition_new(new_model, old_definition->id);
oval_definition_set_version(new_definition, old_definition->version);
oval_definition_set_class(new_definition, old_definition->class);
oval_definition_set_deprecated(new_definition, old_definition->deprecated);
oval_definition_set_title(new_definition, old_definition->title);
oval_definition_set_description(new_definition, old_definition->description);
struct oval_affected_iterator *affecteds = oval_definition_get_affected(old_definition);
while (oval_affected_iterator_has_more(affecteds)) {
struct oval_affected *old_affected = oval_affected_iterator_next(affecteds);
oval_definition_add_affected(new_definition, oval_affected_clone(new_model, old_affected));
}
oval_affected_iterator_free(affecteds);
struct oval_reference_iterator *references = oval_definition_get_references(old_definition);
while (oval_reference_iterator_has_more(references)) {
struct oval_reference *old_reference = oval_reference_iterator_next(references);
oval_definition_add_reference(new_definition, oval_reference_clone(new_model, old_reference));
}
oval_reference_iterator_free(references);
struct oval_string_iterator *notes = oval_definition_get_notes(old_definition);
while (oval_string_iterator_has_more(notes)) {
char *old_note = oval_string_iterator_next(notes);
oval_definition_add_note(new_definition, old_note);
}
oval_string_iterator_free(notes);
new_definition->anyxml = strdup(old_definition->anyxml);
oval_definition_set_criteria(new_definition, oval_criteria_node_clone(new_model, old_definition->criteria));
}
return new_definition;
}
void oval_definition_free(struct oval_definition *definition)
{
__attribute__nonnull__(definition);
if (definition->id != NULL)
free(definition->id);
if (definition->title != NULL)
free(definition->title);
if (definition->description != NULL)
free(definition->description);
if (definition->criteria != NULL)
oval_criteria_node_free(definition->criteria);
oval_collection_free_items(definition->affected, (oscap_destruct_func) oval_affected_free);
oval_collection_free_items(definition->reference, (oscap_destruct_func) oval_reference_free);
oval_collection_free_items(definition->notes, (oscap_destruct_func) free);
free(definition->anyxml);
definition->affected = NULL;
definition->criteria = NULL;
definition->description = NULL;
definition->id = NULL;
definition->reference = NULL;
definition->notes = NULL;
definition->anyxml = NULL;
definition->title = NULL;
free(definition);
}
bool oval_definition_iterator_has_more(struct oval_definition_iterator
*oc_definition)
{
return oval_collection_iterator_has_more((struct oval_iterator *)
oc_definition);
}
struct oval_definition *oval_definition_iterator_next(struct
oval_definition_iterator
*oc_definition)
{
return (struct oval_definition *)
oval_collection_iterator_next((struct oval_iterator *)
oc_definition);
}
void oval_definition_iterator_free(struct
oval_definition_iterator
*oc_definition)
{
oval_collection_iterator_free((struct oval_iterator *)
oc_definition);
}
void oval_definition_set_version(struct oval_definition *definition, int version)
{
__attribute__nonnull__(definition);
definition->version = version;
}
void oval_definition_set_class(struct oval_definition *definition, oval_definition_class_t class)
{
__attribute__nonnull__(definition);
definition->class = class;
}
void oval_definition_set_deprecated(struct oval_definition *definition, bool deprecated)
{
__attribute__nonnull__(definition);
definition->deprecated = deprecated;
}
void oval_definition_set_title(struct oval_definition *definition, char *title)
{
__attribute__nonnull__(definition);
if (definition->title != NULL)
free(definition->title);
definition->title = (title == NULL) ? NULL : oscap_strdup(title);
}
void oval_definition_set_description(struct oval_definition *definition, char *description)
{
__attribute__nonnull__(definition);
if (definition->description)
free(definition->description);
definition->description = (description == NULL) ? NULL : oscap_strdup(description);
}
void oval_definition_set_criteria(struct oval_definition *definition, struct oval_criteria_node *criteria)
{
__attribute__nonnull__(definition);
definition->criteria = criteria;
}
void oval_definition_add_affected(struct oval_definition *definition, struct oval_affected *affected)
{
__attribute__nonnull__(definition);
oval_collection_add(definition->affected, affected);
}
void oval_definition_add_reference(struct oval_definition *definition, struct oval_reference *ref)
{
__attribute__nonnull__(definition);
oval_collection_add(definition->reference, ref);
}
void oval_definition_add_note(struct oval_definition *definition, char *note) {
__attribute__nonnull__(definition);
oval_collection_add(definition->notes, note);
}
static void _oval_definition_title_consumer(char *string, void *user)
{
__attribute__nonnull__(user);
struct oval_definition *definition = (struct oval_definition *)user;
char *title = definition->title;
if (title == NULL)
title = oscap_strdup(string);
else {
int newsize = strlen(title) + strlen(string) + 1;
char *newtitle = (char *)malloc(newsize * sizeof(char));
if (newtitle == NULL)
return;
strcpy(newtitle, title);
strcat(newtitle, string);
free(title);
title = newtitle;
}
definition->title = title;
}
static void _oval_definition_description_consumer(char *string, void *user)
{
__attribute__nonnull__(user);
struct oval_definition *definition = (struct oval_definition *)user;
char *description = definition->description;
if (description == NULL)
description = oscap_strdup(string);
else {
int newsize = strlen(description) + strlen(string) + 1;
char *newdescription = (char *)malloc(newsize * sizeof(char));
if (newdescription == NULL)
return;
*newdescription = '\0';
strcpy(newdescription, description);
strcat(newdescription, string);
free(description);
description = newdescription;
}
definition->description = description;
}
static void _oval_definition_affected_consumer(struct oval_affected *affected, void *user)
{
__attribute__nonnull__(user);
struct oval_definition *definition = (struct oval_definition *)user;
oval_collection_add(definition->affected, (void *)affected);
}
static void oval_reference_consume(struct oval_reference *ref, void *def)
{
__attribute__nonnull__(def);
struct oval_definition *definition = def;
oval_collection_add(definition->reference, (void *)ref);
}
static int _oval_definition_parse_metadata(xmlTextReaderPtr reader, struct oval_parser_context *context, void *user)
{
struct oval_definition *definition = (struct oval_definition *)user;
char *tagname = (char *)xmlTextReaderLocalName(reader);
int return_code;
if ((strcmp(tagname, "title") == 0)) {
return_code = oscap_parser_text_value(reader, &_oval_definition_title_consumer, definition);
} else if (strcmp(tagname, "description") == 0) {
return_code = oscap_parser_text_value(reader, &_oval_definition_description_consumer, definition);
} else if (strcmp(tagname, "affected") == 0) {
return_code = oval_affected_parse_tag(reader, context, &_oval_definition_affected_consumer, definition);
} else if (strcmp(tagname, "oval_repository") == 0) { /* NOOP */
return_code = oval_parser_skip_tag(reader, context);
} else if (strcmp(tagname, "reference") == 0) {
return_code = oval_reference_parse_tag(reader, context, &oval_reference_consume, definition);
} else {
definition->anyxml = (char *) xmlTextReaderReadOuterXml(reader);
return_code = oval_parser_skip_tag(reader, context);
}
free(tagname);
return return_code;
}
static void _oval_definition_criteria_consumer(struct oval_criteria_node *criteria, void *user)
{
__attribute__nonnull__(user);
struct oval_definition *definition = (struct oval_definition *)user;
definition->criteria = criteria;
}
static int _oval_definition_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context, void *user)
{
struct oval_definition *definition = (struct oval_definition *)user;
char *tagname = (char *)xmlTextReaderLocalName(reader);
int return_code;
if ((strcmp(tagname, "metadata") == 0)) {
return_code = oval_parser_parse_tag(reader, context, &_oval_definition_parse_metadata, definition);
} else if ((strcmp(tagname, "criteria") == 0)) {
return_code = oval_criteria_parse_tag(reader, context, &_oval_definition_criteria_consumer, definition);
} else {
dD("Skipping tag: %s.", tagname);
return_code = oval_parser_skip_tag(reader, context);
}
free(tagname);
return return_code;
}
int oval_definition_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context, void *usr)
{
struct oval_definition_model *model = context->definition_model;
char *id = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "id");
struct oval_definition *definition = oval_definition_model_get_new_definition(model, id);
free(id);
id = NULL;
char *version = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "version");
oval_definition_set_version(definition, atoi(version));
free(version);
version = NULL;
char *class = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "class");
oval_definition_set_class(definition, oval_definition_class_enum(class));
free(class);
class = NULL;
int deprecated = oval_parser_boolean_attribute(reader, "deprecated", 0);
oval_definition_set_deprecated(definition, deprecated);
int return_code = oval_parser_parse_tag(reader, context, &_oval_definition_parse_tag, definition);
return return_code;
}
xmlNode *oval_definition_to_dom(struct oval_definition *definition, xmlDoc * doc, xmlNode * parent)
{
xmlNode *nodestr, *nodelst;
xmlDoc * docstr;
xmlNs *ns_definitions = xmlSearchNsByHref(doc, parent, OVAL_DEFINITIONS_NAMESPACE);
xmlNode *definition_node = xmlNewTextChild(parent, ns_definitions, BAD_CAST "definition", NULL);
char *id = oval_definition_get_id(definition);
xmlNewProp(definition_node, BAD_CAST "id", BAD_CAST id);
char version[10];
*version = '\0';
snprintf(version, sizeof(version), "%d", oval_definition_get_version(definition));
xmlNewProp(definition_node, BAD_CAST "version", BAD_CAST version);
oval_definition_class_t class = oval_definition_get_class(definition);
xmlNewProp(definition_node, BAD_CAST "class", BAD_CAST oval_definition_class_text(class));
bool deprecated = oval_definition_get_deprecated(definition);
if (deprecated)
xmlNewProp(definition_node, BAD_CAST "deprecated", BAD_CAST "true");
xmlNode *metadata_node = xmlNewTextChild(definition_node, ns_definitions, BAD_CAST "metadata", NULL);
char *title = oval_definition_get_title(definition);
xmlNewTextChild(metadata_node, ns_definitions, BAD_CAST "title", BAD_CAST title);
struct oval_affected_iterator *affecteds = oval_definition_get_affected(definition);
while (oval_affected_iterator_has_more(affecteds)) {
xmlNode *affected_node = xmlNewTextChild(metadata_node, ns_definitions, BAD_CAST "affected", NULL);
struct oval_affected *affected = oval_affected_iterator_next(affecteds);
oval_affected_family_t family = oval_affected_get_family(affected);
xmlNewProp(affected_node, BAD_CAST "family", BAD_CAST oval_affected_family_get_text(family));
struct oval_string_iterator *platforms = oval_affected_get_platforms(affected);
while (oval_string_iterator_has_more(platforms)) {
char *platform = oval_string_iterator_next(platforms);
xmlNewTextChild(affected_node, ns_definitions, BAD_CAST "platform", BAD_CAST platform);
}
oval_string_iterator_free(platforms);
struct oval_string_iterator *products = oval_affected_get_products(affected);
while (oval_string_iterator_has_more(products)) {
char *product = oval_string_iterator_next(products);
xmlNewTextChild(affected_node, ns_definitions, BAD_CAST "product", BAD_CAST product);
}
oval_string_iterator_free(products);
}
oval_affected_iterator_free(affecteds);
struct oval_reference_iterator *references = oval_definition_get_references(definition);
while (oval_reference_iterator_has_more(references)) {
struct oval_reference *ref = oval_reference_iterator_next(references);
xmlNode *referenceNode = xmlNewTextChild(metadata_node, ns_definitions, BAD_CAST "reference", NULL);
char *source = oval_reference_get_source(ref);
char *ref_id = oval_reference_get_id(ref);
char *ref_url = oval_reference_get_url(ref);
xmlNewProp(referenceNode, BAD_CAST "source", BAD_CAST source);
xmlNewProp(referenceNode, BAD_CAST "ref_id", BAD_CAST ref_id);
if (ref_url)
xmlNewProp(referenceNode, BAD_CAST "ref_url", BAD_CAST ref_url);
}
oval_reference_iterator_free(references);
char *description = oval_definition_get_description(definition);
xmlNewTextChild(metadata_node, ns_definitions, BAD_CAST "description", BAD_CAST description);
struct oval_string_iterator *notes = oval_definition_get_notes(definition);
if (oval_string_iterator_has_more(notes)) {
xmlNode *notes_node = xmlNewTextChild(definition_node, ns_definitions, BAD_CAST "notes", NULL);
while (oval_string_iterator_has_more(notes)) {
char *note = oval_string_iterator_next(notes);
xmlNewTextChild(notes_node, ns_definitions, BAD_CAST "note", BAD_CAST note);
}
}
oval_string_iterator_free(notes);
docstr = xmlReadDoc(BAD_CAST definition->anyxml, NULL, NULL, 0);
nodestr = xmlDocGetRootElement(docstr);
nodelst = xmlDocCopyNode(nodestr, doc, 1);
xmlAddChildList(metadata_node, nodelst);
xmlFreeDoc(docstr);
struct oval_criteria_node *criteria = oval_definition_get_criteria(definition);
if (criteria)
oval_criteria_node_to_dom(criteria, doc, definition_node);
return definition_node;
}
const char * oval_definition_model_supported(void)
{
return OVAL_SUPPORTED;
}