aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDF_encryption.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2009-10-20 01:09:19 +0200
committerJay Berkenbilt <ejb@ql.org>2009-10-20 01:09:19 +0200
commit3f8c4c273649c857f5a607dcbb422729fce3a166 (patch)
tree9a71fbfc838cf876f7982f7213ad994c92c0a3fc /libqpdf/QPDF_encryption.cc
parentb67a3c15e768ed88ea3cdf7525c1ddc649aec2fe (diff)
downloadqpdf-3f8c4c273649c857f5a607dcbb422729fce3a166.tar.zst
categorize all error messages and include object information if available
git-svn-id: svn+q:///qpdf/trunk@829 71b93d88-0707-0410-a8cf-f5a4172ac649
Diffstat (limited to 'libqpdf/QPDF_encryption.cc')
-rw-r--r--libqpdf/QPDF_encryption.cc99
1 files changed, 67 insertions, 32 deletions
diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc
index 8962624d..d6b0ae23 100644
--- a/libqpdf/QPDF_encryption.cc
+++ b/libqpdf/QPDF_encryption.cc
@@ -337,14 +337,16 @@ QPDF::initializeEncryption()
(id_obj.getArrayNItems() == 2) &&
id_obj.getArrayItem(0).isString()))
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ "trailer", this->file.getLastOffset(),
"invalid /ID in trailer dictionary");
}
std::string id1 = id_obj.getArrayItem(0).getStringValue();
if (id1.length() != id_bytes)
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ "trailer", this->file.getLastOffset(),
"first /ID string in trailer dictionary has "
"incorrect length");
}
@@ -352,19 +354,23 @@ QPDF::initializeEncryption()
QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt");
if (! encryption_dict.isDictionary())
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ this->last_object_description,
+ this->file.getLastOffset(),
"/Encrypt in trailer dictionary is not a dictionary");
}
if (! (encryption_dict.getKey("/Filter").isName() &&
(encryption_dict.getKey("/Filter").getName() == "/Standard")))
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"unsupported encryption filter");
}
if (! encryption_dict.getKey("/SubFilter").isNull())
{
- warn(QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ warn(QPDFExc(qpdf_e_unsupported, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"file uses encryption SubFilters,"
" which qpdf does not support"));
}
@@ -375,7 +381,8 @@ QPDF::initializeEncryption()
encryption_dict.getKey("/U").isString() &&
encryption_dict.getKey("/P").isInteger()))
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"some encryption dictionary parameters are missing "
"or the wrong type");
}
@@ -389,7 +396,8 @@ QPDF::initializeEncryption()
if (! (((R == 2) || (R == 3) || (R == 4)) &&
((V == 1) || (V == 2) || (V == 4))))
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_unsupported, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"Unsupported /R or /V in encryption dictionary");
}
@@ -397,7 +405,8 @@ QPDF::initializeEncryption()
if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"incorrect length for /O and/or /P in "
"encryption dictionary");
}
@@ -408,7 +417,8 @@ QPDF::initializeEncryption()
Length = encryption_dict.getKey("/Length").getIntValue();
if ((Length % 8) || (Length < 40) || (Length > 128))
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"invalid /Length value in encryption dictionary");
}
}
@@ -471,7 +481,8 @@ QPDF::initializeEncryption()
}
if (this->cf_file != this->cf_stream)
{
- throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ throw QPDFExc(qpdf_e_unsupported, this->file.getName(),
+ "encryption dictionary", this->file.getLastOffset(),
"This document has embedded files that are"
" encrypted differently from the rest of the file."
" qpdf does not presently support this due to"
@@ -492,7 +503,8 @@ QPDF::initializeEncryption()
}
else
{
- throw QPDFExc(this->file.getName() + ": invalid password");
+ throw QPDFExc(qpdf_e_password, this->file.getName(),
+ "", 0, "invalid password");
}
this->encryption_key = compute_encryption_key(this->user_password, data);
@@ -542,7 +554,9 @@ QPDF::decryptString(std::string& str, int objid, int generation)
break;
default:
- warn(QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ this->last_object_description,
+ this->file.getLastOffset(),
"unknown encryption filter for strings"
" (check /StrF in /Encrypt dictionary);"
" strings may be decrypted improperly"));
@@ -554,28 +568,47 @@ QPDF::decryptString(std::string& str, int objid, int generation)
}
std::string key = getKeyForObject(objid, generation, use_aes);
- if (use_aes)
+ try
{
- QTC::TC("qpdf", "QPDF_encryption aes decode string");
- assert(key.length() == Pl_AES_PDF::key_size);
- Pl_Buffer bufpl("decrypted string");
- Pl_AES_PDF pl("aes decrypt string", &bufpl, false,
- (unsigned char const*)key.c_str());
- pl.write((unsigned char*)str.c_str(), str.length());
- pl.finish();
- Buffer* buf = bufpl.getBuffer();
- str = std::string((char*)buf->getBuffer(), (size_t)buf->getSize());
- delete buf;
+ if (use_aes)
+ {
+ QTC::TC("qpdf", "QPDF_encryption aes decode string");
+ assert(key.length() == Pl_AES_PDF::key_size);
+ Pl_Buffer bufpl("decrypted string");
+ Pl_AES_PDF pl("aes decrypt string", &bufpl, false,
+ (unsigned char const*)key.c_str());
+ pl.write((unsigned char*)str.c_str(), str.length());
+ pl.finish();
+ PointerHolder<Buffer> buf = bufpl.getBuffer();
+ str = std::string((char*)buf.getPointer()->getBuffer(),
+ (size_t)buf.getPointer()->getSize());
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF_encryption rc4 decode string");
+ unsigned int vlen = str.length();
+ // Using PointerHolder will cause a new char[] to be deleted
+ // with delete instead of delete [], but it's okay since the
+ // array is of a fundamental type, so there is no destructor
+ // to be called. Using PointerHolder guarantees that tmp will
+ // be freed even if rc4.process throws an exception.
+ PointerHolder<char> tmp = QUtil::copy_string(str);
+ RC4 rc4((unsigned char const*)key.c_str(), key.length());
+ rc4.process((unsigned char*)tmp.getPointer(), vlen);
+ str = std::string(tmp.getPointer(), vlen);
+ }
}
- else
+ catch (QPDFExc& e)
+ {
+ throw;
+ }
+ catch (std::runtime_error& e)
{
- QTC::TC("qpdf", "QPDF_encryption rc4 decode string");
- unsigned int vlen = str.length();
- char* tmp = QUtil::copy_string(str);
- RC4 rc4((unsigned char const*)key.c_str(), key.length());
- rc4.process((unsigned char*)tmp, vlen);
- str = std::string(tmp, vlen);
- delete [] tmp;
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ this->last_object_description, this->file.getLastOffset(),
+ "error decrypting string for object " +
+ QUtil::int_to_string(objid) + " " +
+ QUtil::int_to_string(generation) + ": " + e.what());
}
}
@@ -645,7 +678,9 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation,
default:
// filter local to this stream.
- warn(QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ warn(QPDFExc(qpdf_e_damaged_pdf, this->file.getName(),
+ this->last_object_description,
+ this->file.getLastOffset(),
"unknown encryption filter for streams"
" (check " + method_source + ");"
" streams may be decrypted improperly"));