Commit 5da146c8b53bb5a12c514f83fb52265e4922b5e1

Authored by Jay Berkenbilt
1 parent 5a0aef55

Track separately whether password was user/owner (fixes #159)

ChangeLog
  1 +2019-08-24 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add QPDF::userPasswordMatched() and QPDF::ownerPasswordMatched()
  4 + methods so it can be deterined separately whether the supplied
  5 + password matched the user password, the owner password, or both.
  6 + Fixes #159.
  7 +
1 2019-08-23 Jay Berkenbilt <ejb@ql.org> 8 2019-08-23 Jay Berkenbilt <ejb@ql.org>
2 9
3 * Add --recompress-streams option to qpdf and 10 * Add --recompress-streams option to qpdf and
include/qpdf/QPDF.hh
@@ -406,6 +406,12 @@ class QPDF @@ -406,6 +406,12 @@ class QPDF
406 encryption_method_e& string_method, 406 encryption_method_e& string_method,
407 encryption_method_e& file_method); 407 encryption_method_e& file_method);
408 408
  409 + QPDF_DLL
  410 + bool ownerPasswordMatched() const;
  411 +
  412 + QPDF_DLL
  413 + bool userPasswordMatched() const;
  414 +
409 // Encryption permissions -- not enforced by QPDF 415 // Encryption permissions -- not enforced by QPDF
410 QPDF_DLL 416 QPDF_DLL
411 bool allowAccessibility(); 417 bool allowAccessibility();
@@ -756,6 +762,8 @@ class QPDF @@ -756,6 +762,8 @@ class QPDF
756 std::string cached_object_encryption_key; 762 std::string cached_object_encryption_key;
757 int cached_key_objid; 763 int cached_key_objid;
758 int cached_key_generation; 764 int cached_key_generation;
  765 + bool user_password_matched;
  766 + bool owner_password_matched;
759 }; 767 };
760 768
761 class ForeignStreamData 769 class ForeignStreamData
libqpdf/QPDF.cc
@@ -132,7 +132,9 @@ QPDF::EncryptionParameters::EncryptionParameters() : @@ -132,7 +132,9 @@ QPDF::EncryptionParameters::EncryptionParameters() :
132 cf_string(e_none), 132 cf_string(e_none),
133 cf_file(e_none), 133 cf_file(e_none),
134 cached_key_objid(0), 134 cached_key_objid(0),
135 - cached_key_generation(0) 135 + cached_key_generation(0),
  136 + user_password_matched(false),
  137 + owner_password_matched(false)
136 { 138 {
137 } 139 }
138 140
libqpdf/QPDF_encryption.cc
@@ -1041,21 +1041,43 @@ QPDF::initializeEncryption() @@ -1041,21 +1041,43 @@ QPDF::initializeEncryption()
1041 { 1041 {
1042 // ignore passwords in file 1042 // ignore passwords in file
1043 } 1043 }
1044 - else if (check_owner_password(  
1045 - this->m->encp->user_password,  
1046 - this->m->encp->provided_password, data))  
1047 - {  
1048 - // password supplied was owner password; user_password has  
1049 - // been initialized for V < 5  
1050 - }  
1051 - else if (check_user_password(this->m->encp->provided_password, data))  
1052 - {  
1053 - this->m->encp->user_password = this->m->encp->provided_password;  
1054 - }  
1055 else 1044 else
1056 { 1045 {
1057 - throw QPDFExc(qpdf_e_password, this->m->file->getName(),  
1058 - "", 0, "invalid password"); 1046 + this->m->encp->owner_password_matched = check_owner_password(
  1047 + this->m->encp->user_password,
  1048 + this->m->encp->provided_password, data);
  1049 + if (this->m->encp->owner_password_matched && (V < 5))
  1050 + {
  1051 + // password supplied was owner password; user_password has
  1052 + // been initialized for V < 5
  1053 + if (getTrimmedUserPassword() == this->m->encp->provided_password)
  1054 + {
  1055 + this->m->encp->user_password_matched = true;
  1056 + QTC::TC("qpdf", "QPDF_encryption user matches owner V < 5");
  1057 + }
  1058 + }
  1059 + else
  1060 + {
  1061 + this->m->encp->user_password_matched = check_user_password(
  1062 + this->m->encp->provided_password, data);
  1063 + if (this->m->encp->user_password_matched)
  1064 + {
  1065 + this->m->encp->user_password =
  1066 + this->m->encp->provided_password;
  1067 + }
  1068 + }
  1069 + if (this->m->encp->user_password_matched &&
  1070 + this->m->encp->owner_password_matched)
  1071 + {
  1072 + QTC::TC("qpdf", "QPDF_encryption same password",
  1073 + (V < 5) ? 0 : 1);
  1074 + }
  1075 + if (! (this->m->encp->owner_password_matched ||
  1076 + this->m->encp->user_password_matched))
  1077 + {
  1078 + throw QPDFExc(qpdf_e_password, this->m->file->getName(),
  1079 + "", 0, "invalid password");
  1080 + }
1059 } 1081 }
1060 1082
1061 if (this->m->provided_password_is_hex_key) 1083 if (this->m->provided_password_is_hex_key)
@@ -1440,6 +1462,18 @@ QPDF::isEncrypted(int&amp; R, int&amp; P, int&amp; V, @@ -1440,6 +1462,18 @@ QPDF::isEncrypted(int&amp; R, int&amp; P, int&amp; V,
1440 } 1462 }
1441 } 1463 }
1442 1464
  1465 +bool
  1466 +QPDF::ownerPasswordMatched() const
  1467 +{
  1468 + return this->m->encp->owner_password_matched;
  1469 +}
  1470 +
  1471 +bool
  1472 +QPDF::userPasswordMatched() const
  1473 +{
  1474 + return this->m->encp->user_password_matched;
  1475 +}
  1476 +
1443 static bool 1477 static bool
1444 is_bit_set(int P, int bit) 1478 is_bit_set(int P, int bit)
1445 { 1479 {
manual/qpdf-manual.xml
@@ -4581,6 +4581,17 @@ print &quot;\n&quot;; @@ -4581,6 +4581,17 @@ print &quot;\n&quot;;
4581 </listitem> 4581 </listitem>
4582 <listitem> 4582 <listitem>
4583 <para> 4583 <para>
  4584 + New methods <function>QPDF::userPasswordMatched</function>
  4585 + and <function>QPDF::ownerPasswordMatched</function> have
  4586 + been added to enable a caller to determine whether the
  4587 + supplied password was the user password, the owner password,
  4588 + or both. This information is also displayed by <command>qpdf
  4589 + --show-encryption</command> and <command>qpdf
  4590 + --check</command>.
  4591 + </para>
  4592 + </listitem>
  4593 + <listitem>
  4594 + <para>
4584 Static method 4595 Static method
4585 <function>Pl_Flate::setCompressionLevel</function> can be 4596 <function>Pl_Flate::setCompressionLevel</function> can be
4586 called to set the zlib compression level globally used by 4597 called to set the zlib compression level globally used by
qpdf/qpdf.testcov
@@ -442,3 +442,5 @@ QPDFObjectHandle uint returning UINT_MAX 0 @@ -442,3 +442,5 @@ QPDFObjectHandle uint returning UINT_MAX 0
442 QPDFObjectHandle uint uint returning 0 0 442 QPDFObjectHandle uint uint returning 0 0
443 QPDF xref skipped space 0 443 QPDF xref skipped space 0
444 QPDF eof skipping spaces before xref 1 444 QPDF eof skipping spaces before xref 1
  445 +QPDF_encryption user matches owner V < 5 0
  446 +QPDF_encryption same password 1