1 //========================================================================
5 // Copyright 2004 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
19 #include "GlobalParams.h"
21 # include "XPDFCore.h"
23 # include "WinPDFCore.h"
26 # include "XpdfPluginAPI.h"
28 #include "SecurityHandler.h"
30 //------------------------------------------------------------------------
32 //------------------------------------------------------------------------
34 SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) {
36 SecurityHandler *secHdlr;
37 XpdfSecurityHandler *xsh;
39 encryptDictA->dictLookup("Filter", &filterObj);
40 if (filterObj.isName("Standard")) {
41 secHdlr = new StandardSecurityHandler(docA, encryptDictA);
42 } else if (filterObj.isName()) {
44 if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) {
45 secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh);
48 error(-1, "Couldn't find the '%s' security handler",
55 error(-1, "Missing or invalid 'Filter' entry in encryption dictionary");
62 SecurityHandler::SecurityHandler(PDFDoc *docA) {
66 SecurityHandler::~SecurityHandler() {
69 GBool SecurityHandler::checkEncryption(GString *ownerPassword,
70 GString *userPassword) {
75 if (ownerPassword || userPassword) {
76 authData = makeAuthData(ownerPassword, userPassword);
80 ok = authorize(authData);
82 freeAuthData(authData);
84 for (i = 0; !ok && i < 3; ++i) {
85 if (!(authData = getAuthData())) {
88 ok = authorize(authData);
90 freeAuthData(authData);
94 error(-1, "Incorrect password");
99 //------------------------------------------------------------------------
100 // StandardSecurityHandler
101 //------------------------------------------------------------------------
103 class StandardAuthData {
106 StandardAuthData(GString *ownerPasswordA, GString *userPasswordA) {
107 ownerPassword = ownerPasswordA;
108 userPassword = userPasswordA;
111 ~StandardAuthData() {
113 delete ownerPassword;
120 GString *ownerPassword;
121 GString *userPassword;
124 StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
125 Object *encryptDictA):
126 SecurityHandler(docA)
128 Object versionObj, revisionObj, lengthObj;
129 Object ownerKeyObj, userKeyObj, permObj, fileIDObj;
131 Object cryptFiltersObj, streamFilterObj, stringFilterObj;
132 Object cryptFilterObj, cfmObj, cfLengthObj;
133 Object encryptMetadataObj;
140 encryptDictA->dictLookup("V", &versionObj);
141 encryptDictA->dictLookup("R", &revisionObj);
142 encryptDictA->dictLookup("Length", &lengthObj);
143 encryptDictA->dictLookup("O", &ownerKeyObj);
144 encryptDictA->dictLookup("U", &userKeyObj);
145 encryptDictA->dictLookup("P", &permObj);
146 doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj);
147 if (versionObj.isInt() &&
148 revisionObj.isInt() &&
149 ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 &&
150 userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 &&
152 encVersion = versionObj.getInt();
153 encRevision = revisionObj.getInt();
154 // revision 2 forces a 40-bit key - some buggy PDF generators
155 // set the Length value incorrectly
156 if (encRevision == 2 || !lengthObj.isInt()) {
159 fileKeyLength = lengthObj.getInt() / 8;
161 encryptMetadata = gTrue;
162 //~ this currently only handles a subset of crypt filter functionality
163 if (encVersion == 4 && encRevision == 4) {
164 encryptDictA->dictLookup("CF", &cryptFiltersObj);
165 encryptDictA->dictLookup("StmF", &streamFilterObj);
166 encryptDictA->dictLookup("StrF", &stringFilterObj);
167 if (cryptFiltersObj.isDict() &&
168 streamFilterObj.isName() &&
169 stringFilterObj.isName() &&
170 !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) {
171 if (cryptFiltersObj.dictLookup(streamFilterObj.getName(),
172 &cryptFilterObj)->isDict()) {
173 if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) {
176 if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
177 //~ according to the spec, this should be cfLengthObj / 8
178 fileKeyLength = cfLengthObj.getInt();
184 cryptFilterObj.free();
186 stringFilterObj.free();
187 streamFilterObj.free();
188 cryptFiltersObj.free();
189 if (encryptDictA->dictLookup("EncryptMetadata",
190 &encryptMetadataObj)->isBool()) {
191 encryptMetadata = encryptMetadataObj.getBool();
193 encryptMetadataObj.free();
195 permFlags = permObj.getInt();
196 ownerKey = ownerKeyObj.getString()->copy();
197 userKey = userKeyObj.getString()->copy();
198 if (encVersion >= 1 && encVersion <= 2 &&
199 encRevision >= 2 && encRevision <= 3) {
200 if (fileIDObj.isArray()) {
201 if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) {
202 fileID = fileIDObj1.getString()->copy();
204 fileID = new GString();
208 fileID = new GString();
212 error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
213 encVersion, encRevision);
216 error(-1, "Weird encryption info");
218 if (fileKeyLength > 16) {
230 StandardSecurityHandler::~StandardSecurityHandler() {
242 void *StandardSecurityHandler::makeAuthData(GString *ownerPassword,
243 GString *userPassword) {
244 return new StandardAuthData(ownerPassword ? ownerPassword->copy()
246 userPassword ? userPassword->copy()
250 void *StandardSecurityHandler::getAuthData() {
255 if (!(core = (XPDFCore *)doc->getGUIData()) ||
256 !(password = core->getPassword())) {
259 return new StandardAuthData(password, password->copy());
260 #elif HAVE_WINPDFCORE
264 if (!(core = (WinPDFCore *)doc->getGUIData()) ||
265 !(password = core->getPassword())) {
268 return new StandardAuthData(password, password->copy());
274 void StandardSecurityHandler::freeAuthData(void *authData) {
275 delete (StandardAuthData *)authData;
278 GBool StandardSecurityHandler::authorize(void *authData) {
279 GString *ownerPassword, *userPassword;
285 ownerPassword = ((StandardAuthData *)authData)->ownerPassword;
286 userPassword = ((StandardAuthData *)authData)->userPassword;
288 ownerPassword = NULL;
291 if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength,
292 ownerKey, userKey, permFlags, fileID,
293 ownerPassword, userPassword, fileKey,
294 encryptMetadata, &ownerPasswordOk)) {
300 #ifdef ENABLE_PLUGINS
302 //------------------------------------------------------------------------
303 // ExternalSecurityHandler
304 //------------------------------------------------------------------------
306 ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA,
307 Object *encryptDictA,
308 XpdfSecurityHandler *xshA):
309 SecurityHandler(docA)
311 encryptDictA->copy(&encryptDict);
315 if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA,
316 (XpdfObject)encryptDictA, &docData)) {
323 ExternalSecurityHandler::~ExternalSecurityHandler() {
324 (*xsh->freeDoc)(xsh->handlerData, docData);
328 void *ExternalSecurityHandler::makeAuthData(GString *ownerPassword,
329 GString *userPassword) {
333 opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL;
334 upw = userPassword ? userPassword->getCString() : (char *)NULL;
335 if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) {
341 void *ExternalSecurityHandler::getAuthData() {
344 if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) {
350 void ExternalSecurityHandler::freeAuthData(void *authData) {
351 (*xsh->freeAuthData)(xsh->handlerData, docData, authData);
354 GBool ExternalSecurityHandler::authorize(void *authData) {
361 permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData);
362 if (!(permFlags & xpdfPermissionOpen)) {
365 if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) {
368 if ((fileKeyLength = length) > 16) {
371 memcpy(fileKey, key, fileKeyLength);
372 (*xsh->freeKey)(xsh->handlerData, docData, key, length);
376 #endif // ENABLE_PLUGINS