1
//========================================================================
5
// Copyright 2004 Glyph & Cog, LLC
7
//========================================================================
9
//========================================================================
11
// Modified under the Poppler project - http://poppler.freedesktop.org
13
// All changes made under the Poppler project to this file are licensed
14
// under GPL version 2 or later
16
// Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
18
// To see a description of the changes please see the Changelog file that
19
// came with your tarball or type make ChangeLog if you are building from git
21
//========================================================================
25
#ifdef USE_GCC_PRAGMAS
26
#pragma implementation
29
#include "GooString.h"
33
#include "GlobalParams.h"
35
# include "XPDFCore.h"
37
# include "WinPDFCore.h"
40
# include "XpdfPluginAPI.h"
42
#include "SecurityHandler.h"
46
//------------------------------------------------------------------------
48
//------------------------------------------------------------------------
50
SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) {
52
SecurityHandler *secHdlr;
54
XpdfSecurityHandler *xsh;
57
encryptDictA->dictLookup("Filter", &filterObj);
58
if (filterObj.isName("Standard")) {
59
secHdlr = new StandardSecurityHandler(docA, encryptDictA);
60
} else if (filterObj.isName()) {
62
if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) {
63
secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh);
66
error(-1, "Couldn't find the '%s' security handler",
73
error(-1, "Missing or invalid 'Filter' entry in encryption dictionary");
80
SecurityHandler::SecurityHandler(PDFDoc *docA) {
84
SecurityHandler::~SecurityHandler() {
87
GBool SecurityHandler::checkEncryption(GooString *ownerPassword,
88
GooString *userPassword) {
93
if (ownerPassword || userPassword) {
94
authData = makeAuthData(ownerPassword, userPassword);
98
ok = authorize(authData);
100
freeAuthData(authData);
102
for (i = 0; !ok && i < 3; ++i) {
103
if (!(authData = getAuthData())) {
106
ok = authorize(authData);
108
freeAuthData(authData);
112
error(-1, "Incorrect password");
117
//------------------------------------------------------------------------
118
// StandardSecurityHandler
119
//------------------------------------------------------------------------
121
class StandardAuthData {
124
StandardAuthData(GooString *ownerPasswordA, GooString *userPasswordA) {
125
ownerPassword = ownerPasswordA;
126
userPassword = userPasswordA;
129
~StandardAuthData() {
131
delete ownerPassword;
138
GooString *ownerPassword;
139
GooString *userPassword;
142
StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
143
Object *encryptDictA):
144
SecurityHandler(docA)
146
Object versionObj, revisionObj, lengthObj;
147
Object ownerKeyObj, userKeyObj, permObj, fileIDObj;
149
Object cryptFiltersObj, streamFilterObj, stringFilterObj;
150
Object cryptFilterObj, cfmObj, cfLengthObj;
151
Object encryptMetadataObj;
158
encryptDictA->dictLookup("V", &versionObj);
159
encryptDictA->dictLookup("R", &revisionObj);
160
encryptDictA->dictLookup("Length", &lengthObj);
161
encryptDictA->dictLookup("O", &ownerKeyObj);
162
encryptDictA->dictLookup("U", &userKeyObj);
163
encryptDictA->dictLookup("P", &permObj);
164
if (permObj.isUint()) {
165
unsigned int permUint = permObj.getUint();
166
int perms = permUint - UINT_MAX - 1;
168
permObj.initInt(perms);
170
doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj);
171
if (versionObj.isInt() &&
172
revisionObj.isInt() &&
173
ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 &&
174
userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 &&
176
encVersion = versionObj.getInt();
177
encRevision = revisionObj.getInt();
178
encAlgorithm = cryptRC4;
179
// revision 2 forces a 40-bit key - some buggy PDF generators
180
// set the Length value incorrectly
181
if (encRevision == 2 || !lengthObj.isInt()) {
184
fileKeyLength = lengthObj.getInt() / 8;
186
encryptMetadata = gTrue;
187
//~ this currently only handles a subset of crypt filter functionality
188
if (encVersion == 4 && encRevision == 4) {
189
encryptDictA->dictLookup("CF", &cryptFiltersObj);
190
encryptDictA->dictLookup("StmF", &streamFilterObj);
191
encryptDictA->dictLookup("StrF", &stringFilterObj);
192
if (cryptFiltersObj.isDict() &&
193
streamFilterObj.isName() &&
194
stringFilterObj.isName() &&
195
!strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
196
if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
197
&cryptFilterObj)->isDict()) {
198
cryptFilterObj.dictLookup("CFM", &cfmObj);
199
if (cfmObj.isName("V2")) {
202
if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
203
//~ according to the spec, this should be cfLengthObj / 8
204
fileKeyLength = cfLengthObj.getInt();
207
} else if (cfmObj.isName("AESV2")) {
210
encAlgorithm = cryptAES;
211
if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
212
//~ according to the spec, this should be cfLengthObj / 8
213
fileKeyLength = cfLengthObj.getInt();
219
cryptFilterObj.free();
221
stringFilterObj.free();
222
streamFilterObj.free();
223
cryptFiltersObj.free();
224
if (encryptDictA->dictLookup("EncryptMetadata",
225
&encryptMetadataObj)->isBool()) {
226
encryptMetadata = encryptMetadataObj.getBool();
228
encryptMetadataObj.free();
230
permFlags = permObj.getInt();
231
ownerKey = ownerKeyObj.getString()->copy();
232
userKey = userKeyObj.getString()->copy();
233
if (encVersion >= 1 && encVersion <= 2 &&
234
encRevision >= 2 && encRevision <= 3) {
235
if (fileIDObj.isArray()) {
236
if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) {
237
fileID = fileIDObj1.getString()->copy();
239
fileID = new GooString();
243
fileID = new GooString();
247
error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
248
encVersion, encRevision);
251
error(-1, "Weird encryption info");
253
if (fileKeyLength > 16) {
265
StandardSecurityHandler::~StandardSecurityHandler() {
277
void *StandardSecurityHandler::makeAuthData(GooString *ownerPassword,
278
GooString *userPassword) {
279
return new StandardAuthData(ownerPassword ? ownerPassword->copy()
281
userPassword ? userPassword->copy()
282
: (GooString *)NULL);
285
void *StandardSecurityHandler::getAuthData() {
290
if (!(core = (XPDFCore *)doc->getGUIData()) ||
291
!(password = core->getPassword())) {
294
return new StandardAuthData(password, password->copy());
295
#elif HAVE_WINPDFCORE
299
if (!(core = (WinPDFCore *)doc->getGUIData()) ||
300
!(password = core->getPassword())) {
303
return new StandardAuthData(password, password->copy());
309
void StandardSecurityHandler::freeAuthData(void *authData) {
310
delete (StandardAuthData *)authData;
313
GBool StandardSecurityHandler::authorize(void *authData) {
314
GooString *ownerPassword, *userPassword;
320
ownerPassword = ((StandardAuthData *)authData)->ownerPassword;
321
userPassword = ((StandardAuthData *)authData)->userPassword;
323
ownerPassword = NULL;
326
if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength,
327
ownerKey, userKey, permFlags, fileID,
328
ownerPassword, userPassword, fileKey,
329
encryptMetadata, &ownerPasswordOk)) {
335
#ifdef ENABLE_PLUGINS
337
//------------------------------------------------------------------------
338
// ExternalSecurityHandler
339
//------------------------------------------------------------------------
341
ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA,
342
Object *encryptDictA,
343
XpdfSecurityHandler *xshA):
344
SecurityHandler(docA)
346
encryptDictA->copy(&encryptDict);
348
encAlgorithm = cryptRC4; //~ this should be obtained via getKey
351
if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA,
352
(XpdfObject)encryptDictA, &docData)) {
359
ExternalSecurityHandler::~ExternalSecurityHandler() {
360
(*xsh->freeDoc)(xsh->handlerData, docData);
364
void *ExternalSecurityHandler::makeAuthData(GooString *ownerPassword,
365
GooString *userPassword) {
369
opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL;
370
upw = userPassword ? userPassword->getCString() : (char *)NULL;
371
if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) {
377
void *ExternalSecurityHandler::getAuthData() {
380
if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) {
386
void ExternalSecurityHandler::freeAuthData(void *authData) {
387
(*xsh->freeAuthData)(xsh->handlerData, docData, authData);
390
GBool ExternalSecurityHandler::authorize(void *authData) {
397
permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData);
398
if (!(permFlags & xpdfPermissionOpen)) {
401
if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) {
404
if ((fileKeyLength = length) > 16) {
407
memcpy(fileKey, key, fileKeyLength);
408
(*xsh->freeKey)(xsh->handlerData, docData, key, length);
412
#endif // ENABLE_PLUGINS