Commit c5ed1b8075f412b2e9cfd9cf01f41ba04d3af2bc
1 parent
551dfbf6
Handle invalid encryption Length (fixes #333)
Showing
6 changed files
with
102 additions
and
14 deletions
ChangeLog
libqpdf/QPDF_encryption.cc
| ... | ... | @@ -935,22 +935,38 @@ QPDF::initializeEncryption() |
| 935 | 935 | pad_short_parameter(Perms, Perms_key_bytes_V5); |
| 936 | 936 | } |
| 937 | 937 | |
| 938 | - int Length = 40; | |
| 939 | - if (encryption_dict.getKey("/Length").isInteger()) | |
| 938 | + int Length = 0; | |
| 939 | + if (V <= 1) | |
| 940 | 940 | { |
| 941 | - Length = encryption_dict.getKey("/Length").getIntValueAsInt(); | |
| 942 | - if (R < 3) | |
| 941 | + Length = 40; | |
| 942 | + } | |
| 943 | + else if (V == 4) | |
| 944 | + { | |
| 945 | + Length = 128; | |
| 946 | + } | |
| 947 | + else if (V == 5) | |
| 948 | + { | |
| 949 | + Length = 256; | |
| 950 | + } | |
| 951 | + else | |
| 952 | + { | |
| 953 | + if (encryption_dict.getKey("/Length").isInteger()) | |
| 954 | + { | |
| 955 | + Length = encryption_dict.getKey("/Length").getIntValueAsInt(); | |
| 956 | + if ((Length % 8) || (Length < 40) || (Length > 128)) | |
| 957 | + { | |
| 958 | + Length = 0; | |
| 959 | + } | |
| 960 | + } | |
| 961 | + if (Length == 0) | |
| 943 | 962 | { |
| 944 | - // Force Length to 40 regardless of what the file says. | |
| 945 | - Length = 40; | |
| 963 | + Length = 128; | |
| 946 | 964 | } |
| 947 | - if ((Length % 8) || (Length < 40) || (Length > 256)) | |
| 948 | - { | |
| 949 | - throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), | |
| 950 | - "encryption dictionary", | |
| 951 | - this->m->file->getLastOffset(), | |
| 952 | - "invalid /Length value in encryption dictionary"); | |
| 953 | - } | |
| 965 | + } | |
| 966 | + if (Length == 0) | |
| 967 | + { | |
| 968 | + // Still no Length? Just take a guess. | |
| 969 | + Length = 128; | |
| 954 | 970 | } |
| 955 | 971 | |
| 956 | 972 | this->m->encp->encrypt_metadata = true; | ... | ... |
manual/qpdf-manual.xml
| ... | ... | @@ -4353,6 +4353,14 @@ print "\n"; |
| 4353 | 4353 | segmentation fault. |
| 4354 | 4354 | </para> |
| 4355 | 4355 | </listitem> |
| 4356 | + <listitem> | |
| 4357 | + <para> | |
| 4358 | + When reading encrypted files, follow the spec more closely | |
| 4359 | + regarding encryption key length. This allows qpdf to open | |
| 4360 | + encrypted files in most cases when they have invalid or | |
| 4361 | + missing /Length keys in the encryption dictionary. | |
| 4362 | + </para> | |
| 4363 | + </listitem> | |
| 4356 | 4364 | </itemizedlist> |
| 4357 | 4365 | </listitem> |
| 4358 | 4366 | <listitem> | ... | ... |
qpdf/qtest/qpdf.test
| ... | ... | @@ -3523,7 +3523,7 @@ foreach my $d (@enc_key) |
| 3523 | 3523 | } |
| 3524 | 3524 | |
| 3525 | 3525 | # Miscellaneous encryption tests |
| 3526 | -$n_tests += 2; | |
| 3526 | +$n_tests += 3; | |
| 3527 | 3527 | |
| 3528 | 3528 | $td->runtest("set encryption before set filename", |
| 3529 | 3529 | {$td->COMMAND => "test_driver 63 minimal.pdf"}, |
| ... | ... | @@ -3534,6 +3534,11 @@ $td->runtest("check file's validity", |
| 3534 | 3534 | {$td->FILE => "encrypt-before-filename.out", |
| 3535 | 3535 | $td->EXIT_STATUS => 0}, |
| 3536 | 3536 | $td->NORMALIZE_NEWLINES); |
| 3537 | +$td->runtest("handle missing/invalid Length", | |
| 3538 | + {$td->COMMAND => "qpdf --check bad-encryption-length.pdf"}, | |
| 3539 | + {$td->FILE => "bad-encryption-length.out", | |
| 3540 | + $td->EXIT_STATUS => 0}, | |
| 3541 | + $td->NORMALIZE_NEWLINES); | |
| 3537 | 3542 | |
| 3538 | 3543 | show_ntests(); |
| 3539 | 3544 | # ---------- | ... | ... |
qpdf/qtest/qpdf/bad-encryption-length.out
0 → 100644
| 1 | +checking bad-encryption-length.pdf | |
| 2 | +PDF Version: 1.4 | |
| 3 | +R = 3 | |
| 4 | +P = -4 | |
| 5 | +User password = | |
| 6 | +extract for accessibility: allowed | |
| 7 | +extract for any purpose: allowed | |
| 8 | +print low resolution: allowed | |
| 9 | +print high resolution: allowed | |
| 10 | +modify document assembly: allowed | |
| 11 | +modify forms: allowed | |
| 12 | +modify annotations: allowed | |
| 13 | +modify other: allowed | |
| 14 | +modify anything: allowed | |
| 15 | +File is not linearized | |
| 16 | +No syntax or stream encoding errors found; the file may still contain | |
| 17 | +errors that qpdf cannot detect | ... | ... |
qpdf/qtest/qpdf/bad-encryption-length.pdf
0 → 100644
No preview for this file type