Browse code

fix encrypted linearized pdf detection (bb #3364).

Török Edvin authored on 2011/10/08 19:36:12
Showing 1 changed files
... ...
@@ -873,6 +873,9 @@ static void handle_pdfname(struct pdf_struct *pdf, struct pdf_obj *obj,
873 873
     }
874 874
 }
875 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);
876 879
 static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
877 880
 {
878 881
     /* enough to hold common pdf names, we don't need all the names */
... ...
@@ -948,8 +951,17 @@ static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
948 948
 
949 949
 	handle_pdfname(pdf, obj, pdfname, escapes, &objstate);
950 950
 	if (objstate == STATE_LINEARIZED) {
951
+	    long trailer_end, trailer;
951 952
 	    pdfobj_flag(pdf, obj, LINEARIZED_PDF);
952 953
 	    objstate = STATE_NONE;
954
+	    trailer_end = pdf_readint(q, dict_length, "/H");
955
+	    trailer = trailer_end - 1024;
956
+	    if (trailer < 0) trailer = 0;
957
+	    q2 = pdf->map + trailer;
958
+	    cli_dbgmsg("cli_pdf: looking for trailer in linearized pdf: %d - %d\n", trailer, trailer_end);
959
+	    pdf->fileID = pdf_readstring(q2, trailer_end - trailer, "/ID", &pdf->fileIDlen);
960
+	    if (pdf->fileID)
961
+		cli_dbgmsg("found fileID\n");
953 962
 	}
954 963
 	if (objstate == STATE_LAUNCHACTION)
955 964
 	    pdfobj_flag(pdf, obj, HAS_LAUNCHACTION);
... ...
@@ -1319,14 +1331,17 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1319 1319
     char *O, *U;
1320 1320
     const char *q, *q2;
1321 1321
 
1322
-    if (pdf->enc_objid == ~0u || !pdf->fileID)
1322
+    if (pdf->enc_objid == ~0u)
1323 1323
 	return;
1324
-    obj = find_obj(pdf, pdf->objs, pdf->enc_objid);
1325
-    if (!obj)
1324
+    if (!pdf->fileID) {
1325
+	cli_dbgmsg("cli_pdf: pdf_handle_enc no file ID\n");
1326 1326
 	return;
1327
-    required_flags = (1 << OBJ_HASFILTERS) | (1 << OBJ_FILTER_STANDARD);
1328
-    if (!(obj->flags & required_flags))
1327
+    }
1328
+    obj = find_obj(pdf, pdf->objs, pdf->enc_objid);
1329
+    if (!obj) {
1330
+	cli_dbgmsg("cli_pdf: can't find encrypted object %d %d\n", pdf->enc_objid>>8, pdf->enc_objid&0xff);
1329 1331
 	return;
1332
+    }
1330 1333
     len = obj_size(pdf, obj, 1);
1331 1334
     q = pdf->map + obj->start;
1332 1335
 
... ...
@@ -1338,21 +1353,25 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1338 1338
 	    cli_dbgmsg("cli_pdf: invalid P\n");
1339 1339
 	    break;
1340 1340
 	}
1341
-	length = pdf_readint(q, len, "/Length");
1342
-	if (length == ~0u)
1343
-	    length = 40;
1344
-	if (length < 40) {
1345
-	    cli_dbgmsg("cli_pdf: invalid length: %d\n", length);
1346
-	    length = 40;
1347
-	}
1348 1341
 
1349 1342
 	q2 = cli_memstr(q, len, "/Standard", 9);
1350 1343
 	if (!q2) {
1351 1344
 	    cli_dbgmsg("cli_pdf: /Standard not found\n");
1352 1345
 	    break;
1353 1346
 	}
1354
-	len -= q2-q;
1355
-	q = q2;
1347
+	/* we can have both of these:
1348
+	* /AESV2/Length /Standard/Length
1349
+	* /Length /Standard
1350
+	* make sure we don't mistake AES's length for Standard's */
1351
+	length = pdf_readint(q2, len - (q2 - q), "/Length");
1352
+	if (length == ~0u)
1353
+	    length = pdf_readint(q, len, "/Length");
1354
+	if (length == ~0u)
1355
+	    length = 40;
1356
+	if (length < 40) {
1357
+	    cli_dbgmsg("cli_pdf: invalid length: %d\n", length);
1358
+	    length = 40;
1359
+	}
1356 1360
 
1357 1361
 	R = pdf_readint(q, len, "/R");
1358 1362
 	if (R == ~0u) {