Commit 966429e718c8a0cd458c8efe5aa463cd0052aad0

Authored by Jay Berkenbilt
1 parent 6ec22f11

Update CLI and manual for new encryption granularity (fixes #214)

ChangeLog
@@ -16,6 +16,11 @@ @@ -16,6 +16,11 @@
16 16
17 2019-01-14 Jay Berkenbilt <ejb@ql.org> 17 2019-01-14 Jay Berkenbilt <ejb@ql.org>
18 18
  19 + * Add new CLI flags to 128-bit and 256-bit encryption: --assemble,
  20 + --annotate, --form, and --modify-other to control encryption
  21 + permissions with more granularity than was allowed with the
  22 + --modify flag. Fixes #214.
  23 +
19 * Add new versions of 24 * Add new versions of
20 QPDFWriter::setR{3,4,5,6}EncryptionParameters that allow 25 QPDFWriter::setR{3,4,5,6}EncryptionParameters that allow
21 individual setting of the various permission bits. The old 26 individual setting of the various permission bits. The old
manual/qpdf-manual.xml
@@ -786,7 +786,12 @@ make @@ -786,7 +786,12 @@ make
786 <listitem> 786 <listitem>
787 <para> 787 <para>
788 Determines whether or not to allow accessibility to visually 788 Determines whether or not to allow accessibility to visually
789 - impaired. 789 + impaired. The qpdf library disregards this field when AES is
  790 + used or when 256-bit encryption is used. You should really
  791 + never disable accessibility, but qpdf lets you do it in case
  792 + you need to configure a file this way for testing purposes.
  793 + The PDF spec says that conforming readers should disregard
  794 + this permission and always allow accessibility.
790 </para> 795 </para>
791 </listitem> 796 </listitem>
792 </varlistentry> 797 </varlistentry>
@@ -799,6 +804,45 @@ make @@ -799,6 +804,45 @@ make
799 </listitem> 804 </listitem>
800 </varlistentry> 805 </varlistentry>
801 <varlistentry> 806 <varlistentry>
  807 + <term><option>--assemble=[yn]</option></term>
  808 + <listitem>
  809 + <para>
  810 + Determines whether document assembly (rotation and reordering
  811 + of pages) is allowed.
  812 + </para>
  813 + </listitem>
  814 + </varlistentry>
  815 + <varlistentry>
  816 + <term><option>--annotate=[yn]</option></term>
  817 + <listitem>
  818 + <para>
  819 + Determines whether modifying annotations is allowed. This
  820 + includes adding comments and filling in form fields. Also
  821 + allows editing of form fields if
  822 + <option>--modify-other=y</option> is given.
  823 + </para>
  824 + </listitem>
  825 + </varlistentry>
  826 + <varlistentry>
  827 + <term><option>--form=[yn]</option></term>
  828 + <listitem>
  829 + <para>
  830 + Determines whether filling form fields is allowed.
  831 + </para>
  832 + </listitem>
  833 + </varlistentry>
  834 + <varlistentry>
  835 + <term><option>--modify-other=[yn]</option></term>
  836 + <listitem>
  837 + <para>
  838 + Allow all document editing except those controlled separately
  839 + by the <option>--assemble</option>,
  840 + <option>--annotate</option>, and <option>--form</option>
  841 + options.
  842 + </para>
  843 + </listitem>
  844 + </varlistentry>
  845 + <varlistentry>
802 <term><option>--print=<replaceable>print-opt</replaceable></option></term> 846 <term><option>--print=<replaceable>print-opt</replaceable></option></term>
803 <listitem> 847 <listitem>
804 <para> 848 <para>
@@ -829,10 +873,10 @@ make @@ -829,10 +873,10 @@ make
829 <term><option>--modify=<replaceable>modify-opt</replaceable></option></term> 873 <term><option>--modify=<replaceable>modify-opt</replaceable></option></term>
830 <listitem> 874 <listitem>
831 <para> 875 <para>
832 - Controls modify access. 876 + Controls modify access. This way of controlling modify access
  877 + has less granularity than new options added in qpdf 8.4.
833 <option><replaceable>modify-opt</replaceable></option> may be 878 <option><replaceable>modify-opt</replaceable></option> may be
834 - one of the following, each of which implies all the options  
835 - that follow it: 879 + one of the following:
836 <itemizedlist> 880 <itemizedlist>
837 <listitem> 881 <listitem>
838 <para> 882 <para>
@@ -841,12 +885,14 @@ make @@ -841,12 +885,14 @@ make
841 </listitem> 885 </listitem>
842 <listitem> 886 <listitem>
843 <para> 887 <para>
844 - <option>annotate</option>: allow comment authoring and form operations 888 + <option>annotate</option>: allow comment authoring, form
  889 + operations, and document assembly
845 </para> 890 </para>
846 </listitem> 891 </listitem>
847 <listitem> 892 <listitem>
848 <para> 893 <para>
849 <option>form</option>: allow form field fill-in and signing 894 <option>form</option>: allow form field fill-in and signing
  895 + and document assembly
850 </para> 896 </para>
851 </listitem> 897 </listitem>
852 <listitem> 898 <listitem>
@@ -860,6 +906,12 @@ make @@ -860,6 +906,12 @@ make
860 </para> 906 </para>
861 </listitem> 907 </listitem>
862 </itemizedlist> 908 </itemizedlist>
  909 + Using the <option>--modify</option> option does not allow you
  910 + to create certain combinations of permissions such as allowing
  911 + form filling but not allowing document assembly. Starting with
  912 + qpdf 8.4, you can either just use the other options to control
  913 + fields individually, or you can use something like
  914 + <option>--modify=form --assembly=n</option> to fine tune.
863 </para> 915 </para>
864 </listitem> 916 </listitem>
865 </varlistentry> 917 </varlistentry>
qpdf/qpdf.cc
@@ -631,6 +631,10 @@ class ArgParser @@ -631,6 +631,10 @@ class ArgParser
631 void arg128Print(char* parameter); 631 void arg128Print(char* parameter);
632 void arg128Modify(char* parameter); 632 void arg128Modify(char* parameter);
633 void arg128ClearTextMetadata(); 633 void arg128ClearTextMetadata();
  634 + void arg128Assemble(char* parameter);
  635 + void arg128Annotate(char* parameter);
  636 + void arg128Form(char* parameter);
  637 + void arg128ModOther(char* parameter);
634 void arg128UseAes(char* parameter); 638 void arg128UseAes(char* parameter);
635 void arg128ForceV4(); 639 void arg128ForceV4();
636 void arg256ForceR5(); 640 void arg256ForceR5();
@@ -857,11 +861,16 @@ ArgParser::initOptionTable() @@ -857,11 +861,16 @@ ArgParser::initOptionTable()
857 char const* print128_choices[] = {"full", "low", "none", 0}; 861 char const* print128_choices[] = {"full", "low", "none", 0};
858 (*t)["print"] = oe_requiredChoices( 862 (*t)["print"] = oe_requiredChoices(
859 &ArgParser::arg128Print, print128_choices); 863 &ArgParser::arg128Print, print128_choices);
  864 + (*t)["assemble"] = oe_requiredChoices(&ArgParser::arg128Assemble, yn);
  865 + (*t)["annotate"] = oe_requiredChoices(&ArgParser::arg128Annotate, yn);
  866 + (*t)["form"] = oe_requiredChoices(&ArgParser::arg128Form, yn);
  867 + (*t)["modify-other"] = oe_requiredChoices(&ArgParser::arg128ModOther, yn);
860 char const* modify128_choices[] = 868 char const* modify128_choices[] =
861 {"all", "annotate", "form", "assembly", "none", 0}; 869 {"all", "annotate", "form", "assembly", "none", 0};
862 (*t)["modify"] = oe_requiredChoices( 870 (*t)["modify"] = oe_requiredChoices(
863 &ArgParser::arg128Modify, modify128_choices); 871 &ArgParser::arg128Modify, modify128_choices);
864 (*t)["cleartext-metadata"] = oe_bare(&ArgParser::arg128ClearTextMetadata); 872 (*t)["cleartext-metadata"] = oe_bare(&ArgParser::arg128ClearTextMetadata);
  873 +
865 // The above 128-bit options are also 256-bit options, so copy 874 // The above 128-bit options are also 256-bit options, so copy
866 // what we have so far. Then continue separately with 128 and 256. 875 // what we have so far. Then continue separately with 128 and 256.
867 this->encrypt256_option_table = this->encrypt128_option_table; 876 this->encrypt256_option_table = this->encrypt128_option_table;
@@ -1048,7 +1057,11 @@ ArgParser::argHelp() @@ -1048,7 +1057,11 @@ ArgParser::argHelp()
1048 << " --accessibility=[yn] allow accessibility to visually impaired\n" 1057 << " --accessibility=[yn] allow accessibility to visually impaired\n"
1049 << " --extract=[yn] allow other text/graphic extraction\n" 1058 << " --extract=[yn] allow other text/graphic extraction\n"
1050 << " --print=print-opt control printing access\n" 1059 << " --print=print-opt control printing access\n"
1051 - << " --modify=modify-opt control modify access\n" 1060 + << " --assemble=[yn] allow document assembly\n"
  1061 + << " --annotate=[yn] allow commenting/filling form fields\n"
  1062 + << " --form=[yn] allow filling form fields\n"
  1063 + << " --modify-other=[yn] allow other modifications\n"
  1064 + << " --modify=modify-opt control modify access (old way)\n"
1052 << " --cleartext-metadata prevents encryption of metadata\n" 1065 << " --cleartext-metadata prevents encryption of metadata\n"
1053 << " --use-aes=[yn] indicates whether to use AES encryption\n" 1066 << " --use-aes=[yn] indicates whether to use AES encryption\n"
1054 << " --force-V4 forces use of V=4 encryption handler\n" 1067 << " --force-V4 forces use of V=4 encryption handler\n"
@@ -1072,7 +1085,8 @@ ArgParser::argHelp() @@ -1072,7 +1085,8 @@ ArgParser::argHelp()
1072 << " assembly allow document assembly only\n" 1085 << " assembly allow document assembly only\n"
1073 << " none allow no modifications\n" 1086 << " none allow no modifications\n"
1074 << "\n" 1087 << "\n"
1075 - << "The default for each permission option is to be fully permissive.\n" 1088 + << "The default for each permission option is to be fully permissive. Please\n"
  1089 + << "refer to the manual for more details on the modify options.\n"
1076 << "\n" 1090 << "\n"
1077 << "Specifying cleartext-metadata forces the PDF version to at least 1.5.\n" 1091 << "Specifying cleartext-metadata forces the PDF version to at least 1.5.\n"
1078 << "Specifying use of AES forces the PDF version to at least 1.6. These\n" 1092 << "Specifying use of AES forces the PDF version to at least 1.6. These\n"
@@ -1915,6 +1929,30 @@ ArgParser::arg128ClearTextMetadata() @@ -1915,6 +1929,30 @@ ArgParser::arg128ClearTextMetadata()
1915 } 1929 }
1916 1930
1917 void 1931 void
  1932 +ArgParser::arg128Assemble(char* parameter)
  1933 +{
  1934 + o.r3_assemble = (strcmp(parameter, "y") == 0);
  1935 +}
  1936 +
  1937 +void
  1938 +ArgParser::arg128Annotate(char* parameter)
  1939 +{
  1940 + o.r3_annotate_and_form = (strcmp(parameter, "y") == 0);
  1941 +}
  1942 +
  1943 +void
  1944 +ArgParser::arg128Form(char* parameter)
  1945 +{
  1946 + o.r3_form_filling = (strcmp(parameter, "y") == 0);
  1947 +}
  1948 +
  1949 +void
  1950 +ArgParser::arg128ModOther(char* parameter)
  1951 +{
  1952 + o.r3_modify_other = (strcmp(parameter, "y") == 0);
  1953 +}
  1954 +
  1955 +void
1918 ArgParser::arg128UseAes(char* parameter) 1956 ArgParser::arg128UseAes(char* parameter)
1919 { 1957 {
1920 o.use_aes = (strcmp(parameter, "y") == 0); 1958 o.use_aes = (strcmp(parameter, "y") == 0);
qpdf/qtest/qpdf.test
@@ -2687,6 +2687,24 @@ my @encrypted_files = @@ -2687,6 +2687,24 @@ my @encrypted_files =
2687 ['R3,V2,U=view,O=master', 'master', 2687 ['R3,V2,U=view,O=master', 'master',
2688 '-accessibility=n -print=low', -2564, 2688 '-accessibility=n -print=low', -2564,
2689 0, 1, 1, 0, 1, 1, 1, 1, 1], 2689 0, 1, 1, 0, 1, 1, 1, 1, 1],
  2690 + ['R3,V2,U=view,O=master', 'master',
  2691 + '-modify=all -assemble=n', -1028,
  2692 + 1, 1, 1, 1, 0, 1, 1, 1, 0],
  2693 + ['R3,V2,U=view,O=master', 'master',
  2694 + '-modify=none -form=y', -1068,
  2695 + 1, 1, 1, 1, 0, 1, 0, 0, 0],
  2696 + ['R3,V2,U=view,O=master', 'master',
  2697 + '-modify=annotate -assemble=n', -1036,
  2698 + 1, 1, 1, 1, 0, 1, 1, 0, 0],
  2699 + ['R3,V2,U=view,O=master', 'master',
  2700 + '-form=n', -260,
  2701 + 1, 1, 1, 1, 1, 0, 1, 1, 0],
  2702 + ['R3,V2,U=view,O=master', 'master',
  2703 + '-annotate=n', -36,
  2704 + 1, 1, 1, 1, 1, 1, 0, 1, 0],
  2705 + ['R3,V2,U=view,O=master', 'master',
  2706 + '-modify-other=n', -12,
  2707 + 1, 1, 1, 1, 1, 1, 1, 0, 0],
2690 ['R2,V1', '', 2708 ['R2,V1', '',
2691 '-print=n -modify=n -extract=n -annotate=n', -64, 2709 '-print=n -modify=n -extract=n -annotate=n', -64,
2692 0, 0, 0, 0, 0, 0, 0, 0, 0], 2710 0, 0, 0, 0, 0, 0, 0, 0, 0],
qpdf/qtest/qpdf/completion-encrypt-128.out
1 --force-V4 1 --force-V4
2 -!--annotate=  
3 !--force-R5 2 !--force-R5
qpdf/qtest/qpdf/completion-encrypt-256.out
1 --force-R5 1 --force-R5
2 -!--annotate=  
3 !--force-V4 2 !--force-V4