~ubuntu-branches/ubuntu/raring/clamav/raring-security

« back to all changes in this revision

Viewing changes to libclamav/pdf.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2011-10-24 11:57:42 UTC
  • mfrom: (0.47.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20111024115742-8g7826vbzwi0vxyi
Tags: 0.97.3+dfsg-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Drop build-dep on electric-fence (in Universe)
  - Add apparmor profiles for clamd and freshclam along with maintainer
    script changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
281
281
        case HAS_OPENACTION:
282
282
            s = "has /OpenAction";
283
283
            break;
 
284
        case HAS_LAUNCHACTION:
 
285
            s = "has /LaunchAction";
 
286
            break;
284
287
        case BAD_STREAMLEN:
285
288
            s = "bad /Length, too small";
286
289
            break;
493
496
    return length;
494
497
}
495
498
 
496
 
#define DUMP_MASK ((1 << OBJ_FILTER_FLATE) | (1 << OBJ_FILTER_DCT) | (1 << OBJ_FILTER_AH) | (1 << OBJ_FILTER_A85) | (1 << OBJ_EMBEDDED_FILE) | (1 << OBJ_JAVASCRIPT) | (1 << OBJ_OPENACTION))
 
499
#define DUMP_MASK ((1 << OBJ_FILTER_FLATE) | (1 << OBJ_FILTER_DCT) | (1 << OBJ_FILTER_AH) | (1 << OBJ_FILTER_A85) | (1 << OBJ_EMBEDDED_FILE) | (1 << OBJ_JAVASCRIPT) | (1 << OBJ_OPENACTION) | (1 << OBJ_LAUNCHACTION))
497
500
 
498
501
static int obj_size(struct pdf_struct *pdf, struct pdf_obj *obj, int binary)
499
502
{
771
774
    STATE_JAVASCRIPT,
772
775
    STATE_OPENACTION,
773
776
    STATE_LINEARIZED,
 
777
    STATE_LAUNCHACTION,
774
778
    STATE_ANY /* for actions table below */
775
779
};
776
780
 
811
815
    {"Length", OBJ_DICT, STATE_FILTER, STATE_NONE},
812
816
    {"S", OBJ_DICT, STATE_NONE, STATE_S},
813
817
    {"Type", OBJ_DICT, STATE_NONE, STATE_NONE},
814
 
    {"OpenAction", OBJ_OPENACTION, STATE_ANY, STATE_OPENACTION}
 
818
    {"OpenAction", OBJ_OPENACTION, STATE_ANY, STATE_OPENACTION},
 
819
    {"Launch", OBJ_LAUNCHACTION, STATE_ANY, STATE_LAUNCHACTION}
815
820
};
816
821
 
817
822
#define KNOWN_FILTERS ((1 << OBJ_FILTER_AH) | (1 << OBJ_FILTER_RL) | (1 << OBJ_FILTER_A85) | (1 << OBJ_FILTER_FLATE) | (1 << OBJ_FILTER_LZW) | (1 << OBJ_FILTER_FAX) | (1 << OBJ_FILTER_DCT) | (1 << OBJ_FILTER_JPX) | (1 << OBJ_FILTER_CRYPT))
868
873
    }
869
874
}
870
875
 
 
876
static char *pdf_readstring(const char *q0, int len, const char *key, unsigned *slen);
 
877
static int pdf_readint(const char *q0, int len, const char *key);
 
878
static const char *pdf_getdict(const char *q0, int* len, const char *key);
871
879
static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
872
880
{
873
881
    /* enough to hold common pdf names, we don't need all the names */
943
951
 
944
952
        handle_pdfname(pdf, obj, pdfname, escapes, &objstate);
945
953
        if (objstate == STATE_LINEARIZED) {
 
954
            long trailer_end, trailer;
946
955
            pdfobj_flag(pdf, obj, LINEARIZED_PDF);
947
956
            objstate = STATE_NONE;
 
957
            trailer_end = pdf_readint(q, dict_length, "/H");
 
958
            if (trailer_end > 0 && trailer_end < pdf->size) {
 
959
                trailer = trailer_end - 1024;
 
960
                if (trailer < 0) trailer = 0;
 
961
                q2 = pdf->map + trailer;
 
962
                cli_dbgmsg("cli_pdf: looking for trailer in linearized pdf: %ld - %ld\n", trailer, trailer_end);
 
963
                pdf->fileID = pdf_readstring(q2, trailer_end - trailer, "/ID", &pdf->fileIDlen);
 
964
                if (pdf->fileID)
 
965
                    cli_dbgmsg("found fileID\n");
 
966
            }
948
967
        }
 
968
        if (objstate == STATE_LAUNCHACTION)
 
969
            pdfobj_flag(pdf, obj, HAS_LAUNCHACTION);
949
970
        if (dict_length > 0 && (objstate == STATE_JAVASCRIPT ||
950
971
            objstate == STATE_OPENACTION)) {
951
972
            if (objstate == STATE_OPENACTION)
1035
1056
{
1036
1057
    const char *q;
1037
1058
 
 
1059
    if (*len <= 0) {
 
1060
        cli_dbgmsg("cli_pdf: bad length %d\n", *len);
 
1061
        return NULL;
 
1062
    }
1038
1063
    q = cli_memstr(q0, *len, key, strlen(key));
1039
1064
    if (!q) {
1040
1065
        cli_dbgmsg("cli_pdf: %s not found in dict\n", key);
1065
1090
    if (*q == '(') {
1066
1091
        int paren = 1;
1067
1092
        start = ++q;
1068
 
        for (;paren > 0 && len > 0; q++) {
 
1093
        for (;paren > 0 && len > 0; q++,len--) {
1069
1094
            switch (*q) {
1070
1095
                case '(':
1071
1096
                    paren++;
1265
1290
            memcpy(data, key_padding, 32);
1266
1291
            arc4_init(&arc4, pdf->key, pdf->keylen);
1267
1292
            arc4_apply(&arc4, data, 32);
1268
 
            dbg_printhex("computed U", data, 32);
 
1293
            dbg_printhex("computed U (R2)", data, 32);
1269
1294
            if (!memcmp(data, U, 32))
1270
1295
                password_empty = 1;
1271
1296
        } else if (R >= 3) {
1285
1310
                arc4_init(&arc4, data, len);
1286
1311
                arc4_apply(&arc4, result, 16);
1287
1312
            }
1288
 
            dbg_printhex("computed U", result, 16);
 
1313
            dbg_printhex("fileID", pdf->fileID, pdf->fileIDlen);
 
1314
            dbg_printhex("computed U (R>=3)", result, 16);
1289
1315
            if (!memcmp(result, U, 16))
1290
1316
                password_empty = 1;
1291
1317
        } else {
1311
1337
    char *O, *U;
1312
1338
    const char *q, *q2;
1313
1339
 
1314
 
    if (pdf->enc_objid == ~0u || !pdf->fileID)
1315
 
        return;
 
1340
    if (pdf->enc_objid == ~0u)
 
1341
        return;
 
1342
    if (!pdf->fileID) {
 
1343
        cli_dbgmsg("cli_pdf: pdf_handle_enc no file ID\n");
 
1344
        return;
 
1345
    }
1316
1346
    obj = find_obj(pdf, pdf->objs, pdf->enc_objid);
1317
 
    if (!obj)
1318
 
        return;
1319
 
    required_flags = (1 << OBJ_HASFILTERS) | (1 << OBJ_FILTER_STANDARD);
1320
 
    if (!(obj->flags & required_flags))
1321
 
        return;
 
1347
    if (!obj) {
 
1348
        cli_dbgmsg("cli_pdf: can't find encrypted object %d %d\n", pdf->enc_objid>>8, pdf->enc_objid&0xff);
 
1349
        return;
 
1350
    }
1322
1351
    len = obj_size(pdf, obj, 1);
1323
1352
    q = pdf->map + obj->start;
1324
1353
 
1336
1365
            cli_dbgmsg("cli_pdf: /Standard not found\n");
1337
1366
            break;
1338
1367
        }
1339
 
        len -= q2-q;
1340
 
        q = q2;
 
1368
        /* we can have both of these:
 
1369
        * /AESV2/Length /Standard/Length
 
1370
        * /Length /Standard
 
1371
        * make sure we don't mistake AES's length for Standard's */
 
1372
        length = pdf_readint(q2, len - (q2 - q), "/Length");
 
1373
        if (length == ~0u)
 
1374
            length = pdf_readint(q, len, "/Length");
 
1375
        if (length == ~0u)
 
1376
            length = 40;
 
1377
        if (length < 40) {
 
1378
            cli_dbgmsg("cli_pdf: invalid length: %d\n", length);
 
1379
            length = 40;
 
1380
        }
1341
1381
 
1342
1382
        R = pdf_readint(q, len, "/R");
1343
1383
        if (R == ~0u) {
1385
1425
                break;
1386
1426
            }
1387
1427
        }
1388
 
        length = pdf_readint(q, len, "/Length");
1389
 
        if (length == ~0u)
1390
 
            length = 40;
1391
 
        if (length < 40) {
1392
 
            cli_dbgmsg("cli_pdf: invalid length: %d\n", length);
1393
 
            length = 40;
1394
 
        }
1395
1428
        cli_dbgmsg("cli_pdf: Encrypt R: %d, P %x, length: %d\n", R, P, length);
1396
1429
        if (length % 8) {
1397
1430
            cli_dbgmsg("cli_pdf: wrong key length, not multiple of 8\n");