bb#11187 - corrections to prevent evasion and add clarity

ooxml: added clarity on various parsing errors in json output
ooxml: changed behavior to continue parsing other propfiles if one is malformed
pull/18/head
Kevin Lin 11 years ago
parent b6768907aa
commit 3e8eed1823
  1. 190
      libclamav/ooxml.c

@ -78,11 +78,29 @@ static int ooxml_is_int(const char *value, size_t len, int32_t *val)
return 1; return 1;
} }
static int ooxml_add_parse_error(json_object *wrkptr, const xmlChar *errstr)
{
json_object *perr;
if (!wrkptr)
return CL_ENULLARG;
perr = cli_jsonarray(wrkptr, "ParseErrors");
if (perr == NULL) {
return CL_EMEM;
}
return cli_jsonstr(perr, NULL, errstr);
}
static int ooxml_parse_value(json_object *wrkptr, const char *arrname, const xmlChar *node_value) static int ooxml_parse_value(json_object *wrkptr, const char *arrname, const xmlChar *node_value)
{ {
json_object *newobj, *arrobj; json_object *newobj, *arrobj;
int val; int val;
if (!wrkptr)
return CL_ENULLARG;
arrobj = cli_jsonarray(wrkptr, arrname); arrobj = cli_jsonarray(wrkptr, arrname);
if (arrobj == NULL) { if (arrobj == NULL) {
return CL_EMEM; return CL_EMEM;
@ -247,7 +265,7 @@ static int ooxml_parse_element(cli_ctx *ctx, xmlTextReaderPtr reader, json_objec
if (node_type != XML_READER_TYPE_ELEMENT) { if (node_type != XML_READER_TYPE_ELEMENT) {
cli_dbgmsg("ooxml_parse_element: first node typed %d, not %d\n", node_type, XML_READER_TYPE_ELEMENT); cli_dbgmsg("ooxml_parse_element: first node typed %d, not %d\n", node_type, XML_READER_TYPE_ELEMENT);
return CL_EPARSE; /* first type is not an element */ return CL_EFORMAT; /* first type is not an element */
} }
node_name = xmlTextReaderConstLocalName(reader); node_name = xmlTextReaderConstLocalName(reader);
@ -267,7 +285,7 @@ static int ooxml_parse_element(cli_ctx *ctx, xmlTextReaderPtr reader, json_objec
/* generate json object */ /* generate json object */
thisjobj = cli_jsonobj(wrkptr, element_tag); thisjobj = cli_jsonobj(wrkptr, element_tag);
if (!thisjobj) { if (!thisjobj) {
return CL_EPARSE; return CL_EMEM;
} }
cli_dbgmsg("ooxml_parse_element: generated json object [%s]\n", element_tag); cli_dbgmsg("ooxml_parse_element: generated json object [%s]\n", element_tag);
@ -406,10 +424,8 @@ static int ooxml_parse_document(int fd, cli_ctx *ctx)
ret = ooxml_parse_element(ctx, reader, ctx->wrkproperty, 0, NULL); ret = ooxml_parse_element(ctx, reader, ctx->wrkproperty, 0, NULL);
if (ret != CL_SUCCESS && ret != CL_ETIMEOUT && ret != CL_BREAK) { if (ret != CL_SUCCESS && ret != CL_ETIMEOUT && ret != CL_BREAK)
cli_warnmsg("ooxml_parse_document: encountered issue in parsing properties document\n"); cli_warnmsg("ooxml_parse_document: encountered issue in parsing properties document\n");
cli_jsonbool(ctx->wrkproperty, "ParseError", 1);
}
xmlTextReaderClose(reader); xmlTextReaderClose(reader);
xmlFreeTextReader(reader); xmlFreeTextReader(reader);
@ -418,21 +434,35 @@ static int ooxml_parse_document(int fd, cli_ctx *ctx)
static int ooxml_core_cb(int fd, cli_ctx *ctx) static int ooxml_core_cb(int fd, cli_ctx *ctx)
{ {
int ret;
cli_dbgmsg("in ooxml_core_cb\n"); cli_dbgmsg("in ooxml_core_cb\n");
return ooxml_parse_document(fd, ctx); ret = ooxml_parse_document(fd, ctx);
//return ooxml_basic_json(fd, ctx, "CoreProperties"); if (ret == CL_EPARSE)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_CORE_XMLPARSER");
else if (ret == CL_EFORMAT)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_CORE_MALFORMED");
return ret;
} }
static int ooxml_extn_cb(int fd, cli_ctx *ctx) static int ooxml_extn_cb(int fd, cli_ctx *ctx)
{ {
int ret;
cli_dbgmsg("in ooxml_extn_cb\n"); cli_dbgmsg("in ooxml_extn_cb\n");
return ooxml_parse_document(fd, ctx); ret = ooxml_parse_document(fd, ctx);
//return ooxml_basic_json(fd, ctx, "ExtendedProperties"); if (ret == CL_EPARSE)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_EXTN_XMLPARSER");
else if (ret == CL_EFORMAT)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_EXTN_MALFORMED");
return ret;
} }
static int ooxml_content_cb(int fd, cli_ctx *ctx) static int ooxml_content_cb(int fd, cli_ctx *ctx)
{ {
int ret = CL_SUCCESS, tmp, toval = 0; int ret = CL_SUCCESS, tmp, toval = 0, state;
int core=0, extn=0, cust=0, dsig=0; int core=0, extn=0, cust=0, dsig=0;
int mcore=0, mextn=0, mcust=0; int mcore=0, mextn=0, mcust=0;
const xmlChar *name, *value, *CT, *PN; const xmlChar *name, *value, *CT, *PN;
@ -444,11 +474,12 @@ static int ooxml_content_cb(int fd, cli_ctx *ctx)
reader = xmlReaderForFd(fd, "[Content_Types].xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS); reader = xmlReaderForFd(fd, "[Content_Types].xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS);
if (reader == NULL) { if (reader == NULL) {
cli_dbgmsg("ooxml_content_cb: xmlReaderForFd error for ""[Content_Types].xml""\n"); cli_dbgmsg("ooxml_content_cb: xmlReaderForFd error for ""[Content_Types].xml""\n");
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_XML_READER_FD");
return CL_SUCCESS; // libxml2 failed! return CL_SUCCESS; // libxml2 failed!
} }
/* locate core-properties, extended-properties, and custom-properties (optional) */ /* locate core-properties, extended-properties, and custom-properties (optional) */
while (xmlTextReaderRead(reader) == 1) { while ((state = xmlTextReaderRead(reader)) == 1) {
if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
ret = CL_ETIMEOUT; ret = CL_ETIMEOUT;
goto ooxml_content_exit; goto ooxml_content_exit;
@ -480,88 +511,107 @@ static int ooxml_content_cb(int fd, cli_ctx *ctx)
if (!CT && !PN) continue; if (!CT && !PN) continue;
if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.core-properties+xml")) { if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.core-properties+xml")) {
if (!core) { /* default: /docProps/core.xml*/
/* default: /docProps/core.xml*/ tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff); if (tmp == CL_ETIMEOUT) {
if (tmp == CL_ETIMEOUT) { ret = tmp;
ret = tmp; }
} else if (tmp != CL_VIRUS) {
else if (tmp != CL_VIRUS) { cli_dbgmsg("cli_process_ooxml: failed to find core properties file \"%s\"!\n", PN);
cli_dbgmsg("cli_process_ooxml: failed to find core properties file \"%s\"!\n", PN); mcore++;
mcore++; }
} else {
else { cli_dbgmsg("ooxml_content_cb: found core properties file \"%s\" @ %x\n", PN, loff);
cli_dbgmsg("ooxml_content_cb: found core properties file \"%s\" @ %x\n", PN, loff); if (!core) {
ret = unzip_single_internal(ctx, loff, ooxml_core_cb); tmp = unzip_single_internal(ctx, loff, ooxml_core_cb);
core++; if (tmp == CL_ETIMEOUT || tmp == CL_EMEM) {
ret = tmp;
}
} }
core++;
} }
} }
else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.extended-properties+xml")) { else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.extended-properties+xml")) {
if (!extn) { /* default: /docProps/app.xml */
/* default: /docProps/app.xml */ tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff); if (tmp == CL_ETIMEOUT) {
if (tmp == CL_ETIMEOUT) { ret = tmp;
ret = tmp; }
} else if (tmp != CL_VIRUS) {
else if (tmp != CL_VIRUS) { cli_dbgmsg("cli_process_ooxml: failed to find extended properties file \"%s\"!\n", PN);
cli_dbgmsg("cli_process_ooxml: failed to find extended properties file \"%s\"!\n", PN); mextn++;
mextn++; }
} else {
else { cli_dbgmsg("ooxml_content_cb: found extended properties file \"%s\" @ %x\n", PN, loff);
cli_dbgmsg("ooxml_content_cb: found extended properties file \"%s\" @ %x\n", PN, loff); if (!extn) {
ret = unzip_single_internal(ctx, loff, ooxml_extn_cb); tmp = unzip_single_internal(ctx, loff, ooxml_extn_cb);
extn++; if (tmp == CL_ETIMEOUT || tmp == CL_EMEM) {
ret = tmp;
}
} }
extn++;
} }
} }
else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.custom-properties+xml")) { else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.custom-properties+xml")) {
if (!cust) { /* default: /docProps/custom.xml */
/* default: /docProps/custom.xml */ tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff); if (tmp == CL_ETIMEOUT) {
if (tmp == CL_ETIMEOUT) { ret = tmp;
ret = tmp; }
} else if (tmp != CL_VIRUS) {
else if (tmp != CL_VIRUS) { cli_dbgmsg("cli_process_ooxml: failed to find custom properties file \"%s\"!\n", PN);
cli_dbgmsg("cli_process_ooxml: failed to find custom properties file \"%s\"!\n", PN); mcust++;
mcust++; }
} else {
else { cli_dbgmsg("ooxml_content_cb: found custom properties file \"%s\" @ %x\n", PN, loff);
cli_dbgmsg("ooxml_content_cb: found custom properties file \"%s\" @ %x\n", PN, loff); /* custom properties are not parsed */
cust++; cust++;
//ret = unzip_single_internal(ctx, loff, ooxml_cust_cb);
}
} }
} }
else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")) { else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")) {
dsig++; dsig++;
} }
if (ret != CL_BREAK && ret != CL_SUCCESS) if (ret != CL_SUCCESS)
goto ooxml_content_exit; goto ooxml_content_exit;
} }
ooxml_content_exit: ooxml_content_exit:
if (core) if (core) {
cli_jsonint(ctx->wrkproperty, "CorePropertiesFileCount", core); cli_jsonint(ctx->wrkproperty, "CorePropertiesFileCount", core);
if (core > 1)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_CORE_PROPFILES");
}
else if (!mcore) else if (!mcore)
cli_dbgmsg("cli_process_ooxml: file does not contain core properties file\n"); cli_dbgmsg("cli_process_ooxml: file does not contain core properties file\n");
if (mcore) if (mcore) {
cli_jsonint(ctx->wrkproperty, "CorePropertiesMissingFileCount", core); cli_jsonint(ctx->wrkproperty, "CorePropertiesMissingFileCount", mcore);
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_CORE_PROPFILES");
}
if (extn) if (extn) {
cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesFileCount", extn); cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesFileCount", extn);
if (extn > 1)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_EXTN_PROPFILES");
}
else if (!mextn) else if (!mextn)
cli_dbgmsg("cli_process_ooxml: file does not contain extended properties file\n"); cli_dbgmsg("cli_process_ooxml: file does not contain extended properties file\n");
if (mextn) if (mextn) {
cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesMissingFileCount", extn); cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesMissingFileCount", mextn);
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_EXTN_PROPFILES");
}
if (cust) if (cust) {
cli_jsonint(ctx->wrkproperty, "CustomPropertiesFileCount", cust); cli_jsonint(ctx->wrkproperty, "CustomPropertiesFileCount", cust);
if (cust > 1)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_CUSTOM_PROPFILES");
}
else if (!mcust) else if (!mcust)
cli_dbgmsg("cli_process_ooxml: file does not contain custom properties file\n"); cli_dbgmsg("cli_process_ooxml: file does not contain custom properties file\n");
if (mcust) if (mcust) {
cli_jsonint(ctx->wrkproperty, "CustomPropertiesMissingFileCount", cust); cli_jsonint(ctx->wrkproperty, "CustomPropertiesMissingFileCount", mcust);
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_CUST_PROPFILES");
}
if (dsig) { if (dsig) {
cli_jsonint(ctx->wrkproperty, "DigitalSignaturesCount", dsig); cli_jsonint(ctx->wrkproperty, "DigitalSignaturesCount", dsig);
@ -620,15 +670,23 @@ int cli_process_ooxml(cli_ctx *ctx)
/* find "[Content Types].xml" */ /* find "[Content Types].xml" */
tmp = unzip_search_single(ctx, "[Content_Types].xml", 18, &loff); tmp = unzip_search_single(ctx, "[Content_Types].xml", 18, &loff);
if (tmp == CL_ETIMEOUT) { if (tmp == CL_ETIMEOUT) {
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_TIMEOUT");
return CL_ETIMEOUT; return CL_ETIMEOUT;
} }
else if (tmp != CL_VIRUS) { else if (tmp != CL_VIRUS) {
cli_dbgmsg("cli_process_ooxml: failed to find ""[Content_Types].xml""!\n"); cli_dbgmsg("cli_process_ooxml: failed to find ""[Content_Types].xml""!\n");
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_NO_CONTENT_TYPES");
return CL_EFORMAT; return CL_EFORMAT;
} }
cli_dbgmsg("cli_process_ooxml: found ""[Content_Types].xml"" @ %x\n", loff); cli_dbgmsg("cli_process_ooxml: found ""[Content_Types].xml"" @ %x\n", loff);
return unzip_single_internal(ctx, loff, ooxml_content_cb); tmp = unzip_single_internal(ctx, loff, ooxml_content_cb);
if (tmp == CL_ETIMEOUT)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_TIMEOUT");
else if (tmp == CL_EMEM)
ooxml_add_parse_error(ctx->wrkproperty, "OOXML_ERROR_OUTOFMEM");
return tmp;
#else #else
UNUSEDPARAM(ctx); UNUSEDPARAM(ctx);
cli_dbgmsg("in cli_processooxml\n"); cli_dbgmsg("in cli_processooxml\n");

Loading…
Cancel
Save