[Libreoffice-commits] core.git: 10 commits - comphelper/Library_comphelper.mk comphelper/source external/gpgmepp fpicker/source include/sal offapi/com package/inc package/source sfx2/source vcl/unx xmlsecurity/inc xmlsecurity/source
Thorsten Behrens
Thorsten.Behrens at CIB.de
Thu Dec 7 17:23:25 UTC 2017
comphelper/Library_comphelper.mk | 1
comphelper/source/misc/storagehelper.cxx | 118 +++++++-
external/gpgmepp/ExternalProject_gpgmepp.mk | 5
fpicker/source/office/OfficeControlAccess.cxx | 1
fpicker/source/win32/filepicker/VistaFilePicker.cxx | 2
fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx | 8
fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx | 1
fpicker/source/win32/misc/resourceprovider.cxx | 3
include/sal/log-areas.dox | 1
offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl | 31 ++
offapi/com/sun/star/security/XDocumentDigitalSignatures.idl | 2
package/inc/PackageConstants.hxx | 1
package/inc/ZipPackage.hxx | 1
package/source/manifest/ManifestDefines.hxx | 13
package/source/manifest/ManifestExport.cxx | 175 +++++++++++-
package/source/xstor/xstorage.cxx | 60 ++++
package/source/xstor/xstorage.hxx | 1
package/source/zippackage/ZipPackage.cxx | 25 +
sfx2/source/dialog/filedlghelper.cxx | 22 +
vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx | 4
vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx | 1
vcl/unx/gtk/fpicker/resourceprovider.cxx | 1
vcl/unx/kde4/KDE4FilePicker.cxx | 6
xmlsecurity/inc/certificatechooser.hxx | 2
xmlsecurity/source/component/documentdigitalsignatures.cxx | 32 +-
xmlsecurity/source/component/documentdigitalsignatures.hxx | 4
xmlsecurity/source/dialogs/certificatechooser.cxx | 38 +-
xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx | 14
xmlsecurity/source/gpg/CertificateImpl.cxx | 6
29 files changed, 514 insertions(+), 65 deletions(-)
New commits:
commit ed50a0a2ce51584fa3a8fba0094220a4bf25c650
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Thu Dec 7 18:18:47 2017 +0100
gpg4libre: handle unavailable gpg crypto tools more gracefully
Change-Id: I58af9d38ea8d202d2bda64cdf45204646ac9fd29
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index 9d1244973de7..dd7de2c3bafe 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -349,7 +349,7 @@ DocumentDigitalSignatures::ImplVerifySignatures(
rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
}
}
- else // GPG
+ else if (xGpgSecEnv.is()) // GPG
{
// TODO not ideal to retrieve cert by keyID, might
// collide, or PGPKeyID format might change - can't we
commit 1e12447f7ea601e158808290f4f67d84efba06e2
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Thu Dec 7 14:31:36 2017 +0100
gpg4libre: return key fingerprint / hashes including null character
Change-Id: I6b32444bab6848e2b5ddec02fd949c71114a66b2
diff --git a/xmlsecurity/source/gpg/CertificateImpl.cxx b/xmlsecurity/source/gpg/CertificateImpl.cxx
index 16eeda80441f..c831011ca50e 100644
--- a/xmlsecurity/source/gpg/CertificateImpl.cxx
+++ b/xmlsecurity/source/gpg/CertificateImpl.cxx
@@ -158,7 +158,7 @@ Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSHA1Thumbprint()
// This is mapped to the fingerprint for gpg
const char* keyId = m_pKey.primaryFingerprint();
return comphelper::arrayToSequence<sal_Int8>(
- keyId, strlen(keyId));
+ keyId, strlen(keyId)+1);
}
Sequence<sal_Int8> CertificateImpl::getSHA256Thumbprint()
@@ -167,7 +167,7 @@ Sequence<sal_Int8> CertificateImpl::getSHA256Thumbprint()
// SHA1 actually)
const char* keyId = m_pKey.primaryFingerprint();
return comphelper::arrayToSequence<sal_Int8>(
- keyId, strlen(keyId));
+ keyId, strlen(keyId)+1);
}
Sequence< sal_Int8 > SAL_CALL CertificateImpl::getMD5Thumbprint()
@@ -175,7 +175,7 @@ Sequence< sal_Int8 > SAL_CALL CertificateImpl::getMD5Thumbprint()
// This is mapped to the shorter keyID for gpg
const char* keyId = m_pKey.keyID();
return comphelper::arrayToSequence<sal_Int8>(
- keyId, strlen(keyId));
+ keyId, strlen(keyId)+1);
}
CertificateKind SAL_CALL CertificateImpl::getCertificateKind()
commit 626e73eafe953b102107031721a0b145fb713e9d
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Thu Dec 7 05:11:15 2017 +0100
gpg4libre: permit multi-select encrypt cert
And pass down all necessary parameters everywhere
Change-Id: I152b9d84c0e35be9e5193a9a6f67de9fb86133b0
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx
index a05fb1358f3f..7fa46554b595 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -17,6 +17,8 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <config_gpgme.h>
+
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
#include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
@@ -459,6 +461,9 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat
uno::Sequence< uno::Reference< security::XCertificate > > xSignCertificates=
xSigner->chooseEncryptionCertificate();
+ if (!xSignCertificates.hasElements())
+ return uno::Sequence< beans::NamedValue >(); // user cancelled
+
// generate one encrypted key entry for each recipient
// ---------------------------------------------------
@@ -478,13 +483,13 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat
{
uno::Sequence < sal_Int8 > aKeyID;
if (pCerts->is())
- aKeyID = (*pCerts)->getSHA256Thumbprint();
+ aKeyID = (*pCerts)->getSHA1Thumbprint();
std::vector<GpgME::Key> keys;
keys.push_back(
ctx->key(
reinterpret_cast<const char*>(aKeyID.getConstArray()),
- err, true));
+ err, false));
// ctx is setup now, let's encrypt the lot!
GpgME::Data plain(
@@ -504,7 +509,9 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat
len += curr;
if(crypt_res.error() || !len)
- throw uno::RuntimeException("The GpgME library failed to encrypt.");
+ throw lang::IllegalArgumentException(
+ "Not a suitable key, or failed to encrypt.",
+ css::uno::Reference<css::uno::XInterface>(), i);
uno::Sequence < sal_Int8 > aCipherValue(len);
result = cipher.seek(0,SEEK_SET);
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 1df274126d87..3858ea12175b 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -94,6 +94,7 @@ certain functionality.
@li @c comphelper
@li @c comphelper.backupfilehelper
@li @c comphelper.container - EmbeddedObjectContainer
+ at li @c comphelper.crypto
@section cppu
diff --git a/offapi/com/sun/star/security/XDocumentDigitalSignatures.idl b/offapi/com/sun/star/security/XDocumentDigitalSignatures.idl
index 85507940d316..519f77cb62dd 100644
--- a/offapi/com/sun/star/security/XDocumentDigitalSignatures.idl
+++ b/offapi/com/sun/star/security/XDocumentDigitalSignatures.idl
@@ -148,7 +148,7 @@ interface XDocumentDigitalSignatures : com::sun::star::uno::XInterface
@since LibreOffice 6.0
*/
- com::sun::star::security::XCertificate chooseEncryptionCertificate( [out] string Description );
+ sequence< com::sun::star::security::XCertificate > chooseEncryptionCertificate( );
/** This method shows the CertificateChooser dialog, used by document and PDF signing
Shows only private certificates and returns usage string in addition to description.
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index 4482d2887c41..84e248bfa390 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -1521,8 +1521,26 @@ ErrCode FileDialogHelper_Impl::execute( std::vector<OUString>& rpURLList,
bool bGpg = false;
if ( ( aValue >>= bGpg ) && bGpg )
{
- // ask for a key
- rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( ::comphelper::OStorageHelper::CreateGpgPackageEncryptionData() ) ) );
+ uno::Sequence< beans::NamedValue > aEncryptionData;
+ while(true)
+ {
+ try
+ {
+ // ask for keys
+ aEncryptionData = ::comphelper::OStorageHelper::CreateGpgPackageEncryptionData();
+ break; // user cancelled or we've some keys now
+ }
+ catch( const IllegalArgumentException& )
+ {
+ ScopedVclPtrInstance< MessageDialog > aBox(
+ mpPreferredParentWindow,
+ SfxResId(RID_SVXSTR_INCORRECT_PASSWORD));
+ aBox->Execute();
+ }
+ }
+
+ if ( aEncryptionData.hasElements() )
+ rpSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData) ) );
}
}
catch( const IllegalArgumentException& ){}
diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx
index 3834dfb111a1..2ae3c1822b1f 100644
--- a/xmlsecurity/inc/certificatechooser.hxx
+++ b/xmlsecurity/inc/certificatechooser.hxx
@@ -92,7 +92,7 @@ public:
short Execute() override;
- css::uno::Reference< css::security::XCertificate > GetSelectedCertificate();
+ css::uno::Sequence<css::uno::Reference< css::security::XCertificate > > GetSelectedCertificates();
css::uno::Reference< css::xml::crypto::XXMLSecurityContext > GetSelectedSecurityContext();
/// Gets the description string provided when selecting the certificate.
OUString GetDescription();
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index bc52bdb30ff1..9d1244973de7 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -456,7 +456,7 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
return bFound;
}
-Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificateImpl(std::map<OUString, OUString>& rProperties, const UserAction eAction)
+uno::Sequence< Reference< css::security::XCertificate > > DocumentDigitalSignatures::chooseCertificatesImpl(std::map<OUString, OUString>& rProperties, const UserAction eAction)
{
std::vector< Reference< css::xml::crypto::XXMLSecurityContext > > xSecContexts;
@@ -468,17 +468,17 @@ Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertif
ScopedVclPtrInstance< CertificateChooser > aChooser(nullptr, mxCtx, xSecContexts, eAction);
+ uno::Sequence< Reference< css::security::XCertificate > > xCerts(1);
+ xCerts[0] = Reference< css::security::XCertificate >(nullptr);
+
if (aChooser->Execute() != RET_OK)
- return Reference< css::security::XCertificate >(nullptr);
+ return xCerts;
- Reference< css::security::XCertificate > xCert = aChooser->GetSelectedCertificate();
+ xCerts = aChooser->GetSelectedCertificates();
rProperties["Description"] = aChooser->GetDescription();
rProperties["Usage"] = aChooser->GetUsageText();
- if ( !xCert.is() )
- return Reference< css::security::XCertificate >(nullptr);
-
- return xCert;
+ return xCerts;
}
Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificate(OUString& rDescription)
@@ -489,23 +489,27 @@ Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertif
Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseSigningCertificate(OUString& rDescription)
{
std::map<OUString, OUString> aProperties;
- Reference< css::security::XCertificate > xCert = chooseCertificateImpl( aProperties, UserAction::Sign );
+ Reference< css::security::XCertificate > xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0];
rDescription = aProperties["Description"];
return xCert;
}
-Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseEncryptionCertificate(OUString& rDescription)
+css::uno::Sequence< Reference< css::security::XCertificate > > DocumentDigitalSignatures::chooseEncryptionCertificate()
{
std::map<OUString, OUString> aProperties;
- Reference< css::security::XCertificate > xCert = chooseCertificateImpl( aProperties, UserAction::Encrypt );
- rDescription = aProperties["Description"];
- return xCert;
+ uno::Sequence< Reference< css::security::XCertificate > > aCerts=
+ chooseCertificatesImpl( aProperties, UserAction::Encrypt );
+ if (aCerts.getLength() == 1 && !aCerts[0].is())
+ // our error case contract is: empty sequence, so map that!
+ return uno::Sequence< Reference< css::security::XCertificate > >();
+ else
+ return aCerts;
}
css::uno::Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificateWithProps(Sequence<::com::sun::star::beans::PropertyValue>& rProperties)
{
std::map<OUString, OUString> aProperties;
- auto xCert = chooseCertificateImpl( aProperties, UserAction::Sign );
+ auto xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0];
std::vector<css::beans::PropertyValue> vec;
for (const auto& pair : aProperties)
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.hxx b/xmlsecurity/source/component/documentdigitalsignatures.hxx
index 2dbc55685929..9ef24ab36e5e 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.hxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.hxx
@@ -63,7 +63,7 @@ private:
/// @throws css::uno::RuntimeException
css::uno::Sequence< css::security::DocumentSignatureInformation > ImplVerifySignatures( const css::uno::Reference< css::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode );
- css::uno::Reference< css::security::XCertificate > chooseCertificateImpl(std::map<OUString, OUString>& rProperties, const UserAction eAction);
+ css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > chooseCertificatesImpl(std::map<OUString, OUString>& rProperties, const UserAction eAction);
public:
explicit DocumentDigitalSignatures( const css::uno::Reference< css::uno::XComponentContext>& rxCtx );
@@ -106,7 +106,7 @@ public:
css::uno::Reference< css::security::XCertificate > SAL_CALL chooseCertificate(OUString& rDescription) override;
css::uno::Reference< css::security::XCertificate > SAL_CALL chooseSigningCertificate(OUString& rDescription) override;
- css::uno::Reference< css::security::XCertificate > SAL_CALL chooseEncryptionCertificate(OUString& rDescription) override;
+ css::uno::Sequence<css::uno::Reference< css::security::XCertificate > > SAL_CALL chooseEncryptionCertificate() override;
css::uno::Reference< css::security::XCertificate > SAL_CALL chooseCertificateWithProps(css::uno::Sequence<::com::sun::star::beans::PropertyValue>& Properties) override;
};
diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx b/xmlsecurity/source/dialogs/certificatechooser.cxx
index 08a897f9f0ba..a334e0250225 100644
--- a/xmlsecurity/source/dialogs/certificatechooser.cxx
+++ b/xmlsecurity/source/dialogs/certificatechooser.cxx
@@ -228,15 +228,33 @@ void CertificateChooser::ImplInitialize()
}
-uno::Reference< css::security::XCertificate > CertificateChooser::GetSelectedCertificate()
+uno::Sequence<uno::Reference< css::security::XCertificate > > CertificateChooser::GetSelectedCertificates()
{
+ std::vector< uno::Reference< css::security::XCertificate > > aRet;
SvTreeListEntry* pSel = m_pCertLB->FirstSelected();
- if( !pSel )
- return uno::Reference< css::security::XCertificate >();
- UserData* userData = static_cast<UserData*>(pSel->GetUserData());
- uno::Reference<security::XCertificate> xCert = userData->xCertificate;
- return xCert;
+ if (meAction == UserAction::Encrypt)
+ {
+ // for encryption, multiselection is enabled
+ while(pSel)
+ {
+ UserData* userData = static_cast<UserData*>(pSel->GetUserData());
+ aRet.push_back( userData->xCertificate );
+ pSel = m_pCertLB->NextSelected(pSel);
+ }
+ }
+ else
+ {
+ uno::Reference< css::security::XCertificate > xCert;
+ if( pSel )
+ {
+ UserData* userData = static_cast<UserData*>(pSel->GetUserData());
+ xCert = userData->xCertificate;
+ }
+ aRet.push_back( xCert );
+ }
+
+ return comphelper::containerToSequence(aRet);
}
uno::Reference<xml::crypto::XXMLSecurityContext> CertificateChooser::GetSelectedSecurityContext()
@@ -257,13 +275,15 @@ OUString CertificateChooser::GetDescription()
OUString CertificateChooser::GetUsageText()
{
- uno::Reference<css::security::XCertificate> xCert = GetSelectedCertificate();
- return xCert.is() ? UsageInClearText(xCert->getCertificateUsage()) : OUString();
+ uno::Sequence< uno::Reference<css::security::XCertificate> > xCerts =
+ GetSelectedCertificates();
+ return (xCerts.hasElements() && xCerts[0].is()) ?
+ UsageInClearText(xCerts[0]->getCertificateUsage()) : OUString();
}
IMPL_LINK_NOARG(CertificateChooser, CertificateHighlightHdl, SvTreeListBox*, void)
{
- bool bEnable = GetSelectedCertificate().is();
+ bool bEnable = m_pCertLB->GetSelectionCount() > 0;
m_pViewBtn->Enable( bEnable );
m_pOKBtn->Enable( bEnable );
m_pDescriptionED->Enable(bEnable);
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index 42ca15d05faf..195c74ec5c3e 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -406,7 +406,7 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, Button*, void)
if ( aChooser->Execute() == RET_OK )
{
sal_Int32 nSecurityId;
- if (!maSignatureManager.add(aChooser->GetSelectedCertificate(), aChooser->GetSelectedSecurityContext(),
+ if (!maSignatureManager.add(aChooser->GetSelectedCertificates()[0], aChooser->GetSelectedSecurityContext(),
aChooser->GetDescription(), nSecurityId, m_bAdESCompliant))
return;
mbSignaturesChanged = true;
commit 5d0f3cc3f9e6fc687ba6a40cebf2096d70e4f811
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Thu Dec 7 05:08:37 2017 +0100
gpg4libre: pass proper debug flags down to gpgmepp
Change-Id: Ide3f6e9fa218bcd26deaadbbdbed0c8905e66db9
diff --git a/external/gpgmepp/ExternalProject_gpgmepp.mk b/external/gpgmepp/ExternalProject_gpgmepp.mk
index 73a0ad68e6cd..a10d41556b0c 100644
--- a/external/gpgmepp/ExternalProject_gpgmepp.mk
+++ b/external/gpgmepp/ExternalProject_gpgmepp.mk
@@ -59,6 +59,11 @@ $(call gb_ExternalProject_get_state_target,gpgmepp,build):
$(gb_COMPILEROPTFLAGS),$(gb_COMPILERNOOPTFLAGS)) \
$(if $(ENABLE_DEBUG),$(gb_DEBUG_CFLAGS)) \
$(if $(filter $(true),$(gb_SYMBOL)),$(gb_DEBUGINFO_FLAGS))' \
+ CXXFLAGS='$(CXXFLAGS) \
+ $(if $(ENABLE_OPTIMIZED), \
+ $(gb_COMPILEROPTFLAGS),$(gb_COMPILERNOOPTFLAGS)) \
+ $(if $(ENABLE_DEBUG),$(gb_DEBUG_CXXFLAGS) -D_GLIBCXX_DEBUG) \
+ $(if $(filter $(true),$(gb_SYMBOL)),$(gb_DEBUGINFO_FLAGS))' \
$(if $(filter LINUX,$(OS)), \
'LDFLAGS=-Wl$(COMMA)-z$(COMMA)origin \
-Wl$(COMMA)-rpath$(COMMA)\$$$$ORIGIN') \
commit 757087a9829941bade8259673b57507d48cbdfc6
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Wed Dec 6 15:20:54 2017 +0100
gpg4libre: add KDE4 fpicker gpg crypt chechbox
Change-Id: Iba8fb0e0ac732f36cd1d880884bde1121e6b1eab
diff --git a/vcl/unx/kde4/KDE4FilePicker.cxx b/vcl/unx/kde4/KDE4FilePicker.cxx
index 7268bac1dc02..4488d04489b5 100644
--- a/vcl/unx/kde4/KDE4FilePicker.cxx
+++ b/vcl/unx/kde4/KDE4FilePicker.cxx
@@ -533,6 +533,9 @@ void KDE4FilePicker::addCustomControl(sal_Int16 controlId)
case CHECKBOX_PASSWORD:
resId = STR_FPICKER_PASSWORD;
break;
+ case CHECKBOX_GPGENCRYPTION:
+ resId = STR_FPICKER_GPGENCRYPT;
+ break;
case CHECKBOX_FILTEROPTIONS:
resId = STR_FPICKER_FILTER_OPTIONS;
break;
@@ -571,6 +574,7 @@ void KDE4FilePicker::addCustomControl(sal_Int16 controlId)
{
case CHECKBOX_AUTOEXTENSION:
case CHECKBOX_PASSWORD:
+ case CHECKBOX_GPGENCRYPTION:
case CHECKBOX_FILTEROPTIONS:
case CHECKBOX_READONLY:
case CHECKBOX_LINK:
@@ -657,6 +661,7 @@ void SAL_CALL KDE4FilePicker::initialize( const uno::Sequence<uno::Any> &args )
{
operationMode = KFileDialog::Saving;
addCustomControl( CHECKBOX_PASSWORD );
+ addCustomControl( CHECKBOX_GPGENCRYPTION );
break;
}
case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
@@ -664,6 +669,7 @@ void SAL_CALL KDE4FilePicker::initialize( const uno::Sequence<uno::Any> &args )
operationMode = KFileDialog::Saving;
addCustomControl( CHECKBOX_AUTOEXTENSION );
addCustomControl( CHECKBOX_PASSWORD );
+ addCustomControl( CHECKBOX_GPGENCRYPTION );
addCustomControl( CHECKBOX_FILTEROPTIONS );
break;
}
commit 9992fe1051d7dea3fddeb1d45b0e2a0a3f43ab08
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Mon Dec 4 02:22:09 2017 +0100
gpg4libre: add gtk fpicker gpg crypt chechbox
Change-Id: I27b494530a2b61eb37c4a9f7c3e1f9845f045e66
diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx b/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
index 8a71c2de712e..dfc5274bbb63 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
+++ b/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
@@ -161,6 +161,7 @@ SalGtkFilePicker::SalGtkFilePicker( const uno::Reference< uno::XComponentContext
switch( i ) {
LABEL_TOGGLE( AUTOEXTENSION );
LABEL_TOGGLE( PASSWORD );
+ LABEL_TOGGLE( GPGENCRYPTION );
LABEL_TOGGLE( FILTEROPTIONS );
LABEL_TOGGLE( READONLY );
LABEL_TOGGLE( LINK );
@@ -1069,6 +1070,7 @@ GtkWidget *SalGtkFilePicker::getWidget( sal_Int16 nControlId, GType *pType )
{
MAP_TOGGLE( AUTOEXTENSION );
MAP_TOGGLE( PASSWORD );
+ MAP_TOGGLE( GPGENCRYPTION );
MAP_TOGGLE( FILTEROPTIONS );
MAP_TOGGLE( READONLY );
MAP_TOGGLE( LINK );
@@ -1611,12 +1613,14 @@ void SAL_CALL SalGtkFilePicker::initialize( const uno::Sequence<uno::Any>& aArgu
eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
first_button_text = GTK_STOCK_SAVE;
mbToggleVisibility[PASSWORD] = true;
+ mbToggleVisibility[GPGENCRYPTION] = true;
// TODO
break;
case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
first_button_text = GTK_STOCK_SAVE;
mbToggleVisibility[PASSWORD] = true;
+ mbToggleVisibility[GPGENCRYPTION] = true;
mbToggleVisibility[FILTEROPTIONS] = true;
// TODO
break;
diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx b/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx
index 4c24307e7fd2..1266ac5cfdd3 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx
+++ b/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx
@@ -166,6 +166,7 @@ class SalGtkFilePicker : public SalGtkPicker, public SalGtkFilePicker_Base
LINK,
PREVIEW,
SELECTION,
+ GPGENCRYPTION,
TOGGLE_LAST
};
diff --git a/vcl/unx/gtk/fpicker/resourceprovider.cxx b/vcl/unx/gtk/fpicker/resourceprovider.cxx
index e41c7bf5fd25..3e5469a7c392 100644
--- a/vcl/unx/gtk/fpicker/resourceprovider.cxx
+++ b/vcl/unx/gtk/fpicker/resourceprovider.cxx
@@ -38,6 +38,7 @@ static const struct
} CtrlIdToResIdTable[] = {
{ CHECKBOX_AUTOEXTENSION, STR_FPICKER_AUTO_EXTENSION },
{ CHECKBOX_PASSWORD, STR_FPICKER_PASSWORD },
+ { CHECKBOX_GPGENCRYPTION, STR_FPICKER_GPGENCRYPT },
{ CHECKBOX_FILTEROPTIONS, STR_FPICKER_FILTER_OPTIONS },
{ CHECKBOX_READONLY, STR_FPICKER_READONLY },
{ CHECKBOX_LINK, STR_FPICKER_INSERT_AS_LINK },
commit 926dc6c984a4224cf895596504dca1a814a0cb43
Author: Thorsten Behrens <thorsten.behrens at cib.de>
Date: Thu Nov 23 23:28:13 2017 +0100
gpg4libre: add gpg encrypt checbox to win32 filepicker
Change-Id: Ia6315e8b1f04228984afd2fbca3c059df9589497
diff --git a/fpicker/source/office/OfficeControlAccess.cxx b/fpicker/source/office/OfficeControlAccess.cxx
index 1b30f285734b..be9a91f212af 100644
--- a/fpicker/source/office/OfficeControlAccess.cxx
+++ b/fpicker/source/office/OfficeControlAccess.cxx
@@ -77,6 +77,7 @@ namespace svt
{ "FilterList", LISTBOX_FILTER, PROPERTY_FLAGS_COMMON },
{ "FilterListLabel", LISTBOX_FILTER_LABEL, PROPERTY_FLAGS_COMMON | PropFlags::Text },
{ "FilterOptionsBox", CHECKBOX_FILTEROPTIONS, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX },
+ { "GpgPassword", CHECKBOX_GPGENCRYPTION, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_CHECKBOX },
{ "HelpButton", PUSHBUTTON_HELP, PROPERTY_FLAGS_COMMON | PropFlags::Text },
{ "ImageTemplateList", LISTBOX_IMAGE_TEMPLATE, PROPERTY_FLAGS_COMMON | PROPERTY_FLAGS_LISTBOX },
{ "ImageTemplateListLabel", LISTBOX_IMAGE_TEMPLATE_LABEL, PROPERTY_FLAGS_COMMON | PropFlags::Text },
diff --git a/fpicker/source/win32/filepicker/VistaFilePicker.cxx b/fpicker/source/win32/filepicker/VistaFilePicker.cxx
index 449be62fb848..54ff672579ff 100644
--- a/fpicker/source/win32/filepicker/VistaFilePicker.cxx
+++ b/fpicker/source/win32/filepicker/VistaFilePicker.cxx
@@ -396,6 +396,7 @@ void SAL_CALL VistaFilePicker::initialize(const css::uno::Sequence< css::uno::An
bFileOpenDialog = false;
nFeatures |= FEATURE_AUTOEXTENSION;
nFeatures |= FEATURE_PASSWORD;
+ nFeatures |= FEATURE_GPGPASSWORD;
}
break;
@@ -405,6 +406,7 @@ void SAL_CALL VistaFilePicker::initialize(const css::uno::Sequence< css::uno::An
nFeatures |= FEATURE_AUTOEXTENSION;
nFeatures |= FEATURE_PASSWORD;
nFeatures |= FEATURE_FILTEROPTIONS;
+ nFeatures |= FEATURE_GPGPASSWORD;
}
break;
diff --git a/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx b/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx
index 2b0fffe337d7..35be52b6101a 100644
--- a/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx
+++ b/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx
@@ -590,6 +590,13 @@ void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_I
setLabelToControl(iCustom, nControlId);
}
+ if ((nFeatures & FEATURE_GPGPASSWORD) == FEATURE_GPGPASSWORD)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION;
+ iCustom->AddCheckButton (nControlId, L"GpgPassword", false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY)
{
nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY;
@@ -1110,6 +1117,7 @@ void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef& rRequest)
switch (nId)
{
case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION :
case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
diff --git a/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx b/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx
index 70272ad8c1c0..5161d787e767 100644
--- a/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx
+++ b/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx
@@ -67,6 +67,7 @@ static const ::sal_Int32 FEATURE_IMAGETEMPLATE = 128;
static const ::sal_Int32 FEATURE_PLAY = 256;
static const ::sal_Int32 FEATURE_READONLY = 512;
static const ::sal_Int32 FEATURE_VERSION = 1024;
+static const ::sal_Int32 FEATURE_GPGPASSWORD = 2048;
static const OUString PROP_PICKER_LISTENER("picker_listener" ); // [XFilePickerListenert]
static const OUString PROP_DIALOG_SHOW_RESULT("dialog_show_result" ); // [sal_Bool] true=OK, false=CANCEL
diff --git a/fpicker/source/win32/misc/resourceprovider.cxx b/fpicker/source/win32/misc/resourceprovider.cxx
index bc9c270774b5..b7b70d4d45de 100644
--- a/fpicker/source/win32/misc/resourceprovider.cxx
+++ b/fpicker/source/win32/misc/resourceprovider.cxx
@@ -61,7 +61,8 @@ Entry const CtrlIdToResIdTable[] = {
{ LISTBOX_IMAGE_TEMPLATE_LABEL, STR_SVT_FILEPICKER_IMAGE_TEMPLATE },
{ CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION },
{ FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE },
- { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION }
+ { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION },
+ { CHECKBOX_GPGENCRYPTION, STR_SVT_FILEPICKER_GPGENCRYPT }
};
const sal_Int32 SIZE_TABLE = SAL_N_ELEMENTS( CtrlIdToResIdTable );
commit c22236d733eff274cbd18e72109ff440177fab67
Author: Thorsten Behrens <thorsten.behrens at cib.de>
Date: Thu Nov 23 22:18:09 2017 +0100
gpg4libre: find keymanager executable on Windows
Change-Id: If93c06ad90d708b0fbaf476bda6fdb902bd77b1e
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index ba726e04d0a5..42ca15d05faf 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -468,9 +468,17 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, Button*, void)
IMPL_STATIC_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, Button*, void)
{
- const OUString aGUIServers[] = { OUString("kleopatra"), OUString("seahorse"), OUString("gpa"), OUString("kgpg") };
- // FIXME: the same for Windows + registry search for gpg4win
+#ifdef _WIN32
+ // FIXME: call GpgME::dirInfo("bindir") somewhere in
+ // SecurityEnvironmentGpg or whatnot
+ // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
+ const OUString aGUIServers[] = { OUString("kleopatra.exe"), OUString("launch-gpa.exe"), OUString("gpa.exe"),
+ OUString("bin\\kleopatra.exe"), OUString("bin\\launch-gpa.exe"), OUString("bin\\gpa.exe") };
+ const char* cPath = "C:\\Program Files (x86)\\GNU\\GnuPG";
+#else
+ const OUString aGUIServers[] = { OUString("kleopatra"), OUString("seahorse"), OUString("gpa"), OUString("kgpg") };
const char* cPath = getenv("PATH");
+#endif
if (cPath)
{
commit 0a58fdfdf48ec95295eca195b07424e98381af3f
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Sun Aug 20 03:38:05 2017 +0200
gpg4libre: [API CHANGE] add storage helper for GPG encryption data
OpenPGP encryption needs to pass down slightly different meta data
to package / zip storage.
Change-Id: Idba9ad7a821cb33070cf5e5a0f79ae55db99b276
diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index e997bd5e6f32..4a24d65da15c 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -37,6 +37,7 @@ $(eval $(call gb_Library_add_defs,comphelper,\
))
$(eval $(call gb_Library_use_externals,comphelper,\
+ gpgmepp \
boost_headers \
icuuc \
icu_headers \
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx
index 166955d3b226..a05fb1358f3f 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -19,6 +19,7 @@
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
+#include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/StorageFactory.hpp>
@@ -43,6 +44,7 @@
#include <rtl/random.h>
#include <osl/time.h>
#include <osl/diagnose.h>
+#include <sax/tools/converter.hxx>
#include <ucbhelper/content.hxx>
@@ -50,6 +52,15 @@
#include <comphelper/processfactory.hxx>
#include <comphelper/documentconstants.hxx>
#include <comphelper/storagehelper.hxx>
+#include <comphelper/sequence.hxx>
+
+#if GPGME_HAVE_GPGME
+# include <gpgme.h>
+# include <context.h>
+# include <encryptionresult.h>
+# include <key.h>
+# include <data.h>
+#endif
using namespace ::com::sun::star;
@@ -194,11 +205,21 @@ void OStorageHelper::SetCommonStorageEncryptionData(
const uno::Reference< embed::XStorage >& xStorage,
const uno::Sequence< beans::NamedValue >& aEncryptionData )
{
- uno::Reference< embed::XEncryptionProtectedSource2 > xEncrSet( xStorage, uno::UNO_QUERY );
+ uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY );
if ( !xEncrSet.is() )
throw io::IOException(); // TODO
- xEncrSet->setEncryptionData( aEncryptionData );
+ if ( aEncryptionData.getLength() == 2 &&
+ aEncryptionData[0].Name == "GpgInfos" &&
+ aEncryptionData[1].Name == "EncryptionKey" )
+ {
+ xEncrSet->setGpgProperties(
+ aEncryptionData[0].Value.get< uno::Sequence< uno::Sequence< beans::NamedValue > > >() );
+ xEncrSet->setEncryptionData(
+ aEncryptionData[1].Value.get< uno::Sequence< beans::NamedValue > >() );
+ }
+ else
+ xEncrSet->setEncryptionData( aEncryptionData );
}
@@ -409,6 +430,7 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData(
uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionData()
{
+#if GPGME_HAVE_GPGME
// generate session key
// --------------------
@@ -425,34 +447,95 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat
rtl_random_destroyPool(aRandomPool);
uno::Sequence< beans::NamedValue > aContainer(2);
- uno::Sequence< beans::NamedValue > aGpgEncryptionData(3);
+ std::vector< uno::Sequence< beans::NamedValue > > aGpgEncryptions;
+ uno::Sequence< beans::NamedValue > aGpgEncryptionEntry(3);
uno::Sequence< beans::NamedValue > aEncryptionData(1);
- // TODO fire certificate chooser dialog
uno::Reference< security::XDocumentDigitalSignatures > xSigner(
security::DocumentDigitalSignatures::createWithVersion(
comphelper::getProcessComponentContext(), "1.2" ) );
- // The user may provide a description while choosing a certificate.
- OUString aDescription;
- uno::Reference< security::XCertificate > xSignCertificate=
- xSigner->chooseEncryptionCertificate(aDescription);
+ // fire up certificate chooser dialog - user can multi-select!
+ uno::Sequence< uno::Reference< security::XCertificate > > xSignCertificates=
+ xSigner->chooseEncryptionCertificate();
+
+ // generate one encrypted key entry for each recipient
+ // ---------------------------------------------------
+
+ std::unique_ptr<GpgME::Context> ctx;
+ GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
+ if (err)
+ throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+ if (ctx == nullptr)
+ throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ ctx->setArmor(false);
- uno::Sequence < sal_Int8 > aKeyID;
- if (xSignCertificate.is())
+ // TODO: add self-encryption key from user config
+ const uno::Reference< security::XCertificate >* pCerts=xSignCertificates.getConstArray();
+ for (sal_uInt32 i = 0, nNum = xSignCertificates.getLength(); i < nNum; i++, pCerts++)
{
- aKeyID = xSignCertificate->getSHA1Thumbprint();
+ uno::Sequence < sal_Int8 > aKeyID;
+ if (pCerts->is())
+ aKeyID = (*pCerts)->getSHA256Thumbprint();
+
+ std::vector<GpgME::Key> keys;
+ keys.push_back(
+ ctx->key(
+ reinterpret_cast<const char*>(aKeyID.getConstArray()),
+ err, true));
+
+ // ctx is setup now, let's encrypt the lot!
+ GpgME::Data plain(
+ reinterpret_cast<const char*>(aVector.getConstArray()),
+ aVector.getLength(), false);
+ GpgME::Data cipher;
+
+ GpgME::EncryptionResult crypt_res = ctx->encrypt(
+ keys, plain,
+ cipher, GpgME::Context::NoCompress);
+
+ off_t result = cipher.seek(0,SEEK_SET);
+ (void) result;
+ assert(result == 0);
+ int len=0, curr=0; char buf;
+ while( (curr=cipher.read(&buf, 1)) )
+ len += curr;
+
+ if(crypt_res.error() || !len)
+ throw uno::RuntimeException("The GpgME library failed to encrypt.");
+
+ uno::Sequence < sal_Int8 > aCipherValue(len);
+ result = cipher.seek(0,SEEK_SET);
+ assert(result == 0);
+ if( cipher.read(aCipherValue.getArray(), len) != len )
+ throw uno::RuntimeException("The GpgME library failed to read the encrypted value.");
+
+ SAL_INFO("comphelper.crypto", "Generated gpg crypto of length: " << len);
+
+ aGpgEncryptionEntry[0].Name = "KeyId";
+ aGpgEncryptionEntry[0].Value <<= aKeyID;
+ aGpgEncryptionEntry[1].Name = "KeyPacket";
+ aGpgEncryptionEntry[1].Value <<= aKeyID;
+ aGpgEncryptionEntry[2].Name = "CipherValue";
+ aGpgEncryptionEntry[2].Value <<= aCipherValue;
+
+ aGpgEncryptions.push_back(aGpgEncryptionEntry);
}
- aGpgEncryptionData[0].Name = "KeyId";
- aGpgEncryptionData[0].Value <<= aKeyID;
+ aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
+ aEncryptionData[0].Value <<= aVector;
aContainer[0].Name = "GpgInfos";
- aContainer[0].Value <<= aGpgEncryptionData;
+ aContainer[0].Value <<= comphelper::containerToSequence(aGpgEncryptions);
aContainer[1].Name = "EncryptionKey";
aContainer[1].Value <<= aEncryptionData;
return aContainer;
+#else
+ return uno::Sequence< beans::NamedValue >();
+#endif
}
bool OStorageHelper::IsValidZipEntryFileName( const OUString& aName, bool bSlashAllowed )
diff --git a/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl b/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl
index 5ddcc6831844..ecba64d51995 100644
--- a/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl
+++ b/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl
@@ -84,6 +84,37 @@ interface XEncryptionProtectedStorage: XEncryptionProtectedSource2
/** allows to get the encryption algorithms of the object.
*/
sequence< ::com::sun::star::beans::NamedValue > getEncryptionAlgorithms();
+
+ /** set OpenPGP-specific encryption properties
+
+ <p>
+ When provided, switch ODF package encryption to OpenPGP.
+ </p>
+ <p>
+ For each recipient, add one sequence of named values, each of
+ the same structure. The following values could be part of that
+ provided sequence:
+ </p>
+ <dl>
+ <dt>KeyId</dt>
+ <dd>
+ specifies OpenPGP key ID or fingerprint of the public
+ key used to encrypt this session key against
+ </dd>
+ <dt>KeyPacket</dt>
+ <dd>
+ (optional) public key packet of the key used to encrypt
+ </dd>
+ <dt>CipherValue</dt>
+ <dd>
+ OpenPGP-encrypted session key for this recipient
+ </dd>
+ </dl>
+
+ @since LibreOffice 6.0
+ */
+ void setGpgProperties( [in] sequence< sequence< ::com::sun::star::beans::NamedValue > > aProps )
+ raises( ::com::sun::star::lang::IllegalArgumentException );
};
diff --git a/package/inc/PackageConstants.hxx b/package/inc/PackageConstants.hxx
index df7bebcf6bd4..b81c0dd0a904 100644
--- a/package/inc/PackageConstants.hxx
+++ b/package/inc/PackageConstants.hxx
@@ -51,6 +51,7 @@ const sal_Int32 n_ConstDigestDecrypt = 1056; // 1024 + 32
#define ENCRYPTION_KEY_PROPERTY "EncryptionKey"
#define STORAGE_ENCRYPTION_KEYS_PROPERTY "StorageEncryptionKeys"
#define ENCRYPTION_ALGORITHMS_PROPERTY "EncryptionAlgorithms"
+#define ENCRYPTION_GPG_PROPERTIES "EncryptionGpGProperties"
#define HAS_ENCRYPTED_ENTRIES_PROPERTY "HasEncryptedEntries"
#define HAS_NONENCRYPTED_ENTRIES_PROPERTY "HasNonEncryptedEntries"
#define IS_INCONSISTENT_PROPERTY "IsInconsistent"
diff --git a/package/inc/ZipPackage.hxx b/package/inc/ZipPackage.hxx
index 61b0fc883575..f46eb33b0172 100644
--- a/package/inc/ZipPackage.hxx
+++ b/package/inc/ZipPackage.hxx
@@ -72,6 +72,7 @@ class ZipPackage final : public cppu::WeakImplHelper
css::uno::Sequence< css::beans::NamedValue > m_aStorageEncryptionKeys;
css::uno::Sequence< sal_Int8 > m_aEncryptionKey;
+ css::uno::Sequence< css::uno::Sequence< css::beans::NamedValue > > m_aGpgProps;
FolderHash m_aRecent;
OUString m_aURL;
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index cbcceece39ea..66678d7c378d 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -4205,6 +4205,66 @@ void SAL_CALL OStorage::setEncryptionAlgorithms( const uno::Sequence< beans::Nam
}
}
+void SAL_CALL OStorage::setGpgProperties( const uno::Sequence< uno::Sequence< beans::NamedValue > >& aProps )
+{
+ ::osl::MutexGuard aGuard( m_pData->m_xSharedMutex->GetMutex() );
+
+ if ( !m_pImpl )
+ {
+ SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
+ throw lang::DisposedException( THROW_WHERE );
+ }
+
+ if ( m_pData->m_nStorageType != embed::StorageFormats::PACKAGE )
+ throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
+
+ if ( !aProps.getLength() )
+ throw uno::RuntimeException( THROW_WHERE "Unexpected empty encryption algorithms list!" );
+
+ SAL_WARN_IF( !m_pData->m_bIsRoot, "package.xstor", "setGpgProperties() method is not available for nonroot storages!" );
+ if ( m_pData->m_bIsRoot )
+ {
+ try {
+ m_pImpl->ReadContents();
+ }
+ catch ( const uno::RuntimeException& aRuntimeException )
+ {
+ SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
+ throw;
+ }
+ catch ( const uno::Exception& aException )
+ {
+ SAL_INFO("package.xstor", "Rethrow: " << aException.Message);
+
+ uno::Any aCaught( ::cppu::getCaughtException() );
+ throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
+ static_cast< OWeakObject* >( this ),
+ aCaught );
+ }
+
+ uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
+ try
+ {
+ xPackPropSet->setPropertyValue( ENCRYPTION_GPG_PROPERTIES,
+ uno::makeAny( aProps ) );
+ }
+ catch ( const uno::RuntimeException& aRuntimeException )
+ {
+ SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
+ throw;
+ }
+ catch( const uno::Exception& aException )
+ {
+ SAL_INFO("package.xstor", "Rethrow: " << aException.Message);
+
+ uno::Any aCaught( ::cppu::getCaughtException() );
+ throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
+ static_cast< OWeakObject* >( this ),
+ aCaught );
+ }
+ }
+}
+
uno::Sequence< beans::NamedValue > SAL_CALL OStorage::getEncryptionAlgorithms()
{
::osl::MutexGuard aGuard( m_pData->m_xSharedMutex->GetMutex() );
diff --git a/package/source/xstor/xstorage.hxx b/package/source/xstor/xstorage.hxx
index 262b317e4def..82cffa69a2fe 100644
--- a/package/source/xstor/xstorage.hxx
+++ b/package/source/xstor/xstorage.hxx
@@ -459,6 +459,7 @@ public:
// XEncryptionProtectedStorage
virtual void SAL_CALL setEncryptionAlgorithms( const css::uno::Sequence< css::beans::NamedValue >& aAlgorithms ) override;
+ virtual void SAL_CALL setGpgProperties( const css::uno::Sequence< css::uno::Sequence< css::beans::NamedValue > >& aCryptProps ) override;
virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL getEncryptionAlgorithms() override;
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index 7eef97c5341f..769c7f662bba 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -1208,7 +1208,9 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile()
if ( m_nFormat == embed::StorageFormats::PACKAGE )
{
- uno::Sequence < PropertyValue > aPropSeq( PKG_SIZE_NOENCR_MNFST );
+ bool bIsGpgEncrypt = m_aGpgProps.hasElements();
+ uno::Sequence < PropertyValue > aPropSeq(
+ bIsGpgEncrypt ? PKG_SIZE_NOENCR_MNFST+1 : PKG_SIZE_NOENCR_MNFST );
aPropSeq [PKG_MNFST_MEDIATYPE].Name = sMediaType;
aPropSeq [PKG_MNFST_MEDIATYPE].Value <<= m_xRootFolder->GetMediaType();
aPropSeq [PKG_MNFST_VERSION].Name = sVersion;
@@ -1216,6 +1218,11 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile()
aPropSeq [PKG_MNFST_FULLPATH].Name = sFullPath;
aPropSeq [PKG_MNFST_FULLPATH].Value <<= OUString("/");
+ if( bIsGpgEncrypt )
+ {
+ aPropSeq[PKG_SIZE_NOENCR_MNFST].Name = "KeyInfo";
+ aPropSeq[PKG_SIZE_NOENCR_MNFST].Value <<= m_aGpgProps;
+ }
aManList.push_back( aPropSeq );
}
@@ -1751,6 +1758,22 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const
}
}
}
+ else if ( aPropertyName == ENCRYPTION_GPG_PROPERTIES )
+ {
+ uno::Sequence< uno::Sequence< beans::NamedValue > > aGpgProps;
+ if ( m_pZipFile || !( aValue >>= aGpgProps ) || aGpgProps.getLength() == 0 )
+ {
+ throw IllegalArgumentException(THROW_WHERE "unexpected Gpg properties are provided.", uno::Reference< uno::XInterface >(), 2 );
+ }
+
+ m_aGpgProps = aGpgProps;
+
+ // override algorithm defaults (which are some legacy ODF
+ // defaults) with reasonable values
+ m_nStartKeyGenerationID = 0; // this is unused for PGP
+ m_nCommonEncryptionID = xml::crypto::CipherID::AES_CBC_W3C_PADDING;
+ m_nChecksumDigestID = xml::crypto::DigestID::SHA512_1K;
+ }
else
throw UnknownPropertyException(THROW_WHERE );
}
commit 3f775118a6d9e6cbd49edf7d5309e29edeeaff47
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date: Fri Aug 18 21:34:11 2017 +0200
gpg4libre: add manifest entries for gpg encryption
Change-Id: I71bd7e2c6c73d997fa1ed5bb36fdc2873daca10c
diff --git a/package/source/manifest/ManifestDefines.hxx b/package/source/manifest/ManifestDefines.hxx
index 968aed648e6a..c68c241c7514 100644
--- a/package/source/manifest/ManifestDefines.hxx
+++ b/package/source/manifest/ManifestDefines.hxx
@@ -24,8 +24,10 @@
#define MANIFEST_NSPREFIX "manifest:"
#define ELEMENT_MANIFEST "manifest:manifest"
#define ATTRIBUTE_XMLNS "xmlns:manifest"
+#define ATTRIBUTE_XMLNS_LOEXT "xmlns:loext"
#define MANIFEST_NAMESPACE "http://openoffice.org/2001/manifest"
#define MANIFEST_OASIS_NAMESPACE "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
+#define MANIFEST_LOEXT_NAMESPACE "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
#define MANIFEST_DOCTYPE "<!DOCTYPE manifest:manifest PUBLIC \"-//OpenOffice.org//DTD Manifest 1.0//EN\" \"Manifest.dtd\">"
#define ATTRIBUTE_CDATA "CDATA"
@@ -34,6 +36,16 @@
#define ATTRIBUTE_VERSION "manifest:version"
#define ATTRIBUTE_MEDIA_TYPE "manifest:media-type"
#define ATTRIBUTE_SIZE "manifest:size"
+#define ELEMENT_MANIFEST_KEYINFO "loext:keyinfo"
+#define ELEMENT_ENCRYPTED_KEYINFO "loext:KeyInfo"
+#define ELEMENT_ENCRYPTEDKEY "loext:encrypted-key"
+#define ELEMENT_ENCRYPTIONMETHOD "loext:encryption-method"
+#define ELEMENT_PGPDATA "loext:PGPData"
+#define ELEMENT_PGPKEYID "loext:PGPKeyID"
+#define ELEMENT_PGPKEYPACKET "loext:PGPKeyPacket"
+#define ATTRIBUTE_ALGORITHM "loext:PGPAlgorithm"
+#define ELEMENT_CIPHERDATA "loext:CipherData"
+#define ELEMENT_CIPHERVALUE "loext:CipherValue"
#define ELEMENT_ENCRYPTION_DATA "manifest:encryption-data"
#define ATTRIBUTE_CHECKSUM_TYPE "manifest:checksum-type"
@@ -69,6 +81,7 @@
#define AES256_URL "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
#define PBKDF2_NAME "PBKDF2"
+#define PGP_NAME "PGP"
#define PBKDF2_URL "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#pbkdf2"
#endif
diff --git a/package/source/manifest/ManifestExport.cxx b/package/source/manifest/ManifestExport.cxx
index 60a5128e945d..5cf87334ca62 100644
--- a/package/source/manifest/ManifestExport.cxx
+++ b/package/source/manifest/ManifestExport.cxx
@@ -23,6 +23,7 @@
#include <com/sun/star/xml/crypto/DigestID.hpp>
#include <com/sun/star/xml/crypto/CipherID.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
#include "ManifestDefines.hxx"
@@ -66,11 +67,25 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
const OUString sChecksumTypeAttribute ( ATTRIBUTE_CHECKSUM_TYPE );
const OUString sChecksumAttribute ( ATTRIBUTE_CHECKSUM);
+ const OUString sKeyInfoElement ( ELEMENT_ENCRYPTED_KEYINFO );
+ const OUString sManifestKeyInfoElement ( ELEMENT_MANIFEST_KEYINFO );
+ const OUString sEncryptedKeyElement ( ELEMENT_ENCRYPTEDKEY );
+ const OUString sEncryptionMethodElement ( ELEMENT_ENCRYPTIONMETHOD );
+ const OUString sPgpDataElement ( ELEMENT_PGPDATA );
+ const OUString sPgpKeyIDElement ( ELEMENT_PGPKEYID );
+ const OUString sPGPKeyPacketElement ( ELEMENT_PGPKEYPACKET );
+ const OUString sAlgorithmAttribute ( ATTRIBUTE_ALGORITHM );
+ const OUString sCipherDataElement ( ELEMENT_CIPHERDATA );
+ const OUString sCipherValueElement ( ELEMENT_CIPHERVALUE );
+ const OUString sKeyInfo ( "KeyInfo" );
+ const OUString sPgpKeyIDProperty ( "KeyId" );
+ const OUString sPgpKeyPacketProperty ( "KeyPacket" );
+ const OUString sCipherValueProperty ( "CipherValue" );
const OUString sFullPathProperty ( "FullPath" );
const OUString sVersionProperty ( "Version" );
const OUString sMediaTypeProperty ( "MediaType" );
const OUString sIterationCountProperty ( "IterationCount" );
- const OUString sDerivedKeySizeProperty ( "DerivedKeySize" );
+ const OUString sDerivedKeySizeProperty ( "DerivedKeySize" );
const OUString sSaltProperty ( "Salt" );
const OUString sInitialisationVectorProperty( "InitialisationVector" );
const OUString sSizeProperty ( "Size" );
@@ -92,6 +107,7 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
const OUString sAES256_URL ( AES256_URL );
const OUString sPBKDF2_Name ( PBKDF2_NAME );
+ const OUString sPGP_Name ( PGP_NAME );
::comphelper::AttributeList * pRootAttrList = new ::comphelper::AttributeList;
const uno::Sequence < beans::PropertyValue > *pSequence = rManList.getConstArray();
@@ -100,6 +116,7 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
// find the mediatype of the document if any
OUString aDocMediaType;
OUString aDocVersion;
+ sal_Int32 nRootFolderPropIndex=-1;
for (sal_uInt32 nInd = 0; nInd < nManLength ; nInd++ )
{
OUString aMediaType;
@@ -130,6 +147,7 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
{
aDocMediaType = aMediaType;
aDocVersion = aVersion;
+ nRootFolderPropIndex = nInd;
break;
}
}
@@ -164,9 +182,14 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
bAcceptNonemptyVersion = true;
if ( aDocVersion.compareTo( ODFVER_012_TEXT ) >= 0 )
{
- // this is ODF12 generation, let encrypted streams contain start-key-generation entry
+ // this is ODF12 or later generation, let encrypted
+ // streams contain start-key-generation entry
bStoreStartKeyGeneration = true;
pRootAttrList->AddAttribute ( sVersionAttribute, sCdataAttribute, aDocVersion );
+ // plus gpg4libre extensions - loext NS for that
+ pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS_LOEXT,
+ sCdataAttribute,
+ MANIFEST_LOEXT_NAMESPACE );
}
}
else
@@ -192,6 +215,116 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
}
xHandler->startElement( sManifestElement, xRootAttrList );
+ const uno::Any *pKeyInfoProperty = nullptr;
+ if ( nRootFolderPropIndex >= 0 )
+ {
+ // do we have package-wide encryption info?
+ const beans::PropertyValue *pValue =
+ pSequence[nRootFolderPropIndex].getConstArray();
+ for (sal_uInt32 j = 0, nNum = pSequence[nRootFolderPropIndex].getLength(); j < nNum; j++, pValue++)
+ {
+ if (pValue->Name == sKeyInfo )
+ pKeyInfoProperty = &pValue->Value;
+ }
+
+ if ( pKeyInfoProperty )
+ {
+ // yeah, so that goes directly below the manifest:manifest
+ // element
+ ::comphelper::AttributeList * pNewAttrList = new ::comphelper::AttributeList;
+ uno::Reference < xml::sax::XAttributeList > xNewAttrList (pNewAttrList);
+ OUStringBuffer aBuffer;
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ // ==== manifest:keyinfo & children
+ xHandler->startElement( sManifestKeyInfoElement, nullptr );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ uno::Sequence< uno::Sequence < beans::NamedValue > > aKeyInfoSequence;
+ *pKeyInfoProperty >>= aKeyInfoSequence;
+ const uno::Sequence < beans::NamedValue > *pKeyInfoSequence = aKeyInfoSequence.getConstArray();
+ const sal_uInt32 nKeyInfoLength = aKeyInfoSequence.getLength();
+ for (sal_uInt32 nInd = 0; nInd < nKeyInfoLength ; nInd++ )
+ {
+ uno::Sequence < sal_Int8 > aPgpKeyID;
+ uno::Sequence < sal_Int8 > aPgpKeyPacket;
+ uno::Sequence < sal_Int8 > aCipherValue;
+ const beans::NamedValue *pNValue = pKeyInfoSequence[nInd].getConstArray();
+ for (sal_uInt32 j = 0, nNum = pKeyInfoSequence[nInd].getLength(); j < nNum; j++, pNValue++)
+ {
+ if (pNValue->Name == sPgpKeyIDProperty )
+ pNValue->Value >>= aPgpKeyID;
+ else if (pNValue->Name == sPgpKeyPacketProperty )
+ pNValue->Value >>= aPgpKeyPacket;
+ else if (pNValue->Name == sCipherValueProperty )
+ pNValue->Value >>= aCipherValue;
+ }
+
+ if (aPgpKeyID.hasElements() && aCipherValue.hasElements() )
+ {
+ // ==== manifest:encrypted-key & children - one for each recipient
+ xHandler->startElement( sEncryptedKeyElement, nullptr );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ // TODO: the algorithm should rather be configurable
+ pNewAttrList->AddAttribute ( sAlgorithmAttribute, sCdataAttribute,
+ "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" );
+ xHandler->startElement( sEncryptionMethodElement, xNewAttrList );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sEncryptionMethodElement );
+
+ xHandler->startElement( sKeyInfoElement, nullptr );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->startElement( sPgpDataElement, nullptr );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->startElement( sPgpKeyIDElement, nullptr );
+ ::sax::Converter::encodeBase64(aBuffer, aPgpKeyID);
+ xHandler->characters( aBuffer.makeStringAndClear() );
+ xHandler->endElement( sPgpKeyIDElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ // key packet is optional
+ if (aPgpKeyPacket.hasElements())
+ {
+ xHandler->startElement( sPGPKeyPacketElement, nullptr );
+ ::sax::Converter::encodeBase64(aBuffer, aPgpKeyPacket);
+ xHandler->characters( aBuffer.makeStringAndClear() );
+ xHandler->endElement( sPGPKeyPacketElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ }
+
+ xHandler->endElement( sPgpDataElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->endElement( sKeyInfoElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->startElement( sCipherDataElement, nullptr );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->startElement( sCipherValueElement, nullptr );
+ ::sax::Converter::encodeBase64(aBuffer, aCipherValue);
+ xHandler->characters( aBuffer.makeStringAndClear() );
+ xHandler->endElement( sCipherValueElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->endElement( sCipherDataElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+
+ xHandler->endElement( sEncryptedKeyElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ }
+ }
+
+ xHandler->endElement( sManifestKeyInfoElement );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ }
+ }
+
+ // now write individual file entries
for (sal_uInt32 i = 0 ; i < nManLength ; i++)
{
::comphelper::AttributeList *pAttrList = new ::comphelper::AttributeList;
@@ -314,22 +447,36 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
pNewAttrList = new ::comphelper::AttributeList;
xNewAttrList = pNewAttrList;
- pNewAttrList->AddAttribute ( sKeyDerivationNameAttribute, sCdataAttribute, sPBKDF2_Name );
-
- if ( bStoreStartKeyGeneration )
+ if ( pKeyInfoProperty )
{
- aBuffer.append( nDerivedKeySize );
- pNewAttrList->AddAttribute ( sKeySizeAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
+ pNewAttrList->AddAttribute ( sKeyDerivationNameAttribute,
+ sCdataAttribute,
+ sPGP_Name );
+ // no start-key-generation needed, our session key has
+ // max size already
+ bStoreStartKeyGeneration = false;
}
+ else
+ {
+ pNewAttrList->AddAttribute ( sKeyDerivationNameAttribute,
+ sCdataAttribute,
+ sPBKDF2_Name );
+
+ if ( bStoreStartKeyGeneration )
+ {
+ aBuffer.append( nDerivedKeySize );
+ pNewAttrList->AddAttribute ( sKeySizeAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
+ }
- sal_Int32 nCount = 0;
- *pIterationCount >>= nCount;
- aBuffer.append (nCount);
- pNewAttrList->AddAttribute ( sIterationCountAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
+ sal_Int32 nCount = 0;
+ *pIterationCount >>= nCount;
+ aBuffer.append (nCount);
+ pNewAttrList->AddAttribute ( sIterationCountAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
- *pSalt >>= aSequence;
- ::sax::Converter::encodeBase64(aBuffer, aSequence);
- pNewAttrList->AddAttribute ( sSaltAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
+ *pSalt >>= aSequence;
+ ::sax::Converter::encodeBase64(aBuffer, aSequence);
+ pNewAttrList->AddAttribute ( sSaltAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
+ }
xHandler->ignorableWhitespace ( sWhiteSpace );
xHandler->startElement( sKeyDerivationElement , xNewAttrList);
More information about the Libreoffice-commits
mailing list