/*! \file cve_priv.c
* \brief Common Vulnerability and Exposure dictionary
*
* See details at:
* http://cve.mitre.org/
* http://nvd.nist.gov/download.cfm
*
*/
/*
* 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:
* Maros Barabas <mbarabas@redhat.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <libxml/xmlreader.h>
#include <libxml/xmlwriter.h>
#include "public/cve_nvd.h"
#include "cve_priv.h"
#include "common/list.h"
#include "common/_error.h"
#include "common/xmltext_priv.h"
#include "common/elements.h"
#include "CPE/cpelang_priv.h"
#include "CVSS/cvss_priv.h"
#include "CVSS/public/cvss_score.h"
#include "source/oscap_source_priv.h"
#include "source/public/oscap_source.h"
/***************************************************************************/
/* Variable definitions
* */
/**
* @struct cve_list
* cve_list is the top level element of the CVE List provided by MITRE.
* It represents holds all CVE Items.
*/
struct cve_model {
char *pub_date;
char *nvd_xml_version;
struct oscap_list *entries; /* 1-n */
};
OSCAP_IGETINS_GEN(cve_entry, cve_model, entries, entry)
OSCAP_ITERATOR_REMOVE_F(cve_entry)
OSCAP_ACCESSOR_STRING(cve_model, nvd_xml_version)
OSCAP_ACCESSOR_STRING(cve_model, pub_date)
/*
*/
struct cve_reference {
char *value; /* summary */
char *href; /* href */
char *type; /* reference type */
char *source; /* source */
char *lang;
};
OSCAP_ACCESSOR_STRING(cve_reference, value)
OSCAP_ACCESSOR_STRING(cve_reference, href)
OSCAP_ACCESSOR_STRING(cve_reference, type)
OSCAP_ACCESSOR_STRING(cve_reference, source)
OSCAP_ACCESSOR_STRING(cve_reference, lang)
/*
*/
struct cve_summary {
char *summary;
};
OSCAP_ACCESSOR_STRING(cve_summary, summary)
/*
*/
struct cve_product {
char *value;
};
OSCAP_ACCESSOR_STRING(cve_product, value)
/*
*/
struct cwe_entry {
char *value;
};
OSCAP_ACCESSOR_STRING(cwe_entry, value)
/*
*/
struct cve_configuration {
char *id;
struct cpe_testexpr *expr; /* [cpe:lang] expression (0-1) */
};
OSCAP_ACCESSOR_STRING(cve_configuration, id)
/*
*/
struct cve_entry {
char *id;
char *cve_id;
struct oscap_list *products; /* vulnerable SW list */
char *published; /* published datetime */
char *modified; /* last modified datetime */
struct cvss_impact *cvss; /* [cvss] score definition */
char *sec_protection;
char *cwe; /* cwe (0-1) */
struct oscap_list *summaries; /* summaries */
struct oscap_list *references; /* cve references */
struct oscap_list *configurations; /* cve vulnerability confs */
};
OSCAP_ACCESSOR_STRING(cve_entry, id)
OSCAP_ACCESSOR_STRING(cve_entry, published)
OSCAP_ACCESSOR_STRING(cve_entry, modified)
OSCAP_ACCESSOR_STRING(cve_entry, sec_protection)
OSCAP_ACCESSOR_STRING(cve_entry, cwe)
OSCAP_IGETINS_GEN(cve_product, cve_entry, products, product)
OSCAP_IGETINS_GEN(cve_reference, cve_entry, references, reference)
OSCAP_IGETINS_GEN(cve_summary, cve_entry, summaries, summary)
OSCAP_IGETINS_GEN(cve_configuration, cve_entry, configurations, configuration)
OSCAP_ITERATOR_REMOVE_F(cve_product)
OSCAP_ITERATOR_REMOVE_F(cve_reference)
OSCAP_ITERATOR_REMOVE_F(cve_summary)
OSCAP_ITERATOR_REMOVE_F(cve_configuration)
/* End of variable definitions
* */
/***************************************************************************/
/***************************************************************************/
/* XML string variables definitions
* */
#define TAG_NVD_STR BAD_CAST "nvd"
#define ATTR_XML_LANG_STR BAD_CAST "xml:lang"
/* Vulnerability entry info */
#define TAG_CVE_STR BAD_CAST "entry"
#define TAG_DISCOVERED_DATETIME_STR BAD_CAST "discovered-datetime"
#define TAG_PUBLISHED_DATETIME_STR BAD_CAST "published-datetime"
#define TAG_LAST_MODIFIED_DATETIME_STR BAD_CAST "last-modified-datetime"
#define TAG_CWE_STR BAD_CAST "cwe"
#define TAG_SUMMARY_STR BAD_CAST "summary"
#define TAG_VULNERABLE_CONFIGURATION_STR BAD_CAST "vulnerable-configuration"
#define TAG_VULNERABLE_SOFTWARE_LIST_STR BAD_CAST "vulnerable-software-list"
#define TAG_SECURITY_PROTECTION_STR BAD_CAST "security-protection"
#define TAG_PRODUCT_STR BAD_CAST "product"
#define ATTR_CVE_ID_STR BAD_CAST "id"
#define ATTR_VULNERABLE_CONFIGURATION_ID_STR BAD_CAST "id"
#define TAG_CVE_ID_STR BAD_CAST "cve-id"
#define TAG_SOURCE_STR BAD_CAST "source"
/* CVSS */
#define TAG_CVSS_STR BAD_CAST "cvss"
/* CWE */
#define TAG_CWE_STR BAD_CAST "cwe"
#define ATTR_CWEID_STR BAD_CAST "id"
/* Vulnerability reference info */
#define TAG_REFERENCES_STR BAD_CAST "references"
#define TAG_REFERENCE_STR BAD_CAST "reference"
#define TAG_REFERENCE_SOURCE_STR BAD_CAST "source"
#define ATTR_REFERENCE_TYPE_STR BAD_CAST "reference_type"
#define ATTR_REFERENCE_HREF_STR BAD_CAST "href"
#define NS_VULN_STR BAD_CAST "vuln"
#define TAG_ASSESSMENT_CHECK_STR BAD_CAST "assessment_check"
#define TAG_SCANNER_STR BAD_CAST "scanner"
#define TAG_DEFINITION_STR BAD_CAST "definition"
/* namespaces */
#define CVE_NS BAD_CAST "http://scap.nist.gov/schema/vulnerability/0.4"
#define FEED_NS BAD_CAST "http://scap.nist.gov/schema/feed/vulnerability/2.0"
#define FEED_NS_LOCATION BAD_CAST "http://scap.nist.gov/schema/feed/vulnerability/2.0 http://nvd.nist.gov/schema/nvd-cve-feed_2.0.xsd"
/* End of XML string variables definitions
* */
/***************************************************************************/
const struct cvss_impact *cve_entry_get_cvss(const struct cve_entry *item)
{
if (item == NULL)
return NULL;
return item->cvss;
}
const struct cpe_testexpr *cve_configuration_get_expr(const struct cve_configuration *item)
{
if (item == NULL)
return NULL;
return item->expr;
}
/***************************************************************************/
/* Constructors of CVE structures cve_*<structure>*_new()
* More info in representive header file.
* returns the type of <structure>
*/
struct cve_entry *cve_entry_new()
{
struct cve_entry *ret;
ret = malloc(sizeof(struct cve_entry));
if (ret == NULL)
return NULL;
ret->products = oscap_list_new();
ret->references = oscap_list_new();
ret->summaries = oscap_list_new();
ret->configurations = oscap_list_new();
ret->id = NULL;
ret->cve_id = NULL;
ret->published = NULL;
ret->modified = NULL;
ret->cvss = NULL;
ret->cwe = NULL;
ret->sec_protection = NULL;
return ret;
}
struct cve_entry * cve_entry_clone(struct cve_entry * old_entry)
{
struct cve_entry * new_entry = cve_entry_new();
new_entry->id = oscap_strdup(old_entry->id);
new_entry->cve_id = oscap_strdup(old_entry->cve_id);
new_entry->published = oscap_strdup(old_entry->published);
new_entry->modified = oscap_strdup(old_entry->modified);
new_entry->cwe = oscap_strdup(old_entry->cwe);
new_entry->sec_protection = oscap_strdup(old_entry->sec_protection);
new_entry->cvss = cvss_impact_clone(old_entry->cvss);
new_entry->products = oscap_list_clone(old_entry->products, (oscap_clone_func) cve_product_clone);
new_entry->references = oscap_list_clone(old_entry->references, (oscap_clone_func) cve_reference_clone);
new_entry->summaries = oscap_list_clone(old_entry->summaries, (oscap_clone_func) cve_summary_clone);
new_entry->configurations = oscap_list_clone(old_entry->configurations, (oscap_clone_func) cve_configuration_clone);
return new_entry;
}
struct cve_configuration *cve_configuration_new()
{
struct cve_configuration *ret;
ret = malloc(sizeof(struct cve_configuration));
if (ret == NULL)
return NULL;
ret->id = NULL;
ret->expr = cpe_testexpr_new();
return ret;
}
struct cve_configuration * cve_configuration_clone(struct cve_configuration * old_conf)
{
struct cve_configuration * new_conf = cve_configuration_new();
new_conf->id = oscap_strdup(old_conf->id);
new_conf->expr = cpe_testexpr_clone(old_conf->expr);
return new_conf;
}
struct cwe_entry *cwe_entry_new()
{
struct cwe_entry *ret;
ret = malloc(sizeof(struct cwe_entry));
if (ret == NULL)
return NULL;
ret->value = NULL;
return ret;
}
struct cwe_entry * cwe_entry_clone(struct cwe_entry * old_entry)
{
struct cwe_entry * new_entry = cwe_entry_new();
new_entry->value = oscap_strdup(old_entry->value);
return new_entry;
}
struct cve_product *cve_product_new()
{
struct cve_product *ret;
ret = malloc(sizeof(struct cve_product));
if (ret == NULL)
return NULL;
ret->value = NULL;
return ret;
}
struct cve_product * cve_product_clone(struct cve_product * old_product)
{
struct cve_product * product = cve_product_new();
product->value = oscap_strdup(old_product->value);
return product;
}
struct cve_summary *cve_summary_new()
{
struct cve_summary *ret;
ret = malloc(sizeof(struct cve_summary));
if (ret == NULL)
return NULL;
ret->summary = NULL;
return ret;
}
struct cve_summary * cve_summary_clone(struct cve_summary * old_sum)
{
struct cve_summary * sum = cve_summary_new();
sum->summary = oscap_strdup(old_sum->summary);
return sum;
}
struct cve_reference *cve_reference_new()
{
struct cve_reference *ret;
ret = calloc(1, sizeof(struct cve_reference));
if (ret == NULL)
return NULL;
return ret;
}
struct cve_reference * cve_reference_clone(struct cve_reference * old_ref)
{
struct cve_reference * ref = cve_reference_new();
ref->value = oscap_strdup(old_ref->value);
ref->href = oscap_strdup(old_ref->href);
ref->type = oscap_strdup(old_ref->type);
ref->source = oscap_strdup(old_ref->source);
ref->lang = oscap_strdup(old_ref->lang);
return ref;
}
struct cve_model *cve_model_new()
{
struct cve_model *ret;
ret = malloc(sizeof(struct cve_model));
if (ret == NULL)
return NULL;
memset(ret, 0, sizeof(struct cve_model));
ret->nvd_xml_version = NULL;
ret->entries = oscap_list_new();
return ret;
}
struct cve_model * cve_model_clone(struct cve_model * old_model)
{
struct cve_model * new_model = cve_model_new();
new_model->entries = oscap_list_clone(old_model->entries, (oscap_clone_func) cve_entry_clone);
return new_model;
}
/* End of CVE structures' contructors
* */
/***************************************************************************/
/***************************************************************************/
/* Private parsing functions cve_*<structure>*_parse( xmlTextReaderPtr )
* More info in representive header file.
* returns the type of <structure>
*/
struct cve_model *cve_model_parse_xml(const char *file)
{
__attribute__nonnull__(file);
struct cve_model *ret = NULL;
int rc;
struct oscap_source *source = oscap_source_new_from_file(file);
xmlTextReader *reader = oscap_source_get_xmlTextReader(source);
if (!reader) {
oscap_source_free(source);
return NULL;
}
rc = xmlTextReaderNextNode(reader);
if (rc == -1) {
xmlFreeTextReader(reader);
oscap_source_free(source);
return NULL;
}
ret = cve_model_parse(reader);
xmlFreeTextReader(reader);
oscap_source_free(source);
return ret;
}
struct cve_model *cve_model_parse(xmlTextReaderPtr reader)
{
__attribute__nonnull__(reader);
struct cve_model *ret = NULL;
struct cve_entry *entry = NULL;
if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_NVD_STR) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
ret = cve_model_new();
if (ret == NULL)
return NULL;
ret->nvd_xml_version = (char*) xmlTextReaderGetAttribute(reader, BAD_CAST "nvd_xml_version");
ret->pub_date = (char*) xmlTextReaderGetAttribute(reader, BAD_CAST "pub_date");
/* skip nodes until new element */
xmlTextReaderNextElement(reader);
/* CVE-specification: entry */
while (xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CVE_STR) == 0) {
entry = cve_entry_parse(reader);
if (entry)
oscap_list_add(ret->entries, entry);
xmlTextReaderNextElement(reader);
}
}
return ret;
}
struct cve_entry *cve_entry_parse(xmlTextReaderPtr reader)
{
__attribute__nonnull__(reader);
struct cve_entry *ret;
struct cve_product *product;
struct cve_reference *refer;
struct cve_summary *summary;
struct cve_configuration *conf;
/* allocate platform structure here */
ret = cve_entry_new();
if (ret == NULL)
return NULL;
/* parse platform attributes here */
ret->id = (char *)xmlTextReaderGetAttribute(reader, ATTR_CVE_ID_STR);
if (ret->id == NULL) {
cve_entry_free(ret);
return NULL; /* if there is no "id" in entry element, return NULL */
}
/* If <empty /> then return, because there is no child element */
if (xmlTextReaderIsEmptyElement(reader))
return ret;
/* skip from <entry> node to next one */
xmlTextReaderNextNode(reader);
/* while we have element that is not "entry", it is inside this element, otherwise it's ended
* element </entry> and we should end. If there is no one from "if" statement cases, we are parsing
* attribute or text ,.. and we can continue to next node.
* */
while (xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CVE_STR) != 0) {
if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) {
xmlTextReaderNextNode(reader);
continue;
}
if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_VULNERABLE_CONFIGURATION_STR)) {
conf = malloc(sizeof(struct cve_configuration));
conf->id = (char *)xmlTextReaderGetAttribute(reader, ATTR_CVE_ID_STR);
xmlTextReaderNextElement(reader);
conf->expr = cpe_testexpr_parse(reader);
oscap_list_add(ret->configurations, conf);
continue;
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_VULNERABLE_SOFTWARE_LIST_STR)) {
/* this will be list of products */
xmlTextReaderNextNode(reader);
while (xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_VULNERABLE_SOFTWARE_LIST_STR) != 0) {
if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_PRODUCT_STR) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
product = cve_product_new();
if (product) {
product->value = oscap_element_string_copy(reader);
oscap_list_add(ret->products, product);
}
}
xmlTextReaderNextNode(reader);
}
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CVE_ID_STR)) {
ret->cve_id = oscap_element_string_copy(reader);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_DISCOVERED_DATETIME_STR)) {
/* Skip the discovered-datetime in the XML file */
xmlTextReaderNextNode(reader);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_PUBLISHED_DATETIME_STR)) {
ret->published = oscap_element_string_copy(reader);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_LAST_MODIFIED_DATETIME_STR)) {
ret->modified = oscap_element_string_copy(reader);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CVSS_STR)) {
if (ret->cvss == NULL) ret->cvss = cvss_impact_new_from_xml(reader);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_SECURITY_PROTECTION_STR)) {
ret->sec_protection = oscap_element_string_copy(reader);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CWE_STR)) {
ret->cwe = (char *)xmlTextReaderGetAttribute(reader, ATTR_CVE_ID_STR);
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_REFERENCES_STR)) {
refer = cve_reference_new();
if (refer) {
refer->type = (char *)xmlTextReaderGetAttribute(reader, ATTR_REFERENCE_TYPE_STR);
refer->lang = (char *)xmlTextReaderGetAttribute(reader, BAD_CAST "xml:lang");
xmlTextReaderNextNode(reader);
while (xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_REFERENCES_STR) != 0) {
if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_SOURCE_STR) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
refer->source = oscap_element_string_copy(reader);
} else
if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_REFERENCE_STR) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
refer->href =
(char *)xmlTextReaderGetAttribute(reader, ATTR_REFERENCE_HREF_STR);
refer->value = oscap_element_string_copy(reader);
}
xmlTextReaderNextNode(reader);
}
oscap_list_add(ret->references, refer);
}
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_SUMMARY_STR)) {
summary = cve_summary_new();
if (summary) {
summary->summary = oscap_element_string_copy(reader);
oscap_list_add(ret->summaries, summary);
}
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_ASSESSMENT_CHECK_STR)) {
/* Skip the assessment_check section in the XML file */
while (xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) {
xmlTextReaderNextNode(reader);
}
} else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_SCANNER_STR)) {
/* Skip the scanner section in the XML file */
xmlTextReaderNextNode(reader);
while (xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_SCANNER_STR) != 0) {
if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_DEFINITION_STR) &&
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
while (xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) {
xmlTextReaderNextNode(reader);
}
}
xmlTextReaderNextNode(reader);
}
} else {
oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unknown XML element in CVE entry: %s",
(const char*) xmlTextReaderConstLocalName(reader));
cve_entry_free(ret);
return NULL;
}
/* get the next node */
xmlTextReaderNextNode(reader);
}
return ret;
}
/***************************************************************************/
/* Private exporting functions cve_*<structure>*_export( xmlTextWriterPtr )
* More info in representive header file.
* returns the type of <structure>
*/
void cve_model_export_xml(struct cve_model *cve, const char *file)
{
__attribute__nonnull__(cve);
__attribute__nonnull__(file);
/* TODO: ad macro to check return value from xmlTextWriter* functions */
xmlTextWriterPtr writer;
writer = xmlNewTextWriterFilename(file, 0);
if (writer == NULL) {
oscap_setxmlerr(xmlGetLastError());
return;
}
/* Set properties of writer TODO: make public function to edit this ?? */
xmlTextWriterSetIndent(writer, 1);
xmlTextWriterSetIndentString(writer, BAD_CAST " ");
xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
cve_export(cve, writer);
xmlTextWriterEndDocument(writer);
xmlFreeTextWriter(writer);
if (xmlGetLastError() != NULL)
oscap_setxmlerr(xmlGetLastError());
}
void cve_export(const struct cve_model *cve, xmlTextWriterPtr writer)
{
__attribute__nonnull__(cve);
__attribute__nonnull__(writer);
xmlTextWriterStartElementNS(writer, NULL, TAG_NVD_STR, FEED_NS);
xmlTextWriterWriteAttribute(writer, BAD_CAST "nvd_xml_version", BAD_CAST cve->nvd_xml_version);
if (cve->pub_date) {
xmlTextWriterWriteAttribute(writer, BAD_CAST "pub_date", BAD_CAST cve->pub_date);
}
xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns:xsi", BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
xmlTextWriterWriteAttribute(writer, BAD_CAST "xsi:schemaLocation", FEED_NS_LOCATION);
/* dump its contents to XML tree */
OSCAP_FOREACH(cve_entry, e, cve_model_get_entries(cve), cve_entry_export(e, writer);)
xmlTextWriterEndElement(writer);
if (xmlGetLastError() != NULL)
oscap_setxmlerr(xmlGetLastError());
}
void cve_reference_export(const struct cve_reference *refer, xmlTextWriterPtr writer)
{
__attribute__nonnull__(refer);
__attribute__nonnull__(writer);
/* references */
xmlTextWriterStartElementNS(writer, NULL, TAG_REFERENCES_STR, CVE_NS);
if ((refer->type) != NULL)
xmlTextWriterWriteAttribute(writer, ATTR_REFERENCE_TYPE_STR, BAD_CAST refer->type);
if (refer->lang)
xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang", BAD_CAST refer->lang);
if ((refer->source) != NULL) {
xmlTextWriterStartElementNS(writer, NULL, TAG_SOURCE_STR, NULL);
xmlTextWriterWriteString(writer, BAD_CAST refer->source);
xmlTextWriterEndElement(writer);
}
/* reference */
xmlTextWriterStartElementNS(writer, NULL, TAG_REFERENCE_STR, NULL);
if (refer->lang) xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang", BAD_CAST refer->lang);
if ((refer->href) != NULL)
xmlTextWriterWriteAttribute(writer, ATTR_REFERENCE_HREF_STR, BAD_CAST refer->href);
xmlTextWriterWriteString(writer, BAD_CAST refer->value);
/* reference */
xmlTextWriterEndElement(writer);
/* references */
xmlTextWriterEndElement(writer);
if (xmlGetLastError() != NULL)
oscap_setxmlerr(xmlGetLastError());
}
void cve_summary_export(const struct cve_summary *sum, xmlTextWriterPtr writer)
{
__attribute__nonnull__(sum);
__attribute__nonnull__(writer);
xmlTextWriterStartElementNS(writer, NULL, TAG_SUMMARY_STR, CVE_NS);
xmlTextWriterWriteString(writer, BAD_CAST sum->summary);
/*</summary> */
xmlTextWriterEndElement(writer);
if (xmlGetLastError() != NULL)
oscap_setxmlerr(xmlGetLastError());
}
void cve_entry_export(const struct cve_entry *entry, xmlTextWriterPtr writer)
{
__attribute__nonnull__(entry);
__attribute__nonnull__(writer);
xmlTextWriterStartElementNS(writer, NULL, TAG_CVE_STR, NULL);
if ((entry->id) != NULL)
xmlTextWriterWriteAttribute(writer, ATTR_CVE_ID_STR, BAD_CAST entry->id);
OSCAP_FOREACH(cve_configuration, conf, cve_entry_get_configurations(entry),
/* dump its contents to XML tree */
xmlTextWriterStartElementNS(writer, NULL, TAG_VULNERABLE_CONFIGURATION_STR, CVE_NS);
xmlTextWriterWriteAttribute(writer, ATTR_VULNERABLE_CONFIGURATION_ID_STR, BAD_CAST conf->id);
cpe_testexpr_export(conf->expr, writer); xmlTextWriterEndElement(writer);)
if (oscap_list_get_itemcount(entry->products) != 0) {
/* TODO: make vulnerable-software-list element with namespace */
xmlTextWriterStartElementNS(writer, NULL, TAG_VULNERABLE_SOFTWARE_LIST_STR, CVE_NS);
OSCAP_FOREACH(cve_product, product, cve_entry_get_products(entry),
/* dump its contents to XML tree */
xmlTextWriterStartElementNS(writer, NULL, TAG_PRODUCT_STR, NULL);
xmlTextWriterWriteString(writer, BAD_CAST product->value);
xmlTextWriterEndElement(writer);)
/*</vulnerable-software-list> */
xmlTextWriterEndElement(writer);
}
if ((entry->cve_id) != NULL)
xmlTextWriterWriteElementNS(writer, NULL, TAG_CVE_ID_STR, CVE_NS, BAD_CAST entry->cve_id);
if ((entry->published) != NULL)
xmlTextWriterWriteElementNS(writer, NULL, TAG_PUBLISHED_DATETIME_STR, CVE_NS, BAD_CAST entry->published);
if ((entry->modified) != NULL)
xmlTextWriterWriteElementNS(writer, NULL, TAG_LAST_MODIFIED_DATETIME_STR, CVE_NS, BAD_CAST entry->modified);
if ((entry->cvss) != NULL) {
cvss_impact_export(entry->cvss, writer);
}
if ((entry->sec_protection) != NULL)
xmlTextWriterWriteElementNS(writer, NULL, TAG_SECURITY_PROTECTION_STR, CVE_NS, BAD_CAST entry->sec_protection);
if ((entry->cwe) != NULL) {
xmlTextWriterStartElementNS(writer, NULL, TAG_CWE_STR, CVE_NS);
xmlTextWriterWriteAttribute(writer, ATTR_CWEID_STR, BAD_CAST entry->cwe);
xmlTextWriterEndElement(writer);
}
if ((entry->references) != NULL) {
/* TODO: make references element with namespace */
OSCAP_FOREACH(cve_reference, refer, cve_entry_get_references(entry),
/* dump its contents to XML tree */
cve_reference_export(refer, writer);)
}
if ((entry->references) != NULL) {
/* TODO: make references element with namespace */
OSCAP_FOREACH(cve_summary, sum, cve_entry_get_summaries(entry),
/* dump its contents to XML tree */
cve_summary_export(sum, writer);)
}
/* </entry> */
xmlTextWriterEndElement(writer);
if (xmlGetLastError() != NULL)
oscap_setxmlerr(xmlGetLastError());
}
/***************************************************************************/
/* Free functions - all will free their subtree so use carefuly !
*/
void cve_summary_free(struct cve_summary *summary)
{
if (summary == NULL)
return;
xmlFree(summary->summary);
free(summary);
}
void cve_model_free(struct cve_model *cve_model)
{
if (cve_model == NULL)
return;
oscap_list_free(cve_model->entries, (oscap_destruct_func) cve_entry_free);
free(cve_model->pub_date);
free(cve_model->nvd_xml_version);
free(cve_model);
}
void cve_configuration_free(struct cve_configuration *conf)
{
if (conf == NULL)
return;
xmlFree(conf->id);
cpe_testexpr_free(conf->expr);
free(conf);
}
void cve_product_free(struct cve_product *product)
{
if (product == NULL)
return;
xmlFree(product->value);
free(product);
}
void cve_reference_free(struct cve_reference *ref)
{
if (ref == NULL)
return;
xmlFree(ref->value);
xmlFree(ref->href);
xmlFree(ref->type);
xmlFree(ref->source);
xmlFree(ref->lang);
free(ref);
}
void cwe_entry_free(struct cwe_entry *entry)
{
if (entry == NULL)
return;
xmlFree(entry->value);
free(entry);
}
void cve_entry_free(struct cve_entry *entry)
{
if (entry == NULL)
return;
xmlFree(entry->id);
xmlFree(entry->cve_id);
xmlFree(entry->published);
xmlFree(entry->modified);
xmlFree(entry->sec_protection);
xmlFree(entry->cwe);
cvss_impact_free(entry->cvss);
oscap_list_free(entry->products, (oscap_destruct_func) cve_product_free);
oscap_list_free(entry->references, (oscap_destruct_func) cve_reference_free);
oscap_list_free(entry->summaries, (oscap_destruct_func) cve_summary_free);
oscap_list_free(entry->configurations, (oscap_destruct_func) cve_configuration_free);
free(entry);
}
/* End of free functions
* */
/***************************************************************************/