Commit 909a0b3f3a0fddfab6abd1f0775cdd50f1406be6
1 parent
3d33a3a1
Implement --disable-signatures (fixes #1015)
Showing
14 changed files
with
103 additions
and
40 deletions
ChangeLog
| 1 | +2023-12-23 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * Add QPDFAcroFormDocumentHelper::disableDigitalSignatures and the | |
| 4 | + --disable-signatures command-line argument. This disables any | |
| 5 | + digital signature fields, leaving their visual representations | |
| 6 | + intact. | |
| 7 | + | |
| 1 | 8 | 2023-12-22 Jay Berkenbilt <ejb@ql.org> |
| 2 | 9 | |
| 3 | 10 | * Generate a more complete qpdf "man page" from the same source as | ... | ... |
include/qpdf/QPDFJob.hh
| ... | ... | @@ -557,6 +557,7 @@ class QPDFJob |
| 557 | 557 | bool linearize{false}; |
| 558 | 558 | bool decrypt{false}; |
| 559 | 559 | bool remove_restrictions{false}; |
| 560 | + bool disable_signatures{false}; | |
| 560 | 561 | int split_pages{0}; |
| 561 | 562 | bool progress{false}; |
| 562 | 563 | std::function<void(int)> progress_handler{nullptr}; | ... | ... |
include/qpdf/auto_job_c_main.hh
| ... | ... | @@ -11,6 +11,7 @@ QPDF_DLL Config* checkLinearization(); |
| 11 | 11 | QPDF_DLL Config* coalesceContents(); |
| 12 | 12 | QPDF_DLL Config* decrypt(); |
| 13 | 13 | QPDF_DLL Config* deterministicId(); |
| 14 | +QPDF_DLL Config* disableSignatures(); | |
| 14 | 15 | QPDF_DLL Config* externalizeInlineImages(); |
| 15 | 16 | QPDF_DLL Config* filteredStreamData(); |
| 16 | 17 | QPDF_DLL Config* flattenRotation(); | ... | ... |
job.sums
| ... | ... | @@ -4,17 +4,17 @@ generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a |
| 4 | 4 | include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4 |
| 5 | 5 | include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42 |
| 6 | 6 | include/qpdf/auto_job_c_enc.hh 28446f3c32153a52afa239ea40503e6cc8ac2c026813526a349e0cd4ae17ddd5 |
| 7 | -include/qpdf/auto_job_c_main.hh dbfc221d1533120d1aa9c361d8d2483dea5fcb1c0fd95144d98d305e64ed32a6 | |
| 7 | +include/qpdf/auto_job_c_main.hh 36b5ff48ae0dca67415efececa4470cda45364b10d0905e7de9971a2af1795ea | |
| 8 | 8 | include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c18911614fe8e568ec |
| 9 | 9 | include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1 |
| 10 | -job.yml 4f89fc7b622df897d30d403d8035aa36fc7de8d8c43042c736e0300d904cb05c | |
| 10 | +job.yml 3c030ce21138967b8a6768b386c0d3bfab9ef41cafbb6ec52f30a81194a7421d | |
| 11 | 11 | libqpdf/qpdf/auto_job_decl.hh 9c6f701c29f3f764d620186bed92685a2edf2e4d11e4f4532862c05470cfc4d2 |
| 12 | -libqpdf/qpdf/auto_job_help.hh bbd37ac0e8b3e38892a328ca08829d6e71c31ea3ab6c1a91b5f6983018695ef9 | |
| 13 | -libqpdf/qpdf/auto_job_init.hh b4c2b3724fba61f1206fd3bae81951636852592f67a63ef9539839c2c5995065 | |
| 12 | +libqpdf/qpdf/auto_job_help.hh 57ea412972105bf302b78b88ae2d6abfc93cae6f5ff99a55e78f860db9354643 | |
| 13 | +libqpdf/qpdf/auto_job_init.hh 4413804cc784f288245039af053bfe74bc2755e994308220d1939e452011e5a5 | |
| 14 | 14 | libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297 |
| 15 | -libqpdf/qpdf/auto_job_json_init.hh f5acb9aa103131cb68dec0e12c4d237a6459bdb49b24773c24f0c2724a462b8f | |
| 16 | -libqpdf/qpdf/auto_job_schema.hh b53c006fec2e75b1b73588d242d49a32f7d3db820b1541de106c5d4c27fbb4d9 | |
| 15 | +libqpdf/qpdf/auto_job_json_init.hh 7682e1e3bc465a3818036e1831aaf205478cc2e47ba5abe483d37c037b6bcf56 | |
| 16 | +libqpdf/qpdf/auto_job_schema.hh 039ee828cf91ece434f0c57706aecc40798e5537308737e01efc8f61eb20685f | |
| 17 | 17 | manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580 |
| 18 | -manual/cli.rst 7bbeb2f234ca3d095c069f52e4a3c5e42a525b5ef6231955d036a6313eaffcd2 | |
| 19 | -manual/qpdf.1 745cb32c1772e6d84ef962aca7a439ee045226ae547330778a4a3ba3cd8d25df | |
| 18 | +manual/cli.rst 97aa745b37ef9824ae4cd159577f65b94935bbc545250c9065ed7d65670c68eb | |
| 19 | +manual/qpdf.1 e4ffa50a6ed735860a92571d33319a2b5e6aa73cacba1bb73f80bf209be7c040 | |
| 20 | 20 | manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b | ... | ... |
job.yml
| ... | ... | @@ -104,6 +104,7 @@ options: |
| 104 | 104 | - copy-attachments-from |
| 105 | 105 | - decrypt |
| 106 | 106 | - deterministic-id |
| 107 | + - disable-signatures | |
| 107 | 108 | - empty |
| 108 | 109 | - encrypt |
| 109 | 110 | - externalize-inline-images |
| ... | ... | @@ -319,6 +320,7 @@ json: |
| 319 | 320 | decode-level: |
| 320 | 321 | decrypt: |
| 321 | 322 | deterministic-id: |
| 323 | + disable-signatures: | |
| 322 | 324 | static-aes-iv: |
| 323 | 325 | static-id: |
| 324 | 326 | no-original-object-ids: | ... | ... |
libqpdf/QPDFJob.cc
| ... | ... | @@ -2129,6 +2129,10 @@ QPDFJob::handleTransformations(QPDF& pdf) |
| 2129 | 2129 | if (m->remove_restrictions) { |
| 2130 | 2130 | pdf.removeSecurityRestrictions(); |
| 2131 | 2131 | } |
| 2132 | + if (m->disable_signatures) { | |
| 2133 | + make_afdh(); | |
| 2134 | + afdh->disableDigitalSignatures(); | |
| 2135 | + } | |
| 2132 | 2136 | if (m->externalize_inline_images || (m->optimize_images && (!m->keep_inline_images))) { |
| 2133 | 2137 | for (auto& ph: dh.getAllPages()) { |
| 2134 | 2138 | ph.externalizeInlineImages(m->ii_min_bytes); | ... | ... |
libqpdf/QPDFJob_config.cc
| ... | ... | @@ -145,6 +145,13 @@ QPDFJob::Config::deterministicId() |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | QPDFJob::Config* |
| 148 | +QPDFJob::Config::disableSignatures() | |
| 149 | +{ | |
| 150 | + o.m->disable_signatures = true; | |
| 151 | + return this; | |
| 152 | +} | |
| 153 | + | |
| 154 | +QPDFJob::Config* | |
| 148 | 155 | QPDFJob::Config::encryptionFilePassword(std::string const& parameter) |
| 149 | 156 | { |
| 150 | 157 | o.m->encryption_file_password = QUtil::make_shared_cstr(parameter); | ... | ... |
libqpdf/qpdf/auto_job_help.hh
| ... | ... | @@ -157,9 +157,15 @@ encrypted. Normally qpdf preserves whatever encryption was |
| 157 | 157 | present on the input file. This option overrides that behavior. |
| 158 | 158 | )"); |
| 159 | 159 | ap.addOptionHelp("--remove-restrictions", "transformation", "remove security restrictions from input file", R"(Remove restrictions associated with digitally signed PDF files. |
| 160 | -This may be combined with --decrypt to allow free editing of | |
| 161 | -previously signed/encrypted files. This option invalidates the | |
| 162 | -signature but leaves its visual appearance intact. | |
| 160 | +This may be combined with --decrypt and --disable-signatures to | |
| 161 | +allow free editing of previously signed/encrypted files. This | |
| 162 | +option invalidates the signature but leaves its visual | |
| 163 | +appearance intact. See also --disable-signatures. | |
| 164 | +)"); | |
| 165 | +ap.addOptionHelp("--disable-signatures", "transformation", "disable digital signature fields", R"(Remove all digital signature fields from a file. The appearance | |
| 166 | +of the digital signature, if any, will remain on the page, but | |
| 167 | +it will no longer be a signature field. See also | |
| 168 | +--remove-restrictions. | |
| 163 | 169 | )"); |
| 164 | 170 | ap.addOptionHelp("--copy-encryption", "transformation", "copy another file's encryption details", R"(--copy-encryption=file |
| 165 | 171 | |
| ... | ... | @@ -167,14 +173,14 @@ Copy encryption details from the specified file instead of |
| 167 | 173 | preserving the input file's encryption. Use --encryption-file-password |
| 168 | 174 | to specify the encryption file's password. |
| 169 | 175 | )"); |
| 176 | +} | |
| 177 | +static void add_help_3(QPDFArgParser& ap) | |
| 178 | +{ | |
| 170 | 179 | ap.addOptionHelp("--encryption-file-password", "transformation", "supply password for --copy-encryption", R"(--encryption-file-password=password |
| 171 | 180 | |
| 172 | 181 | If the file named in --copy-encryption requires a password, use |
| 173 | 182 | this option to supply the password. |
| 174 | 183 | )"); |
| 175 | -} | |
| 176 | -static void add_help_3(QPDFArgParser& ap) | |
| 177 | -{ | |
| 178 | 184 | ap.addOptionHelp("--qdf", "transformation", "enable viewing PDF code in a text editor", R"(Create a PDF file suitable for viewing in a text editor and even |
| 179 | 185 | editing. This is for editing the PDF code, not the page contents. |
| 180 | 186 | All streams that can be uncompressed are uncompressed, and |
| ... | ... | @@ -284,6 +290,9 @@ Force the output PDF file's PDF version header to be the specified |
| 284 | 290 | value, even if the file uses features that may not be available |
| 285 | 291 | in that version. |
| 286 | 292 | )"); |
| 293 | +} | |
| 294 | +static void add_help_4(QPDFArgParser& ap) | |
| 295 | +{ | |
| 287 | 296 | ap.addHelpTopic("page-ranges", "page range syntax", R"(A full description of the page range syntax, with examples, can be |
| 288 | 297 | found in the manual. Summary: |
| 289 | 298 | |
| ... | ... | @@ -297,9 +306,6 @@ resulting set of pages, where :odd starts with the first page and |
| 297 | 306 | :even starts with the second page. These are odd and even pages |
| 298 | 307 | from the resulting set, not based on the original page numbers. |
| 299 | 308 | )"); |
| 300 | -} | |
| 301 | -static void add_help_4(QPDFArgParser& ap) | |
| 302 | -{ | |
| 303 | 309 | ap.addHelpTopic("modification", "change parts of the PDF", R"(Modification options make systematic changes to certain parts of |
| 304 | 310 | the PDF, causing the PDF to render differently from the original. |
| 305 | 311 | )"); |
| ... | ... | @@ -475,13 +481,13 @@ ap.addOptionHelp("--user-password", "encryption", "specify user password", R"(-- |
| 475 | 481 | |
| 476 | 482 | Set the user password of the encrypted file. |
| 477 | 483 | )"); |
| 484 | +} | |
| 485 | +static void add_help_5(QPDFArgParser& ap) | |
| 486 | +{ | |
| 478 | 487 | ap.addOptionHelp("--owner-password", "encryption", "specify owner password", R"(--owner-password=owner-password |
| 479 | 488 | |
| 480 | 489 | Set the owner password of the encrypted file. |
| 481 | 490 | )"); |
| 482 | -} | |
| 483 | -static void add_help_5(QPDFArgParser& ap) | |
| 484 | -{ | |
| 485 | 491 | ap.addOptionHelp("--bits", "encryption", "specify encryption key length", R"(--bits={48|128|256} |
| 486 | 492 | |
| 487 | 493 | Specify the encryption key length. For best security, always use |
| ... | ... | @@ -653,15 +659,15 @@ the destination pages. See qpdf --help=page-ranges for help |
| 653 | 659 | with the page range syntax. The page range may be omitted |
| 654 | 660 | if --repeat is used. |
| 655 | 661 | )"); |
| 662 | +} | |
| 663 | +static void add_help_6(QPDFArgParser& ap) | |
| 664 | +{ | |
| 656 | 665 | ap.addOptionHelp("--repeat", "overlay-underlay", "overlay/underlay pages to repeat", R"(--repeat=page-range |
| 657 | 666 | |
| 658 | 667 | Specify pages from the overlay/underlay that are repeated after |
| 659 | 668 | "from" pages have been exhausted. See qpdf --help=page-ranges |
| 660 | 669 | for help with the page range syntax. |
| 661 | 670 | )"); |
| 662 | -} | |
| 663 | -static void add_help_6(QPDFArgParser& ap) | |
| 664 | -{ | |
| 665 | 671 | ap.addHelpTopic("attachments", "work with embedded files", R"(It is possible to list, add, or delete embedded files (also known |
| 666 | 672 | as attachments) and to copy attachments from other files. See help |
| 667 | 673 | on individual options for details. Run qpdf --help=add-attachment |
| ... | ... | @@ -770,6 +776,9 @@ ap.addOptionHelp("--requires-password", "inspection", "silently test a file's pa |
| 770 | 776 | 2: the file is not encrypted |
| 771 | 777 | 3: the file is encrypted, and correct password (if any) has been supplied |
| 772 | 778 | )"); |
| 779 | +} | |
| 780 | +static void add_help_7(QPDFArgParser& ap) | |
| 781 | +{ | |
| 773 | 782 | ap.addOptionHelp("--check", "inspection", "partially check whether PDF is valid", R"(Check the structure of the PDF file as well as a number of other |
| 774 | 783 | aspects of the file, and write information about the file to |
| 775 | 784 | standard output. Note that qpdf does not perform any validation |
| ... | ... | @@ -777,9 +786,6 @@ of the actual PDF page content or semantic correctness of the |
| 777 | 786 | PDF file. It merely checks that the PDF file is syntactically |
| 778 | 787 | valid. See also qpdf --help=exit-status. |
| 779 | 788 | )"); |
| 780 | -} | |
| 781 | -static void add_help_7(QPDFArgParser& ap) | |
| 782 | -{ | |
| 783 | 789 | ap.addOptionHelp("--show-encryption", "inspection", "information about encrypted files", R"(Show document encryption parameters. Also show the document's |
| 784 | 790 | user password if the owner password is given and the file was |
| 785 | 791 | encrypted using older encryption formats that allow user |
| ... | ... | @@ -860,6 +866,9 @@ This option is repeatable. If given, only specified objects will |
| 860 | 866 | be shown in the "objects" key of the JSON output. Otherwise, all |
| 861 | 867 | objects will be shown. |
| 862 | 868 | )"); |
| 869 | +} | |
| 870 | +static void add_help_8(QPDFArgParser& ap) | |
| 871 | +{ | |
| 863 | 872 | ap.addOptionHelp("--json-stream-data", "json", "how to handle streams in json output", R"(--json-stream-data={none|inline|file} |
| 864 | 873 | |
| 865 | 874 | When used with --json, this option controls whether streams in |
| ... | ... | @@ -871,9 +880,6 @@ object number. The prefix can be overridden with |
| 871 | 880 | when --json-output is specified, in which case the default is |
| 872 | 881 | "inline". |
| 873 | 882 | )"); |
| 874 | -} | |
| 875 | -static void add_help_8(QPDFArgParser& ap) | |
| 876 | -{ | |
| 877 | 883 | ap.addOptionHelp("--json-stream-prefix", "json", "prefix for json stream data files", R"(--json-stream-prefix=file-prefix |
| 878 | 884 | |
| 879 | 885 | When used with --json-stream-data=file, --json-stream-data=file-prefix | ... | ... |
libqpdf/qpdf/auto_job_init.hh
| ... | ... | @@ -43,6 +43,7 @@ this->ap.addBare("coalesce-contents", [this](){c_main->coalesceContents();}); |
| 43 | 43 | this->ap.addBare("copy-attachments-from", b(&ArgParser::argCopyAttachmentsFrom)); |
| 44 | 44 | this->ap.addBare("decrypt", [this](){c_main->decrypt();}); |
| 45 | 45 | this->ap.addBare("deterministic-id", [this](){c_main->deterministicId();}); |
| 46 | +this->ap.addBare("disable-signatures", [this](){c_main->disableSignatures();}); | |
| 46 | 47 | this->ap.addBare("empty", b(&ArgParser::argEmpty)); |
| 47 | 48 | this->ap.addBare("encrypt", b(&ArgParser::argEncrypt)); |
| 48 | 49 | this->ap.addBare("externalize-inline-images", [this](){c_main->externalizeInlineImages();}); | ... | ... |
libqpdf/qpdf/auto_job_json_init.hh
| ... | ... | @@ -71,6 +71,9 @@ popHandler(); // key: decrypt |
| 71 | 71 | pushKey("deterministicId"); |
| 72 | 72 | addBare([this]() { c_main->deterministicId(); }); |
| 73 | 73 | popHandler(); // key: deterministicId |
| 74 | +pushKey("disableSignatures"); | |
| 75 | +addBare([this]() { c_main->disableSignatures(); }); | |
| 76 | +popHandler(); // key: disableSignatures | |
| 74 | 77 | pushKey("staticAesIv"); |
| 75 | 78 | addBare([this]() { c_main->staticAesIv(); }); |
| 76 | 79 | popHandler(); // key: staticAesIv | ... | ... |
libqpdf/qpdf/auto_job_schema.hh
| ... | ... | @@ -16,6 +16,7 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({ |
| 16 | 16 | "decodeLevel": "control which streams to uncompress", |
| 17 | 17 | "decrypt": "remove encryption from input file", |
| 18 | 18 | "deterministicId": "generate ID deterministically", |
| 19 | + "disableSignatures": "disable digital signature fields", | |
| 19 | 20 | "staticAesIv": "use a fixed AES vector", |
| 20 | 21 | "staticId": "use a fixed document ID", |
| 21 | 22 | "noOriginalObjectIds": "omit original object IDs in qdf", | ... | ... |
manual/cli.rst
| ... | ... | @@ -736,22 +736,40 @@ Related Options |
| 736 | 736 | whatever encryption was present on the input file. This |
| 737 | 737 | functionality is not intended to be used for bypassing copyright |
| 738 | 738 | restrictions or other restrictions placed on files by their |
| 739 | - producers. See also :qpdf:ref:`--copy-encryption` and | |
| 740 | - :qpdf:ref:`--remove-restrictions`. | |
| 739 | + producers. See also :qpdf:ref:`--copy-encryption`, | |
| 740 | + :qpdf:ref:`--remove-restrictions`, and | |
| 741 | + :qpdf:ref:`--disable-signatures`. | |
| 741 | 742 | |
| 742 | 743 | .. qpdf:option:: --remove-restrictions |
| 743 | 744 | |
| 744 | 745 | .. help: remove security restrictions from input file |
| 745 | 746 | |
| 746 | 747 | Remove restrictions associated with digitally signed PDF files. |
| 747 | - This may be combined with --decrypt to allow free editing of | |
| 748 | - previously signed/encrypted files. This option invalidates the | |
| 749 | - signature but leaves its visual appearance intact. | |
| 748 | + This may be combined with --decrypt and --disable-signatures to | |
| 749 | + allow free editing of previously signed/encrypted files. This | |
| 750 | + option invalidates the signature but leaves its visual | |
| 751 | + appearance intact. See also --disable-signatures. | |
| 750 | 752 | |
| 751 | 753 | Remove security restrictions associated with digitally signed PDF |
| 752 | - files. This may be combined with :qpdf:ref:--decrypt: to allow | |
| 753 | - free editing of previously signed/encrypted files. This option | |
| 754 | - invalidates the signature but leaves its visual appearance intact. | |
| 754 | + files. This may be combined with :qpdf:ref:`--decrypt` and | |
| 755 | + :qpdf:ref:`--disable-signatures` to allow free editing of | |
| 756 | + previously signed/encrypted files. This option invalidates the | |
| 757 | + signature but leaves its visual appearance intact. See also | |
| 758 | + :qpdf:ref:`--disable-signatures`. | |
| 759 | + | |
| 760 | +.. qpdf:option:: --disable-signatures | |
| 761 | + | |
| 762 | + .. help: disable digital signature fields | |
| 763 | + | |
| 764 | + Remove all digital signature fields from a file. The appearance | |
| 765 | + of the digital signature, if any, will remain on the page, but | |
| 766 | + it will no longer be a signature field. See also | |
| 767 | + --remove-restrictions. | |
| 768 | + | |
| 769 | + Remove all digital signature fields from a file. The appearance | |
| 770 | + of the digital signature, if any, will remain on the page, but | |
| 771 | + it will no longer be a signature field. See also | |
| 772 | + :qpdf:ref:`--remove-restrictions`. | |
| 755 | 773 | |
| 756 | 774 | .. qpdf:option:: --copy-encryption=file |
| 757 | 775 | ... | ... |
manual/qpdf.1
| ... | ... | @@ -221,9 +221,16 @@ present on the input file. This option overrides that behavior. |
| 221 | 221 | .TP |
| 222 | 222 | .B --remove-restrictions \-\- remove security restrictions from input file |
| 223 | 223 | Remove restrictions associated with digitally signed PDF files. |
| 224 | -This may be combined with --decrypt to allow free editing of | |
| 225 | -previously signed/encrypted files. This option invalidates the | |
| 226 | -signature but leaves its visual appearance intact. | |
| 224 | +This may be combined with --decrypt and --disable-signatures to | |
| 225 | +allow free editing of previously signed/encrypted files. This | |
| 226 | +option invalidates the signature but leaves its visual | |
| 227 | +appearance intact. See also --disable-signatures. | |
| 228 | +.TP | |
| 229 | +.B --disable-signatures \-\- disable digital signature fields | |
| 230 | +Remove all digital signature fields from a file. The appearance | |
| 231 | +of the digital signature, if any, will remain on the page, but | |
| 232 | +it will no longer be a signature field. See also | |
| 233 | +--remove-restrictions. | |
| 227 | 234 | .TP |
| 228 | 235 | .B --copy-encryption \-\- copy another file's encryption details |
| 229 | 236 | --copy-encryption=file | ... | ... |
manual/release-notes.rst
| ... | ... | @@ -71,6 +71,11 @@ Planned changes for future 12.x (subject to change): |
| 71 | 71 | shell completion and allows creation of passwords that start |
| 72 | 72 | with ``-``. |
| 73 | 73 | |
| 74 | + - Add ``QPDFAcroFormDocumentHelper::disableDigitalSignatures`` and | |
| 75 | + the :qpdf:ref:`--disable-signatures` command-line argument. This | |
| 76 | + disables any digital signature fields, leaving their visual | |
| 77 | + representations intact. | |
| 78 | + | |
| 74 | 79 | - Build Enhancements: |
| 75 | 80 | |
| 76 | 81 | - The qpdf test suite now passes when qpdf is linked with an | ... | ... |