~ubuntu-branches/ubuntu/vivid/clamav/vivid

« back to all changes in this revision

Viewing changes to libclamav/ole2_extract.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Andrzej Siewior, Sebastian Andrzej Siewior, Scott Kitterman
  • Date: 2014-11-19 22:28:22 UTC
  • mfrom: (0.48.11 sid)
  • Revision ID: package-import@ubuntu.com-20141119222822-7ehs2eo3wtu99ev3
Tags: 0.98.5+dfsg-1
[ Sebastian Andrzej Siewior ]
* import new upsstream version, refresh patches:
  dropped:
   - LLVM-3.5-version-check-update.patch
   - add-support-for-LLVM-3.5.patch
   - fix-test-failure-on-powerpc-again.patch
  updated:
   - hardcode-LLVM-linker-flag-because-llvm-config-return
   - added "bb-10731-Allow-to-specificy-a-group-for-the-socket-o" as
     dependecy for "clamav-milter-add-additinal-SMFIF_-flags-before-invo"
  (Closes: #763300)
* Add "Bump-.so-version-number", likely the RPM version of 769384.
* Add "llvm-don-t-use-system-libs", since we don't link against .a libs, we
  don't need the deps either.

[ Scott Kitterman ]
* Update libclamav6: embedded-library lintian override for new libclamav6 so
  version

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <fcntl.h>
29
29
#include <stdio.h>
30
30
#include <string.h>
 
31
#include <ctype.h>
 
32
#include <stdlib.h>
 
33
#include <errno.h>
 
34
#include <conv.h>
31
35
#ifdef  HAVE_UNISTD_H
32
36
#include <unistd.h>
33
37
#endif
34
 
#include <ctype.h>
35
 
#include <stdlib.h>
36
 
#include "clamav.h"
37
38
 
38
39
#include "clamav.h"
39
40
#include "cltypes.h"
42
43
#include "scanners.h"
43
44
#include "fmap.h"
44
45
#include "json_api.h"
 
46
#if HAVE_JSON
 
47
#include "msdoc.h"
 
48
#endif
45
49
 
46
50
#ifdef DEBUG_OLE2_LIST
47
51
#define ole2_listmsg(...) cli_dbgmsg( __VA_ARGS__)
1312
1316
 
1313
1317
    return ret == CL_BREAK ? CL_CLEAN : ret;
1314
1318
}
1315
 
 
1316
 
/* Summary and Document Information Parsing to JSON */
1317
 
#if HAVE_JSON
1318
 
 
1319
 
#define WINUNICODE 0x04B0
1320
 
#define PROPCNTLIMIT 25
1321
 
#define PROPSTRLIMIT 62
1322
 
 
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))
1326
 
 
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
1347
 
};
1348
 
 
1349
 
enum docsum_pidsi {
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
1377
 
};
1378
 
 
1379
 
enum property_type {
1380
 
    PT_EMPTY    = 0x0000,
1381
 
    PT_NULL     = 0x0001,
1382
 
    PT_INT16    = 0x0002,
1383
 
    PT_INT32    = 0x0003,
1384
 
    PT_FLOAT32  = 0x0004,
1385
 
    PT_DOUBLE64 = 0x0005,
1386
 
    PT_DATE     = 0x0007,
1387
 
    PT_BSTR     = 0x0008,
1388
 
    PT_BOOL    = 0x000B,
1389
 
    PT_INT8v1  = 0x0010,
1390
 
    PT_UINT8   = 0x0011,
1391
 
    PT_UINT16  = 0x0012,
1392
 
    PT_UINT32  = 0x0013,
1393
 
    PT_INT64   = 0x0014,
1394
 
    PT_UINT64  = 0x0015,
1395
 
    PT_INT32v1  = 0x0016,
1396
 
    PT_UINT32v1 = 0x0017,
1397
 
    PT_LPSTR  = 0x001E,
1398
 
    PT_LPWSTR = 0x001F,
1399
 
    PT_FILETIME = 0x0040,
1400
 
        
1401
 
    /* More Types not currently handled */
1402
 
};
1403
 
 
1404
 
typedef struct summary_stub {
1405
 
    uint16_t byte_order;
1406
 
    uint16_t version;
1407
 
    uint32_t system; /* implementation-specific */
1408
 
    uint8_t CLSID[16];
1409
 
 
1410
 
    uint32_t num_propsets; /* 1 or 2 */
1411
 
} summary_stub_t;
1412
 
 
1413
 
typedef struct propset_summary_entry {
1414
 
    uint8_t FMTID[16];
1415
 
    uint32_t offset;
1416
 
} propset_entry_t;
1417
 
 
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
1429
 
 
1430
 
typedef struct summary_ctx {
1431
 
    cli_ctx *ctx;
1432
 
    int mode;
1433
 
    fmap_t *sfmap;
1434
 
    json_object *summary;
1435
 
    size_t maplen;
1436
 
    uint32_t flags;
1437
 
 
1438
 
    /* propset metadata */
1439
 
    uint32_t pssize; /* track from propset start, not tail start */
1440
 
    int16_t codepage;
1441
 
    int writecp;
1442
 
 
1443
 
    /* property metadata */
1444
 
    const char *propname;
1445
 
 
1446
 
    /* timeout meta */
1447
 
    int toval;
1448
 
} summary_ctx_t;
1449
 
 
1450
 
static int
1451
 
ole2_process_property(summary_ctx_t *sctx, unsigned char *databuf, uint32_t offset)
1452
 
{
1453
 
    uint16_t proptype, padding;
1454
 
    int ret = CL_SUCCESS;
1455
 
 
1456
 
    if (cli_json_timeout_cycle_check(sctx->ctx, &(sctx->toval)) != CL_SUCCESS) {
1457
 
        sctx->flags |= OLE2_SUMMARY_FLAG_TIMEOUT;
1458
 
        return CL_ETIMEOUT;
1459
 
    }
1460
 
 
1461
 
    if (offset+sizeof(proptype)+sizeof(padding) > sctx->pssize) {
1462
 
        sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1463
 
        return CL_EFORMAT;
1464
 
    }
1465
 
 
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);
1472
 
 
1473
 
    //cli_dbgmsg("proptype: 0x%04x\n", proptype);
1474
 
    if (padding != 0) {
1475
 
        cli_dbgmsg("ole2_process_property: invalid padding value, non-zero\n");
1476
 
        sctx->flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
1477
 
        return CL_EFORMAT;
1478
 
    }
1479
 
 
1480
 
    switch (proptype) {
1481
 
    case PT_EMPTY:
1482
 
    case PT_NULL:
1483
 
        ret = cli_jsonnull(sctx->summary, sctx->propname);
1484
 
        break;
1485
 
    case PT_INT16:
1486
 
        {
1487
 
            int16_t dout;
1488
 
            if (offset+sizeof(dout) > sctx->pssize) {
1489
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1490
 
                return CL_EFORMAT;
1491
 
            }
1492
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1493
 
            offset+=sizeof(dout);
1494
 
            /* endian conversion */
1495
 
            dout = sum16_endian_convert(dout);
1496
 
 
1497
 
            if (sctx->writecp)
1498
 
                sctx->codepage = dout;
1499
 
 
1500
 
            ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1501
 
            break;
1502
 
        }
1503
 
    case PT_INT32:
1504
 
    case PT_INT32v1:
1505
 
        {
1506
 
            int32_t dout;
1507
 
            if (offset+sizeof(dout) > sctx->pssize) {
1508
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1509
 
                return CL_EFORMAT;
1510
 
            }
1511
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1512
 
            offset+=sizeof(dout);
1513
 
            /* endian conversion */
1514
 
            dout = sum32_endian_convert(dout);
1515
 
 
1516
 
            ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1517
 
            break;
1518
 
        }
1519
 
    case PT_FLOAT32: /* review this please */
1520
 
        {
1521
 
            float dout;
1522
 
            if (offset+sizeof(dout) > sctx->pssize) {
1523
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1524
 
                return CL_EFORMAT;
1525
 
            }
1526
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1527
 
            offset+=sizeof(dout);
1528
 
            /* endian conversion */
1529
 
            dout = sum32_endian_convert(dout);
1530
 
 
1531
 
            ret = cli_jsondouble(sctx->summary, sctx->propname, dout);
1532
 
            break;
1533
 
        }
1534
 
    case PT_DATE:
1535
 
    case PT_DOUBLE64: /* review this please */
1536
 
        {
1537
 
            double dout;
1538
 
            if (offset+sizeof(dout) > sctx->pssize) {
1539
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1540
 
                return CL_EFORMAT;
1541
 
            }
1542
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1543
 
            offset+=sizeof(dout);
1544
 
            /* endian conversion */
1545
 
            dout = sum64_endian_convert(dout);
1546
 
 
1547
 
            ret = cli_jsondouble(sctx->summary, sctx->propname, dout);
1548
 
            break;
1549
 
        }
1550
 
    case PT_BOOL:
1551
 
        {
1552
 
            uint16_t dout;
1553
 
            if (offset+sizeof(dout) > sctx->pssize) {
1554
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1555
 
                return CL_EFORMAT;
1556
 
            }
1557
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1558
 
            offset+=sizeof(dout);
1559
 
            /* no need for endian conversion */
1560
 
 
1561
 
            ret = cli_jsonbool(sctx->summary, sctx->propname, dout);
1562
 
            break;
1563
 
        }
1564
 
    case PT_INT8v1:
1565
 
        {
1566
 
            int8_t dout;
1567
 
            if (offset+sizeof(dout) > sctx->pssize) {
1568
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1569
 
                return CL_EFORMAT;
1570
 
            }
1571
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1572
 
            offset+=sizeof(dout);
1573
 
            /* no need for endian conversion */
1574
 
 
1575
 
            ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1576
 
            break;
1577
 
        }
1578
 
    case PT_UINT8:
1579
 
        {
1580
 
            uint8_t dout;
1581
 
            if (offset+sizeof(dout) > sctx->pssize) {
1582
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1583
 
                return CL_EFORMAT;
1584
 
            }
1585
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1586
 
            offset+=sizeof(dout);
1587
 
            /* no need for endian conversion */
1588
 
 
1589
 
            ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1590
 
            break;
1591
 
        }
1592
 
    case PT_UINT16:
1593
 
        {
1594
 
            uint16_t dout;
1595
 
            if (offset+sizeof(dout) > sctx->pssize) {
1596
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1597
 
                return CL_EFORMAT;
1598
 
            }
1599
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1600
 
            offset+=sizeof(dout);
1601
 
            /* endian conversion */
1602
 
            dout = sum16_endian_convert(dout);
1603
 
 
1604
 
            if (sctx->writecp)
1605
 
                sctx->codepage = dout;
1606
 
 
1607
 
            ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1608
 
            break;
1609
 
        }
1610
 
    case PT_UINT32:
1611
 
    case PT_UINT32v1:
1612
 
        {
1613
 
            uint32_t dout;
1614
 
            if (offset+sizeof(dout) > sctx->pssize) {
1615
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1616
 
                return CL_EFORMAT;
1617
 
            }
1618
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1619
 
            offset+=sizeof(dout);
1620
 
            /* endian conversion */
1621
 
            dout = sum32_endian_convert(dout);
1622
 
 
1623
 
            ret = cli_jsonint(sctx->summary, sctx->propname, dout);
1624
 
            break;
1625
 
        }
1626
 
    case PT_INT64:
1627
 
        {
1628
 
            int64_t dout;
1629
 
            if (offset+sizeof(dout) > sctx->pssize) {
1630
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1631
 
                return CL_EFORMAT;
1632
 
            }
1633
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1634
 
            offset+=sizeof(dout);
1635
 
            /* endian conversion */
1636
 
            dout = sum64_endian_convert(dout);
1637
 
 
1638
 
            ret = cli_jsonint64(sctx->summary, sctx->propname, dout);
1639
 
            break;
1640
 
        }
1641
 
    case PT_UINT64:
1642
 
        {
1643
 
            uint64_t dout;
1644
 
            if (offset+sizeof(dout) > sctx->pssize) {
1645
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1646
 
                return CL_EFORMAT;
1647
 
            }
1648
 
            memcpy(&dout, databuf+offset, sizeof(dout));
1649
 
            offset+=sizeof(dout);
1650
 
            /* endian conversion */
1651
 
            dout = sum64_endian_convert(dout);
1652
 
 
1653
 
            ret = cli_jsonint64(sctx->summary, sctx->propname, dout);
1654
 
            break;
1655
 
        }
1656
 
    case PT_BSTR:
1657
 
    case PT_LPSTR:
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;
1661
 
            break;
1662
 
        }
1663
 
        else if (sctx->codepage != WINUNICODE) {
1664
 
            uint32_t strsize;
1665
 
            char *outstr;
1666
 
 
1667
 
            if (offset+sizeof(strsize) > sctx->pssize) {
1668
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1669
 
                return CL_EFORMAT;
1670
 
            }
1671
 
 
1672
 
            memcpy(&strsize, databuf+offset, sizeof(strsize));
1673
 
            offset+=sizeof(strsize);
1674
 
            /* endian conversion */
1675
 
            strsize = sum32_endian_convert(strsize);
1676
 
 
1677
 
            if (offset+strsize > sctx->pssize) {
1678
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1679
 
                return CL_EFORMAT;
1680
 
            }
1681
 
 
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;
1688
 
            }
1689
 
 
1690
 
            outstr = cli_calloc(strsize+1, 1); /* last char must be NULL */
1691
 
            if (!outstr) {
1692
 
                return CL_EMEM;
1693
 
            }
1694
 
            strncpy(outstr, (const char *)(databuf+offset), strsize);
1695
 
            ret = cli_jsonstr(sctx->summary, sctx->propname, outstr);
1696
 
            free(outstr);
1697
 
            break;
1698
 
        }
1699
 
        /* fall-through for unicode strings */
1700
 
    case PT_LPWSTR:
1701
 
        {
1702
 
            uint32_t strsize;
1703
 
            char *outstr, *outstr2;
1704
 
 
1705
 
            if (offset+sizeof(strsize) > sctx->pssize) {
1706
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1707
 
                return CL_EFORMAT;
1708
 
            }
1709
 
            memcpy(&strsize, databuf+offset, sizeof(strsize));
1710
 
            offset+=sizeof(strsize);
1711
 
            /* endian conversion */
1712
 
            strsize = sum32_endian_convert(strsize);
1713
 
            
1714
 
            if (proptype == PT_LPSTR) { /* fall-through specifics */
1715
 
                if (strsize % 2) {
1716
 
                    cli_dbgmsg("ole2_process_property: LPSTR using wchar not sized a multiple of 2\n");
1717
 
                    sctx->flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
1718
 
                    return CL_EFORMAT;
1719
 
                }
1720
 
            }
1721
 
            else {
1722
 
                strsize*=2; /* Unicode strings are by length, not size */
1723
 
            }
1724
 
 
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);
1731
 
            }
1732
 
 
1733
 
            if (offset+strsize > sctx->pssize) {
1734
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1735
 
                return CL_EFORMAT;
1736
 
            }
1737
 
            outstr = cli_calloc(strsize+2, 1); /* last two chars must be NULL */
1738
 
            if (!outstr) {
1739
 
                return CL_EMEM;
1740
 
            }
1741
 
            strncpy(outstr, (const char *)(databuf+offset), strsize);
1742
 
            outstr2 = (char*)get_property_name2(outstr, strsize);
1743
 
            if (outstr2) {
1744
 
                ret = cli_jsonstr(sctx->summary, sctx->propname, outstr2);
1745
 
                free(outstr2);
1746
 
            }
1747
 
            free(outstr);
1748
 
            break;
1749
 
        }
1750
 
    case PT_FILETIME:
1751
 
        {
1752
 
            uint32_t ltime, htime;
1753
 
            uint64_t wtime = 0, utime =0;
1754
 
 
1755
 
            if (offset+sizeof(ltime)+sizeof(htime) > sctx->pssize) {
1756
 
                sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
1757
 
                return CL_EFORMAT;
1758
 
            }
1759
 
            memcpy(&ltime, 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);
1765
 
 
1766
 
            /* UNIX timestamp formatting */
1767
 
            wtime = htime;
1768
 
            wtime <<= 32;
1769
 
            wtime |= ltime;
1770
 
 
1771
 
            utime = wtime / 10000000;
1772
 
            utime -= 11644473600LL;
1773
 
 
1774
 
            if ((uint32_t)((utime & 0xFFFFFFFF00000000) >> 32)) {
1775
 
                cli_dbgmsg("ole2_process_property: UNIX timestamp is larger than 32-bit number\n");
1776
 
            }
1777
 
            else {
1778
 
                ret = cli_jsonint(sctx->summary, sctx->propname, (uint32_t)(utime & 0xFFFFFFFF));
1779
 
            }
1780
 
            break;
1781
 
        }
1782
 
    default:
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;
1786
 
    }
1787
 
 
1788
 
    return ret;
1789
 
}
1790
 
 
1791
 
static void ole2_translate_docsummary_propid(summary_ctx_t *sctx, uint32_t propid)
1792
 
{
1793
 
    switch(propid) {
1794
 
    case DSPID_CODEPAGE:
1795
 
        sctx->writecp = 1; /* must be set ONLY for codepage */
1796
 
        sctx->propname = "CodePage";
1797
 
        break;
1798
 
    case DSPID_CATEGORY:
1799
 
        sctx->propname = "Category";
1800
 
        break;
1801
 
    case DSPID_PRESFORMAT:
1802
 
        sctx->propname = "PresentationTarget";
1803
 
        break;
1804
 
    case DSPID_BYTECOUNT:
1805
 
        sctx->propname = "Bytes";
1806
 
        break;
1807
 
    case DSPID_LINECOUNT:
1808
 
        sctx->propname = "Lines";
1809
 
        break;
1810
 
    case DSPID_PARCOUNT:
1811
 
        sctx->propname = "Paragraphs";
1812
 
        break;
1813
 
    case DSPID_SLIDECOUNT:
1814
 
        sctx->propname = "Slides";
1815
 
        break;
1816
 
    case DSPID_NOTECOUNT:
1817
 
        sctx->propname = "Notes";
1818
 
        break;
1819
 
    case DSPID_HIDDENCOUNT:
1820
 
        sctx->propname = "HiddenSlides";
1821
 
        break;
1822
 
    case DSPID_MMCLIPCOUNT:
1823
 
        sctx->propname = "MMClips";
1824
 
        break;
1825
 
    case DSPID_SCALE:
1826
 
        sctx->propname = "Scale";
1827
 
        break;
1828
 
    case DSPID_HEADINGPAIR: /* VT_VARIANT | VT_VECTOR */
1829
 
        sctx->propname = "HeadingPairs";
1830
 
        break;
1831
 
    case DSPID_DOCPARTS:    /* VT_VECTOR | VT_LPSTR */
1832
 
        sctx->propname = "DocPartTitles";
1833
 
        break;
1834
 
    case DSPID_MANAGER:
1835
 
        sctx->propname = "Manager";
1836
 
        break;
1837
 
    case DSPID_COMPANY:
1838
 
        sctx->propname = "Company";
1839
 
        break;
1840
 
    case DSPID_LINKSDIRTY:
1841
 
        sctx->propname = "LinksDirty";
1842
 
        break;
1843
 
    case DSPID_CCHWITHSPACES:
1844
 
        sctx->propname = "Char&WSCount";
1845
 
        break;
1846
 
    case DSPID_SHAREDDOC:   /* SHOULD BE FALSE! */
1847
 
        sctx->propname = "SharedDoc";
1848
 
        break;
1849
 
    case DSPID_LINKBASE:    /* moved to user-defined */
1850
 
        sctx->propname = "LinkBase";
1851
 
        break;
1852
 
    case DSPID_HLINKS:      /* moved to user-defined */
1853
 
        sctx->propname = "HyperLinks";
1854
 
        break;
1855
 
    case DSPID_HYPERLINKSCHANGED:
1856
 
        sctx->propname = "HyperLinksChanged";
1857
 
        break;
1858
 
    case DSPID_VERSION:
1859
 
        sctx->propname = "Version";
1860
 
        break;
1861
 
    case DSPID_DIGSIG:
1862
 
        sctx->propname = "DigitalSig";
1863
 
        break;
1864
 
    case DSPID_CONTENTTYPE:
1865
 
        sctx->propname = "ContentType";
1866
 
        break;
1867
 
    case DSPID_CONTENTSTATUS:
1868
 
        sctx->propname = "ContentStatus";
1869
 
        break;
1870
 
    case DSPID_LANGUAGE:
1871
 
        sctx->propname = "Language";
1872
 
        break;
1873
 
    case DSPID_DOCVERSION:
1874
 
        sctx->propname = "DocVersion";
1875
 
        break;
1876
 
    default:
1877
 
        cli_dbgmsg("ole2_docsum_propset_json: unrecognized propid!\n");
1878
 
        sctx->flags |= OLE2_SUMMARY_FLAG_UNKNOWN_PROPID;
1879
 
    }
1880
 
}
1881
 
 
1882
 
static void ole2_translate_summary_propid(summary_ctx_t *sctx, uint32_t propid)
1883
 
{
1884
 
    switch(propid) {
1885
 
    case SPID_CODEPAGE:
1886
 
        sctx->writecp = 1; /* must be set ONLY for codepage */
1887
 
        sctx->propname = "CodePage";
1888
 
        break;
1889
 
    case SPID_TITLE:
1890
 
        sctx->propname = "Title";
1891
 
        break;
1892
 
    case SPID_SUBJECT:
1893
 
        sctx->propname = "Subject";
1894
 
        break;
1895
 
    case SPID_AUTHOR:
1896
 
        sctx->propname = "Author";
1897
 
        break;
1898
 
    case SPID_KEYWORDS:
1899
 
        sctx->propname = "Keywords";
1900
 
        break;
1901
 
    case SPID_COMMENTS:
1902
 
        sctx->propname = "Comments";
1903
 
        break;
1904
 
    case SPID_TEMPLATE:
1905
 
        sctx->propname = "Template";
1906
 
        break;
1907
 
    case SPID_LASTAUTHOR:
1908
 
        sctx->propname = "LastAuthor";
1909
 
        break;
1910
 
    case SPID_REVNUMBER:
1911
 
        sctx->propname = "RevNumber";
1912
 
        break;
1913
 
    case SPID_EDITTIME:
1914
 
        sctx->propname = "EditTime";
1915
 
        break;
1916
 
    case SPID_LASTPRINTED:
1917
 
        sctx->propname = "LastPrinted";
1918
 
        break;
1919
 
    case SPID_CREATEDTIME:
1920
 
        sctx->propname = "CreatedTime";
1921
 
        break;
1922
 
    case SPID_MODIFIEDTIME:
1923
 
        sctx->propname = "ModifiedTime";
1924
 
        break;
1925
 
    case SPID_PAGECOUNT:
1926
 
        sctx->propname = "PageCount";
1927
 
        break;
1928
 
    case SPID_WORDCOUNT:
1929
 
        sctx->propname = "WordCount";
1930
 
        break;
1931
 
    case SPID_CHARCOUNT:
1932
 
        sctx->propname = "CharCount";
1933
 
        break;
1934
 
    case SPID_THUMBNAIL:
1935
 
        sctx->propname = "Thumbnail";
1936
 
        break;
1937
 
    case SPID_APPNAME:
1938
 
        sctx->propname = "AppName";
1939
 
        break;
1940
 
    case SPID_SECURITY:
1941
 
        sctx->propname = "Security";
1942
 
        break;
1943
 
    default:
1944
 
        cli_dbgmsg("ole2_translate_summary_propid: unrecognized propid!\n");
1945
 
        sctx->flags |= OLE2_SUMMARY_FLAG_UNKNOWN_PROPID;
1946
 
    }
1947
 
}
1948
 
 
1949
 
static int ole2_summary_propset_json(summary_ctx_t *sctx, off_t offset)
1950
 
{
1951
 
    unsigned char *hdr, *ps;
1952
 
    uint32_t numprops, limitprops;
1953
 
    off_t foff = offset, psoff = 0;
1954
 
    uint32_t poffset;
1955
 
    int ret;
1956
 
    unsigned int i;
1957
 
 
1958
 
    cli_dbgmsg("in ole2_summary_propset_json\n");
1959
 
 
1960
 
    /* summary ctx propset-specific setup*/
1961
 
    sctx->codepage = 0;
1962
 
    sctx->writecp = 0;
1963
 
    sctx->propname = NULL;
1964
 
 
1965
 
    /* examine property set metadata */
1966
 
    if ((foff+(2*sizeof(uint32_t))) > sctx->maplen) {
1967
 
        sctx->flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
1968
 
        return CL_EFORMAT;
1969
 
    }
1970
 
    hdr = (unsigned char*)fmap_need_off_once(sctx->sfmap, foff, (2*sizeof(uint32_t)));
1971
 
    if (!hdr) {
1972
 
        sctx->flags |= OLE2_SUMMARY_ERROR_DATABUF;
1973
 
        return CL_EREAD;
1974
 
    }
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;
1986
 
    }
1987
 
    else {
1988
 
        limitprops = numprops;
1989
 
    }
1990
 
    cli_dbgmsg("ole2_summary_propset_json: processing %u of %u (%u max) propeties\n",
1991
 
               limitprops, numprops, PROPCNTLIMIT);
1992
 
 
1993
 
    /* extract remaining fragment of propset */
1994
 
    if ((size_t)(foff+(sctx->pssize)) > (size_t)(sctx->maplen)) {
1995
 
        sctx->flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
1996
 
        return CL_EFORMAT;
1997
 
    }
1998
 
    ps = (unsigned char*)fmap_need_off_once(sctx->sfmap, foff, sctx->pssize);
1999
 
    if (!ps) {
2000
 
        sctx->flags |= OLE2_SUMMARY_ERROR_DATABUF;
2001
 
        return CL_EREAD;
2002
 
    }
2003
 
 
2004
 
    /* iterate over the properties */
2005
 
    for (i = 0; i < limitprops; ++i) {
2006
 
        uint32_t propid, propoff;
2007
 
 
2008
 
        if (psoff+sizeof(propid)+sizeof(poffset) > sctx->pssize) {
2009
 
            sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
2010
 
            return CL_EFORMAT;
2011
 
        }
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);
2020
 
 
2021
 
        sctx->propname = NULL; sctx->writecp = 0;
2022
 
        if (!sctx->mode)
2023
 
            ole2_translate_summary_propid(sctx, propid);
2024
 
        else
2025
 
            ole2_translate_docsummary_propid(sctx, propid);
2026
 
 
2027
 
        if (sctx->propname != NULL) {
2028
 
            ret = ole2_process_property(sctx, ps, propoff);
2029
 
            if (ret != CL_SUCCESS)
2030
 
                return ret;
2031
 
        }
2032
 
        else {
2033
 
            /* add unknown propid flag */
2034
 
        }
2035
 
    }
2036
 
 
2037
 
    return CL_SUCCESS;
2038
 
}
2039
 
 
2040
 
static int cli_ole2_summary_json_cleanup(summary_ctx_t *sctx, int retcode)
2041
 
{
2042
 
    json_object *jarr;
2043
 
 
2044
 
    cli_dbgmsg("in cli_ole2_summary_json_cleanup: %d[%x]\n", retcode, sctx->flags);
2045
 
 
2046
 
    if (sctx->sfmap) {
2047
 
        funmap(sctx->sfmap);
2048
 
    }
2049
 
 
2050
 
    if (sctx->flags) {
2051
 
        jarr = cli_jsonarray(sctx->summary, "ParseErrors");
2052
 
 
2053
 
        /* check errors */
2054
 
        if (sctx->flags & OLE2_SUMMARY_ERROR_TOOSMALL) {
2055
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_TOOSMALL");
2056
 
        }
2057
 
        if (sctx->flags & OLE2_SUMMARY_ERROR_OOB) {
2058
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_OOB");
2059
 
        }
2060
 
        if (sctx->flags & OLE2_SUMMARY_ERROR_DATABUF) {
2061
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_DATABUF");
2062
 
        }
2063
 
        if (sctx->flags & OLE2_SUMMARY_ERROR_INVALID_ENTRY) {
2064
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_INVALID_ENTRY");
2065
 
        }
2066
 
        if (sctx->flags & OLE2_SUMMARY_LIMIT_PROPS) {
2067
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_LIMIT_PROPS");
2068
 
        }
2069
 
        if (sctx->flags & OLE2_SUMMARY_FLAG_TIMEOUT) {
2070
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_TIMEOUT");
2071
 
        }
2072
 
        if (sctx->flags & OLE2_SUMMARY_FLAG_CODEPAGE) {
2073
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_CODEPAGE");
2074
 
        }
2075
 
        if (sctx->flags & OLE2_SUMMARY_FLAG_UNKNOWN_PROPID) {
2076
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_UNKNOWN_PROPID");
2077
 
        }
2078
 
        if (sctx->flags & OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE) {
2079
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE");
2080
 
        }
2081
 
        if (sctx->flags & OLE2_SUMMARY_FLAG_TRUNC_STR) {
2082
 
            cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_TRUNC_STR");
2083
 
        }
2084
 
    }
2085
 
 
2086
 
    return retcode;
2087
 
}
2088
 
 
2089
 
 
2090
 
#endif /* HAVE_JSON */
2091
 
 
2092
 
#if HAVE_JSON
2093
 
int cli_ole2_summary_json(cli_ctx *ctx, int fd, int mode)
2094
 
{
2095
 
    summary_ctx_t sctx;
2096
 
    STATBUF statbuf;
2097
 
    off_t foff = 0;
2098
 
    unsigned char *databuf;
2099
 
    summary_stub_t sumstub;
2100
 
    propset_entry_t pentry;
2101
 
    int ret = CL_SUCCESS;
2102
 
 
2103
 
    cli_dbgmsg("in cli_ole2_summary_json\n");
2104
 
 
2105
 
    /* preliminary sanity checks */
2106
 
    if (ctx == NULL) {
2107
 
        return CL_ENULLARG;
2108
 
    }
2109
 
 
2110
 
    if (fd < 0) {
2111
 
        cli_dbgmsg("ole2_summary_json: invalid file descriptor\n");
2112
 
        return CL_ENULLARG; /* placeholder */
2113
 
    }
2114
 
 
2115
 
    if (mode != 0 && mode != 1) {
2116
 
        cli_dbgmsg("ole2_summary_json: invalid mode specified\n");
2117
 
        return CL_ENULLARG; /* placeholder */
2118
 
    }
2119
 
 
2120
 
    /* summary ctx setup */
2121
 
    memset(&sctx, 0, sizeof(sctx));
2122
 
    sctx.ctx = ctx;
2123
 
    sctx.mode = mode;
2124
 
 
2125
 
    if (FSTAT(fd, &statbuf) == -1) {
2126
 
        cli_dbgmsg("ole2_summary_json: cannot stat file descriptor\n");
2127
 
        return CL_ESTAT;
2128
 
    }
2129
 
 
2130
 
    sctx.sfmap = fmap(fd, 0, statbuf.st_size);
2131
 
    if (!sctx.sfmap) {
2132
 
        cli_dbgmsg("ole2_summary_json: failed to get fmap\n");
2133
 
        return CL_EMAP;
2134
 
    }
2135
 
    sctx.maplen = sctx.sfmap->len;
2136
 
    cli_dbgmsg("ole2_summary_json: streamsize: %u\n", sctx.maplen);
2137
 
 
2138
 
    if (!mode)
2139
 
        sctx.summary = cli_jsonobj(ctx->wrkproperty, "SummaryInfo");
2140
 
    else
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);
2145
 
    }
2146
 
 
2147
 
    sctx.codepage = 0;
2148
 
    sctx.writecp = 0;
2149
 
 
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);
2154
 
    }
2155
 
    databuf = (unsigned char*)fmap_need_off_once(sctx.sfmap, foff, sizeof(summary_stub_t));
2156
 
    if (!databuf) {
2157
 
        sctx.flags |= OLE2_SUMMARY_ERROR_DATABUF;
2158
 
        return cli_ole2_summary_json_cleanup(&sctx, CL_EREAD);
2159
 
    }
2160
 
    foff += sizeof(summary_stub_t);
2161
 
    memcpy(&sumstub, databuf, sizeof(summary_stub_t));
2162
 
 
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);;
2169
 
    }
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);
2177
 
    }
2178
 
 
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);
2181
 
 
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);
2186
 
    }
2187
 
    databuf = (unsigned char*)fmap_need_off_once(sctx.sfmap, foff, sizeof(propset_entry_t));
2188
 
    if (!databuf) {
2189
 
        sctx.flags |= OLE2_SUMMARY_ERROR_DATABUF;
2190
 
        return cli_ole2_summary_json_cleanup(&sctx, CL_EREAD);
2191
 
    }
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);
2196
 
 
2197
 
    if ((ret = ole2_summary_propset_json(&sctx, pentry.offset)) != CL_SUCCESS) {
2198
 
        return cli_ole2_summary_json_cleanup(&sctx, ret);
2199
 
    }
2200
 
 
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);
2204
 
    }
2205
 
 
2206
 
    return cli_ole2_summary_json_cleanup(&sctx, CL_SUCCESS);
2207
 
}
2208
 
#endif /* HAVE_JSON */