2
* Copyright (C) 2014 Cisco Systems, Inc.
4
* Authors: Steven Morgan <smorgan@sourcefire.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22
#include "clamav-config.h"
29
#include <openssl/ssl.h>
30
#include <openssl/err.h>
32
#include "libclamav/crypto.h"
38
#ifndef LIBXML_WRITER_ENABLED
39
#define LIBXML_WRITER_ENABLED 1
42
#include <libxml/xmlreader.h>
49
static const xmlChar * openioc_read(xmlTextReaderPtr reader)
52
if (xmlTextReaderRead(reader) != 1)
54
name = xmlTextReaderConstLocalName(reader);
56
cli_dbgmsg("openioc_parse: xmlTextReaderRead read %s%s\n", name,
57
xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT?" end tag":"");
63
static int openioc_is_context_hash(xmlTextReaderPtr reader)
65
xmlChar * document = xmlTextReaderGetAttribute(reader, (const xmlChar *)"document");
66
xmlChar * search = xmlTextReaderGetAttribute(reader, (const xmlChar *)"search");
69
if ((document != NULL && search != NULL) &&
70
!xmlStrcmp(document, (const xmlChar *)"FileItem") &&
71
(!xmlStrcmp(search, (const xmlChar *)"FileItem/Md5sum") ||
72
!xmlStrcmp(search, (const xmlChar *)"FileItem/Sha1sum") ||
73
!xmlStrcmp(search, (const xmlChar *)"FileItem/Sha256sum")))
82
static int openioc_parse_content(xmlTextReaderPtr reader, struct openioc_hash ** elems, int context_hash)
84
const xmlChar * xmlval;
85
struct openioc_hash * elem;
88
if (context_hash == 0) {
89
xmlChar * type = xmlTextReaderGetAttribute(reader, (const xmlChar *)"type");
91
cli_dbgmsg("openioc_parse: xmlTextReaderGetAttribute no type attribute "
92
"for <Content> element\n");
95
if (xmlStrcasecmp(type, (const xmlChar *)"sha1") &&
96
xmlStrcasecmp(type, (const xmlChar *)"sha256") &&
97
xmlStrcasecmp(type, (const xmlChar *)"md5")) {
105
if (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) {
106
xmlval = xmlTextReaderConstValue(reader);
108
elem = cli_calloc(1, sizeof(struct openioc_hash));
110
cli_dbgmsg("openioc_parse: calloc fails for openioc_hash.\n");
113
elem->hash = xmlStrdup(xmlval);
117
cli_dbgmsg("openioc_parse: xmlTextReaderConstValue() returns NULL for Content md5 value.\n");
121
cli_dbgmsg("openioc_parse: No text for XML Content element.\n");
126
static int openioc_parse_indicatoritem(xmlTextReaderPtr reader, struct openioc_hash ** elems)
128
const xmlChar * name;
130
int context_hash = 0;
133
name = openioc_read(reader);
136
if (xmlStrEqual(name, (const xmlChar *)"Context") &&
137
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
138
context_hash = openioc_is_context_hash(reader);
139
} else if (xmlStrEqual(name, (const xmlChar *)"Content") &&
140
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
141
rc = openioc_parse_content(reader, elems, context_hash);
142
if (rc != CL_SUCCESS) {
145
} else if (xmlStrEqual(name, (const xmlChar *)"IndicatorItem") &&
146
xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) {
153
static int openioc_parse_indicator(xmlTextReaderPtr reader, struct openioc_hash ** elems)
155
const xmlChar * name;
159
name = openioc_read(reader);
162
if (xmlStrEqual(name, (const xmlChar *)"Indicator") &&
163
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
164
rc = openioc_parse_indicator(reader, elems);
165
if (rc != CL_SUCCESS) {
166
cli_dbgmsg("openioc_parse: openioc_parse_indicator recursion error.\n");
169
} else if (xmlStrEqual(name, (const xmlChar *)"IndicatorItem") &&
170
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
171
rc = openioc_parse_indicatoritem(reader, elems);
172
if (rc != CL_SUCCESS) {
175
} else if (xmlStrEqual(name, (const xmlChar *)"Indicator") &&
176
xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) {
183
int openioc_parse(const char * fname, int fd, struct cl_engine *engine, unsigned int options)
186
xmlTextReaderPtr reader = NULL;
187
const xmlChar * name;
188
struct openioc_hash * elems = NULL, * elem = NULL;
189
const char * iocp = NULL;
200
cli_dbgmsg("openioc_parse: XML parsing file %s\n", fname);
202
reader = xmlReaderForFd(fd, NULL, NULL, 0);
203
if (reader == NULL) {
204
cli_dbgmsg("openioc_parse: xmlReaderForFd error\n");
207
rc = xmlTextReaderRead(reader);
209
name = xmlTextReaderConstLocalName(reader);
210
cli_dbgmsg("openioc_parse: xmlTextReaderRead read %s\n", name);
211
if (xmlStrEqual(name, (const xmlChar *)"Indicator") &&
212
xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
213
rc = openioc_parse_indicator(reader, &elems);
214
if (rc != CL_SUCCESS) {
215
xmlTextReaderClose(reader);
216
xmlFreeTextReader(reader);
220
if (xmlStrEqual(name, (const xmlChar *)"ioc") &&
221
xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) {
224
rc = xmlTextReaderRead(reader);
227
iocp = strrchr(fname, *PATHSEP);
234
ioclen = strlen(fname);
237
if (NULL == engine->hm_hdb) {
238
engine->hm_hdb = mpool_calloc(engine->mempool, 1, sizeof(struct cli_matcher));
239
if (NULL == engine->hm_hdb) {
240
xmlTextReaderClose(reader);
241
xmlFreeTextReader(reader);
245
engine->hm_hdb->mempool = engine->mempool;
250
while (elems != NULL) {
258
while (isspace(*hash))
260
hashlen = strlen(hash);
267
while (isspace(*vp) && vp > hash) {
271
virusname = calloc(1, ioclen+hashlen+2);
272
if (NULL == virusname) {
273
cli_dbgmsg("openioc_parse: mpool_malloc for virname memory failed.\n");
274
xmlTextReaderClose(reader);
275
xmlFreeTextReader(reader);
280
for (i=0; i<ioclen; i++, sp++, vp++) {
303
for (i=0; i<hashlen; i++, sp++) {
310
virusname = cli_mpool_virname(engine->mempool, virusname, options & CL_DB_OFFICIAL);
312
cli_dbgmsg("openioc_parse: mpool_malloc for virname memory failed.\n");
313
xmlTextReaderClose(reader);
314
xmlFreeTextReader(reader);
321
rc = hm_addhash_str(engine->hm_hdb, hash, 0, virusname);
322
if (rc != CL_SUCCESS)
323
cli_dbgmsg("openioc_parse: hm_addhash_str failed with %i hash len %i for %s.\n",
324
rc, hashlen, virusname);
333
cli_warnmsg("openioc_parse: No hash signatures extracted from %s.\n", fname);
335
cli_dbgmsg("openioc_parse: %i hash signature%s extracted from %s.\n",
336
hash_count, hash_count==1?"":"s", fname);
338
xmlTextReaderClose(reader);
339
xmlFreeTextReader(reader);
344
int openioc_parse(const char * fname, int fd, struct cl_engine *engine, unsigned int options)
346
cli_dbgmsg("openioc_parse: libxml2 support is compiled out and is needed for OpenIOC support.\n");