1313
1317
return ret == CL_BREAK ? CL_CLEAN : ret;
1316
/* Summary and Document Information Parsing to JSON */
1319
#define WINUNICODE 0x04B0
1320
#define PROPCNTLIMIT 25
1321
#define PROPSTRLIMIT 62
1323
#define sum16_endian_convert(v) le16_to_host((uint16_t)(v))
1324
#define sum32_endian_convert(v) le32_to_host((uint32_t)(v))
1325
#define sum64_endian_convert(v) le64_to_host((uint64_t)(v))
1327
enum summary_pidsi {
1328
SPID_CODEPAGE = 0x00000001,
1329
SPID_TITLE = 0x00000002,
1330
SPID_SUBJECT = 0x00000003,
1331
SPID_AUTHOR = 0x00000004,
1332
SPID_KEYWORDS = 0x00000005,
1333
SPID_COMMENTS = 0x00000006,
1334
SPID_TEMPLATE = 0x00000007,
1335
SPID_LASTAUTHOR = 0x00000008,
1336
SPID_REVNUMBER = 0x00000009,
1337
SPID_EDITTIME = 0x0000000A,
1338
SPID_LASTPRINTED = 0x0000000B,
1339
SPID_CREATEDTIME = 0x0000000C,
1340
SPID_MODIFIEDTIME = 0x0000000D,
1341
SPID_PAGECOUNT = 0x0000000E,
1342
SPID_WORDCOUNT = 0x0000000F,
1343
SPID_CHARCOUNT = 0x00000010,
1344
SPID_THUMBNAIL = 0x00000011,
1345
SPID_APPNAME = 0x00000012,
1346
SPID_SECURITY = 0x00000013
1350
DSPID_CODEPAGE = 0x00000001,
1351
DSPID_CATEGORY = 0x00000002,
1352
DSPID_PRESFORMAT = 0x00000003,
1353
DSPID_BYTECOUNT = 0x00000004,
1354
DSPID_LINECOUNT = 0x00000005,
1355
DSPID_PARCOUNT = 0x00000006,
1356
DSPID_SLIDECOUNT = 0x00000007,
1357
DSPID_NOTECOUNT = 0x00000008,
1358
DSPID_HIDDENCOUNT = 0x00000009,
1359
DSPID_MMCLIPCOUNT = 0x0000000A,
1360
DSPID_SCALE = 0x0000000B,
1361
DSPID_HEADINGPAIR = 0x0000000C, /* VT_VARIANT | VT_VECTOR */
1362
DSPID_DOCPARTS = 0x0000000D, /* VT_VECTOR | VT_LPSTR */
1363
DSPID_MANAGER = 0x0000000E,
1364
DSPID_COMPANY = 0x0000000F,
1365
DSPID_LINKSDIRTY = 0x00000010,
1366
DSPID_CCHWITHSPACES = 0x00000011,
1367
DSPID_SHAREDDOC = 0x00000013, /* must be false */
1368
DSPID_LINKBASE = 0x00000014, /* moved to user-defined */
1369
DSPID_HLINKS = 0x00000015, /* moved to user-defined */
1370
DSPID_HYPERLINKSCHANGED = 0x00000016,
1371
DSPID_VERSION = 0x00000017,
1372
DSPID_DIGSIG = 0x00000018,
1373
DSPID_CONTENTTYPE = 0x0000001A,
1374
DSPID_CONTENTSTATUS = 0x0000001B,
1375
DSPID_LANGUAGE = 0x0000001C,
1376
DSPID_DOCVERSION = 0x0000001D
1379
enum property_type {
1384
PT_FLOAT32 = 0x0004,
1385
PT_DOUBLE64 = 0x0005,
1395
PT_INT32v1 = 0x0016,
1396
PT_UINT32v1 = 0x0017,
1399
PT_FILETIME = 0x0040,
1401
/* More Types not currently handled */
1404
typedef struct summary_stub {
1405
uint16_t byte_order;
1407
uint32_t system; /* implementation-specific */
1410
uint32_t num_propsets; /* 1 or 2 */
1413
typedef struct propset_summary_entry {
1418
/* metadata structures */
1419
#define OLE2_SUMMARY_ERROR_TOOSMALL 0x00000001
1420
#define OLE2_SUMMARY_ERROR_OOB 0x00000002
1421
#define OLE2_SUMMARY_ERROR_DATABUF 0x00000004
1422
#define OLE2_SUMMARY_ERROR_INVALID_ENTRY 0x00000008
1423
#define OLE2_SUMMARY_LIMIT_PROPS 0x00000010
1424
#define OLE2_SUMMARY_FLAG_TIMEOUT 0x00000020
1425
#define OLE2_SUMMARY_FLAG_CODEPAGE 0x00000040
1426
#define OLE2_SUMMARY_FLAG_UNKNOWN_PROPID 0x00000080
1427
#define OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE 0x00000100
1428
#define OLE2_SUMMARY_FLAG_TRUNC_STR 0x00000200
1430
typedef struct summary_ctx {
1434
json_object *summary;
1438
/* propset metadata */
1439
uint32_t pssize; /* track from propset start, not tail start */
1443
/* property metadata */
1444
const char *propname;
1451
ole2_process_property(summary_ctx_t *sctx, unsigned char *databuf, uint32_t offset)
1453
uint16_t proptype, padding;
1454
int ret = CL_SUCCESS;
1456
if (cli_json_timeout_cycle_check(sctx->ctx, &(sctx->toval)) != CL_SUCCESS) {
1457
sctx->flags |= OLE2_SUMMARY_FLAG_TIMEOUT;
1461
if (offset+sizeof(proptype)+sizeof(padding) > sctx->pssize) {
1462
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1466
memcpy(&proptype, databuf+offset, sizeof(proptype));
1467
offset+=sizeof(proptype);
1468
memcpy(&padding, databuf+offset, sizeof(padding));
1469
offset+=sizeof(padding);
1470
/* endian conversion */
1471
proptype = sum16_endian_convert(proptype);
1473
//cli_dbgmsg("proptype: 0x%04x\n", proptype);
1475
cli_dbgmsg("ole2_process_property: invalid padding value, non-zero\n");
1476
sctx->flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
1483
ret = cli_jsonnull(sctx->summary, sctx->propname);
1488
if (offset+sizeof(dout) > sctx->pssize) {
1489
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1492
memcpy(&dout, databuf+offset, sizeof(dout));
1493
offset+=sizeof(dout);
1494
/* endian conversion */
1495
dout = sum16_endian_convert(dout);
1498
sctx->codepage = dout;
1500
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1507
if (offset+sizeof(dout) > sctx->pssize) {
1508
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1511
memcpy(&dout, databuf+offset, sizeof(dout));
1512
offset+=sizeof(dout);
1513
/* endian conversion */
1514
dout = sum32_endian_convert(dout);
1516
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1519
case PT_FLOAT32: /* review this please */
1522
if (offset+sizeof(dout) > sctx->pssize) {
1523
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1526
memcpy(&dout, databuf+offset, sizeof(dout));
1527
offset+=sizeof(dout);
1528
/* endian conversion */
1529
dout = sum32_endian_convert(dout);
1531
ret = cli_jsondouble(sctx->summary, sctx->propname, dout);
1535
case PT_DOUBLE64: /* review this please */
1538
if (offset+sizeof(dout) > sctx->pssize) {
1539
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1542
memcpy(&dout, databuf+offset, sizeof(dout));
1543
offset+=sizeof(dout);
1544
/* endian conversion */
1545
dout = sum64_endian_convert(dout);
1547
ret = cli_jsondouble(sctx->summary, sctx->propname, dout);
1553
if (offset+sizeof(dout) > sctx->pssize) {
1554
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1557
memcpy(&dout, databuf+offset, sizeof(dout));
1558
offset+=sizeof(dout);
1559
/* no need for endian conversion */
1561
ret = cli_jsonbool(sctx->summary, sctx->propname, dout);
1567
if (offset+sizeof(dout) > sctx->pssize) {
1568
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1571
memcpy(&dout, databuf+offset, sizeof(dout));
1572
offset+=sizeof(dout);
1573
/* no need for endian conversion */
1575
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1581
if (offset+sizeof(dout) > sctx->pssize) {
1582
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1585
memcpy(&dout, databuf+offset, sizeof(dout));
1586
offset+=sizeof(dout);
1587
/* no need for endian conversion */
1589
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1595
if (offset+sizeof(dout) > sctx->pssize) {
1596
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1599
memcpy(&dout, databuf+offset, sizeof(dout));
1600
offset+=sizeof(dout);
1601
/* endian conversion */
1602
dout = sum16_endian_convert(dout);
1605
sctx->codepage = dout;
1607
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1614
if (offset+sizeof(dout) > sctx->pssize) {
1615
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1618
memcpy(&dout, databuf+offset, sizeof(dout));
1619
offset+=sizeof(dout);
1620
/* endian conversion */
1621
dout = sum32_endian_convert(dout);
1623
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1629
if (offset+sizeof(dout) > sctx->pssize) {
1630
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1633
memcpy(&dout, databuf+offset, sizeof(dout));
1634
offset+=sizeof(dout);
1635
/* endian conversion */
1636
dout = sum64_endian_convert(dout);
1638
ret = cli_jsonint64(sctx->summary, sctx->propname, dout);
1644
if (offset+sizeof(dout) > sctx->pssize) {
1645
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1648
memcpy(&dout, databuf+offset, sizeof(dout));
1649
offset+=sizeof(dout);
1650
/* endian conversion */
1651
dout = sum64_endian_convert(dout);
1653
ret = cli_jsonint64(sctx->summary, sctx->propname, dout);
1658
if (sctx->codepage == 0) {
1659
cli_dbgmsg("ole2_propset_json: current codepage is unknown, cannot parse char stream\n");
1660
sctx->flags |= OLE2_SUMMARY_FLAG_CODEPAGE;
1663
else if (sctx->codepage != WINUNICODE) {
1667
if (offset+sizeof(strsize) > sctx->pssize) {
1668
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1672
memcpy(&strsize, databuf+offset, sizeof(strsize));
1673
offset+=sizeof(strsize);
1674
/* endian conversion */
1675
strsize = sum32_endian_convert(strsize);
1677
if (offset+strsize > sctx->pssize) {
1678
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1682
/* limitation on string length */
1683
if (strsize > PROPSTRLIMIT) {
1684
cli_dbgmsg("ole2_process_property: property string sized %lu truncated to size %lu\n",
1685
(unsigned long)strsize, (unsigned long)PROPSTRLIMIT);
1686
sctx->flags |= OLE2_SUMMARY_FLAG_TRUNC_STR;
1687
strsize = PROPSTRLIMIT;
1690
outstr = cli_calloc(strsize+1, 1); /* last char must be NULL */
1694
strncpy(outstr, (const char *)(databuf+offset), strsize);
1695
ret = cli_jsonstr(sctx->summary, sctx->propname, outstr);
1699
/* fall-through for unicode strings */
1703
char *outstr, *outstr2;
1705
if (offset+sizeof(strsize) > sctx->pssize) {
1706
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1709
memcpy(&strsize, databuf+offset, sizeof(strsize));
1710
offset+=sizeof(strsize);
1711
/* endian conversion */
1712
strsize = sum32_endian_convert(strsize);
1714
if (proptype == PT_LPSTR) { /* fall-through specifics */
1716
cli_dbgmsg("ole2_process_property: LPSTR using wchar not sized a multiple of 2\n");
1717
sctx->flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
1722
strsize*=2; /* Unicode strings are by length, not size */
1725
/* limitation on string length */
1726
if (strsize > (2*PROPSTRLIMIT)) {
1727
cli_dbgmsg("ole2_process_property: property string sized %lu truncated to size %lu\n",
1728
(unsigned long)strsize, (unsigned long)(2*PROPSTRLIMIT));
1729
sctx->flags |= OLE2_SUMMARY_FLAG_TRUNC_STR;
1730
strsize = (2*PROPSTRLIMIT);
1733
if (offset+strsize > sctx->pssize) {
1734
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1737
outstr = cli_calloc(strsize+2, 1); /* last two chars must be NULL */
1741
strncpy(outstr, (const char *)(databuf+offset), strsize);
1742
outstr2 = (char*)get_property_name2(outstr, strsize);
1744
ret = cli_jsonstr(sctx->summary, sctx->propname, outstr2);
1752
uint32_t ltime, htime;
1753
uint64_t wtime = 0, utime =0;
1755
if (offset+sizeof(ltime)+sizeof(htime) > sctx->pssize) {
1756
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1759
memcpy(<ime, databuf+offset, sizeof(ltime));
1760
offset+=sizeof(ltime);
1761
memcpy(&htime, databuf+offset, sizeof(htime));
1762
offset+=sizeof(ltime);
1763
ltime = sum32_endian_convert(ltime);
1764
htime = sum32_endian_convert(htime);
1766
/* UNIX timestamp formatting */
1771
utime = wtime / 10000000;
1772
utime -= 11644473600LL;
1774
if ((uint32_t)((utime & 0xFFFFFFFF00000000) >> 32)) {
1775
cli_dbgmsg("ole2_process_property: UNIX timestamp is larger than 32-bit number\n");
1778
ret = cli_jsonint(sctx->summary, sctx->propname, (uint32_t)(utime & 0xFFFFFFFF));
1783
cli_dbgmsg("ole2_process_property: unhandled property type 0x%04x for %s property\n",
1784
proptype, sctx->propname);
1785
sctx->flags |= OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE;
1791
static void ole2_translate_docsummary_propid(summary_ctx_t *sctx, uint32_t propid)
1794
case DSPID_CODEPAGE:
1795
sctx->writecp = 1; /* must be set ONLY for codepage */
1796
sctx->propname = "CodePage";
1798
case DSPID_CATEGORY:
1799
sctx->propname = "Category";
1801
case DSPID_PRESFORMAT:
1802
sctx->propname = "PresentationTarget";
1804
case DSPID_BYTECOUNT:
1805
sctx->propname = "Bytes";
1807
case DSPID_LINECOUNT:
1808
sctx->propname = "Lines";
1810
case DSPID_PARCOUNT:
1811
sctx->propname = "Paragraphs";
1813
case DSPID_SLIDECOUNT:
1814
sctx->propname = "Slides";
1816
case DSPID_NOTECOUNT:
1817
sctx->propname = "Notes";
1819
case DSPID_HIDDENCOUNT:
1820
sctx->propname = "HiddenSlides";
1822
case DSPID_MMCLIPCOUNT:
1823
sctx->propname = "MMClips";
1826
sctx->propname = "Scale";
1828
case DSPID_HEADINGPAIR: /* VT_VARIANT | VT_VECTOR */
1829
sctx->propname = "HeadingPairs";
1831
case DSPID_DOCPARTS: /* VT_VECTOR | VT_LPSTR */
1832
sctx->propname = "DocPartTitles";
1835
sctx->propname = "Manager";
1838
sctx->propname = "Company";
1840
case DSPID_LINKSDIRTY:
1841
sctx->propname = "LinksDirty";
1843
case DSPID_CCHWITHSPACES:
1844
sctx->propname = "Char&WSCount";
1846
case DSPID_SHAREDDOC: /* SHOULD BE FALSE! */
1847
sctx->propname = "SharedDoc";
1849
case DSPID_LINKBASE: /* moved to user-defined */
1850
sctx->propname = "LinkBase";
1852
case DSPID_HLINKS: /* moved to user-defined */
1853
sctx->propname = "HyperLinks";
1855
case DSPID_HYPERLINKSCHANGED:
1856
sctx->propname = "HyperLinksChanged";
1859
sctx->propname = "Version";
1862
sctx->propname = "DigitalSig";
1864
case DSPID_CONTENTTYPE:
1865
sctx->propname = "ContentType";
1867
case DSPID_CONTENTSTATUS:
1868
sctx->propname = "ContentStatus";
1870
case DSPID_LANGUAGE:
1871
sctx->propname = "Language";
1873
case DSPID_DOCVERSION:
1874
sctx->propname = "DocVersion";
1877
cli_dbgmsg("ole2_docsum_propset_json: unrecognized propid!\n");
1878
sctx->flags |= OLE2_SUMMARY_FLAG_UNKNOWN_PROPID;
1882
static void ole2_translate_summary_propid(summary_ctx_t *sctx, uint32_t propid)
1886
sctx->writecp = 1; /* must be set ONLY for codepage */
1887
sctx->propname = "CodePage";
1890
sctx->propname = "Title";
1893
sctx->propname = "Subject";
1896
sctx->propname = "Author";
1899
sctx->propname = "Keywords";
1902
sctx->propname = "Comments";
1905
sctx->propname = "Template";
1907
case SPID_LASTAUTHOR:
1908
sctx->propname = "LastAuthor";
1910
case SPID_REVNUMBER:
1911
sctx->propname = "RevNumber";
1914
sctx->propname = "EditTime";
1916
case SPID_LASTPRINTED:
1917
sctx->propname = "LastPrinted";
1919
case SPID_CREATEDTIME:
1920
sctx->propname = "CreatedTime";
1922
case SPID_MODIFIEDTIME:
1923
sctx->propname = "ModifiedTime";
1925
case SPID_PAGECOUNT:
1926
sctx->propname = "PageCount";
1928
case SPID_WORDCOUNT:
1929
sctx->propname = "WordCount";
1931
case SPID_CHARCOUNT:
1932
sctx->propname = "CharCount";
1934
case SPID_THUMBNAIL:
1935
sctx->propname = "Thumbnail";
1938
sctx->propname = "AppName";
1941
sctx->propname = "Security";
1944
cli_dbgmsg("ole2_translate_summary_propid: unrecognized propid!\n");
1945
sctx->flags |= OLE2_SUMMARY_FLAG_UNKNOWN_PROPID;
1949
static int ole2_summary_propset_json(summary_ctx_t *sctx, off_t offset)
1951
unsigned char *hdr, *ps;
1952
uint32_t numprops, limitprops;
1953
off_t foff = offset, psoff = 0;
1958
cli_dbgmsg("in ole2_summary_propset_json\n");
1960
/* summary ctx propset-specific setup*/
1963
sctx->propname = NULL;
1965
/* examine property set metadata */
1966
if ((foff+(2*sizeof(uint32_t))) > sctx->maplen) {
1967
sctx->flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
1970
hdr = (unsigned char*)fmap_need_off_once(sctx->sfmap, foff, (2*sizeof(uint32_t)));
1972
sctx->flags |= OLE2_SUMMARY_ERROR_DATABUF;
1975
//foff+=(2*sizeof(uint32_t)); // keep foff pointing to start of propset segment
1976
psoff+=(2*sizeof(uint32_t));
1977
memcpy(&(sctx->pssize), hdr, sizeof(sctx->pssize));
1978
memcpy(&numprops, hdr+sizeof(sctx->pssize), sizeof(numprops));
1979
/* endian conversion */
1980
sctx->pssize = sum32_endian_convert(sctx->pssize);
1981
numprops = sum32_endian_convert(numprops);
1982
cli_dbgmsg("ole2_summary_propset_json: pssize: %u, numprops: %u\n", sctx->pssize, numprops);
1983
if (numprops > PROPCNTLIMIT) {
1984
sctx->flags |= OLE2_SUMMARY_LIMIT_PROPS;
1985
limitprops = PROPCNTLIMIT;
1988
limitprops = numprops;
1990
cli_dbgmsg("ole2_summary_propset_json: processing %u of %u (%u max) propeties\n",
1991
limitprops, numprops, PROPCNTLIMIT);
1993
/* extract remaining fragment of propset */
1994
if ((size_t)(foff+(sctx->pssize)) > (size_t)(sctx->maplen)) {
1995
sctx->flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
1998
ps = (unsigned char*)fmap_need_off_once(sctx->sfmap, foff, sctx->pssize);
2000
sctx->flags |= OLE2_SUMMARY_ERROR_DATABUF;
2004
/* iterate over the properties */
2005
for (i = 0; i < limitprops; ++i) {
2006
uint32_t propid, propoff;
2008
if (psoff+sizeof(propid)+sizeof(poffset) > sctx->pssize) {
2009
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
2012
memcpy(&propid, ps+psoff, sizeof(propid));
2013
psoff+=sizeof(propid);
2014
memcpy(&propoff, ps+psoff, sizeof(propoff));
2015
psoff+=sizeof(propoff);
2016
/* endian conversion */
2017
propid = sum32_endian_convert(propid);
2018
propoff = sum32_endian_convert(propoff);
2019
cli_dbgmsg("ole2_summary_propset_json: propid: 0x%08x, propoff: %u\n", propid, propoff);
2021
sctx->propname = NULL; sctx->writecp = 0;
2023
ole2_translate_summary_propid(sctx, propid);
2025
ole2_translate_docsummary_propid(sctx, propid);
2027
if (sctx->propname != NULL) {
2028
ret = ole2_process_property(sctx, ps, propoff);
2029
if (ret != CL_SUCCESS)
2033
/* add unknown propid flag */
2040
static int cli_ole2_summary_json_cleanup(summary_ctx_t *sctx, int retcode)
2044
cli_dbgmsg("in cli_ole2_summary_json_cleanup: %d[%x]\n", retcode, sctx->flags);
2047
funmap(sctx->sfmap);
2051
jarr = cli_jsonarray(sctx->summary, "ParseErrors");
2054
if (sctx->flags & OLE2_SUMMARY_ERROR_TOOSMALL) {
2055
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_TOOSMALL");
2057
if (sctx->flags & OLE2_SUMMARY_ERROR_OOB) {
2058
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_OOB");
2060
if (sctx->flags & OLE2_SUMMARY_ERROR_DATABUF) {
2061
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_DATABUF");
2063
if (sctx->flags & OLE2_SUMMARY_ERROR_INVALID_ENTRY) {
2064
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_INVALID_ENTRY");
2066
if (sctx->flags & OLE2_SUMMARY_LIMIT_PROPS) {
2067
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_LIMIT_PROPS");
2069
if (sctx->flags & OLE2_SUMMARY_FLAG_TIMEOUT) {
2070
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_TIMEOUT");
2072
if (sctx->flags & OLE2_SUMMARY_FLAG_CODEPAGE) {
2073
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_CODEPAGE");
2075
if (sctx->flags & OLE2_SUMMARY_FLAG_UNKNOWN_PROPID) {
2076
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_UNKNOWN_PROPID");
2078
if (sctx->flags & OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE) {
2079
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE");
2081
if (sctx->flags & OLE2_SUMMARY_FLAG_TRUNC_STR) {
2082
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_TRUNC_STR");
2090
#endif /* HAVE_JSON */
2093
int cli_ole2_summary_json(cli_ctx *ctx, int fd, int mode)
2098
unsigned char *databuf;
2099
summary_stub_t sumstub;
2100
propset_entry_t pentry;
2101
int ret = CL_SUCCESS;
2103
cli_dbgmsg("in cli_ole2_summary_json\n");
2105
/* preliminary sanity checks */
2111
cli_dbgmsg("ole2_summary_json: invalid file descriptor\n");
2112
return CL_ENULLARG; /* placeholder */
2115
if (mode != 0 && mode != 1) {
2116
cli_dbgmsg("ole2_summary_json: invalid mode specified\n");
2117
return CL_ENULLARG; /* placeholder */
2120
/* summary ctx setup */
2121
memset(&sctx, 0, sizeof(sctx));
2125
if (FSTAT(fd, &statbuf) == -1) {
2126
cli_dbgmsg("ole2_summary_json: cannot stat file descriptor\n");
2130
sctx.sfmap = fmap(fd, 0, statbuf.st_size);
2132
cli_dbgmsg("ole2_summary_json: failed to get fmap\n");
2135
sctx.maplen = sctx.sfmap->len;
2136
cli_dbgmsg("ole2_summary_json: streamsize: %u\n", sctx.maplen);
2139
sctx.summary = cli_jsonobj(ctx->wrkproperty, "SummaryInfo");
2141
sctx.summary = cli_jsonobj(ctx->wrkproperty, "DocSummaryInfo");
2142
if (!sctx.summary) {
2143
cli_errmsg("ole2_summary_json: no memory for json object.\n");
2144
return cli_ole2_summary_json_cleanup(&sctx, CL_EMEM);
2150
/* acquire property stream metadata */
2151
if (sctx.maplen < sizeof(summary_stub_t)) {
2152
sctx.flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
2153
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);
2155
databuf = (unsigned char*)fmap_need_off_once(sctx.sfmap, foff, sizeof(summary_stub_t));
2157
sctx.flags |= OLE2_SUMMARY_ERROR_DATABUF;
2158
return cli_ole2_summary_json_cleanup(&sctx, CL_EREAD);
2160
foff += sizeof(summary_stub_t);
2161
memcpy(&sumstub, databuf, sizeof(summary_stub_t));
2163
/* endian conversion and checks */
2164
sumstub.byte_order = le16_to_host(sumstub.byte_order);
2165
if (sumstub.byte_order != 0xfffe) {
2166
cli_dbgmsg("ole2_summary_json: byteorder 0x%x is invalid\n", sumstub.byte_order);
2167
sctx.flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
2168
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);;
2170
sumstub.version = sum16_endian_convert(sumstub.version); /*unused*/
2171
sumstub.system = sum32_endian_convert(sumstub.system); /*unused*/
2172
sumstub.num_propsets = sum32_endian_convert(sumstub.num_propsets);
2173
if (sumstub.num_propsets != 1 && sumstub.num_propsets != 2) {
2174
cli_dbgmsg("ole2_summary_json: invalid number of property sets\n");
2175
sctx.flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
2176
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);
2179
cli_dbgmsg("ole2_summary_json: byteorder 0x%x\n", sumstub.byte_order);
2180
cli_dbgmsg("ole2_summary_json: %u property set(s) detected\n", sumstub.num_propsets);
2182
/* first property set (index=0) is always SummaryInfo or DocSummaryInfo */
2183
if ((sctx.maplen-foff) < sizeof(propset_entry_t)) {
2184
sctx.flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
2185
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);
2187
databuf = (unsigned char*)fmap_need_off_once(sctx.sfmap, foff, sizeof(propset_entry_t));
2189
sctx.flags |= OLE2_SUMMARY_ERROR_DATABUF;
2190
return cli_ole2_summary_json_cleanup(&sctx, CL_EREAD);
2192
foff += sizeof(propset_entry_t);
2193
memcpy(&pentry, databuf, sizeof(propset_entry_t));
2194
/* endian conversion */
2195
pentry.offset = sum32_endian_convert(pentry.offset);
2197
if ((ret = ole2_summary_propset_json(&sctx, pentry.offset)) != CL_SUCCESS) {
2198
return cli_ole2_summary_json_cleanup(&sctx, ret);
2201
/* second property set (index=1) is always a custom property set (if present) */
2202
if (sumstub.num_propsets == 2) {
2203
cli_jsonbool(ctx->wrkproperty, "HasUserDefinedProperties", 1);
2206
return cli_ole2_summary_json_cleanup(&sctx, CL_SUCCESS);
2208
#endif /* HAVE_JSON */