From a8c93bd324d0362a26c1e6591eead5c52f865c0d Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 21 Aug 2017 21:33:44 -0400 Subject: Push QPDF member variables into a nested class Pushing member variables into a nested class enables addition of new member variables without breaking binary compatibility. --- libqpdf/QPDF_encryption.cc | 176 +++++++++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 85 deletions(-) (limited to 'libqpdf/QPDF_encryption.cc') diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 6c0c97ef..81325591 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -760,9 +760,9 @@ QPDF::interpretCF(QPDFObjectHandle cf) if (cf.isName()) { std::string filter = cf.getName(); - if (this->crypt_filters.count(filter) != 0) + if (this->m->crypt_filters.count(filter) != 0) { - return this->crypt_filters[filter]; + return this->m->crypt_filters[filter]; } else if (filter == "/Identity") { @@ -783,29 +783,29 @@ QPDF::interpretCF(QPDFObjectHandle cf) void QPDF::initializeEncryption() { - if (this->encryption_initialized) + if (this->m->encryption_initialized) { return; } - this->encryption_initialized = true; + this->m->encryption_initialized = true; // After we initialize encryption parameters, we must used stored // key information and never look at /Encrypt again. Otherwise, // things could go wrong if someone mutates the encryption // dictionary. - if (! this->trailer.hasKey("/Encrypt")) + if (! this->m->trailer.hasKey("/Encrypt")) { return; } - // Go ahead and set this->encryption here. That way, isEncrypted + // Go ahead and set this->m->encrypted here. That way, isEncrypted // will return true even if there were errors reading the // encryption dictionary. - this->encrypted = true; + this->m->encrypted = true; std::string id1; - QPDFObjectHandle id_obj = this->trailer.getKey("/ID"); + QPDFObjectHandle id_obj = this->m->trailer.getKey("/ID"); if ((id_obj.isArray() && (id_obj.getArrayNItems() == 2) && id_obj.getArrayItem(0).isString())) @@ -817,31 +817,31 @@ QPDF::initializeEncryption() // Treating a missing ID as the empty string enables qpdf to // decrypt some invalid encrypted files with no /ID that // poppler can read but Adobe Reader can't. - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "trailer", this->file->getLastOffset(), + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "trailer", this->m->file->getLastOffset(), "invalid /ID in trailer dictionary")); } - QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt"); + QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt"); if (! encryption_dict.isDictionary()) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - this->last_object_description, - this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), "/Encrypt in trailer dictionary is not a dictionary"); } if (! (encryption_dict.getKey("/Filter").isName() && (encryption_dict.getKey("/Filter").getName() == "/Standard"))) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), "unsupported encryption filter"); } if (! encryption_dict.getKey("/SubFilter").isNull()) { - warn(QPDFExc(qpdf_e_unsupported, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + warn(QPDFExc(qpdf_e_unsupported, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), "file uses encryption SubFilters," " which qpdf does not support")); } @@ -852,8 +852,8 @@ QPDF::initializeEncryption() encryption_dict.getKey("/U").isString() && encryption_dict.getKey("/P").isInteger())) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), "some encryption dictionary parameters are missing " "or the wrong type"); } @@ -869,15 +869,15 @@ QPDF::initializeEncryption() if (! (((R >= 2) && (R <= 6)) && ((V == 1) || (V == 2) || (V == 4) || (V == 5)))) { - throw QPDFExc(qpdf_e_unsupported, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(), + "encryption dictionary", this->m->file->getLastOffset(), "Unsupported /R or /V in encryption dictionary; R = " + QUtil::int_to_string(R) + " (max 6), V = " + QUtil::int_to_string(V) + " (max 5)"); } - this->encryption_V = V; - this->encryption_R = R; + this->m->encryption_V = V; + this->m->encryption_R = R; // OE, UE, and Perms are only present if V >= 5. std::string OE; @@ -890,8 +890,9 @@ QPDF::initializeEncryption() pad_short_parameter(U, key_bytes); if (! ((O.length() == key_bytes) && (U.length() == key_bytes))) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", + this->m->file->getLastOffset(), "incorrect length for /O and/or /U in " "encryption dictionary"); } @@ -902,8 +903,9 @@ QPDF::initializeEncryption() encryption_dict.getKey("/UE").isString() && encryption_dict.getKey("/Perms").isString())) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", + this->m->file->getLastOffset(), "some V=5 encryption dictionary parameters are " "missing or the wrong type"); } @@ -922,8 +924,9 @@ QPDF::initializeEncryption() (UE.length() < OUE_key_bytes_V5) || (Perms.length() < Perms_key_bytes_V5)) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", + this->m->file->getLastOffset(), "incorrect length for some of" " /O, /U, /OE, /UE, or /Perms in" " encryption dictionary"); @@ -936,16 +939,17 @@ QPDF::initializeEncryption() Length = encryption_dict.getKey("/Length").getIntValue(); if ((Length % 8) || (Length < 40) || (Length > 256)) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", + this->m->file->getLastOffset(), "invalid /Length value in encryption dictionary"); } } - this->encrypt_metadata = true; + this->m->encrypt_metadata = true; if ((V >= 4) && (encryption_dict.getKey("/EncryptMetadata").isBool())) { - this->encrypt_metadata = + this->m->encrypt_metadata = encryption_dict.getKey("/EncryptMetadata").getBoolValue(); } @@ -986,40 +990,40 @@ QPDF::initializeEncryption() method = e_unknown; } } - this->crypt_filters[filter] = method; + this->m->crypt_filters[filter] = method; } } QPDFObjectHandle StmF = encryption_dict.getKey("/StmF"); QPDFObjectHandle StrF = encryption_dict.getKey("/StrF"); QPDFObjectHandle EFF = encryption_dict.getKey("/EFF"); - this->cf_stream = interpretCF(StmF); - this->cf_string = interpretCF(StrF); + this->m->cf_stream = interpretCF(StmF); + this->m->cf_string = interpretCF(StrF); if (EFF.isName()) { - this->cf_file = interpretCF(EFF); + this->m->cf_file = interpretCF(EFF); } else { - this->cf_file = this->cf_stream; + this->m->cf_file = this->m->cf_stream; } } EncryptionData data(V, R, Length / 8, P, O, U, OE, UE, Perms, - id1, this->encrypt_metadata); + id1, this->m->encrypt_metadata); if (check_owner_password( - this->user_password, this->provided_password, data)) + this->m->user_password, this->m->provided_password, data)) { // password supplied was owner password; user_password has // been initialized for V < 5 } - else if (check_user_password(this->provided_password, data)) + else if (check_user_password(this->m->provided_password, data)) { - this->user_password = this->provided_password; + this->m->user_password = this->m->provided_password; } else { - throw QPDFExc(qpdf_e_password, this->file->getName(), + throw QPDFExc(qpdf_e_password, this->m->file->getName(), "", 0, "invalid password"); } @@ -1028,8 +1032,8 @@ QPDF::initializeEncryption() // For V < 5, the user password is encrypted with the owner // password, and the user password is always used for // computing the encryption key. - this->encryption_key = compute_encryption_key( - this->user_password, data); + this->m->encryption_key = compute_encryption_key( + this->m->user_password, data); } else { @@ -1037,12 +1041,13 @@ QPDF::initializeEncryption() // compute the encryption key, and neither password can be // used to recover the other. bool perms_valid; - this->encryption_key = recover_encryption_key_with_password( - this->provided_password, data, perms_valid); + this->m->encryption_key = recover_encryption_key_with_password( + this->m->provided_password, data, perms_valid); if (! perms_valid) { - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - "encryption dictionary", this->file->getLastOffset(), + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + "encryption dictionary", + this->m->file->getLastOffset(), "/Perms field in encryption dictionary" " doesn't match expected value")); } @@ -1052,23 +1057,24 @@ QPDF::initializeEncryption() std::string QPDF::getKeyForObject(int objid, int generation, bool use_aes) { - if (! this->encrypted) + if (! this->m->encrypted) { throw std::logic_error( "request for encryption key in non-encrypted PDF"); } - if (! ((objid == this->cached_key_objid) && - (generation == this->cached_key_generation))) + if (! ((objid == this->m->cached_key_objid) && + (generation == this->m->cached_key_generation))) { - this->cached_object_encryption_key = - compute_data_key(this->encryption_key, objid, generation, - use_aes, this->encryption_V, this->encryption_R); - this->cached_key_objid = objid; - this->cached_key_generation = generation; + this->m->cached_object_encryption_key = + compute_data_key(this->m->encryption_key, objid, generation, + use_aes, this->m->encryption_V, + this->m->encryption_R); + this->m->cached_key_objid = objid; + this->m->cached_key_generation = generation; } - return this->cached_object_encryption_key; + return this->m->cached_object_encryption_key; } void @@ -1079,9 +1085,9 @@ QPDF::decryptString(std::string& str, int objid, int generation) return; } bool use_aes = false; - if (this->encryption_V >= 4) + if (this->m->encryption_V >= 4) { - switch (this->cf_string) + switch (this->m->cf_string) { case e_none: return; @@ -1098,15 +1104,15 @@ QPDF::decryptString(std::string& str, int objid, int generation) break; default: - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - this->last_object_description, - this->file->getLastOffset(), + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), "unknown encryption filter for strings" " (check /StrF in /Encrypt dictionary);" " strings may be decrypted improperly")); // To avoid repeated warnings, reset cf_string. Assume // we'd want to use AES if V == 4. - this->cf_string = e_aes; + this->m->cf_string = e_aes; break; } } @@ -1145,9 +1151,9 @@ QPDF::decryptString(std::string& str, int objid, int generation) } catch (std::runtime_error& e) { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - this->last_object_description, - this->file->getLastOffset(), + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), "error decrypting string for object " + QUtil::int_to_string(objid) + " " + QUtil::int_to_string(generation) + ": " + e.what()); @@ -1170,7 +1176,7 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, return; } bool use_aes = false; - if (this->encryption_V >= 4) + if (this->m->encryption_V >= 4) { encryption_method_e method = e_unknown; std::string method_source = "/StmF from /Encrypt dictionary"; @@ -1221,21 +1227,21 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, if (method == e_unknown) { - if ((! this->encrypt_metadata) && (type == "/Metadata")) + if ((! this->m->encrypt_metadata) && (type == "/Metadata")) { QTC::TC("qpdf", "QPDF_encryption cleartext metadata"); method = e_none; } else { - if (this->attachment_streams.count( + if (this->m->attachment_streams.count( QPDFObjGen(objid, generation)) > 0) { - method = this->cf_file; + method = this->m->cf_file; } else { - method = this->cf_stream; + method = this->m->cf_stream; } } } @@ -1259,15 +1265,15 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, default: // filter local to this stream. - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - this->last_object_description, - this->file->getLastOffset(), + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), + this->m->last_object_description, + this->m->file->getLastOffset(), "unknown encryption filter for streams" " (check " + method_source + ");" " streams may be decrypted improperly")); // To avoid repeated warnings, reset cf_stream. Assume // we'd want to use AES if V == 4. - this->cf_stream = e_aes; + this->m->cf_stream = e_aes; break; } } @@ -1331,13 +1337,13 @@ QPDF::compute_encryption_parameters_V5( std::string const& QPDF::getPaddedUserPassword() const { - return this->user_password; + return this->m->user_password; } std::string QPDF::getTrimmedUserPassword() const { - std::string result = this->user_password; + std::string result = this->m->user_password; trim_user_password(result); return result; } @@ -1345,13 +1351,13 @@ QPDF::getTrimmedUserPassword() const std::string QPDF::getEncryptionKey() const { - return this->encryption_key; + return this->m->encryption_key; } bool QPDF::isEncrypted() const { - return this->encrypted; + return this->m->encrypted; } bool @@ -1368,7 +1374,7 @@ QPDF::isEncrypted(int& R, int& P, int& V, encryption_method_e& string_method, encryption_method_e& file_method) { - if (this->encrypted) + if (this->m->encrypted) { QPDFObjectHandle trailer = getTrailer(); QPDFObjectHandle encrypt = trailer.getKey("/Encrypt"); @@ -1378,9 +1384,9 @@ QPDF::isEncrypted(int& R, int& P, int& V, P = Pkey.getIntValue(); R = Rkey.getIntValue(); V = Vkey.getIntValue(); - stream_method = this->cf_stream; - string_method = this->cf_stream; - file_method = this->cf_file; + stream_method = this->m->cf_stream; + string_method = this->m->cf_stream; + file_method = this->m->cf_file; return true; } else -- cgit v1.2.3-70-g09d2