summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2024-11-22 23:46:29 +0900
committerTomaž Vajngerl <quikee@gmail.com>2024-12-24 07:28:38 +0100
commit6912dd8dda491740d35e1aabe8518330b412684e (patch)
treed919f09d0191bd500b75e38164420cccacadaf1b
parent7257cd8b5420e398f14456e6713de61850223dba (diff)
pdf: properly encrypt metadata (for Revision 6+)
Metadata should also be encrypted, and it is the default, so also encrypt the metadata and properly set the flags in encrypt dict. Change-Id: I083faa8174a1ed4b43ecaceaa11e27e87562e1b1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177038 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178764 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--vcl/inc/pdf/COSWriter.hxx14
-rw-r--r--vcl/inc/pdf/IPDFEncryptor.hxx1
-rw-r--r--vcl/inc/pdf/PDFEncryptor.hxx1
-rw-r--r--vcl/inc/pdf/PDFEncryptorR6.hxx1
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx106
-rw-r--r--vcl/source/pdf/PDFEncryptorR6.cxx2
6 files changed, 76 insertions, 49 deletions
diff --git a/vcl/inc/pdf/COSWriter.hxx b/vcl/inc/pdf/COSWriter.hxx
index 4c90f6f4968e..b47dabbe5c7e 100644
--- a/vcl/inc/pdf/COSWriter.hxx
+++ b/vcl/inc/pdf/COSWriter.hxx
@@ -75,7 +75,7 @@ class COSWriter
}
public:
- COSWriter(std::shared_ptr<IPDFEncryptor> const& pPDFEncryptor)
+ COSWriter(std::shared_ptr<IPDFEncryptor> const& pPDFEncryptor = nullptr)
: mpPDFEncryptor(pPDFEncryptor)
, maLine(1024)
{
@@ -92,9 +92,11 @@ public:
OStringBuffer& getLine() { return maLine; }
void startDict() { maLine.append("<<"); }
-
void endDict() { maLine.append(">>\n"); }
+ void startStream() { maLine.append("stream\n"); }
+ void endStream() { maLine.append("\nendstream\n"); }
+
void write(std::string_view key, std::string_view value)
{
maLine.append(key);
@@ -108,6 +110,14 @@ public:
maLine.append(value);
}
+ void writeReference(std::string_view key, sal_Int32 nObjectID)
+ {
+ maLine.append(key);
+ maLine.append(" ");
+ maLine.append(nObjectID);
+ maLine.append(" 0 R");
+ }
+
void writeKeyAndUnicode(std::string_view key, OUString const& rString)
{
maLine.append(key);
diff --git a/vcl/inc/pdf/IPDFEncryptor.hxx b/vcl/inc/pdf/IPDFEncryptor.hxx
index 61ef8676da46..099e16783d54 100644
--- a/vcl/inc/pdf/IPDFEncryptor.hxx
+++ b/vcl/inc/pdf/IPDFEncryptor.hxx
@@ -52,6 +52,7 @@ public:
/** the numerical value of the access permissions, according to PDF spec, must be signed */
virtual sal_Int32 getAccessPermissions() = 0;
+ virtual bool isMetadataEncrypted() = 0;
/** Encrypted access permission
*
diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx
index 9a65c5a0043b..1583da4779c0 100644
--- a/vcl/inc/pdf/PDFEncryptor.hxx
+++ b/vcl/inc/pdf/PDFEncryptor.hxx
@@ -47,6 +47,7 @@ public:
sal_Int32 getRevision() override { return 3; };
sal_Int32 getAccessPermissions() override { return m_nAccessPermissions; }
+ bool isMetadataEncrypted() override { return false; }
sal_Int32 getKeyLength() override { return m_nKeyLength; }
sal_Int32 getRC4KeyLength() { return m_nRC4KeyLength; }
diff --git a/vcl/inc/pdf/PDFEncryptorR6.hxx b/vcl/inc/pdf/PDFEncryptorR6.hxx
index 56fe094469c6..ca7a6e388b2d 100644
--- a/vcl/inc/pdf/PDFEncryptorR6.hxx
+++ b/vcl/inc/pdf/PDFEncryptorR6.hxx
@@ -128,6 +128,7 @@ public:
sal_Int32 getVersion() override { return 5; }
sal_Int32 getRevision() override { return 6; }
sal_Int32 getAccessPermissions() override { return m_nAccessPermissions; }
+ bool isMetadataEncrypted() override { return true; }
/** Key length - AES 256 bit */
sal_Int32 getKeyLength() override { return 256 / 8; }
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index ae63f2844d37..5444ff99a563 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -5622,9 +5622,9 @@ bool PDFWriterImpl::emitCatalog()
if( nMetadataObject )
{
- aLine.append("/Metadata ");
- aLine.append( nMetadataObject );
- aLine.append( " 0 R" );
+ COSWriter aWriter;
+ aWriter.writeReference("/Metadata", nMetadataObject);
+ aLine.append(aWriter.getLine());
}
aLine.append( ">>\n"
@@ -6025,52 +6025,64 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
//get the object number for all the destinations
sal_Int32 nObject = createObject();
- if( updateObject( nObject ) )
- {
- pdf::XmpMetadata aMetadata;
+ if (!updateObject(nObject))
+ return 0;
- if (m_nPDFA_Version > 0)
- aMetadata.mnPDF_A = m_nPDFA_Version;
-
- aMetadata.mbPDF_UA = m_bIsPDF_UA;
-
- lcl_assignMeta(m_aContext.DocumentInfo.Title, aMetadata.msTitle);
- lcl_assignMeta(m_aContext.DocumentInfo.Author, aMetadata.msAuthor);
- lcl_assignMeta(m_aContext.DocumentInfo.Subject, aMetadata.msSubject);
- lcl_assignMeta(m_aContext.DocumentInfo.Producer, aMetadata.msProducer);
- aMetadata.msPDFVersion = getPDFVersionStr(m_aContext.Version);
- lcl_assignMeta(m_aContext.DocumentInfo.Keywords, aMetadata.msKeywords);
- lcl_assignMeta(m_aContext.DocumentInfo.Contributor, aMetadata.maContributor);
- lcl_assignMeta(m_aContext.DocumentInfo.Coverage, aMetadata.msCoverage);
- lcl_assignMeta(m_aContext.DocumentInfo.Identifier, aMetadata.msIdentifier);
- lcl_assignMeta(m_aContext.DocumentInfo.Publisher, aMetadata.maPublisher);
- lcl_assignMeta(m_aContext.DocumentInfo.Relation, aMetadata.maRelation);
- lcl_assignMeta(m_aContext.DocumentInfo.Rights, aMetadata.msRights);
- lcl_assignMeta(m_aContext.DocumentInfo.Source, aMetadata.msSource);
- lcl_assignMeta(m_aContext.DocumentInfo.Type, aMetadata.msType);
- lcl_assignMeta(m_aContext.DocumentInfo.Creator, aMetadata.m_sCreatorTool);
- aMetadata.m_sCreateDate = m_aCreationMetaDateString;
-
- OStringBuffer aMetadataObj( 1024 );
-
- aMetadataObj.append( nObject );
- aMetadataObj.append( " 0 obj\n" );
-
- aMetadataObj.append( "<</Type/Metadata/Subtype/XML/Length " );
-
- aMetadataObj.append( sal_Int32(aMetadata.getSize()) );
- aMetadataObj.append( ">>\nstream\n" );
- if ( !writeBuffer( aMetadataObj ) )
- return 0;
- //emit the stream
- if ( !writeBufferBytes( aMetadata.getData(), aMetadata.getSize() ) )
+ pdf::XmpMetadata aMetadata;
+
+ if (m_nPDFA_Version > 0)
+ aMetadata.mnPDF_A = m_nPDFA_Version;
+
+ aMetadata.mbPDF_UA = m_bIsPDF_UA;
+
+ lcl_assignMeta(m_aContext.DocumentInfo.Title, aMetadata.msTitle);
+ lcl_assignMeta(m_aContext.DocumentInfo.Author, aMetadata.msAuthor);
+ lcl_assignMeta(m_aContext.DocumentInfo.Subject, aMetadata.msSubject);
+ lcl_assignMeta(m_aContext.DocumentInfo.Producer, aMetadata.msProducer);
+ aMetadata.msPDFVersion = getPDFVersionStr(m_aContext.Version);
+ lcl_assignMeta(m_aContext.DocumentInfo.Keywords, aMetadata.msKeywords);
+ lcl_assignMeta(m_aContext.DocumentInfo.Contributor, aMetadata.maContributor);
+ lcl_assignMeta(m_aContext.DocumentInfo.Coverage, aMetadata.msCoverage);
+ lcl_assignMeta(m_aContext.DocumentInfo.Identifier, aMetadata.msIdentifier);
+ lcl_assignMeta(m_aContext.DocumentInfo.Publisher, aMetadata.maPublisher);
+ lcl_assignMeta(m_aContext.DocumentInfo.Relation, aMetadata.maRelation);
+ lcl_assignMeta(m_aContext.DocumentInfo.Rights, aMetadata.msRights);
+ lcl_assignMeta(m_aContext.DocumentInfo.Source, aMetadata.msSource);
+ lcl_assignMeta(m_aContext.DocumentInfo.Type, aMetadata.msType);
+ lcl_assignMeta(m_aContext.DocumentInfo.Creator, aMetadata.m_sCreatorTool);
+ aMetadata.m_sCreateDate = m_aCreationMetaDateString;
+
+ {
+ COSWriter aWriter;
+ aWriter.startObject(nObject);
+ aWriter.startDict();
+ aWriter.write("/Type", "/Metadata");
+ aWriter.write("/Subtype", "/XML");
+ aWriter.write("/Length", sal_Int32(aMetadata.getSize()));
+ aWriter.endDict();
+ aWriter.startStream();
+ if (!writeBuffer(aWriter.getLine()))
return 0;
+ }
- if( ! writeBuffer( "\nendstream\nendobj\n\n" ) )
- nObject = 0;
+ //emit the stream
+ bool bEncryptMetadata = m_pPDFEncryptor && m_pPDFEncryptor->isMetadataEncrypted();
+ if (bEncryptMetadata)
+ checkAndEnableStreamEncryption(nObject);
+
+ if (!writeBufferBytes(aMetadata.getData(), aMetadata.getSize()))
+ return 0;
+
+ if (bEncryptMetadata)
+ disableStreamEncryption();
+
+ {
+ COSWriter aWriter;
+ aWriter.endStream();
+ aWriter.endObject();
+ if (!writeBuffer(aWriter.getLine()))
+ return 0;
}
- else
- nObject = 0;
return nObject;
}
@@ -6110,7 +6122,9 @@ sal_Int32 PDFWriterImpl::emitEncrypt()
aWriter.write("/CF", "<</StdCF <</CFM /AESV3 /Length 256>>>>");
aWriter.write("/StmF", "/StdCF");
aWriter.write("/StrF", "/StdCF");
- aWriter.write("/EncryptMetadata", " false ");
+ // Encrypt metadata. Default is true. Relevant for Revision 6+
+ if (!m_pPDFEncryptor->isMetadataEncrypted())
+ aWriter.write("/EncryptMetadata", " false ");
}
else
{
diff --git a/vcl/source/pdf/PDFEncryptorR6.cxx b/vcl/source/pdf/PDFEncryptorR6.cxx
index d951b738246f..52dceddc9636 100644
--- a/vcl/source/pdf/PDFEncryptorR6.cxx
+++ b/vcl/source/pdf/PDFEncryptorR6.cxx
@@ -284,7 +284,7 @@ PDFEncryptorR6::~PDFEncryptorR6() = default;
std::vector<sal_uInt8> PDFEncryptorR6::getEncryptedAccessPermissions(std::vector<sal_uInt8>& rKey)
{
- std::vector<sal_uInt8> aPerms = createPerms(m_nAccessPermissions, false);
+ std::vector<sal_uInt8> aPerms = createPerms(m_nAccessPermissions, isMetadataEncrypted());
return encryptPerms(aPerms, rKey);
}