libclamav/ooxml.c
25556519
 /*
  * OOXML JSON Internals
  * 
c442ca9c
  * Copyright (C) 2014-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
25556519
  * 
  * Authors: Kevin Lin
  * 
  * This program is free software; you can redistribute it and/or modify it under
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  * 
  * This program 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 General Public License for
  * more details.
  * 
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
60d8d2c3
 #include "clamav.h"
c6f7be55
 #include "filetypes.h"
25556519
 #include "others.h"
 #include "unzip.h"
e91e4383
 #if HAVE_JSON
51f8cc3c
 #include "json.h"
e91e4383
 #endif
25556519
 #include "json_api.h"
d8f74681
 #include "msxml_parser.h"
cd94be7a
 #include "ooxml.h"
 
25556519
 #if HAVE_LIBXML2
 #include <libxml/xmlreader.h>
 #endif
 
4823482e
 
871b862e
 
a41009bc
 #if HAVE_LIBXML2 && HAVE_JSON
 
c6f7be55
 /*** OOXML MSDOC ***/
d8f74681
 static const struct key_entry ooxml_keys[] = {
     { "coreproperties",     "CoreProperties",     MSXML_JSON_ROOT | MSXML_JSON_ATTRIB },
     { "title",              "Title",              MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "subject",            "Subject",            MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "creator",            "Author",             MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "keywords",           "Keywords",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "comments",           "Comments",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "description",        "Description",        MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "lastmodifiedby",     "LastAuthor",         MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "revision",           "Revision",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "created",            "Created",            MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "modified",           "Modified",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "category",           "Category",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "contentstatus",      "ContentStatus",      MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
 
     { "properties",         "ExtendedProperties", MSXML_JSON_ROOT | MSXML_JSON_ATTRIB },
     { "application",        "Application",        MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "appversion",         "AppVersion",         MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "characters",         "Characters",         MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "characterswithspaces", "CharactersWithSpaces", MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "company",            "Company",            MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "digsig",             "DigSig",             MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "docsecurity",        "DocSecurity",        MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     //{ "headingpairs",       "HeadingPairs",       MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "hiddenslides",       "HiddenSlides",       MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "hlinks",             "HLinks",             MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "hyperlinkbase",      "HyperlinkBase",      MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "hyperlinkschanged",  "HyperlinksChanged",  MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "lines",              "Lines",              MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "linksuptodate",      "LinksUpToDate",      MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "manager",            "Manager",            MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "mmclips",            "MultimediaClips",    MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "notes",              "Notes",              MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "pages",              "Pages",              MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "paragraphs",         "Paragraphs",         MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "presentationformat", "PresentationFormat", MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     //{ "properties",         "Properties",         MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "scalecrop",          "ScaleCrop",          MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "shareddoc",          "SharedDocs",         MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "slides",             "Slides",             MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "template",           "Template",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     //{ "titleofparts",       "TitleOfParts",       MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "totaltime",          "TotalTime",          MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "words",              "Words",              MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
 
     /* Should NOT Exist */
     { "bindata",            "BinaryData",         MSXML_SCAN_B64 | MSXML_JSON_COUNT | MSXML_JSON_ROOT }
afd00a72
 };
d8f74681
 static size_t num_ooxml_keys = sizeof(ooxml_keys) / sizeof(struct key_entry);
afd00a72
 
a2e6dcee
 static int ooxml_updatelimits(int fd, cli_ctx *ctx)
 {
     STATBUF sb;
     if (FSTAT(fd, &sb) == -1) {
         cli_errmsg("ooxml_updatelimits: Can't fstat descriptor %d\n", fd);
         return CL_ESTAT;
     }
 
     return cli_updatelimits(ctx, sb.st_size);
 }
 
afd00a72
 static int ooxml_parse_document(int fd, cli_ctx *ctx)
 {
     int ret = CL_SUCCESS;
     xmlTextReaderPtr reader = NULL;
 
     cli_dbgmsg("in ooxml_parse_document\n");
 
a2e6dcee
     /* perform engine limit checks in temporary tracking session */
     ret = ooxml_updatelimits(fd, ctx);
     if (ret != CL_CLEAN)
         return ret;
 
d3e752ad
     reader = xmlReaderForFd(fd, "properties.xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS);
afd00a72
     if (reader == NULL) {
         cli_dbgmsg("ooxml_parse_document: xmlReaderForFd error\n");
         return CL_SUCCESS; // internal error from libxml2
     }
 
6732844a
     ret = cli_msxml_parse_document(ctx, reader, ooxml_keys, num_ooxml_keys, MSXML_FLAG_JSON, NULL);
afd00a72
 
3e8eed18
     if (ret != CL_SUCCESS && ret != CL_ETIMEOUT && ret != CL_BREAK)
a0ae4170
         cli_warnmsg("ooxml_parse_document: encountered issue in parsing properties document\n");
d6b181ac
 
afd00a72
     xmlTextReaderClose(reader);
     xmlFreeTextReader(reader);
     return ret;
 }
25556519
 
d39cb658
 static int ooxml_core_cb(int fd, const char* filepath, cli_ctx *ctx)
25556519
 {
3e8eed18
     int ret;
 
25556519
     cli_dbgmsg("in ooxml_core_cb\n");
3e8eed18
     ret = ooxml_parse_document(fd, ctx);
     if (ret == CL_EPARSE)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_CORE_XMLPARSER");
3e8eed18
     else if (ret == CL_EFORMAT)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_CORE_MALFORMED");
3e8eed18
 
     return ret;
25556519
 }
 
d39cb658
 static int ooxml_extn_cb(int fd, const char* filepath, cli_ctx *ctx)
25556519
 {
3e8eed18
     int ret;
 
25556519
     cli_dbgmsg("in ooxml_extn_cb\n");
3e8eed18
     ret = ooxml_parse_document(fd, ctx);
     if (ret == CL_EPARSE)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_EXTN_XMLPARSER");
3e8eed18
     else if (ret == CL_EFORMAT)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_EXTN_MALFORMED");
3e8eed18
 
     return ret;
25556519
 }
 
d39cb658
 static int ooxml_content_cb(int fd, const char* filepath, cli_ctx *ctx)
25556519
 {
3e8eed18
     int ret = CL_SUCCESS, tmp, toval = 0, state;
a41ab49e
     int core=0, extn=0, cust=0, dsig=0;
d48fd4bb
     int mcore=0, mextn=0, mcust=0;
25556519
     const xmlChar *name, *value, *CT, *PN;
     xmlTextReaderPtr reader = NULL;
     uint32_t loff;
 
a2e6dcee
     unsigned long sav_scansize = ctx->scansize;
     unsigned int sav_scannedfiles = ctx->scannedfiles;
 
25556519
     cli_dbgmsg("in ooxml_content_cb\n");
 
a2e6dcee
     /* perform engine limit checks in temporary tracking session */
     ret = ooxml_updatelimits(fd, ctx);
     if (ret != CL_CLEAN)
         return ret;
 
     /* apply a reader to the document */
d3e752ad
     reader = xmlReaderForFd(fd, "[Content_Types].xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS);
25556519
     if (reader == NULL) {
         cli_dbgmsg("ooxml_content_cb: xmlReaderForFd error for ""[Content_Types].xml""\n");
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_XML_READER_FD");
a2e6dcee
 
         ctx->scansize = sav_scansize;
         ctx->scannedfiles = sav_scannedfiles;
25556519
         return CL_SUCCESS; // libxml2 failed!
     }
 
3e8eed18
     /* locate core-properties, extended-properties, and custom-properties (optional) */
     while ((state = xmlTextReaderRead(reader)) == 1) {
20b45621
         if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
             ret = CL_ETIMEOUT;
             goto ooxml_content_exit;
         }
 
25556519
         name = xmlTextReaderConstLocalName(reader);
         if (name == NULL) continue;
 
cd94be7a
         if (strcmp((const char *)name, "Override")) continue;
25556519
 
6e185279
         if (xmlTextReaderHasAttributes(reader) != 1) continue;
25556519
 
871b862e
         CT = PN = NULL;
25556519
         while (xmlTextReaderMoveToNextAttribute(reader) == 1) {
             name = xmlTextReaderConstLocalName(reader);
             value = xmlTextReaderConstValue(reader);
             if (name == NULL || value == NULL) continue;
 
cd94be7a
             if (!xmlStrcmp(name, (const xmlChar *)"ContentType")) {
25556519
                 CT = value;
             }
cd94be7a
             else if (!xmlStrcmp(name, (const xmlChar *)"PartName")) {
25556519
                 PN = value;
             }
 
             cli_dbgmsg("%s: %s\n", name, value);
         }
 
         if (!CT && !PN) continue;
 
cd94be7a
         if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.core-properties+xml")) {
3e8eed18
             /* default: /docProps/core.xml*/
             tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
             if (tmp == CL_ETIMEOUT) {
                 ret = tmp;
             }
             else if (tmp != CL_VIRUS) {
                 cli_dbgmsg("cli_process_ooxml: failed to find core properties file \"%s\"!\n", PN);
                 mcore++;
             }
             else {
                 cli_dbgmsg("ooxml_content_cb: found core properties file \"%s\" @ %x\n", PN, loff);
                 if (!core) {
                     tmp = unzip_single_internal(ctx, loff, ooxml_core_cb);
                     if (tmp == CL_ETIMEOUT || tmp == CL_EMEM) {
                         ret = tmp;
                     }
871b862e
                 }
3e8eed18
                 core++;
25556519
             }
         }
cd94be7a
         else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.extended-properties+xml")) {
3e8eed18
             /* default: /docProps/app.xml */
             tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
             if (tmp == CL_ETIMEOUT) {
                 ret = tmp;
             }
             else if (tmp != CL_VIRUS) {
                 cli_dbgmsg("cli_process_ooxml: failed to find extended properties file \"%s\"!\n", PN);
                 mextn++;
             }
             else {
                 cli_dbgmsg("ooxml_content_cb: found extended properties file \"%s\" @ %x\n", PN, loff);
                 if (!extn) {
                     tmp = unzip_single_internal(ctx, loff, ooxml_extn_cb);
                     if (tmp == CL_ETIMEOUT || tmp == CL_EMEM) {
                         ret = tmp;
                     }
871b862e
                 }
3e8eed18
                 extn++;
25556519
             }
         }
cd94be7a
         else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.custom-properties+xml")) {
3e8eed18
             /* default: /docProps/custom.xml */
             tmp = unzip_search_single(ctx, (const char *)(PN+1), xmlStrlen(PN)-1, &loff);
             if (tmp == CL_ETIMEOUT) {
                 ret = tmp;
             }
             else if (tmp != CL_VIRUS) {
                 cli_dbgmsg("cli_process_ooxml: failed to find custom properties file \"%s\"!\n", PN);
                 mcust++;
             }
             else {
                 cli_dbgmsg("ooxml_content_cb: found custom properties file \"%s\" @ %x\n", PN, loff);
                 /* custom properties are not parsed */
                 cust++;
25556519
             }
         }
cd94be7a
         else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")) {
871b862e
             dsig++;
a41ab49e
         }
25556519
 
3e8eed18
         if (ret != CL_SUCCESS)
25556519
             goto ooxml_content_exit;
     }
 
dac76eb9
  ooxml_content_exit:
3e8eed18
     if (core) {
871b862e
         cli_jsonint(ctx->wrkproperty, "CorePropertiesFileCount", core);
3e8eed18
         if (core > 1)
d8f74681
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_CORE_PROPFILES");
3e8eed18
     }
d48fd4bb
     else if (!mcore)
25556519
         cli_dbgmsg("cli_process_ooxml: file does not contain core properties file\n");
3e8eed18
     if (mcore) {
         cli_jsonint(ctx->wrkproperty, "CorePropertiesMissingFileCount", mcore);
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_CORE_PROPFILES");
3e8eed18
     }
d48fd4bb
 
3e8eed18
     if (extn) {
871b862e
         cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesFileCount", extn);
3e8eed18
         if (extn > 1)
d8f74681
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_EXTN_PROPFILES");
3e8eed18
     }
d48fd4bb
     else if (!mextn)
25556519
         cli_dbgmsg("cli_process_ooxml: file does not contain extended properties file\n");
3e8eed18
     if (mextn) {
         cli_jsonint(ctx->wrkproperty, "ExtendedPropertiesMissingFileCount", mextn);
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_EXTN_PROPFILES");
3e8eed18
     }
d48fd4bb
 
3e8eed18
     if (cust) {
871b862e
         cli_jsonint(ctx->wrkproperty, "CustomPropertiesFileCount", cust);
3e8eed18
         if (cust > 1)
d8f74681
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MULTIPLE_CUSTOM_PROPFILES");
3e8eed18
     }
d48fd4bb
     else if (!mcust)
25556519
         cli_dbgmsg("cli_process_ooxml: file does not contain custom properties file\n");
3e8eed18
     if (mcust) {
         cli_jsonint(ctx->wrkproperty, "CustomPropertiesMissingFileCount", mcust);
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_MISSING_CUST_PROPFILES");
3e8eed18
     }
d48fd4bb
 
871b862e
     if (dsig) {
         cli_jsonint(ctx->wrkproperty, "DigitalSignaturesCount", dsig);
     }
25556519
 
a2e6dcee
     /* restore the engine tracking limits; resets session limit tracking */
     ctx->scansize = sav_scansize;
     ctx->scannedfiles = sav_scannedfiles;
 
25556519
     xmlTextReaderClose(reader);
     xmlFreeTextReader(reader);
     return ret;
 }
c6f7be55
 
 /*** OOXML HWP ***/
 static const struct key_entry ooxml_hwp_keys[] = {
     { "hcfversion",         "HCFVersion",         MSXML_JSON_ROOT | MSXML_JSON_ATTRIB },
 
     { "package",            "Properties",         MSXML_JSON_ROOT | MSXML_JSON_ATTRIB },
1ab521a9
     { "metadata",           "Metadata",           MSXML_JSON_WRKPTR | MSXML_JSON_ATTRIB },
c6f7be55
     { "title",              "Title",              MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "language",           "Language",           MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
333e20b8
     { "meta",               "MetaFields",         MSXML_JSON_WRKPTR | MSXML_JSON_ATTRIB | MSXML_JSON_VALUE | MSXML_JSON_COUNT | MSXML_JSON_MULTI },
c6f7be55
     { "item",               "Contents",           MSXML_JSON_WRKPTR | MSXML_JSON_ATTRIB | MSXML_JSON_COUNT | MSXML_JSON_MULTI }
 };
 static size_t num_ooxml_hwp_keys = sizeof(ooxml_hwp_keys) / sizeof(struct key_entry);
 
d39cb658
 static int ooxml_hwp_cb(int fd, const char* filepath, cli_ctx *ctx)
c6f7be55
 {
     int ret = CL_SUCCESS;
     xmlTextReaderPtr reader = NULL;
 
     cli_dbgmsg("in ooxml_hwp_cb\n");
 
     /* perform engine limit checks in temporary tracking session */
     ret = ooxml_updatelimits(fd, ctx);
     if (ret != CL_CLEAN)
         return ret;
 
     reader = xmlReaderForFd(fd, "ooxml_hwp.xml", NULL, CLAMAV_MIN_XMLREADER_FLAGS);
     if (reader == NULL) {
         cli_dbgmsg("ooxml_hwp_cb: xmlReaderForFd error\n");
         return CL_SUCCESS; // internal error from libxml2
     }
 
6732844a
     ret = cli_msxml_parse_document(ctx, reader, ooxml_hwp_keys, num_ooxml_hwp_keys, MSXML_FLAG_JSON, NULL);
c6f7be55
 
     if (ret != CL_SUCCESS && ret != CL_ETIMEOUT && ret != CL_BREAK)
         cli_warnmsg("ooxml_hwp_cb: encountered issue in parsing properties document\n");
 
     xmlTextReaderClose(reader);
     xmlFreeTextReader(reader);
     return ret;
 }
 
20b45621
 #endif /* HAVE_LIBXML2 && HAVE_JSON */
25556519
 
c8c80ddf
 int cli_ooxml_filetype(cli_ctx *ctx, fmap_t *map)
 {
     struct zip_requests requests;
     int ret;
 
     memset(&requests, 0, sizeof(struct zip_requests));
 
     if ((ret = unzip_search_add(&requests, "xl/", 3)) != CL_SUCCESS) {
         return CL_SUCCESS;
     }
     if ((ret = unzip_search_add(&requests, "ppt/", 4)) != CL_SUCCESS) {
         return CL_SUCCESS;
     }
     if ((ret = unzip_search_add(&requests, "word/", 5)) != CL_SUCCESS) {
         return CL_SUCCESS;
     }
8059ffb7
     if ((ret = unzip_search_add(&requests, "Contents/content.hpf", 22)) != CL_SUCCESS) {
         return CL_SUCCESS;
     }
c8c80ddf
 
     if ((ret = unzip_search(ctx, map, &requests)) == CL_VIRUS) {
         switch (requests.found) {
         case 0:
             return CL_TYPE_OOXML_XL;
         case 1:
             return CL_TYPE_OOXML_PPT;
         case 2:
             return CL_TYPE_OOXML_WORD;
8059ffb7
         case 3:
             return CL_TYPE_OOXML_HWP;
c8c80ddf
         default:
             return CL_SUCCESS;
         }
     }
 
     return CL_SUCCESS;
 }
 
c6f7be55
 int cli_process_ooxml(cli_ctx *ctx, int type)
25556519
 {
a41009bc
 #if HAVE_LIBXML2 && HAVE_JSON
25556519
     uint32_t loff = 0;
c6f7be55
     int ret = CL_SUCCESS;
25556519
 
4823482e
     cli_dbgmsg("in cli_process_ooxml\n");
25556519
     if (!ctx) {
         return CL_ENULLARG;
     }
 
c6f7be55
     if (type == CL_TYPE_OOXML_HWP) {
         /* two files: version.xml and Contents/content.hpf */
         ret = unzip_search_single(ctx, "version.xml", 11, &loff);
         if (ret == CL_ETIMEOUT) {
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_TIMEOUT");
             return CL_ETIMEOUT;
         }
         else if (ret != CL_VIRUS) {
             cli_dbgmsg("cli_process_ooxml: failed to find ""version.xml""!\n");
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_NO_HWP_VERSION");
             return CL_EFORMAT;
         }
         ret = unzip_single_internal(ctx, loff, ooxml_hwp_cb);
 
         if (ret == CL_SUCCESS) {
             ret = unzip_search_single(ctx, "Contents/content.hpf", 20, &loff);
             if (ret == CL_ETIMEOUT) {
                 cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_TIMEOUT");
                 return CL_ETIMEOUT;
             }
             else if (ret != CL_VIRUS) {
                 cli_dbgmsg("cli_process_ooxml: failed to find ""Contents/content.hpf""!\n");
                 cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_NO_HWP_CONTENT");
                 return CL_EFORMAT;
             }
             ret = unzip_single_internal(ctx, loff, ooxml_hwp_cb);
         }
     } else {
         /* find "[Content Types].xml" */
         ret = unzip_search_single(ctx, "[Content_Types].xml", 19, &loff);
         if (ret == CL_ETIMEOUT) {
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_TIMEOUT");
             return CL_ETIMEOUT;
         }
         else if (ret != CL_VIRUS) {
             cli_dbgmsg("cli_process_ooxml: failed to find ""[Content_Types].xml""!\n");
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_NO_CONTENT_TYPES");
             return CL_EFORMAT;
         }
         cli_dbgmsg("cli_process_ooxml: found ""[Content_Types].xml"" @ %x\n", loff);
 
         ret = unzip_single_internal(ctx, loff, ooxml_content_cb);
25556519
     }
 
c6f7be55
     if (ret == CL_ETIMEOUT)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_TIMEOUT");
c6f7be55
     else if (ret == CL_EMEM)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_OUTOFMEM");
c6f7be55
     else if (ret == CL_EMAXSIZE)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_EMAXSIZE");
c6f7be55
     else if (ret == CL_EMAXFILES)
d8f74681
         cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_EMAXFILES");
3e8eed18
 
c6f7be55
     return ret;
25556519
 #else
cd94be7a
     UNUSEDPARAM(ctx);
4823482e
     cli_dbgmsg("in cli_process_ooxml\n");
a41009bc
 #if !HAVE_LIBXML2
4c9e8bbb
     cli_dbgmsg("cli_process_ooxml: libxml2 needs to enabled!\n");
a41009bc
 #endif
 #if !HAVE_JSON
4c9e8bbb
     cli_dbgmsg("cli_process_ooxml: libjson needs to enabled!\n");
a41009bc
 #endif
25556519
     return CL_SUCCESS;
 #endif
 }