~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/poppler/SecurityHandler.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//
 
3
// SecurityHandler.cc
 
4
//
 
5
// Copyright 2004 Glyph & Cog, LLC
 
6
//
 
7
//========================================================================
 
8
 
 
9
//========================================================================
 
10
//
 
11
// Modified under the Poppler project - http://poppler.freedesktop.org
 
12
//
 
13
// All changes made under the Poppler project to this file are licensed
 
14
// under GPL version 2 or later
 
15
//
 
16
// Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
 
17
//
 
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
 
20
//
 
21
//========================================================================
 
22
 
 
23
#include <config.h>
 
24
 
 
25
#ifdef USE_GCC_PRAGMAS
 
26
#pragma implementation
 
27
#endif
 
28
 
 
29
#include "GooString.h"
 
30
#include "PDFDoc.h"
 
31
#include "Decrypt.h"
 
32
#include "Error.h"
 
33
#include "GlobalParams.h"
 
34
#if HAVE_XPDFCORE
 
35
#  include "XPDFCore.h"
 
36
#elif HAVE_WINPDFCORE
 
37
#  include "WinPDFCore.h"
 
38
#endif
 
39
#ifdef ENABLE_PLUGINS
 
40
#  include "XpdfPluginAPI.h"
 
41
#endif
 
42
#include "SecurityHandler.h"
 
43
 
 
44
#include <limits.h>
 
45
 
 
46
//------------------------------------------------------------------------
 
47
// SecurityHandler
 
48
//------------------------------------------------------------------------
 
49
 
 
50
SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) {
 
51
  Object filterObj;
 
52
  SecurityHandler *secHdlr;
 
53
#ifdef ENABLE_PLUGINS
 
54
  XpdfSecurityHandler *xsh;
 
55
#endif
 
56
 
 
57
  encryptDictA->dictLookup("Filter", &filterObj);
 
58
  if (filterObj.isName("Standard")) {
 
59
    secHdlr = new StandardSecurityHandler(docA, encryptDictA);
 
60
  } else if (filterObj.isName()) {
 
61
#ifdef ENABLE_PLUGINS
 
62
    if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) {
 
63
      secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh);
 
64
    } else {
 
65
#endif
 
66
      error(-1, "Couldn't find the '%s' security handler",
 
67
            filterObj.getName());
 
68
      secHdlr = NULL;
 
69
#ifdef ENABLE_PLUGINS
 
70
    }
 
71
#endif
 
72
  } else {
 
73
    error(-1, "Missing or invalid 'Filter' entry in encryption dictionary");
 
74
    secHdlr = NULL;
 
75
  }
 
76
  filterObj.free();
 
77
  return secHdlr;
 
78
}
 
79
 
 
80
SecurityHandler::SecurityHandler(PDFDoc *docA) {
 
81
  doc = docA;
 
82
}
 
83
 
 
84
SecurityHandler::~SecurityHandler() {
 
85
}
 
86
 
 
87
GBool SecurityHandler::checkEncryption(GooString *ownerPassword,
 
88
                                       GooString *userPassword) {
 
89
  void *authData;
 
90
  GBool ok;
 
91
  int i;
 
92
 
 
93
  if (ownerPassword || userPassword) {
 
94
    authData = makeAuthData(ownerPassword, userPassword);
 
95
  } else {
 
96
    authData = NULL;
 
97
  }
 
98
  ok = authorize(authData);
 
99
  if (authData) {
 
100
    freeAuthData(authData);
 
101
  }
 
102
  for (i = 0; !ok && i < 3; ++i) {
 
103
    if (!(authData = getAuthData())) {
 
104
      break;
 
105
    }
 
106
    ok = authorize(authData);
 
107
    if (authData) {
 
108
      freeAuthData(authData);
 
109
    }
 
110
  }
 
111
  if (!ok) {
 
112
    error(-1, "Incorrect password");
 
113
  }
 
114
  return ok;
 
115
}
 
116
 
 
117
//------------------------------------------------------------------------
 
118
// StandardSecurityHandler
 
119
//------------------------------------------------------------------------
 
120
 
 
121
class StandardAuthData {
 
122
public:
 
123
 
 
124
  StandardAuthData(GooString *ownerPasswordA, GooString *userPasswordA) {
 
125
    ownerPassword = ownerPasswordA;
 
126
    userPassword = userPasswordA;
 
127
  }
 
128
 
 
129
  ~StandardAuthData() {
 
130
    if (ownerPassword) {
 
131
      delete ownerPassword;
 
132
    }
 
133
    if (userPassword) {
 
134
      delete userPassword;
 
135
    }
 
136
  }
 
137
 
 
138
  GooString *ownerPassword;
 
139
  GooString *userPassword;
 
140
};
 
141
 
 
142
StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA,
 
143
                                                 Object *encryptDictA):
 
144
  SecurityHandler(docA)
 
145
{
 
146
  Object versionObj, revisionObj, lengthObj;
 
147
  Object ownerKeyObj, userKeyObj, permObj, fileIDObj;
 
148
  Object fileIDObj1;
 
149
  Object cryptFiltersObj, streamFilterObj, stringFilterObj;
 
150
  Object cryptFilterObj, cfmObj, cfLengthObj;
 
151
  Object encryptMetadataObj;
 
152
 
 
153
  ok = gFalse;
 
154
  fileID = NULL;
 
155
  ownerKey = NULL;
 
156
  userKey = NULL;
 
157
 
 
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;
 
167
      permObj.free();
 
168
      permObj.initInt(perms);
 
169
  }
 
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 &&
 
175
      permObj.isInt()) {
 
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()) {
 
182
      fileKeyLength = 5;
 
183
    } else {
 
184
      fileKeyLength = lengthObj.getInt() / 8;
 
185
    }
 
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")) {
 
200
            encVersion = 2;
 
201
            encRevision = 3;
 
202
            if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
 
203
              //~ according to the spec, this should be cfLengthObj / 8
 
204
              fileKeyLength = cfLengthObj.getInt();
 
205
            }
 
206
            cfLengthObj.free();
 
207
          } else if (cfmObj.isName("AESV2")) {
 
208
            encVersion = 2;
 
209
            encRevision = 3;
 
210
            encAlgorithm = cryptAES;
 
211
            if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) {
 
212
              //~ according to the spec, this should be cfLengthObj / 8
 
213
              fileKeyLength = cfLengthObj.getInt();
 
214
            }
 
215
            cfLengthObj.free();
 
216
          }
 
217
          cfmObj.free();
 
218
        }
 
219
        cryptFilterObj.free();
 
220
      }
 
221
      stringFilterObj.free();
 
222
      streamFilterObj.free();
 
223
      cryptFiltersObj.free();
 
224
      if (encryptDictA->dictLookup("EncryptMetadata",
 
225
                                   &encryptMetadataObj)->isBool()) {
 
226
        encryptMetadata = encryptMetadataObj.getBool();
 
227
      }
 
228
      encryptMetadataObj.free();
 
229
    }
 
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();
 
238
        } else {
 
239
          fileID = new GooString();
 
240
        }
 
241
        fileIDObj1.free();
 
242
      } else {
 
243
        fileID = new GooString();
 
244
      }
 
245
      ok = gTrue;
 
246
    } else {
 
247
      error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
 
248
            encVersion, encRevision);
 
249
    }
 
250
  } else {
 
251
    error(-1, "Weird encryption info");
 
252
  }
 
253
  if (fileKeyLength > 16) {
 
254
    fileKeyLength = 16;
 
255
  }
 
256
  fileIDObj.free();
 
257
  permObj.free();
 
258
  userKeyObj.free();
 
259
  ownerKeyObj.free();
 
260
  lengthObj.free();
 
261
  revisionObj.free();
 
262
  versionObj.free();
 
263
}
 
264
 
 
265
StandardSecurityHandler::~StandardSecurityHandler() {
 
266
  if (fileID) {
 
267
    delete fileID;
 
268
  }
 
269
  if (ownerKey) {
 
270
    delete ownerKey;
 
271
  }
 
272
  if (userKey) {
 
273
    delete userKey;
 
274
  }
 
275
}
 
276
 
 
277
void *StandardSecurityHandler::makeAuthData(GooString *ownerPassword,
 
278
                                            GooString *userPassword) {
 
279
  return new StandardAuthData(ownerPassword ? ownerPassword->copy()
 
280
                                            : (GooString *)NULL,
 
281
                              userPassword ? userPassword->copy()
 
282
                                           : (GooString *)NULL);
 
283
}
 
284
 
 
285
void *StandardSecurityHandler::getAuthData() {
 
286
#if HAVE_XPDFCORE
 
287
  XPDFCore *core;
 
288
  GooString *password;
 
289
 
 
290
  if (!(core = (XPDFCore *)doc->getGUIData()) ||
 
291
      !(password = core->getPassword())) {
 
292
    return NULL;
 
293
  }
 
294
  return new StandardAuthData(password, password->copy());
 
295
#elif HAVE_WINPDFCORE
 
296
  WinPDFCore *core;
 
297
  GooString *password;
 
298
 
 
299
  if (!(core = (WinPDFCore *)doc->getGUIData()) ||
 
300
      !(password = core->getPassword())) {
 
301
    return NULL;
 
302
  }
 
303
  return new StandardAuthData(password, password->copy());
 
304
#else
 
305
  return NULL;
 
306
#endif
 
307
}
 
308
 
 
309
void StandardSecurityHandler::freeAuthData(void *authData) {
 
310
  delete (StandardAuthData *)authData;
 
311
}
 
312
 
 
313
GBool StandardSecurityHandler::authorize(void *authData) {
 
314
  GooString *ownerPassword, *userPassword;
 
315
 
 
316
  if (!ok) {
 
317
    return gFalse;
 
318
  }
 
319
  if (authData) {
 
320
    ownerPassword = ((StandardAuthData *)authData)->ownerPassword;
 
321
    userPassword = ((StandardAuthData *)authData)->userPassword;
 
322
  } else {
 
323
    ownerPassword = NULL;
 
324
    userPassword = NULL;
 
325
  }
 
326
  if (!Decrypt::makeFileKey(encVersion, encRevision, fileKeyLength,
 
327
                            ownerKey, userKey, permFlags, fileID,
 
328
                            ownerPassword, userPassword, fileKey,
 
329
                            encryptMetadata, &ownerPasswordOk)) {
 
330
    return gFalse;
 
331
  }
 
332
  return gTrue;
 
333
}
 
334
 
 
335
#ifdef ENABLE_PLUGINS
 
336
 
 
337
//------------------------------------------------------------------------
 
338
// ExternalSecurityHandler
 
339
//------------------------------------------------------------------------
 
340
 
 
341
ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA,
 
342
                                                 Object *encryptDictA,
 
343
                                                 XpdfSecurityHandler *xshA):
 
344
  SecurityHandler(docA)
 
345
{
 
346
  encryptDictA->copy(&encryptDict);
 
347
  xsh = xshA;
 
348
  encAlgorithm = cryptRC4; //~ this should be obtained via getKey
 
349
  ok = gFalse;
 
350
 
 
351
  if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA,
 
352
                      (XpdfObject)encryptDictA, &docData)) {
 
353
    return;
 
354
  }
 
355
 
 
356
  ok = gTrue;
 
357
}
 
358
 
 
359
ExternalSecurityHandler::~ExternalSecurityHandler() {
 
360
  (*xsh->freeDoc)(xsh->handlerData, docData);
 
361
  encryptDict.free();
 
362
}
 
363
 
 
364
void *ExternalSecurityHandler::makeAuthData(GooString *ownerPassword,
 
365
                                            GooString *userPassword) {
 
366
  char *opw, *upw;
 
367
  void *authData;
 
368
 
 
369
  opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL;
 
370
  upw = userPassword ? userPassword->getCString() : (char *)NULL;
 
371
  if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) {
 
372
    return NULL;
 
373
  }
 
374
  return authData;
 
375
}
 
376
 
 
377
void *ExternalSecurityHandler::getAuthData() {
 
378
  void *authData;
 
379
 
 
380
  if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) {
 
381
    return NULL;
 
382
  }
 
383
  return authData;
 
384
}
 
385
 
 
386
void ExternalSecurityHandler::freeAuthData(void *authData) {
 
387
  (*xsh->freeAuthData)(xsh->handlerData, docData, authData);
 
388
}
 
389
 
 
390
GBool ExternalSecurityHandler::authorize(void *authData) {
 
391
  char *key;
 
392
  int length;
 
393
 
 
394
  if (!ok) {
 
395
    return gFalse;
 
396
  }
 
397
  permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData);
 
398
  if (!(permFlags & xpdfPermissionOpen)) {
 
399
    return gFalse;
 
400
  }
 
401
  if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) {
 
402
    return gFalse;
 
403
  }
 
404
  if ((fileKeyLength = length) > 16) {
 
405
    fileKeyLength = 16;
 
406
  }
 
407
  memcpy(fileKey, key, fileKeyLength);
 
408
  (*xsh->freeKey)(xsh->handlerData, docData, key, length);
 
409
  return gTrue;
 
410
}
 
411
 
 
412
#endif // ENABLE_PLUGINS