/**
* @file oval_sysInfo.c
* \brief Open Vulnerability and Assessment Language
*
* See more details at http://oval.mitre.org/
*/
/*
* Copyright 2009--2013 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_system_characteristics_impl.h"
#include "adt/oval_collection_impl.h"
#include "oval_agent_api_impl.h"
#include "common/util.h"
#include "common/debug_priv.h"
#include "common/elements.h"
typedef struct oval_sysinfo {
struct oval_syschar_model *model;
char *osName;
char *osVersion;
char *osArchitecture;
char *primaryHostName;
struct oval_collection *interfaces;
char *anyxml;
} oval_sysinfo_t;
struct oval_sysinfo *oval_sysinfo_new(struct oval_syschar_model *model)
{
oval_sysinfo_t *sysinfo = (oval_sysinfo_t *) malloc(sizeof(oval_sysinfo_t));
if (sysinfo == NULL)
return NULL;
sysinfo->osArchitecture = NULL;
sysinfo->osName = NULL;
sysinfo->osVersion = NULL;
sysinfo->primaryHostName = NULL;
sysinfo->interfaces = oval_collection_new();
sysinfo->model = model;
sysinfo->anyxml = NULL;
return sysinfo;
}
struct oval_sysinfo *oval_sysinfo_clone(struct oval_syschar_model *new_model, struct oval_sysinfo *old_sysinfo)
{
struct oval_sysinfo *new_sysinfo = oval_sysinfo_new(new_model);
struct oval_sysint_iterator *interfaces = oval_sysinfo_get_interfaces(old_sysinfo);
while (oval_sysint_iterator_has_more(interfaces)) {
struct oval_sysint *interface = oval_sysint_iterator_next(interfaces);
oval_sysinfo_add_interface(new_sysinfo, interface);
}
oval_sysint_iterator_free(interfaces);
char *os_architecture = oval_sysinfo_get_os_architecture(old_sysinfo);
if (os_architecture)
oval_sysinfo_set_os_architecture(new_sysinfo, os_architecture);
char *os_name = oval_sysinfo_get_os_name(old_sysinfo);
if (os_name)
oval_sysinfo_set_os_name(new_sysinfo, os_name);
char *os_version = oval_sysinfo_get_os_version(old_sysinfo);
if (os_version)
oval_sysinfo_set_os_version(new_sysinfo, os_version);
char *host_name = oval_sysinfo_get_primary_host_name(old_sysinfo);
if (host_name)
oval_sysinfo_set_primary_host_name(new_sysinfo, host_name);
if (old_sysinfo->anyxml)
new_sysinfo->anyxml = oscap_strdup(old_sysinfo->anyxml);
return new_sysinfo;
}
void oval_sysinfo_free(struct oval_sysinfo *sysinfo)
{
if (sysinfo) {
if (sysinfo->osArchitecture)
free(sysinfo->osArchitecture);
if (sysinfo->osName)
free(sysinfo->osName);
if (sysinfo->osVersion)
free(sysinfo->osVersion);
if (sysinfo->primaryHostName)
free(sysinfo->primaryHostName);
if (sysinfo->anyxml)
free(sysinfo->anyxml);
oval_collection_free_items(sysinfo->interfaces, (oscap_destruct_func) oval_sysint_free);
sysinfo->interfaces = NULL;
sysinfo->osArchitecture = NULL;
sysinfo->osName = NULL;
sysinfo->osVersion = NULL;
sysinfo->primaryHostName = NULL;
sysinfo->anyxml = NULL;
free(sysinfo);
}
}
bool oval_sysinfo_iterator_has_more(struct oval_sysinfo_iterator *oc_sysinfo)
{
return oval_collection_iterator_has_more((struct oval_iterator *)
oc_sysinfo);
}
struct oval_sysinfo *oval_sysinfo_iterator_next(struct oval_sysinfo_iterator
*oc_sysinfo)
{
return (struct oval_sysinfo *)
oval_collection_iterator_next((struct oval_iterator *)oc_sysinfo);
}
void oval_sysinfo_iterator_free(struct oval_sysinfo_iterator *oc_sysinfo)
{
oval_collection_iterator_free((struct oval_iterator *)oc_sysinfo);
}
char *oval_sysinfo_get_os_name(struct oval_sysinfo *sysinfo)
{
__attribute__nonnull__(sysinfo);
return sysinfo->osName;
}
void oval_sysinfo_set_os_name(struct oval_sysinfo *sysinfo, char *osName)
{
__attribute__nonnull__(sysinfo);
if (sysinfo->osName != NULL)
free(sysinfo->osName);
sysinfo->osName = oscap_strdup(osName);
}
char *oval_sysinfo_get_os_version(struct oval_sysinfo *sysinfo)
{
return sysinfo->osVersion;
}
void oval_sysinfo_set_os_version(struct oval_sysinfo *sysinfo, char *osVersion)
{
__attribute__nonnull__(sysinfo);
if (sysinfo->osVersion != NULL)
free(sysinfo->osVersion);
sysinfo->osVersion = oscap_strdup(osVersion);
}
char *oval_sysinfo_get_os_architecture(struct oval_sysinfo *sysinfo)
{
return sysinfo->osArchitecture;
}
void oval_sysinfo_set_os_architecture(struct oval_sysinfo *sysinfo, char *osArchitecture)
{
__attribute__nonnull__(sysinfo);
if (sysinfo->osArchitecture != NULL)
free(sysinfo->osArchitecture);
sysinfo->osArchitecture = oscap_strdup(osArchitecture);
}
char *oval_sysinfo_get_primary_host_name(struct oval_sysinfo *sysinfo)
{
__attribute__nonnull__(sysinfo);
return sysinfo->primaryHostName;
}
void oval_sysinfo_set_primary_host_name(struct oval_sysinfo *sysinfo, char *primaryHostName)
{
__attribute__nonnull__(sysinfo);
if (sysinfo->primaryHostName != NULL)
free(sysinfo->primaryHostName);
sysinfo->primaryHostName = oscap_strdup(primaryHostName);
}
struct oval_sysint_iterator *oval_sysinfo_get_interfaces(struct oval_sysinfo
*sysinfo)
{
__attribute__nonnull__(sysinfo);
return (struct oval_sysint_iterator *)oval_collection_iterator(sysinfo->interfaces);
}
void oval_sysinfo_add_interface(struct oval_sysinfo *sysinfo, struct oval_sysint *interface)
{
__attribute__nonnull__(sysinfo);
oval_collection_add(sysinfo->interfaces, oval_sysint_clone(sysinfo->model, interface));
}
static void _oval_sysinfo_parse_tag_consume_os_name(char *text, void *sysinfo)
{
oval_sysinfo_set_os_name(sysinfo, text);
}
static void _oval_sysinfo_parse_tag_consume_os_version(char *text, void *sysinfo)
{
oval_sysinfo_set_os_version(sysinfo, text);
}
static void _oval_sysinfo_parse_tag_consume_os_architecture(char *text, void *sysinfo)
{
oval_sysinfo_set_os_architecture(sysinfo, text);
}
static void _oval_sysinfo_parse_tag_consume_primary_host_name(char *text, void *sysinfo)
{
oval_sysinfo_set_primary_host_name(sysinfo, text);
}
static void _oval_sysinfo_parse_tag_consume_int(struct oval_sysint *sysint, void *sysinfo)
{
oval_sysinfo_add_interface(sysinfo, sysint);
oval_sysint_free(sysint);
}
static int _oval_sysinfo_parse_tag_parse_tag(xmlTextReaderPtr reader,
struct oval_parser_context *context, void *sysinfo)
{
return oval_sysint_parse_tag(reader, context, &_oval_sysinfo_parse_tag_consume_int, sysinfo);
}
static int _oval_sysinfo_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context, void *user)
{
struct oval_sysinfo *sysinfo = (struct oval_sysinfo *)user;
char *tagname = (char *)xmlTextReaderLocalName(reader);
char *namespace = (char *)xmlTextReaderNamespaceUri(reader);
int return_code = 0;
int is_ovalsys = strcmp((const char *)OVAL_SYSCHAR_NAMESPACE, namespace) == 0;
if (is_ovalsys && (strcmp(tagname, "os_name") == 0)) {
return_code = oscap_parser_text_value(reader, &_oval_sysinfo_parse_tag_consume_os_name, sysinfo);
} else if (is_ovalsys && (strcmp(tagname, "os_version") == 0)) {
return_code = oscap_parser_text_value(reader, &_oval_sysinfo_parse_tag_consume_os_version, sysinfo);
} else if (is_ovalsys && (strcmp(tagname, "architecture") == 0)) {
return_code = oscap_parser_text_value(reader, &_oval_sysinfo_parse_tag_consume_os_architecture, sysinfo);
} else if (is_ovalsys && (strcmp(tagname, "primary_host_name") == 0)) {
return_code = oscap_parser_text_value(reader, &_oval_sysinfo_parse_tag_consume_primary_host_name, sysinfo);
} else if (is_ovalsys && (strcmp(tagname, "interfaces") == 0)) {
return_code = oval_parser_parse_tag(reader, context, &_oval_sysinfo_parse_tag_parse_tag, sysinfo);
} else {
sysinfo->anyxml = (char *) xmlTextReaderReadOuterXml(reader);
return_code = oval_parser_skip_tag(reader, context);
}
free(tagname);
free(namespace);
return return_code;
}
int oval_sysinfo_parse_tag(xmlTextReaderPtr reader, struct oval_parser_context *context)
{
__attribute__nonnull__(context);
oval_sysinfo_t *sysinfo = oval_sysinfo_new(context->syschar_model);
char *tagname = (char *)xmlTextReaderLocalName(reader);
char *namespace = (char *)xmlTextReaderNamespaceUri(reader);
int return_code=0;
int is_ovalsys = strcmp((const char *)OVAL_SYSCHAR_NAMESPACE, namespace) == 0;
if (is_ovalsys) {
return_code = oval_parser_parse_tag(reader, context, &_oval_sysinfo_parse_tag, sysinfo);
} else {
dW("Expected <system_info>, got <%s:%s>", namespace, tagname);
oval_parser_skip_tag(reader, context);
}
if (return_code != 0) {
dW("Parsing of <%s> terminated by an error at line %d.", tagname, xmlTextReaderGetParserLineNumber(reader));
}
oval_syschar_model_set_sysinfo(context->syschar_model, sysinfo);
oval_sysinfo_free(sysinfo);
free(tagname);
free(namespace);
return return_code;
}
void oval_sysinfo_to_dom(struct oval_sysinfo *sysinfo, xmlDoc * doc, xmlNode * tag_parent)
{
xmlNode *nodestr, *nodelst;
xmlDoc *docstr;
int i;
if (sysinfo) {
xmlNs *ns_syschar = xmlSearchNsByHref(doc, tag_parent, OVAL_SYSCHAR_NAMESPACE);
xmlNode *tag_sysinfo = xmlNewTextChild(tag_parent, ns_syschar, BAD_CAST "system_info", NULL);
xmlNewTextChild(tag_sysinfo, ns_syschar, BAD_CAST "os_name", BAD_CAST oval_sysinfo_get_os_name(sysinfo));
xmlNewTextChild(tag_sysinfo, ns_syschar, BAD_CAST "os_version", BAD_CAST oval_sysinfo_get_os_version(sysinfo));
xmlNewTextChild(tag_sysinfo, ns_syschar, BAD_CAST "architecture", BAD_CAST oval_sysinfo_get_os_architecture(sysinfo));
xmlNewTextChild(tag_sysinfo, ns_syschar, BAD_CAST "primary_host_name", BAD_CAST oval_sysinfo_get_primary_host_name(sysinfo));
xmlNode *tag_interfaces = xmlNewTextChild(tag_sysinfo, ns_syschar, BAD_CAST "interfaces", NULL);
struct oval_sysint_iterator *intrfcs = oval_sysinfo_get_interfaces(sysinfo);
for (i = 1; oval_sysint_iterator_has_more(intrfcs); i++) {
struct oval_sysint *intrfc = oval_sysint_iterator_next(intrfcs);
oval_sysint_to_dom(intrfc, doc, tag_interfaces);
}
oval_sysint_iterator_free(intrfcs);
if (sysinfo->anyxml) {
docstr = xmlReadDoc(BAD_CAST sysinfo->anyxml, NULL, NULL, 0);
nodestr = xmlDocGetRootElement(docstr);
nodelst = xmlDocCopyNode(nodestr, doc, 1);
xmlAddChildList(tag_sysinfo, nodelst);
xmlFreeDoc(docstr);
}
}
}