Bug 691256 - OwnerPassword and UserPassword don't work as device parameters
Summary: OwnerPassword and UserPassword don't work as device parameters
Status: RESOLVED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: PDF Writer (show other bugs)
Version: master
Hardware: All All
: P4 normal
Assignee: Ken Sharp
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-04-21 15:51 UTC by Ray Johnston
Modified: 2010-09-28 12:27 UTC (History)
0 users

See Also:
Customer:
Word Size: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ray Johnston 2010-04-21 15:51:40 UTC
while this works:

bin/gswin32c -sDEVICE=pdfwrite -o x.pdf -sUserPassword=rjj -sOwnerPassword=rjj -f examples/tiger.eps

The following creates a PDF that is encrypted, but cannot be opened by Adobe
Acrobat 9 or other PDF viewers:

bin/gswin32c -sDEVICE=pdfwrite -o x.pdf -c "<< /OwnerPassword (rjj) /UserPassword (rjj) >> setpagedevice" -f examples/tiger.eps
Comment 1 Ken Sharp 2010-09-27 14:24:14 UTC
Ray, I could use some advice on this one. As it is, this is 'expected' behaviour, even if its not desirable.

The problem is that on a call to setdevice, the page device is consulted when the device (pdfwrite) is opened, in pdf_open() and this is where the encryption is initialised. Whatever is in the page device dictionary at this time is what gets used to initialise the encryption filter.

On subsequent calls to setdevice, the code in gs_setdevice_no_erase() tests to see if the device is already open, and if it is it does not call gs_opendevice() and therefore doesn't call pdf_open(). So we don't recreate the encryption filter.

gs_setdevice_no_init() does get called, but it doesn't call any device methods it just allows for colour space changes, nothing else. Presumably something somewhere closes the device and reopens it if an important device parameter changes, but I don't know how that's done.

To some extent this is reasonable, pdfwrite really needs to have the encryption filter set up before anything starts making marks; on the other hand, as long as the setpagedevice is encountered before any marking operations then it would be valid to alter the passwords.

However, it seems that we separately check the page device dictionary when writing the trailer dictionary, and if there are passwords, then we write an Encrypt entry. This is bogus because we *haven't* encrypted the file. Simply removing the Encrypt entry allows me to open the file in Acrobat (it can't otherwise be opened, because it has an Encrypt entry, but is not encrypted).

So the problem is that we *must* have the passwords and set up the encryption filter before we make any marking operations. But the setdevice interface doesn't apparently allow for detecting altered entries in the dictionary. I could alter all the pdfwrite methods so that they check to see if there are passwords in the dictionary that haven't been used yet, but that's a lot of coding and prone to go wrong.

My preferred solution is to say that you *must* use the -sUserPassword and -sOwnerPassword to set the encryption, and then to alter the trailer dict emission so that if a password has been added after setup, we don't emit a bogus Encrypt entry.

What do you think ? If I'm missing something about the operation of setdevice, that would be useful to know, maybe I could detect the changed passwords more reasonably.
Comment 2 Ray Johnston 2010-09-27 15:23:18 UTC
I think this is similar to the problem that pdfwrite opens, but never closes
until Ghostscript exits (we have an open enhancement for that).

The .setdevice (and setpagedevice) both are defined as clearing the current
page of any marks, so we shouldn't have to check to see if the page is
'marked'. Thus, I would guess this statement from Ken would be operable:

> pdfwrite really needs to have the encryption
> filter set up before anything starts making marks; on the other hand, as long
> as the setpagedevice is encountered before any marking operations then it
> would be valid to alter the passwords.

Specifically, we can assume that the page is not marked (actually discard
any previous marking operations prior to the setpagedevice/.setdevice action.

There may be an issue that we don't (in the pdfwrite device) know when this
occurs, and maybe we need to have the pdfwrite put_params close the device
when certain parameters get set (such as passwords) just as raster devices
close when the geometry or color depth changes so the device gets re-opened
and can reestablish with the new parameters.

I suggest further discussion on IRC if needed to make sure I am understanding
the issue correctly.
Comment 3 Ken Sharp 2010-09-28 12:27:43 UTC
Fixed in revision 11746:

http://ghostscript.com/pipermail/gs-cvs/2010-September/011773.html

The new password will only take effect if we have no yet output any pages. Once the first page is output we will instead emit a warning that the password cannot be changed.