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

This commit is contained in:
Jay Berkenbilt 2019-01-14 22:42:36 -05:00
parent 6ec22f117d
commit 966429e718
6 changed files with 120 additions and 9 deletions

View File

@ -16,6 +16,11 @@
2019-01-14 Jay Berkenbilt <ejb@ql.org>
* Add new CLI flags to 128-bit and 256-bit encryption: --assemble,
--annotate, --form, and --modify-other to control encryption
permissions with more granularity than was allowed with the
--modify flag. Fixes #214.
* Add new versions of
QPDFWriter::setR{3,4,5,6}EncryptionParameters that allow
individual setting of the various permission bits. The old

View File

@ -786,7 +786,12 @@ make
<listitem>
<para>
Determines whether or not to allow accessibility to visually
impaired.
impaired. The qpdf library disregards this field when AES is
used or when 256-bit encryption is used. You should really
never disable accessibility, but qpdf lets you do it in case
you need to configure a file this way for testing purposes.
The PDF spec says that conforming readers should disregard
this permission and always allow accessibility.
</para>
</listitem>
</varlistentry>
@ -798,6 +803,45 @@ make
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--assemble=[yn]</option></term>
<listitem>
<para>
Determines whether document assembly (rotation and reordering
of pages) is allowed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--annotate=[yn]</option></term>
<listitem>
<para>
Determines whether modifying annotations is allowed. This
includes adding comments and filling in form fields. Also
allows editing of form fields if
<option>--modify-other=y</option> is given.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--form=[yn]</option></term>
<listitem>
<para>
Determines whether filling form fields is allowed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--modify-other=[yn]</option></term>
<listitem>
<para>
Allow all document editing except those controlled separately
by the <option>--assemble</option>,
<option>--annotate</option>, and <option>--form</option>
options.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--print=<replaceable>print-opt</replaceable></option></term>
<listitem>
@ -829,10 +873,10 @@ make
<term><option>--modify=<replaceable>modify-opt</replaceable></option></term>
<listitem>
<para>
Controls modify access.
Controls modify access. This way of controlling modify access
has less granularity than new options added in qpdf 8.4.
<option><replaceable>modify-opt</replaceable></option> may be
one of the following, each of which implies all the options
that follow it:
one of the following:
<itemizedlist>
<listitem>
<para>
@ -841,12 +885,14 @@ make
</listitem>
<listitem>
<para>
<option>annotate</option>: allow comment authoring and form operations
<option>annotate</option>: allow comment authoring, form
operations, and document assembly
</para>
</listitem>
<listitem>
<para>
<option>form</option>: allow form field fill-in and signing
and document assembly
</para>
</listitem>
<listitem>
@ -860,6 +906,12 @@ make
</para>
</listitem>
</itemizedlist>
Using the <option>--modify</option> option does not allow you
to create certain combinations of permissions such as allowing
form filling but not allowing document assembly. Starting with
qpdf 8.4, you can either just use the other options to control
fields individually, or you can use something like
<option>--modify=form --assembly=n</option> to fine tune.
</para>
</listitem>
</varlistentry>

View File

@ -631,6 +631,10 @@ class ArgParser
void arg128Print(char* parameter);
void arg128Modify(char* parameter);
void arg128ClearTextMetadata();
void arg128Assemble(char* parameter);
void arg128Annotate(char* parameter);
void arg128Form(char* parameter);
void arg128ModOther(char* parameter);
void arg128UseAes(char* parameter);
void arg128ForceV4();
void arg256ForceR5();
@ -857,11 +861,16 @@ ArgParser::initOptionTable()
char const* print128_choices[] = {"full", "low", "none", 0};
(*t)["print"] = oe_requiredChoices(
&ArgParser::arg128Print, print128_choices);
(*t)["assemble"] = oe_requiredChoices(&ArgParser::arg128Assemble, yn);
(*t)["annotate"] = oe_requiredChoices(&ArgParser::arg128Annotate, yn);
(*t)["form"] = oe_requiredChoices(&ArgParser::arg128Form, yn);
(*t)["modify-other"] = oe_requiredChoices(&ArgParser::arg128ModOther, yn);
char const* modify128_choices[] =
{"all", "annotate", "form", "assembly", "none", 0};
(*t)["modify"] = oe_requiredChoices(
&ArgParser::arg128Modify, modify128_choices);
(*t)["cleartext-metadata"] = oe_bare(&ArgParser::arg128ClearTextMetadata);
// The above 128-bit options are also 256-bit options, so copy
// what we have so far. Then continue separately with 128 and 256.
this->encrypt256_option_table = this->encrypt128_option_table;
@ -1048,7 +1057,11 @@ ArgParser::argHelp()
<< " --accessibility=[yn] allow accessibility to visually impaired\n"
<< " --extract=[yn] allow other text/graphic extraction\n"
<< " --print=print-opt control printing access\n"
<< " --modify=modify-opt control modify access\n"
<< " --assemble=[yn] allow document assembly\n"
<< " --annotate=[yn] allow commenting/filling form fields\n"
<< " --form=[yn] allow filling form fields\n"
<< " --modify-other=[yn] allow other modifications\n"
<< " --modify=modify-opt control modify access (old way)\n"
<< " --cleartext-metadata prevents encryption of metadata\n"
<< " --use-aes=[yn] indicates whether to use AES encryption\n"
<< " --force-V4 forces use of V=4 encryption handler\n"
@ -1072,7 +1085,8 @@ ArgParser::argHelp()
<< " assembly allow document assembly only\n"
<< " none allow no modifications\n"
<< "\n"
<< "The default for each permission option is to be fully permissive.\n"
<< "The default for each permission option is to be fully permissive. Please\n"
<< "refer to the manual for more details on the modify options.\n"
<< "\n"
<< "Specifying cleartext-metadata forces the PDF version to at least 1.5.\n"
<< "Specifying use of AES forces the PDF version to at least 1.6. These\n"
@ -1914,6 +1928,30 @@ ArgParser::arg128ClearTextMetadata()
o.cleartext_metadata = true;
}
void
ArgParser::arg128Assemble(char* parameter)
{
o.r3_assemble = (strcmp(parameter, "y") == 0);
}
void
ArgParser::arg128Annotate(char* parameter)
{
o.r3_annotate_and_form = (strcmp(parameter, "y") == 0);
}
void
ArgParser::arg128Form(char* parameter)
{
o.r3_form_filling = (strcmp(parameter, "y") == 0);
}
void
ArgParser::arg128ModOther(char* parameter)
{
o.r3_modify_other = (strcmp(parameter, "y") == 0);
}
void
ArgParser::arg128UseAes(char* parameter)
{

View File

@ -2687,6 +2687,24 @@ my @encrypted_files =
['R3,V2,U=view,O=master', 'master',
'-accessibility=n -print=low', -2564,
0, 1, 1, 0, 1, 1, 1, 1, 1],
['R3,V2,U=view,O=master', 'master',
'-modify=all -assemble=n', -1028,
1, 1, 1, 1, 0, 1, 1, 1, 0],
['R3,V2,U=view,O=master', 'master',
'-modify=none -form=y', -1068,
1, 1, 1, 1, 0, 1, 0, 0, 0],
['R3,V2,U=view,O=master', 'master',
'-modify=annotate -assemble=n', -1036,
1, 1, 1, 1, 0, 1, 1, 0, 0],
['R3,V2,U=view,O=master', 'master',
'-form=n', -260,
1, 1, 1, 1, 1, 0, 1, 1, 0],
['R3,V2,U=view,O=master', 'master',
'-annotate=n', -36,
1, 1, 1, 1, 1, 1, 0, 1, 0],
['R3,V2,U=view,O=master', 'master',
'-modify-other=n', -12,
1, 1, 1, 1, 1, 1, 1, 0, 0],
['R2,V1', '',
'-print=n -modify=n -extract=n -annotate=n', -64,
0, 0, 0, 0, 0, 0, 0, 0, 0],

View File

@ -1,3 +1,2 @@
--force-V4
!--annotate=
!--force-R5

View File

@ -1,3 +1,2 @@
--force-R5
!--annotate=
!--force-V4