libclamav/ooxml.c
25556519
 /*
  * OOXML JSON Internals
02840644
  *
e1cbc270
  * Copyright (C) 2014-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
02840644
  *
25556519
  * Authors: Kevin Lin
02840644
  *
25556519
  * 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.
02840644
  *
25556519
  * 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.
02840644
  *
25556519
  * 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
 
a41009bc
 #if HAVE_LIBXML2 && HAVE_JSON
 
27948a03
 // clang-format off
 
c6f7be55
 /*** OOXML MSDOC ***/
d8f74681
 static const struct key_entry ooxml_keys[] = {
27948a03
     { "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 },
d8f74681
     { "characterswithspaces", "CharactersWithSpaces", MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
27948a03
     { "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 },
d8f74681
 
     /* Should NOT Exist */
27948a03
     { "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
 
27948a03
 /*** 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 },
     { "metadata",           "Metadata",               MSXML_JSON_WRKPTR | MSXML_JSON_ATTRIB },
     { "title",              "Title",                  MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "language",           "Language",               MSXML_JSON_WRKPTR | MSXML_JSON_VALUE },
     { "meta",               "MetaFields",             MSXML_JSON_WRKPTR | MSXML_JSON_ATTRIB | MSXML_JSON_VALUE | MSXML_JSON_COUNT | MSXML_JSON_MULTI },
     { "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);
 
 // clang-format on
 
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)
 {
288057e9
     int ret                 = CL_SUCCESS;
afd00a72
     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
 
288057e9
 static int ooxml_core_cb(int fd, const char *filepath, cli_ctx *ctx)
25556519
 {
3e8eed18
     int ret;
 
02840644
     UNUSEDPARAM(filepath);
 
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
 }
 
288057e9
 static int ooxml_extn_cb(int fd, const char *filepath, cli_ctx *ctx)
25556519
 {
3e8eed18
     int ret;
 
02840644
     UNUSEDPARAM(filepath);
 
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
 }
 
288057e9
 static int ooxml_content_cb(int fd, const char *filepath, cli_ctx *ctx)
25556519
 {
3e8eed18
     int ret = CL_SUCCESS, tmp, toval = 0, state;
288057e9
     int core = 0, extn = 0, cust = 0, dsig = 0;
     int mcore = 0, mextn = 0, mcust = 0;
25556519
     const xmlChar *name, *value, *CT, *PN;
     xmlTextReaderPtr reader = NULL;
     uint32_t loff;
 
02840644
     UNUSEDPARAM(filepath);
 
288057e9
     unsigned long sav_scansize    = ctx->scansize;
a2e6dcee
     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) {
288057e9
         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
 
288057e9
         ctx->scansize     = sav_scansize;
a2e6dcee
         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) {
288057e9
             name  = xmlTextReaderConstLocalName(reader);
25556519
             value = xmlTextReaderConstValue(reader);
             if (name == NULL || value == NULL) continue;
 
cd94be7a
             if (!xmlStrcmp(name, (const xmlChar *)"ContentType")) {
25556519
                 CT = value;
288057e9
             } 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*/
288057e9
             tmp = unzip_search_single(ctx, (const char *)(PN + 1), xmlStrlen(PN) - 1, &loff);
3e8eed18
             if (tmp == CL_ETIMEOUT) {
                 ret = tmp;
288057e9
             } else if (tmp != CL_VIRUS) {
3e8eed18
                 cli_dbgmsg("cli_process_ooxml: failed to find core properties file \"%s\"!\n", PN);
                 mcore++;
288057e9
             } else {
3e8eed18
                 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
             }
288057e9
         } else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.extended-properties+xml")) {
3e8eed18
             /* default: /docProps/app.xml */
288057e9
             tmp = unzip_search_single(ctx, (const char *)(PN + 1), xmlStrlen(PN) - 1, &loff);
3e8eed18
             if (tmp == CL_ETIMEOUT) {
                 ret = tmp;
288057e9
             } else if (tmp != CL_VIRUS) {
3e8eed18
                 cli_dbgmsg("cli_process_ooxml: failed to find extended properties file \"%s\"!\n", PN);
                 mextn++;
288057e9
             } else {
3e8eed18
                 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
             }
288057e9
         } else if (!xmlStrcmp(CT, (const xmlChar *)"application/vnd.openxmlformats-officedocument.custom-properties+xml")) {
3e8eed18
             /* default: /docProps/custom.xml */
288057e9
             tmp = unzip_search_single(ctx, (const char *)(PN + 1), xmlStrlen(PN) - 1, &loff);
3e8eed18
             if (tmp == CL_ETIMEOUT) {
                 ret = tmp;
288057e9
             } else if (tmp != CL_VIRUS) {
3e8eed18
                 cli_dbgmsg("cli_process_ooxml: failed to find custom properties file \"%s\"!\n", PN);
                 mcust++;
288057e9
             } else {
3e8eed18
                 cli_dbgmsg("ooxml_content_cb: found custom properties file \"%s\" @ %x\n", PN, loff);
                 /* custom properties are not parsed */
                 cust++;
25556519
             }
288057e9
         } 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;
     }
 
288057e9
 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");
288057e9
     } 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");
288057e9
     } 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");
288057e9
     } 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 */
288057e9
     ctx->scansize     = sav_scansize;
a2e6dcee
     ctx->scannedfiles = sav_scannedfiles;
 
25556519
     xmlTextReaderClose(reader);
     xmlFreeTextReader(reader);
     return ret;
 }
c6f7be55
 
288057e9
 static int ooxml_hwp_cb(int fd, const char *filepath, cli_ctx *ctx)
c6f7be55
 {
288057e9
     int ret                 = CL_SUCCESS;
c6f7be55
     xmlTextReaderPtr reader = NULL;
 
02840644
     UNUSEDPARAM(filepath);
 
c6f7be55
     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) {
288057e9
             case 0:
                 return CL_TYPE_OOXML_XL;
             case 1:
                 return CL_TYPE_OOXML_PPT;
             case 2:
                 return CL_TYPE_OOXML_WORD;
             case 3:
                 return CL_TYPE_OOXML_HWP;
             default:
                 return CL_SUCCESS;
c8c80ddf
         }
     }
 
     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;
288057e9
     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;
288057e9
         } else if (ret != CL_VIRUS) {
             cli_dbgmsg("cli_process_ooxml: failed to find "
                        "version.xml"
                        "!\n");
c6f7be55
             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;
288057e9
             } else if (ret != CL_VIRUS) {
                 cli_dbgmsg("cli_process_ooxml: failed to find "
                            "Contents/content.hpf"
                            "!\n");
c6f7be55
                 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;
288057e9
         } else if (ret != CL_VIRUS) {
             cli_dbgmsg("cli_process_ooxml: failed to find "
                        "[Content_Types].xml"
                        "!\n");
c6f7be55
             cli_json_parse_error(ctx->wrkproperty, "OOXML_ERROR_NO_CONTENT_TYPES");
             return CL_EFORMAT;
         }
288057e9
         cli_dbgmsg("cli_process_ooxml: found "
                    "[Content_Types].xml"
                    " @ %x\n",
                    loff);
c6f7be55
 
         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
 }