diff options
Diffstat (limited to 'xmlsecurity')
17 files changed, 1358 insertions, 609 deletions
diff --git a/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx b/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx index 9e1f8d1667c2..a6e4afac417f 100644 --- a/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx +++ b/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx @@ -36,10 +36,12 @@ #include <vcl/button.hxx> #include <svtools/stdctrl.hxx> #include <svx/simptabl.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> #include <xmlsecurity/documentsignaturehelper.hxx> #include <xmlsecurity/xmlsignaturehelper.hxx> + #ifndef _STLP_VECTOR #include <vector> #endif @@ -53,6 +55,8 @@ namespace io { class XStream; } namespace embed { class XStorage; } +namespace xml { namespace dom { + class XDocumentBuilder; } } }}} namespace css = com::sun::star; @@ -68,10 +72,12 @@ private: css::uno::Reference < css::embed::XStorage > mxStore; css::uno::Reference < css::io::XStream > mxSignatureStream; + css::uno::Reference < css::io::XStream > mxTempSignatureStream; SignatureInformations maCurrentSignatureInformations; bool mbVerifySignatures; bool mbSignaturesChanged; DocumentSignatureMode meSignatureMode; + css::uno::Sequence < css::uno::Sequence < css::beans::PropertyValue > > m_manifest; FixedText maHintDocFT; FixedText maHintBasicFT; @@ -83,6 +89,7 @@ private: FixedInfo maSigsInvalidFI; FixedImage maSigsNotvalidatedImg; FixedInfo maSigsNotvalidatedFI; + FixedInfo maSigsOldSignatureFI; PushButton maViewBtn; PushButton maAddBtn; @@ -93,17 +100,24 @@ private: CancelButton maCancelBtn; HelpButton maHelpBtn; + ::rtl::OUString m_sODFVersion; + //Signals if the document contains already a document signature. This is only + //importent when we are signing macros and if the value is true. + bool m_bHasDocumentSignature; + bool m_bWarningShowSignMacro; + DECL_LINK( ViewButtonHdl, Button* ); DECL_LINK( AddButtonHdl, Button* ); DECL_LINK( RemoveButtonHdl, Button* ); DECL_LINK( SignatureHighlightHdl, void* ); DECL_LINK( SignatureSelectHdl, void* ); DECL_LINK( StartVerifySignatureHdl, void* ); + DECL_LINK( OKButtonHdl, void* ); - void ImplGetSignatureInformations(); + void ImplGetSignatureInformations(bool bUseTempStream); void ImplFillSignaturesBox(); void ImplShowSignaturesDetails(); - SignatureStreamHelper ImplOpenSignatureStream( sal_Int32 eStreamMode ); + SignatureStreamHelper ImplOpenSignatureStream( sal_Int32 eStreamMode, bool bTempStream ); //Checks if adding is allowed. //See the spec at specs/www/appwide/security/Electronic_Signatures_and_Security.sxw @@ -111,10 +125,15 @@ private: bool canAdd(); bool canRemove(); + //Checks if a particular stream is a valid xml stream. Those are treated differently + //when they are signed (c14n transformation) + bool isXML(const ::rtl::OUString& rURI ); + bool canAddRemove(); + public: DigitalSignaturesDialog( Window* pParent, cssu::Reference< cssu::XComponentContext >& rxCtx, DocumentSignatureMode eMode, - sal_Bool bReadOnly ); + sal_Bool bReadOnly, const ::rtl::OUString& sODFVersion, bool bHasDocumentSignature); ~DigitalSignaturesDialog(); // Initialize the dialog and the security environment, returns TRUE on success diff --git a/xmlsecurity/inc/xmlsecurity/documentsignaturehelper.hxx b/xmlsecurity/inc/xmlsecurity/documentsignaturehelper.hxx index 615776b023b7..6fb4ac80badd 100644 --- a/xmlsecurity/inc/xmlsecurity/documentsignaturehelper.hxx +++ b/xmlsecurity/inc/xmlsecurity/documentsignaturehelper.hxx @@ -33,7 +33,7 @@ #include <com/sun/star/uno/Reference.h> #include <rtl/ustring.hxx> - +#include "xmlsecurity/sigstruct.hxx" #ifndef _STLP_VECTOR #include <vector> @@ -64,6 +64,13 @@ namespace css = com::sun::star; enum DocumentSignatureMode { SignatureModeDocumentContent, SignatureModeMacros, SignatureModePackage }; +enum DocumentSignatureAlgorithm +{ + OOo2Document, + OOo3_0Document, + OOo3_2Document +}; + struct SignatureStreamHelper { css::uno::Reference < css::embed::XStorage > xSignatureStorage; @@ -75,14 +82,24 @@ class DocumentSignatureHelper { public: - static SignatureStreamHelper OpenSignatureStream( const css::uno::Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode ); - static std::vector< rtl::OUString > CreateElementList( const css::uno::Reference < css::embed::XStorage >& rxStore, const ::rtl::OUString rRootStorageName, DocumentSignatureMode eMode ); - + static SignatureStreamHelper OpenSignatureStream( + const css::uno::Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, + DocumentSignatureMode eDocSigMode ); + static std::vector< rtl::OUString > CreateElementList( + const css::uno::Reference < css::embed::XStorage >& rxStore, + const ::rtl::OUString rRootStorageName, DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode); + static bool isODFPre_1_2(const ::rtl::OUString & sODFVersion); + static bool isOOo3_2_Signature(const SignatureInformation & sigInfo); + static DocumentSignatureAlgorithm getDocumentAlgorithm( + const ::rtl::OUString & sODFVersion, const SignatureInformation & sigInfo); + static bool checkIfAllFilesAreSigned( const ::std::vector< ::rtl::OUString > & sElementList, + const SignatureInformation & sigInfo, const DocumentSignatureAlgorithm alg); + static bool equalsReferenceUriManifestPath( + const ::rtl::OUString & rUri, const ::rtl::OUString & rPath); static ::rtl::OUString GetDocumentContentSignatureDefaultStreamName(); static ::rtl::OUString GetScriptingContentSignatureDefaultStreamName(); static ::rtl::OUString GetPackageSignatureDefaultStreamName(); - static bool isODFPre_1_2(const ::com::sun::star::uno::Reference < - ::com::sun::star::embed::XStorage >& /*rxStore*/); }; diff --git a/xmlsecurity/inc/xmlsecurity/global.hrc b/xmlsecurity/inc/xmlsecurity/global.hrc index 35e2f3910cef..ef59a9dafa01 100644 --- a/xmlsecurity/inc/xmlsecurity/global.hrc +++ b/xmlsecurity/inc/xmlsecurity/global.hrc @@ -47,8 +47,6 @@ #define RID_XMLSECTP_LOCK 1011 #define RID_XMLSECTP_LOCK_HC 1012 #define RID_XMLSECWB_NO_MOZILLA_PROFILE 1013 -#define RID_XMLSECDLG_OLD_ODF_FORMAT 1014 - #endif diff --git a/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx index 0b98ae55306f..53455b652fa5 100644 --- a/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx +++ b/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx @@ -145,9 +145,10 @@ public: void SetUriBinding( com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding >& rxUriBinding ); com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding > GetUriBinding() const; - // Set the storage which should be used by the default UriBinding - // Must be set before StatrtMission(). - void SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStorage ); + // Set the storage which should be used by the default UriBinding + // Must be set before StatrtMission(). + //sODFVersion indicates the ODF version + void SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStorage, ::rtl::OUString sODFVersion ); // Argument for the Link is a uno::Reference< xml::sax::XAttributeList >* // Return 1 to verify, 0 to skip. diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index c65aed21dd3f..dde41a4ac636 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -54,11 +54,14 @@ #include <tools/urlobj.hxx> #include <vcl/msgbox.hxx> #include <svtools/securityoptions.hxx> -#include <com/sun/star/security/CertificateValidity.hdl> +#include <com/sun/star/security/CertificateValidity.hpp> #include <com/sun/star/security/SerialNumberAdapter.hpp> #include <ucbhelper/contentbroker.hxx> #include <unotools/ucbhelper.hxx> #include <comphelper/componentcontext.hxx> +#include "comphelper/documentconstants.hxx" + +#include "com/sun/star/lang/IllegalArgumentException.hpp" #include <stdio.h> @@ -67,74 +70,145 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; namespace css = ::com::sun::star; -DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ) +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ): + mxCtx(rxCtx), + m_sODFVersion(ODFVER_012_TEXT), + m_nArgumentsCount(0), + m_bHasDocumentSignature(false) +{ +} + +void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments) + throw (css::uno::Exception, css::uno::RuntimeException) { - mxCtx = rxCtx; + if (aArguments.getLength() == 0 || aArguments.getLength() > 2) + throw css::lang::IllegalArgumentException( + OUSTR("DocumentDigitalSignatures::initialize requires one or two arguments"), + Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0); + + m_nArgumentsCount = aArguments.getLength(); + + if (!(aArguments[0] >>= m_sODFVersion)) + throw css::lang::IllegalArgumentException( + OUSTR("DocumentDigitalSignatures::initialize: the first arguments must be a string"), + Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0); + + if (aArguments.getLength() == 2 + && !(aArguments[1] >>= m_bHasDocumentSignature)) + throw css::lang::IllegalArgumentException( + OUSTR("DocumentDigitalSignatures::initialize: the second arguments must be a bool"), + Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 1); + + //the Version is supported as of ODF1.2, so for and 1.1 document or older we will receive the + //an empty string. In this case we set it to ODFVER_010_TEXT. Then we can later check easily + //if initialize was called. Only then m_sODFVersion.getLength() is greater than 0 + if (m_sODFVersion.getLength() == 0) + m_sODFVersion = ODFVER_010_TEXT; } -sal_Bool DocumentDigitalSignatures::signDocumentContent( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& xSignStream ) throw (RuntimeException) +sal_Bool DocumentDigitalSignatures::signDocumentContent( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XStream >& xSignStream) + throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(), "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); return ImplViewSignatures( rxStorage, xSignStream, SignatureModeDocumentContent, false ); } -Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDigitalSignatures::verifyDocumentContentSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (RuntimeException) +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::verifyDocumentContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeDocumentContent ); } -void DocumentDigitalSignatures::showDocumentContentSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (RuntimeException) +void DocumentDigitalSignatures::showDocumentContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); ImplViewSignatures( rxStorage, xSignInStream, SignatureModeDocumentContent, true ); } -::rtl::OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName() throw (::com::sun::star::uno::RuntimeException) +::rtl::OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName() + throw (css::uno::RuntimeException) { return DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); } -sal_Bool DocumentDigitalSignatures::signScriptingContent( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& xSignStream ) throw (RuntimeException) +sal_Bool DocumentDigitalSignatures::signScriptingContent( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + OSL_ENSURE(m_nArgumentsCount == 2, "DocumentDigitalSignatures: Service was not initialized properly"); return ImplViewSignatures( rxStorage, xSignStream, SignatureModeMacros, false ); } -Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDigitalSignatures::verifyScriptingContentSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (RuntimeException) +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::verifyScriptingContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeMacros ); } -void DocumentDigitalSignatures::showScriptingContentSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (RuntimeException) +void DocumentDigitalSignatures::showScriptingContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); ImplViewSignatures( rxStorage, xSignInStream, SignatureModeMacros, true ); } -::rtl::OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName() throw (::com::sun::star::uno::RuntimeException) +::rtl::OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName() + throw (css::uno::RuntimeException) { return DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); } -sal_Bool DocumentDigitalSignatures::signPackage( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& xSignStream ) throw (RuntimeException) +sal_Bool DocumentDigitalSignatures::signPackage( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); return ImplViewSignatures( rxStorage, xSignStream, SignatureModePackage, false ); } -Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDigitalSignatures::verifyPackageSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (RuntimeException) +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::verifyPackageSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModePackage ); } -void DocumentDigitalSignatures::showPackageSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (RuntimeException) +void DocumentDigitalSignatures::showPackageSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException) { + OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); ImplViewSignatures( rxStorage, xSignInStream, SignatureModePackage, true ); } -::rtl::OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName( ) throw (::com::sun::star::uno::RuntimeException) +::rtl::OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName( ) + throw (::com::sun::star::uno::RuntimeException) { return DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); } -sal_Bool DocumentDigitalSignatures::ImplViewSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignStream, DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException) +sal_Bool DocumentDigitalSignatures::ImplViewSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException) { Reference< io::XStream > xStream; if ( xSignStream.is() ) @@ -142,10 +216,13 @@ sal_Bool DocumentDigitalSignatures::ImplViewSignatures( const Reference< ::com:: return ImplViewSignatures( rxStorage, xStream, eMode, bReadOnly ); } -sal_Bool DocumentDigitalSignatures::ImplViewSignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& xSignStream, DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException) +sal_Bool DocumentDigitalSignatures::ImplViewSignatures( + const Reference< css::embed::XStorage >& rxStorage, const Reference< css::io::XStream >& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException) { sal_Bool bChanges = sal_False; - DigitalSignaturesDialog aSignaturesDialog( NULL, mxCtx, eMode, bReadOnly ); + DigitalSignaturesDialog aSignaturesDialog( + NULL, mxCtx, eMode, bReadOnly, m_sODFVersion, m_bHasDocumentSignature); bool bInit = aSignaturesDialog.Init( rtl::OUString() ); DBG_ASSERT( bInit, "Error initializing security context!" ); if ( bInit ) @@ -175,7 +252,10 @@ sal_Bool DocumentDigitalSignatures::ImplViewSignatures( const Reference< ::com:: return bChanges; } -Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDigitalSignatures::ImplVerifySignatures( const Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignStream, DocumentSignatureMode eMode ) throw (RuntimeException) +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::ImplVerifySignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode ) throw (RuntimeException) { if (!rxStorage.is()) { @@ -206,7 +286,7 @@ Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDig if ( !bInit ) return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0); - aSignatureHelper.SetStorage( rxStorage ); + aSignatureHelper.SetStorage(rxStorage, m_sODFVersion); aSignatureHelper.StartMission(); @@ -223,12 +303,17 @@ Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDig if ( nInfos ) { - std::vector< rtl::OUString > aElementsToBeVerified = DocumentSignatureHelper::CreateElementList( rxStorage, ::rtl::OUString(), eMode ); - Reference<security::XSerialNumberAdapter> xSerialNumberAdapter = + Reference<security::XSerialNumberAdapter> xSerialNumberAdapter = ::com::sun::star::security::SerialNumberAdapter::create(mxCtx); for( int n = 0; n < nInfos; ++n ) { + DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm( + m_sODFVersion, aSignInfos[n]); + const std::vector< rtl::OUString > aElementsToBeVerified = + DocumentSignatureHelper::CreateElementList( + rxStorage, ::rtl::OUString(), eMode, mode); + const SignatureInformation& rInfo = aSignInfos[n]; css::security::DocumentSignatureInformation& rSigInfo = arInfos[n]; @@ -273,17 +358,13 @@ Sequence< ::com::sun::star::security::DocumentSignatureInformation > DocumentDig if ( rSigInfo.SignatureIsValid ) { - // Can only be valid if ALL streams are signed, which means real stream count == signed stream count - unsigned int nRealCount = 0; - for ( int i = rInfo.vSignatureReferenceInfors.size(); i; ) - { - const SignatureReferenceInformation& rInf = rInfo.vSignatureReferenceInfors[--i]; - // There is also an extra entry of type TYPE_SAMEDOCUMENT_REFERENCE because of signature date. - if ( ( rInf.nType == TYPE_BINARYSTREAM_REFERENCE ) || ( rInf.nType == TYPE_XMLSTREAM_REFERENCE ) ) - nRealCount++; - } - rSigInfo.SignatureIsValid = ( aElementsToBeVerified.size() == nRealCount ); + rSigInfo.SignatureIsValid = + DocumentSignatureHelper::checkIfAllFilesAreSigned( + aElementsToBeVerified, rInfo, mode); } + if (eMode == SignatureModeDocumentContent) + rSigInfo.PartialDocumentSignature = + ! DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]); } } @@ -298,7 +379,7 @@ void DocumentDigitalSignatures::manageTrustedSources( ) throw (RuntimeException // Macro Security also has some options where no security environment is needed, so raise dialog anyway. // Later I should change the code so the Dialog creates the SecEnv on demand... - cssu::Reference< dcss::xml::crypto::XSecurityEnvironment > xSecEnv; + Reference< dcss::xml::crypto::XSecurityEnvironment > xSecEnv; XMLSignatureHelper aSignatureHelper( mxCtx ); if ( aSignatureHelper.Init( rtl::OUString() ) ) @@ -308,7 +389,8 @@ void DocumentDigitalSignatures::manageTrustedSources( ) throw (RuntimeException aDlg.Execute(); } -void DocumentDigitalSignatures::showCertificate( const Reference< ::com::sun::star::security::XCertificate >& _Certificate ) throw (RuntimeException) +void DocumentDigitalSignatures::showCertificate( + const Reference< css::security::XCertificate >& _Certificate ) throw (RuntimeException) { XMLSignatureHelper aSignatureHelper( mxCtx ); @@ -324,7 +406,8 @@ void DocumentDigitalSignatures::showCertificate( const Reference< ::com::sun::st } -::sal_Bool DocumentDigitalSignatures::isAuthorTrusted( const Reference< ::com::sun::star::security::XCertificate >& Author ) throw (RuntimeException) +::sal_Bool DocumentDigitalSignatures::isAuthorTrusted( + const Reference< css::security::XCertificate >& Author ) throw (RuntimeException) { sal_Bool bFound = sal_False; @@ -377,7 +460,8 @@ void DocumentDigitalSignatures::showCertificate( const Reference< ::com::sun::st return bFound; } -void DocumentDigitalSignatures::addAuthorToTrustedSources( const Reference< ::com::sun::star::security::XCertificate >& Author ) throw (RuntimeException) +void DocumentDigitalSignatures::addAuthorToTrustedSources( + const Reference< css::security::XCertificate >& Author ) throw (RuntimeException) { SvtSecurityOptions aSecOpts; diff --git a/xmlsecurity/source/component/documentdigitalsignatures.hxx b/xmlsecurity/source/component/documentdigitalsignatures.hxx index fb0328bc2347..35d22c62ca6a 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.hxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.hxx @@ -31,21 +31,35 @@ #ifndef _XMLSECURITY_DOCUMENTDIGITALSIGNATURES_HXX #define _XMLSECURITY_DOCUMENTDIGITALSIGNATURES_HXX -#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include "com/sun/star/lang/XInitialization.hpp" #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/io/XInputStream.hpp> #include <xmlsecurity/documentsignaturehelper.hxx> +namespace com { namespace sun { namespace star { -class DocumentDigitalSignatures : public cppu::WeakImplHelper1 + namespace uno { + class XComponentContext; + } +}}} + +class DocumentDigitalSignatures : public cppu::WeakImplHelper2 < - com::sun::star::security::XDocumentDigitalSignatures + com::sun::star::security::XDocumentDigitalSignatures, + com::sun::star::lang::XInitialization > { private: com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > mxCtx; + // will be set by XInitialization. If not we assume true. false means an earlier version. + ::rtl::OUString m_sODFVersion; + //The number of arguments which were passed in XInitialization::initialize + int m_nArgumentsCount; + //Indicates if the document already contains a document signature + bool m_bHasDocumentSignature; sal_Bool ImplViewSignatures( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& xSignStream, DocumentSignatureMode eMode, bool bReadOnly ) throw (::com::sun::star::uno::RuntimeException); sal_Bool ImplViewSignatures( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& rxStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignStream, DocumentSignatureMode eMode, bool bReadOnly ) throw (::com::sun::star::uno::RuntimeException); @@ -58,6 +72,10 @@ public: static ::rtl::OUString GetImplementationName() throw (com::sun::star::uno::RuntimeException); static ::com::sun::star::uno::Sequence < ::rtl::OUString > GetSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); + //XInitialization + void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + // XDocumentDigitalSignatures ::sal_Bool SAL_CALL signDocumentContent( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& xSignStream ) throw (::com::sun::star::uno::RuntimeException); ::com::sun::star::uno::Sequence< ::com::sun::star::security::DocumentSignatureInformation > SAL_CALL verifyDocumentContentSignatures( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xSignInStream ) throw (::com::sun::star::uno::RuntimeException); diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx index fb9b41d5f637..7f04872f7a63 100644 --- a/xmlsecurity/source/dialogs/certificateviewer.cxx +++ b/xmlsecurity/source/dialogs/certificateviewer.cxx @@ -311,8 +311,10 @@ CertificateViewerDetailsTP::CertificateViewerDetailsTP( Window* _pParent, Certif aDetails = XmlSec::GetHexString( aSeq, pHexSep, nLineBreak ); InsertElement( String( XMLSEC_RES( STR_SERIALNUM ) ), aLBEntry, aDetails, true ); - aLBEntry = XmlSec::GetPureContent( xCert->getIssuerName(), ", " ); - aDetails = XmlSec::GetPureContent( xCert->getIssuerName(), "\n", true ); + std::pair< ::rtl::OUString, ::rtl::OUString> pairIssuer = + XmlSec::GetDNForCertDetailsView(xCert->getIssuerName()); + aLBEntry = pairIssuer.first; + aDetails = pairIssuer.second; InsertElement( String( XMLSEC_RES( STR_ISSUER ) ), aLBEntry, aDetails ); /* aSeq = xCert->getIssuerUniqueID(); @@ -333,8 +335,10 @@ CertificateViewerDetailsTP::CertificateViewerDetailsTP( Window* _pParent, Certif aLBEntry += GetSettings().GetUILocaleDataWrapper().getTime( aDateTime.GetTime() ); InsertElement( String( XMLSEC_RES( STR_VALIDTO ) ), aLBEntry, aLBEntry ); - aLBEntry = XmlSec::GetPureContent( xCert->getSubjectName(), ", " ); - aDetails = XmlSec::GetPureContent( xCert->getSubjectName(), "\n", true ); + std::pair< ::rtl::OUString, ::rtl::OUString > pairSubject = + XmlSec::GetDNForCertDetailsView(xCert->getSubjectName()); + aLBEntry = pairSubject.first; + aDetails = pairSubject.second; InsertElement( String( XMLSEC_RES( STR_SUBJECT ) ), aLBEntry, aDetails ); /* aSeq = xCert->getSubjectUniqueID(); diff --git a/xmlsecurity/source/dialogs/dialogs.hrc b/xmlsecurity/source/dialogs/dialogs.hrc index ca329fabf71d..f62a2a422eaf 100644 --- a/xmlsecurity/source/dialogs/dialogs.hrc +++ b/xmlsecurity/source/dialogs/dialogs.hrc @@ -88,6 +88,7 @@ #define IMG_STATE_VALID_HC 13 #define IMG_STATE_BROKEN_HC 14 #define IMG_STATE_NOTVALIDATED_HC 15 +#define FI_STATE_OLDSIGNATURE 16 //#define DS_WIDTH DLGS_WIDTH //#define DS_HEIGHT DLGS_HEIGHT diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index 109959be1554..cf07edb7023e 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -48,13 +48,19 @@ #include <com/sun/star/security/CertificateValidity.hdl> #include <com/sun/star/packages/WrongPasswordException.hpp> #include <com/sun/star/security/SerialNumberAdapter.hpp> +#include <com/sun/star/security/XDocumentDigitalSignatures.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/packages/manifest/XManifestReader.hpp> + #include <rtl/ustrbuf.hxx> +#include <rtl/uri.hxx> #include <tools/date.hxx> #include <tools/time.hxx> #include "dialogs.hrc" +#include "digitalsignaturesdialog.hrc" #include "helpids.hrc" #include "resourcemanager.hxx" @@ -62,18 +68,20 @@ #include <unotools/configitem.hxx> #include <comphelper/componentcontext.hxx> +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) -using namespace ::com::sun::star::security; -namespace css = ::com::sun::star; /* HACK: disable some warnings for MS-C */ #ifdef _MSC_VER #pragma warning (disable : 4355) // 4355: this used in initializer-list #endif +using namespace ::com::sun::star::security; +using namespace ::com::sun::star::uno; using namespace ::com::sun::star; -using ::com::sun::star::uno::Sequence; +namespace css = ::com::sun::star; using ::rtl::OUString; + namespace { class SaveODFItem: public utl::ConfigItem @@ -109,49 +117,70 @@ namespace OUString(RTL_CONSTASCII_USTRINGPARAM( "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion")), 0); } - } -sal_Bool HandleStreamAsXML_Impl( const uno::Reference < embed::XStorage >& rxStore, const rtl::OUString& rURI ) +/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted" + We use the manifest to find out if a file is xml and if it is encrypted. + The parameter is an encoded uri. However, the manifest contains paths. Therefore + the path is encoded as uri, so they can be compared. +*/ +bool DigitalSignaturesDialog::isXML(const rtl::OUString& rURI ) { - sal_Bool bResult = sal_False; + OSL_ASSERT(mxStore.is()); - try + bool bIsXML = false; + bool bPropsAvailable = false; + const OUString sPropFullPath(RTL_CONSTASCII_USTRINGPARAM("FullPath")); + const OUString sPropMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType")); + const OUString sPropDigest(RTL_CONSTASCII_USTRINGPARAM("Digest")); + + for (int i = 0; i < m_manifest.getLength(); i++) { - sal_Int32 nSepPos = rURI.indexOf( '/' ); - if ( nSepPos == -1 ) + Any digest; + const Sequence< css::beans::PropertyValue >& entry = m_manifest[i]; + OUString sPath, sMediaType; + bool bEncrypted = false; + for (int j = 0; j < entry.getLength(); j++) { - uno::Reference< io::XStream > xStream; - xStream = rxStore->cloneStreamElement( rURI ); - if ( !xStream.is() ) - throw uno::RuntimeException(); - - ::rtl::OUString aMediaType; - sal_Bool bEncrypted = sal_False; - uno::Reference< beans::XPropertySet > xProps( xStream, uno::UNO_QUERY_THROW ); - xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) ) >>= aMediaType; - xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsEncrypted" ) ) ) >>= bEncrypted; - bResult = ( aMediaType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "text/xml" ) ) ) && !bEncrypted ); + const css::beans::PropertyValue & prop = entry[j]; + + if (prop.Name.equals( sPropFullPath ) ) + prop.Value >>= sPath; + else if (prop.Name.equals( sPropMediaType ) ) + prop.Value >>= sMediaType; + else if (prop.Name.equals( sPropDigest ) ) + bEncrypted = true; } - else + if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath)) { - rtl::OUString aStoreName = rURI.copy( 0, nSepPos ); - rtl::OUString aElement = rURI.copy( nSepPos+1 ); - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ ); - bResult = HandleStreamAsXML_Impl( xSubStore, aElement ); + bIsXML = sMediaType.equals(OUSTR("text/xml")) && ! bEncrypted; + bPropsAvailable = true; + break; } } - catch( uno::Exception& ) + if (!bPropsAvailable) { - } - - return bResult; + //This would be the case for at least mimetype, META-INF/manifest.xml + //META-INF/macrosignatures.xml. + //Files can only be encrypted if they are in the manifest.xml. + //That is, the current file cannot be encrypted, otherwise bPropsAvailable + //would be true. + OUString aXMLExt( RTL_CONSTASCII_USTRINGPARAM( "XML" ) ); + sal_Int32 nSep = rURI.lastIndexOf( '.' ); + if ( nSep != (-1) ) + { + OUString aExt = rURI.copy( nSep+1 ); + if (aExt.equalsIgnoreAsciiCase(aXMLExt )) + bIsXML = true; + } + } + return bIsXML; } DigitalSignaturesDialog::DigitalSignaturesDialog( Window* pParent, uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, - sal_Bool bReadOnly) + sal_Bool bReadOnly, const ::rtl::OUString& sODFVersion, bool bHasDocumentSignature) :ModalDialog ( pParent, XMLSEC_RES( RID_XMLSECDLG_DIGSIG ) ) ,mxCtx ( rxCtx ) ,maSignatureHelper ( rxCtx ) @@ -166,6 +195,7 @@ DigitalSignaturesDialog::DigitalSignaturesDialog( ,maSigsInvalidFI ( this, XMLSEC_RES( FI_STATE_BROKEN ) ) ,maSigsNotvalidatedImg( this, XMLSEC_RES( IMG_STATE_NOTVALIDATED ) ) ,maSigsNotvalidatedFI ( this, XMLSEC_RES( FI_STATE_NOTVALIDATED ) ) + ,maSigsOldSignatureFI ( this, XMLSEC_RES( FI_STATE_OLDSIGNATURE) ) ,maViewBtn ( this, XMLSEC_RES( BTN_VIEWCERT ) ) ,maAddBtn ( this, XMLSEC_RES( BTN_ADDCERT ) ) ,maRemoveBtn ( this, XMLSEC_RES( BTN_REMOVECERT ) ) @@ -173,6 +203,9 @@ DigitalSignaturesDialog::DigitalSignaturesDialog( ,maOKBtn ( this, XMLSEC_RES( BTN_OK ) ) ,maCancelBtn ( this, XMLSEC_RES( BTN_CANCEL ) ) ,maHelpBtn ( this, XMLSEC_RES( BTN_HELP ) ) + ,m_sODFVersion (sODFVersion) + ,m_bHasDocumentSignature(bHasDocumentSignature) + ,m_bWarningShowSignMacro(false) { // --> PB #i48253 the tablistbox needs its own unique id maSignaturesLB.Window::SetUniqueId( HID_XMLSEC_TREE_SIGNATURESDLG ); @@ -209,6 +242,8 @@ DigitalSignaturesDialog::DigitalSignaturesDialog( maRemoveBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) ); maRemoveBtn.Disable(); + maOKBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, OKButtonHdl) ); + switch( meSignatureMode ) { case SignatureModeDocumentContent: maHintDocFT.Show(); break; @@ -220,6 +255,7 @@ DigitalSignaturesDialog::DigitalSignaturesDialog( XmlSec::AlignAndFitImageAndControl( maSigsValidImg, maSigsValidFI, 5 ); XmlSec::AlignAndFitImageAndControl( maSigsInvalidImg, maSigsInvalidFI, 5 ); XmlSec::AlignAndFitImageAndControl( maSigsNotvalidatedImg, maSigsNotvalidatedFI, 5 ); + XmlSec::AlignAndFitImageAndControl( maSigsNotvalidatedImg, maSigsOldSignatureFI, 5 ); } DigitalSignaturesDialog::~DigitalSignaturesDialog() @@ -243,7 +279,21 @@ BOOL DigitalSignaturesDialog::Init( const rtl::OUString& rTokenName ) void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore ) { mxStore = rxStore; - maSignatureHelper.SetStorage( mxStore ); + maSignatureHelper.SetStorage( mxStore, m_sODFVersion); + + Reference < css::packages::manifest::XManifestReader > xReader( + mxCtx->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.packages.manifest.ManifestReader"), mxCtx), UNO_QUERY_THROW); + + //Get the manifest.xml + Reference < css::embed::XStorage > xSubStore(rxStore->openStorageElement( + OUSTR("META-INF"), css::embed::ElementModes::READ), UNO_QUERY_THROW); + + Reference< css::io::XInputStream > xStream( + xSubStore->openStreamElement(OUSTR("manifest.xml"), css::embed::ElementModes::READ), + UNO_QUERY_THROW); + + m_manifest = xReader->readManifestSequence(xStream); } void DigitalSignaturesDialog::SetSignatureStream( const cssu::Reference < css::io::XStream >& rxStream ) @@ -251,40 +301,70 @@ void DigitalSignaturesDialog::SetSignatureStream( const cssu::Reference < css::i mxSignatureStream = rxStream; } - -bool DigitalSignaturesDialog::canAdd() +bool DigitalSignaturesDialog::canAddRemove() { - bool ret = false; + //m56 + bool ret = true; OSL_ASSERT(mxStore.is()); - bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(mxStore); + bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); SaveODFItem item; bool bSave1_1 = item.isLessODF1_2(); // see specification //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw //Paragraph 'Behavior with regard to ODF 1.2' + //For both, macro and document if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) ) { //#4 ErrorBox err(NULL, XMLSEC_RES(RID_XMLSECDLG_OLD_ODF_FORMAT)); err.Execute(); + ret = false; } - else - ret = true; + //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is + //adding a macro signature will break an existing document signature. + //The sfx2 will remove the documentsignature when the user adds a macro signature + if (meSignatureMode == SignatureModeMacros + && ret) + { + if (m_bHasDocumentSignature && !m_bWarningShowSignMacro) + { + //The warning says that the document signatures will be removed if the user + //continues. He can then either press 'OK' or 'NO' + //It the user presses 'Add' or 'Remove' several times then, then the warning + //is shown every time until the user presses 'OK'. From then on, the warning + //is not displayed anymore as long as the signatures dialog is alive. + if (QueryBox( + NULL, XMLSEC_RES(MSG_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)).Execute() == RET_NO) + ret = false; + else + m_bWarningShowSignMacro = true; + + } + } return ret; } +bool DigitalSignaturesDialog::canAdd() +{ + if (canAddRemove()) + return true; + return false; +} + bool DigitalSignaturesDialog::canRemove() { - return canAdd(); + if (canAddRemove()) + return true; + return false; } short DigitalSignaturesDialog::Execute() { // Verify Signatures and add certificates to ListBox... mbVerifySignatures = true; - ImplGetSignatureInformations(); + ImplGetSignatureInformations(false); ImplFillSignaturesBox(); // Only verify once, content will not change. @@ -304,6 +384,35 @@ IMPL_LINK( DigitalSignaturesDialog, SignatureHighlightHdl, void*, EMPTYARG ) return 0; } +IMPL_LINK( DigitalSignaturesDialog, OKButtonHdl, void*, EMPTYARG ) +{ + // Export all other signatures... + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( + embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE, false ); + uno::Reference< io::XOutputStream > xOutputStream( + aStreamHelper.xSignatureStream, uno::UNO_QUERY ); + uno::Reference< com::sun::star::xml::sax::XDocumentHandler> xDocumentHandler = + maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream ); + + int nInfos = maCurrentSignatureInformations.size(); + for( int n = 0 ; n < nInfos ; ++n ) + maSignatureHelper.ExportSignature( + xDocumentHandler, maCurrentSignatureInformations[ n ] ); + + maSignatureHelper.CloseDocumentHandler( xDocumentHandler); + + // If stream was not provided, we are responsible for committing it.... + if ( !mxSignatureStream.is() ) + { + uno::Reference< embed::XTransactedObject > xTrans( + aStreamHelper.xSignatureStorage, uno::UNO_QUERY ); + xTrans->commit(); + } + + EndDialog(RET_OK); + return 0; +} + IMPL_LINK( DigitalSignaturesDialog, SignatureSelectHdl, void*, EMPTYARG ) { ImplShowSignaturesDetails(); @@ -353,34 +462,33 @@ IMPL_LINK( DigitalSignaturesDialog, AddButtonHdl, Button*, EMPTYARG ) xCert->getIssuerName(), aCertSerial, aStrBuffer.makeStringAndClear()); + std::vector< rtl::OUString > aElements = + DocumentSignatureHelper::CreateElementList( + mxStore, rtl::OUString(), meSignatureMode, OOo3_2Document); - std::vector< rtl::OUString > aElements = DocumentSignatureHelper::CreateElementList( mxStore, rtl::OUString(), meSignatureMode ); - - ::rtl::OUString aXMLExt( RTL_CONSTASCII_USTRINGPARAM( "XML" ) ); sal_Int32 nElements = aElements.size(); for ( sal_Int32 n = 0; n < nElements; n++ ) { - bool bBinaryMode = true; - sal_Int32 nSep = aElements[n].lastIndexOf( '.' ); - if ( nSep != (-1) ) - { - ::rtl::OUString aExt = aElements[n].copy( nSep+1 ); - if ( aExt.equalsIgnoreAsciiCase( aXMLExt ) ) - { - bBinaryMode = !HandleStreamAsXML_Impl( mxStore, aElements[n] ); - } - } + bool bBinaryMode = !isXML(aElements[n]); maSignatureHelper.AddForSigning( nSecurityId, aElements[n], aElements[n], bBinaryMode ); } maSignatureHelper.SetDateTime( nSecurityId, Date(), Time() ); - SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE ); - uno::Reference< io::XOutputStream > xOutputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY ); - uno::Reference< com::sun::star::xml::sax::XDocumentHandler> xDocumentHandler = maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream ); + // We open a signature stream in which the existing and the new + //signature is written. ImplGetSignatureInformation (later in this function) will + //then read the stream an will fill maCurrentSignatureInformations. The final signature + //is written when the user presses OK. Then only maCurrentSignatureInformation and + //a sax writer are used to write the information. + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( + css::embed::ElementModes::WRITE|css::embed::ElementModes::TRUNCATE, true); + Reference< css::io::XOutputStream > xOutputStream( + aStreamHelper.xSignatureStream, UNO_QUERY_THROW); + Reference< css::xml::sax::XDocumentHandler> xDocumentHandler = + maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream ); // Export old signatures... - int nInfos = maCurrentSignatureInformations.size(); + int nInfos = maCurrentSignatureInformations.size(); for ( int n = 0; n < nInfos; n++ ) maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[n]); @@ -392,15 +500,10 @@ IMPL_LINK( DigitalSignaturesDialog, AddButtonHdl, Button*, EMPTYARG ) maSignatureHelper.EndMission(); - // If stream was not provided, we are responsible for committing it.... - if ( !mxSignatureStream.is() ) - { - uno::Reference< embed::XTransactedObject > xTrans( aStreamHelper.xSignatureStorage, uno::UNO_QUERY ); - xTrans->commit(); - } - aStreamHelper = SignatureStreamHelper(); // release objects... + mbSignaturesChanged = true; + sal_Int32 nStatus = maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus; if ( nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED ) @@ -412,7 +515,7 @@ IMPL_LINK( DigitalSignaturesDialog, AddButtonHdl, Button*, EMPTYARG ) // will not contain // SecurityOperationStatus_OPERATION_SUCCEEDED mbVerifySignatures = true; - ImplGetSignatureInformations(); + ImplGetSignatureInformations(true); ImplFillSignaturesBox(); } } @@ -421,7 +524,7 @@ IMPL_LINK( DigitalSignaturesDialog, AddButtonHdl, Button*, EMPTYARG ) { DBG_ERROR( "Exception while adding a signature!" ); // Don't keep invalid entries... - ImplGetSignatureInformations(); + ImplGetSignatureInformations(true); ImplFillSignaturesBox(); } @@ -440,9 +543,12 @@ IMPL_LINK( DigitalSignaturesDialog, RemoveButtonHdl, Button*, EMPTYARG ) maCurrentSignatureInformations.erase( maCurrentSignatureInformations.begin()+nSelected ); // Export all other signatures... - SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE ); - uno::Reference< io::XOutputStream > xOutputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY ); - uno::Reference< com::sun::star::xml::sax::XDocumentHandler> xDocumentHandler = maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream ); + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( + css::embed::ElementModes::WRITE | css::embed::ElementModes::TRUNCATE, true); + Reference< css::io::XOutputStream > xOutputStream( + aStreamHelper.xSignatureStream, UNO_QUERY_THROW); + Reference< css::xml::sax::XDocumentHandler> xDocumentHandler = + maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream ); int nInfos = maCurrentSignatureInformations.size(); for( int n = 0 ; n < nInfos ; ++n ) @@ -452,13 +558,6 @@ IMPL_LINK( DigitalSignaturesDialog, RemoveButtonHdl, Button*, EMPTYARG ) mbSignaturesChanged = true; - // If stream was not provided, we are responsible for committing it.... - if ( !mxSignatureStream.is() ) - { - uno::Reference< embed::XTransactedObject > xTrans( aStreamHelper.xSignatureStorage, uno::UNO_QUERY ); - xTrans->commit(); - } - aStreamHelper = SignatureStreamHelper(); // release objects... ImplFillSignaturesBox(); @@ -467,7 +566,7 @@ IMPL_LINK( DigitalSignaturesDialog, RemoveButtonHdl, Button*, EMPTYARG ) { DBG_ERROR( "Exception while removing a signature!" ); // Don't keep invalid entries... - ImplGetSignatureInformations(); + ImplGetSignatureInformations(true); ImplFillSignaturesBox(); } } @@ -493,12 +592,18 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox() String aNullStr; int nInfos = maCurrentSignatureInformations.size(); int nValidSigs = 0, nValidCerts = 0; + bool bAllNewSignatures = true; if( nInfos ) { - std::vector< rtl::OUString > aElementsToBeVerified = DocumentSignatureHelper::CreateElementList( mxStore, ::rtl::OUString(), meSignatureMode ); for( int n = 0; n < nInfos; ++n ) { + DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm( + m_sODFVersion, maCurrentSignatureInformations[n]); + std::vector< rtl::OUString > aElementsToBeVerified = + DocumentSignatureHelper::CreateElementList( + mxStore, ::rtl::OUString(), meSignatureMode, mode); + const SignatureInformation& rInfo = maCurrentSignatureInformations[n]; //First we try to get the certificate which is embedded in the XML Signature if (rInfo.ouX509Certificate.getLength()) @@ -559,28 +664,42 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox() if ( bSigValid ) { - // Can only be valid if ALL streams are signed, which means real stream count == signed stream count - unsigned int nRealCount = 0; - for ( int i = rInfo.vSignatureReferenceInfors.size(); i; ) - { - const SignatureReferenceInformation& rInf = rInfo.vSignatureReferenceInfors[--i]; - // There is also an extra entry of type TYPE_SAMEDOCUMENT_REFERENCE because of signature date. - if ( ( rInf.nType == TYPE_BINARYSTREAM_REFERENCE ) || ( rInf.nType == TYPE_XMLSTREAM_REFERENCE ) ) - nRealCount++; - } - bSigValid = ( aElementsToBeVerified.size() == nRealCount ); + bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned( + aElementsToBeVerified, rInfo, mode); if( bSigValid ) nValidSigs++; } Image aImage; - if ( bSigValid && bCertValid ) - aImage = maSigsValidImg.GetImage(); - else if ( bSigValid && !bCertValid ) - aImage = maSigsNotvalidatedImg.GetImage(); - else if ( !bSigValid ) + if (!bSigValid) + { aImage = maSigsInvalidImg.GetImage(); + } + else if (bSigValid && !bCertValid) + { + aImage = maSigsNotvalidatedImg.GetImage(); + } + //Check if the signature is a "old" document signature, that is, which was created + //by an version of OOo previous to 3.2 + else if (meSignatureMode == SignatureModeDocumentContent + && bSigValid && bCertValid && !DocumentSignatureHelper::isOOo3_2_Signature( + maCurrentSignatureInformations[n])) + { + aImage = maSigsNotvalidatedImg.GetImage(); + bAllNewSignatures &= false; + } + else if (meSignatureMode == SignatureModeDocumentContent + && bSigValid && bCertValid && DocumentSignatureHelper::isOOo3_2_Signature( + maCurrentSignatureInformations[n])) + { + aImage = maSigsValidImg.GetImage(); + } + else if (meSignatureMode == SignatureModeMacros + && bSigValid && bCertValid) + { + aImage = aImage = maSigsValidImg.GetImage(); + } SvLBoxEntry* pEntry = maSignaturesLB.InsertEntry( aNullStr, aImage, aImage ); maSignaturesLB.SetEntryText( aSubject, pEntry, 1 ); @@ -590,28 +709,37 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox() } } - bool bAllSigsValid = ( nValidSigs == nInfos ); - bool bAllCertsValid = ( nValidCerts == nInfos ); - bool bShowValidState = nInfos && ( bAllSigsValid && bAllCertsValid ); - bool bShowNotValidatedState = nInfos && ( bAllSigsValid && !bAllCertsValid ); + bool bAllSigsValid = (nValidSigs == nInfos); + bool bAllCertsValid = (nValidCerts == nInfos); + bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures); + + bool bShowNotValidatedState = nInfos && (bAllSigsValid && (!bAllCertsValid || !bAllNewSignatures)); bool bShowInvalidState = nInfos && !bAllSigsValid; - maSigsValidImg.Show( bShowValidState ); + + maSigsValidImg.Show( bShowValidState); maSigsValidFI.Show( bShowValidState ); maSigsInvalidImg.Show( bShowInvalidState ); maSigsInvalidFI.Show( bShowInvalidState ); - maSigsNotvalidatedImg.Show( bShowNotValidatedState ); - maSigsNotvalidatedFI.Show( bShowNotValidatedState ); + + maSigsNotvalidatedImg.Show(bShowNotValidatedState); + //bAllNewSignatures is always true if we are not in document mode + maSigsNotvalidatedFI.Show(nInfos && bAllSigsValid && ! bAllCertsValid); + maSigsOldSignatureFI.Show(nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures); SignatureHighlightHdl( NULL ); } -void DigitalSignaturesDialog::ImplGetSignatureInformations() + +//If bUseTempStream is true then the temporary signature stream is used. +//Otherwise the real signature stream is used. +void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream) { maCurrentSignatureInformations.clear(); maSignatureHelper.StartMission(); - SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( embed::ElementModes::READ ); + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( + css::embed::ElementModes::READ, bUseTempStream); if ( aStreamHelper.xSignatureStream.is() ) { uno::Reference< io::XInputStream > xInputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY ); @@ -651,30 +779,72 @@ void DigitalSignaturesDialog::ImplShowSignaturesDetails() } } -SignatureStreamHelper DigitalSignaturesDialog::ImplOpenSignatureStream( sal_Int32 nStreamOpenMode ) +//If bTempStream is true, then a temporary stream is return. If it is false then, the actual +//signature stream is used. +//Everytime the user presses Add a new temporary stream is created. +//We keep the temporary stream as member because ImplGetSignatureInformations +//will later access the stream to create DocumentSignatureInformation objects +//which are stored in maCurrentSignatureInformations. +SignatureStreamHelper DigitalSignaturesDialog::ImplOpenSignatureStream( + sal_Int32 nStreamOpenMode, bool bTempStream) { SignatureStreamHelper aHelper; - if ( !mxSignatureStream.is() ) + if (bTempStream) { - aHelper = DocumentSignatureHelper::OpenSignatureStream( mxStore, nStreamOpenMode, meSignatureMode ); + if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE) + { + //We write always into a new temporary stream. + mxTempSignatureStream = Reference < css::io::XStream >( + mxCtx->getServiceManager()->createInstanceWithContext( + OUSTR( "com.sun.star.io.TempFile" ), mxCtx) , + UNO_QUERY_THROW); + aHelper.xSignatureStream = mxTempSignatureStream; + } + else + { + //When we read from the temp stream, then we must have previously + //created one. + OSL_ASSERT(mxTempSignatureStream.is()); + } + aHelper.xSignatureStream = mxTempSignatureStream; } else { - aHelper.xSignatureStream = mxSignatureStream; - if ( nStreamOpenMode & embed::ElementModes::TRUNCATE ) + //No temporary stream + if (!mxSignatureStream.is()) { - css::uno::Reference < css::io::XTruncate > xTruncate( mxSignatureStream, uno::UNO_QUERY ); - DBG_ASSERT( xTruncate.is(), "ImplOpenSignatureStream - Stream does not support xTruncate!" ); - xTruncate->truncate(); + //We may not have a dedicated stream for writing the signature + //So we take one directly from the storage + //Or DocumentDigitalSignatures::showDocumentContentSignatures was called, + //in which case Add/Remove is not allowed. This is done, for example, if the + //document is readonly + aHelper = DocumentSignatureHelper::OpenSignatureStream( + mxStore, nStreamOpenMode, meSignatureMode ); } else { - css::uno::Reference < css::io::XSeekable > xSeek( mxSignatureStream, uno::UNO_QUERY ); - DBG_ASSERT( xSeek.is(), "ImplOpenSignatureStream - Stream does not support xSeekable!" ); - xSeek->seek( 0 ); + aHelper.xSignatureStream = mxSignatureStream; } } + if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE) + { + css::uno::Reference < css::io::XTruncate > xTruncate( + aHelper.xSignatureStream, UNO_QUERY_THROW); + DBG_ASSERT( xTruncate.is(), "ImplOpenSignatureStream - Stream does not support xTruncate!" ); + xTruncate->truncate(); + } + else if ( bTempStream || mxSignatureStream.is()) + { + //In case we read the signature stream from the storage directly, + //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures + //then XSeakable is not supported + css::uno::Reference < css::io::XSeekable > xSeek( + aHelper.xSignatureStream, UNO_QUERY_THROW); + DBG_ASSERT( xSeek.is(), "ImplOpenSignatureStream - Stream does not support xSeekable!" ); + xSeek->seek( 0 ); + } + return aHelper; } diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.hrc b/xmlsecurity/source/dialogs/digitalsignaturesdialog.hrc new file mode 100644 index 000000000000..19054bd0399b --- /dev/null +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.hrc @@ -0,0 +1,36 @@ +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_DIGITALSIGNATURESDIALOG_HRC
+#define INCLUDED_DIGITALSIGNATURESDIALOG_HRC
+
+//global.hrc in xmlsecurity/inc starts at 1000
+#define RID_DIGITALSIGNATUREDLG_START 2000
+
+#define RID_XMLSECDLG_OLD_ODF_FORMAT RID_DIGITALSIGNATUREDLG_START
+#define MSG_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN (RID_DIGITALSIGNATUREDLG_START + 1)
+#endif
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.src b/xmlsecurity/source/dialogs/digitalsignaturesdialog.src index f102053ce615..016014fbb582 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.src +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.src @@ -30,6 +30,7 @@ #include "dialogs.hrc" #include "helpids.hrc" +#include "digitalsignaturesdialog.hrc" ModalDialog RID_XMLSECDLG_DIGSIG { @@ -87,6 +88,7 @@ ModalDialog RID_XMLSECDLG_DIGSIG { Text [ en-US ] = "The signatures in this document are invalid"; }; + FixedImage IMG_STATE_VALID { Pos = MAP_APPFONT( DS_COL_0, DS_ROW_2A ); @@ -104,6 +106,13 @@ ModalDialog RID_XMLSECDLG_DIGSIG Hide = TRUE; Text [ en-US ] = "The signatures in this document are valid"; }; + FixedText FI_STATE_OLDSIGNATURE + { + Pos = MAP_APPFONT( DS_COL_0, DS_ROW_2A ); + Size = MAP_APPFONT( DS_COL_7-DS_COL_0, RSC_CD_FIXEDTEXT_HEIGHT ); + Hide = TRUE; + Text [ en-US ] = "Not all parts of the document are signed"; + }; FixedImage IMG_STATE_BROKEN { Pos = MAP_APPFONT( DS_COL_0, DS_ROW_2A ); @@ -205,3 +214,13 @@ ErrorBox RID_XMLSECDLG_OLD_ODF_FORMAT "Save document in ODF 1.2 format and add all desired signatures again."; }; + +QueryBox MSG_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN +{ + Buttons = WB_YES_NO ; + DefButton = WB_DEF_NO ; + Message [ en-US ] = "Adding or removing a macro signature will remove all document signatures.\n" + "Do you really want to continue?"; +}; + + diff --git a/xmlsecurity/source/dialogs/resourcemanager.cxx b/xmlsecurity/source/dialogs/resourcemanager.cxx index d8d444a24d18..693d003b0d77 100644 --- a/xmlsecurity/source/dialogs/resourcemanager.cxx +++ b/xmlsecurity/source/dialogs/resourcemanager.cxx @@ -38,7 +38,12 @@ #include <svtools/stdctrl.hxx> #include <svtools/solar.hrc> #include <svtools/syslocale.hxx> +#include <rtl/ustring.h> +#include <rtl/ustrbuf.h> +#include <vector> +using ::rtl::OUString; +using namespace std; namespace XmlSec { @@ -110,122 +115,249 @@ namespace XmlSec return GetLocaleData().getDate( GetDateTime( _rDT ) ); } - String GetPureContent( const String& _rRawString, const char* _pCommaReplacement, bool _bPreserveId ) + /* + Creates two strings based on the distinguished name which are displayed in the + certificate details view. The first string contains only the values of the attribute + and valudes pairs, which are separated by commas. All escape characters ('"') are + removed. + The second string is for the details view at the bottom. It shows the attribute/value + pairs on different lines. All escape characters ('"') are removed. + */ + pair< OUString, OUString> GetDNForCertDetailsView( const OUString & rRawString) { - enum STATE { PRE_ID, ID, EQUALSIGN, PRE_CONT, CONT }; - String s; - STATE e = _bPreserveId? PRE_ID : ID; - - const sal_Unicode* p = _rRawString.GetBuffer(); - sal_Unicode c; - const sal_Unicode cComma = ','; - const sal_Unicode cEqualSign = '='; - const sal_Unicode cSpace = ' '; - String aCommaReplacement; - if( _pCommaReplacement ) - aCommaReplacement = String::CreateFromAscii( _pCommaReplacement ); - - while( *p ) + vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString); + ::rtl::OUStringBuffer s1, s2; + OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = ")); + typedef vector< pair < OUString, OUString > >::const_iterator CIT; + for (CIT i = vecAttrValueOfDN.begin(); i < vecAttrValueOfDN.end(); i ++) { - c = *p; - switch( e ) + if (i != vecAttrValueOfDN.begin()) { - case PRE_ID: - if( c != cSpace ) - { - s += c; - e = ID; - } - break; - case ID: - if( _bPreserveId ) - s += c; - - if( c == cEqualSign ) - e = _bPreserveId? PRE_CONT : CONT; - break; - case EQUALSIGN: - break; - case PRE_CONT: - if( c != cSpace ) - { - s += c; - e = CONT; - } - break; - case CONT: - if( c == cComma ) - { - s += aCommaReplacement; - e = _bPreserveId? PRE_ID : ID; - } - else - s += c; - break; + s1.append(static_cast<sal_Unicode>(',')); + s2.append(static_cast<sal_Unicode>('\n')); } - - ++p; + s1.append(i->second); + s2.append(i->first); + s2.append(sEqual); + s2.append(i->second); } - -// xub_StrLen nEquPos = _rRawString.SearchAscii( "=" ); -// if( nEquPos == STRING_NOTFOUND ) -// s = _rRawString; -// else -// { -// ++nEquPos; -// s = String( _rRawString, nEquPos, STRING_MAXLEN ); -// s.EraseLeadingAndTrailingChars(); -// } - - return s; + return make_pair(s1.makeStringAndClear(), s2.makeStringAndClear()); } - String GetContentPart( const String& _rRawString, const String& _rPartId ) +/* + Whenever the attribute value contains special characters, such as '"' or ',' (without '') + then the value will be enclosed in double quotes by the respective Windows or NSS function + which we use to retrieve, for example, the subject name. If double quotes appear in the value then + they are escaped with a double quote. This function removes the escape characters. +*/ +#ifdef WNT +vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) { - String s; - - xub_StrLen nContStart = _rRawString.Search( _rPartId ); - if( nContStart != STRING_NOTFOUND ) + vector< pair<OUString, OUString> > retVal; + bool bInEscape = false; + bool bInValue = false; + bool bInType = true; + sal_Int32 nTypeNameStart = 0; + OUString sType; + ::rtl::OUStringBuffer sbufValue; + sal_Int32 length = rRawString.getLength(); + + for (sal_Int32 i = 0; i < length; i++) { - nContStart = nContStart + _rPartId.Len(); - ++nContStart; // now it's start of content, directly after Id - - xub_StrLen nContEnd = _rRawString.Search( sal_Unicode( ',' ), nContStart ); + sal_Unicode c = rRawString[i]; - s = String( _rRawString, nContStart, nContEnd - nContStart ); + if (c == '=') + { + if (! bInValue) + { + sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); + sType = sType.trim(); + bInType = false; + } + else + { + sbufValue.append(c); + } + } + else if (c == '"') + { + if (!bInEscape) + { + //If this is the quote is the first of the couple which enclose the + //whole value, because the value contains special characters + //then we just drop it. That is, this character must be followed by + //a character which is not '"'. + if ( i + 1 < length && rRawString[i+1] == '"') + bInEscape = true; + else + bInValue = !bInValue; //value is enclosed in " " + } + else + { + //This quote is escaped by a preceding quote and therefore is + //part of the value + sbufValue.append(c); + bInEscape = false; + } + } + else if (c == ',') + { + //The comma separate the attribute value pairs. + //If the comma is not part of a value (the value would then be enclosed in '"'), + //then we have reached the end of the value + if (!bInValue) + { + OSL_ASSERT(sType.getLength()); + retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); + sType = OUString(); + //The next char is the start of the new type + nTypeNameStart = i + 1; + bInType = true; + } + else + { + //The whole string is enclosed because it contains special characters. + //The enclosing '"' are not part of certificate but will be added by + //the function (Windows or NSS) which retrieves DN + sbufValue.append(c); + } + } + else + { + if (!bInType) + sbufValue.append(c); + } + } + if (sbufValue.getLength()) + { + OSL_ASSERT(sType.getLength()); + retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); } + return retVal; + } +#else +vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) + { + vector< pair<OUString, OUString> > retVal; + //bInEscape == true means that the preceding character is an escape character + bool bInEscape = false; + bool bInValue = false; + bool bInType = true; + sal_Int32 nTypeNameStart = 0; + OUString sType; + ::rtl::OUStringBuffer sbufValue; + sal_Int32 length = rRawString.getLength(); + + for (sal_Int32 i = 0; i < length; i++) + { + sal_Unicode c = rRawString[i]; - return s; + if (c == '=') + { + if (! bInValue) + { + sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); + sType = sType.trim(); + bInType = false; + } + else + { + sbufValue.append(c); + } + } + else if (c == '\\') + { + if (!bInEscape) + { + bInEscape = true; + } + else + { // bInEscape is true + sbufValue.append(c); + bInEscape = false; + } + } + else if (c == '"') + { + //an unescaped '"' is either at the beginning or end of the value + if (!bInEscape) + { + if ( !bInValue) + bInValue = true; + else if (bInValue) + bInValue = false; + } + else + { + //This quote is escaped by a preceding quote and therefore is + //part of the value + sbufValue.append(c); + bInEscape = false; + } + } + else if (c == ',') + { + //The comma separate the attribute value pairs. + //If the comma is not part of a value (the value would then be enclosed in '"'), + //then we have reached the end of the value + if (!bInValue) + { + OSL_ASSERT(sType.getLength()); + retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); + sType = OUString(); + //The next char is the start of the new type + nTypeNameStart = i + 1; + bInType = true; + } + else + { + //The whole string is enclosed because it contains special characters. + //The enclosing '"' are not part of certificate but will be added by + //the function (Windows or NSS) which retrieves DN + sbufValue.append(c); + } + } + else + { + if (!bInType) + { + sbufValue.append(c); + bInEscape = false; + } + } + } + if (sbufValue.getLength()) + { + OSL_ASSERT(sType.getLength()); + retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); + } + return retVal; } - /** - * This Method should consider some string like "C=CN-XXX , O=SUN-XXX , CN=Jack" , - * here the first CN represent china , and the second CN represent the common name , - * so I changed the method to handle this . - * By CP , mailto : chandler.peng@sun.com - **/ +#endif + String GetContentPart( const String& _rRawString ) { - // search over some parts to find a string - //static char* aIDs[] = { "CN", "OU", "O", "E", NULL }; - static char const * aIDs[] = { "CN=", "OU=", "O=", "E=", NULL };// By CP - String sPart; + char const * aIDs[] = { "CN", "OU", "O", "E", NULL }; + OUString retVal; int i = 0; + vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(_rRawString); while ( aIDs[i] ) { - String sPartId = String::CreateFromAscii( aIDs[i++] ); - xub_StrLen nContStart = _rRawString.Search( sPartId ); - if ( nContStart != STRING_NOTFOUND ) + OUString sPartId = OUString::createFromAscii( aIDs[i++] ); + typedef vector< pair < OUString, OUString > >::const_iterator CIT; + for (CIT idn = vecAttrValueOfDN.begin(); idn != vecAttrValueOfDN.end(); idn++) { - nContStart = nContStart + sPartId.Len(); - //++nContStart; // now it's start of content, directly after Id // delete By CP - xub_StrLen nContEnd = _rRawString.Search( sal_Unicode( ',' ), nContStart ); - sPart = String( _rRawString, nContStart, nContEnd - nContStart ); - break; + if (idn->first.equals(sPartId)) + { + retVal = idn->second; + break; + } } + if (retVal.getLength()) + break; } - - return sPart; + return retVal; } String GetHexString( const ::com::sun::star::uno::Sequence< sal_Int8 >& _rSeq, const char* _pSep, UINT16 _nLineBreak ) diff --git a/xmlsecurity/source/dialogs/resourcemanager.hxx b/xmlsecurity/source/dialogs/resourcemanager.hxx index 500ba6501c39..0525010f0abe 100644 --- a/xmlsecurity/source/dialogs/resourcemanager.hxx +++ b/xmlsecurity/source/dialogs/resourcemanager.hxx @@ -36,6 +36,8 @@ #include <com/sun/star/util/DateTime.hpp> #include <com/sun/star/uno/Sequence.hxx> +#include <vector> + class FixedImage; class FixedInfo; class Control; @@ -51,10 +53,10 @@ namespace XmlSec String GetDateTimeString( const rtl::OUString& _rDate, const rtl::OUString& _rTime ); String GetDateString( const ::com::sun::star::util::DateTime& _rDT ); - String GetPureContent( const String& _rRawString, - const char* _pCommaReplacement = ", ", - bool _bPreserveId = false ); // strips "CN=" and so from string - String GetContentPart( const String& _rRawString, const String& _rPartId ); + std::vector< std::pair< ::rtl::OUString, ::rtl::OUString> > + parseDN(const ::rtl::OUString& rRawString); + std::pair< ::rtl::OUString, ::rtl::OUString> GetDNForCertDetailsView( + const ::rtl::OUString & rRawString); String GetContentPart( const String& _rRawString ); String GetHexString( const ::com::sun::star::uno::Sequence< sal_Int8 >& _rSeq, const char* _pSep = ":", UINT16 _nLineBreak = 0xFFFF ); diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx index 37186bd2515c..340b4d14fb70 100644 --- a/xmlsecurity/source/helper/documentsignaturehelper.cxx +++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx @@ -1,291 +1,465 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: documentsignaturehelper.cxx,v $ - * $Revision: 1.11 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_xmlsecurity.hxx" - -#include <xmlsecurity/documentsignaturehelper.hxx> - -#include <com/sun/star/container/XNameAccess.hpp> -#include <com/sun/star/lang/XComponent.hpp> -#include <com/sun/star/lang/DisposedException.hpp> -#include <com/sun/star/embed/XStorage.hpp> -#include <com/sun/star/embed/ElementModes.hpp> -#include "com/sun/star/beans/XPropertySet.hpp" - -#include "comphelper/documentconstants.hxx" -#include <tools/debug.hxx> -#include "rtl/uri.hxx" - -using namespace ::com::sun::star; -namespace css = ::com::sun::star; - -namespace -{ -::rtl::OUString getElement(::rtl::OUString const & version, ::sal_Int32 * index) -{ - while (*index < version.getLength() && version[*index] == '0') { - ++*index; - } - return version.getToken(0, '.', *index); -} - - - -// Return 1 if version1 is greater then version 2, 0 if they are equal -//and -1 if version1 is less version 2 -int compareVersions( - ::rtl::OUString const & version1, ::rtl::OUString const & version2) +/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: documentsignaturehelper.cxx,v $
+ * $Revision: 1.11 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_xmlsecurity.hxx"
+
+#include <xmlsecurity/documentsignaturehelper.hxx>
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include "com/sun/star/beans/XPropertySet.hpp"
+
+#include "comphelper/documentconstants.hxx"
+#include <tools/debug.hxx>
+#include "rtl/uri.hxx"
+
+using namespace ::com::sun::star::uno;
+//using namespace ::com::sun::star;
+namespace css = ::com::sun::star;
+using rtl::OUString;
+
+
+namespace
+{
+::rtl::OUString getElement(::rtl::OUString const & version, ::sal_Int32 * index)
+{
+ while (*index < version.getLength() && version[*index] == '0') {
+ ++*index;
+ }
+ return version.getToken(0, '.', *index);
+}
+
+
+
+// Return 1 if version1 is greater then version 2, 0 if they are equal
+//and -1 if version1 is less version 2
+int compareVersions(
+ ::rtl::OUString const & version1, ::rtl::OUString const & version2)
+{
+ for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) {
+ ::rtl::OUString e1(getElement(version1, &i1));
+ ::rtl::OUString e2(getElement(version2, &i2));
+ if (e1.getLength() < e2.getLength()) {
+ return -1;
+ } else if (e1.getLength() > e2.getLength()) {
+ return 1;
+ } else if (e1 < e2) {
+ return -1;
+ } else if (e1 > e2) {
+ return 1;
+ }
+ }
+ return 0;
+}
+}
+//If the OOo 3.0 mode is used then we exclude
+//'mimetype' and all content of 'META-INF'.
+//If the argument 'bSigning' is true then the element list is created for a signing
+//operation in which case we use the latest signing algorithm. That is all elements
+//we find in the zip storage are added to the list. We do not support the old signatures
+//which did not contain all files.
+//If 'bSigning' is false, then we validate. If the user enabled validating according to OOo 3.0
+//then mimetype and all content of META-INF must be excluded.
+void ImplFillElementList(
+ std::vector< rtl::OUString >& rList, const Reference < css::embed::XStorage >& rxStore,
+ const ::rtl::OUString rRootStorageName, const bool bRecursive,
+ const DocumentSignatureAlgorithm mode)
+{
+ ::rtl::OUString aMetaInfName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) );
+ ::rtl::OUString sMimeTypeName (RTL_CONSTASCII_USTRINGPARAM("mimetype"));
+ ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
+
+ Reference < css::container::XNameAccess > xElements( rxStore, UNO_QUERY );
+ Sequence< ::rtl::OUString > aElements = xElements->getElementNames();
+ sal_Int32 nElements = aElements.getLength();
+ const ::rtl::OUString* pNames = aElements.getConstArray();
+
+ for ( sal_Int32 n = 0; n < nElements; n++ )
+ {
+ if (mode != OOo3_2Document
+ && (pNames[n] == aMetaInfName
+ || pNames[n] == sMimeTypeName))
+ {
+ continue;
+ }
+ else
+ {
+ ::rtl::OUString sEncName = ::rtl::Uri::encode(
+ pNames[n], rtl_UriCharClassRelSegment,
+ rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8);
+ if (sEncName.getLength() == 0 && pNames[n].getLength() != 0)
+ throw css::uno::Exception(::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Failed to encode element name of XStorage")), 0);
+
+ if ( rxStore->isStreamElement( pNames[n] ) )
+ {
+ //Exclude documentsignatures.xml!
+ if (pNames[n].equals(
+ DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()))
+ continue;
+ ::rtl::OUString aFullName( rRootStorageName + sEncName );
+ rList.push_back(aFullName);
+ }
+ else if ( bRecursive && rxStore->isStorageElement( pNames[n] ) )
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( pNames[n], css::embed::ElementModes::READ );
+ rtl::OUString aFullRootName( rRootStorageName + sEncName + aSep );
+ ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode);
+ }
+ }
+ }
+}
+
+
+bool DocumentSignatureHelper::isODFPre_1_2(const ::rtl::OUString & sVersion)
+{
+ //The property version exists only if the document is at least version 1.2
+ //That is, if the document has version 1.1 and sVersion is empty.
+ //The constant is defined in comphelper/documentconstants.hxx
+ if (compareVersions(sVersion, ODFVER_012_TEXT) == -1)
+ return true;
+ return false;
+}
+
+bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo)
+{
+ ::rtl::OUString sManifestURI(RTL_CONSTASCII_USTRINGPARAM("META-INF/manifest.xml"));
+ bool bOOo3_2 = false;
+ typedef ::std::vector< SignatureReferenceInformation >::const_iterator CIT;
+ for (CIT i = sigInfo.vSignatureReferenceInfors.begin();
+ i < sigInfo.vSignatureReferenceInfors.end(); i++)
+ {
+ if (i->ouURI.equals(sManifestURI))
+ {
+ bOOo3_2 = true;
+ break;
+ }
+ }
+ return bOOo3_2;
+}
+
+DocumentSignatureAlgorithm
+DocumentSignatureHelper::getDocumentAlgorithm(
+ const ::rtl::OUString & sODFVersion, const SignatureInformation & sigInfo)
+{
+ OSL_ASSERT(sODFVersion.getLength());
+ DocumentSignatureAlgorithm mode = OOo3_2Document;
+ if (!isOOo3_2_Signature(sigInfo))
+ {
+ if (isODFPre_1_2(sODFVersion))
+ mode = OOo2Document;
+ else
+ mode = OOo3_0Document;
+ }
+ return mode;
+}
+
+//The function creates a list of files which are to be signed or for which
+//the signature is to be validated. The strings are UTF8 encoded URIs which
+//contain '/' as path separators.
+//
+//The algorithm how document signatures are created and validated has
+//changed over time. The change affects only which files within the document
+//are changed. Document signatures created by OOo 2.x only used particular files. Since
+//OOo 3.0 everything except "mimetype" and "META-INF" are signed. As of OOo 3.2 everything
+//except META-INF/documentsignatures.xml is signed.
+//Signatures are validated according to the algorithm which was then used for validation.
+//That is, when validating a signature which was created by OOo 3.0, then mimetype and
+//META-INF are not used.
+//
+//When a signature is created then we always use the latest algorithm. That is, we use
+//that of OOo 3.2
+std::vector< rtl::OUString >
+DocumentSignatureHelper::CreateElementList(
+ const Reference < css::embed::XStorage >& rxStore,
+ const ::rtl::OUString /*rRootStorageName*/, DocumentSignatureMode eMode,
+ const DocumentSignatureAlgorithm mode)
+{
+ std::vector< rtl::OUString > aElements;
+ ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
+
+ switch ( eMode )
+ {
+ case SignatureModeDocumentContent:
+ {
+ if (mode == OOo2Document) //that is, ODF 1.0, 1.1
+ {
+ // 1) Main content
+ ImplFillElementList(aElements, rxStore, ::rtl::OUString(), false, mode);
+
+ // 2) Pictures...
+ rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Pictures" ) );
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode);
+ }
+ catch(css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ // 3) OLE....
+ aSubStorageName = rtl::OUString::createFromAscii( "ObjectReplacements" );
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode);
+ xSubStore.clear();
+
+ // Object folders...
+ rtl::OUString aMatchStr( rtl::OUString::createFromAscii( "Object " ) );
+ Reference < css::container::XNameAccess > xElements( rxStore, UNO_QUERY );
+ Sequence< ::rtl::OUString > aElementNames = xElements->getElementNames();
+ sal_Int32 nElements = aElementNames.getLength();
+ const ::rtl::OUString* pNames = aElementNames.getConstArray();
+ for ( sal_Int32 n = 0; n < nElements; n++ )
+ {
+ if ( ( pNames[n].match( aMatchStr ) ) && rxStore->isStorageElement( pNames[n] ) )
+ {
+ Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( pNames[n], css::embed::ElementModes::READ );
+ ImplFillElementList(aElements, xTmpSubStore, pNames[n]+aSep, true, mode);
+ }
+ }
+ }
+ catch( com::sun::star::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ }
+ else
+ {
+ // Everything except META-INF
+ ImplFillElementList(aElements, rxStore, ::rtl::OUString(), true, mode);
+ }
+ }
+ break;
+ case SignatureModeMacros:
+ {
+ // 1) Macros
+ rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Basic" ) );
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode);
+ }
+ catch( com::sun::star::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+
+ // 2) Dialogs
+ aSubStorageName = rtl::OUString::createFromAscii( "Dialogs") ;
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode);
+ }
+ catch( com::sun::star::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ // 3) Scripts
+ aSubStorageName = rtl::OUString::createFromAscii( "Scripts") ;
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode);
+ }
+ catch( css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ }
+ break;
+ case SignatureModePackage:
+ {
+ // Everything except META-INF
+ ImplFillElementList(aElements, rxStore, ::rtl::OUString(), true, mode);
+ }
+ break;
+ }
+
+ return aElements;
+}
+
+SignatureStreamHelper DocumentSignatureHelper::OpenSignatureStream(
+ const Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode )
+{
+ sal_Int32 nSubStorageOpenMode = css::embed::ElementModes::READ;
+ if ( nOpenMode & css::embed::ElementModes::WRITE )
+ nSubStorageOpenMode = css::embed::ElementModes::WRITE;
+
+ SignatureStreamHelper aHelper;
+
+ try
+ {
+ ::rtl::OUString aSIGStoreName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) );
+ aHelper.xSignatureStorage = rxStore->openStorageElement( aSIGStoreName, nSubStorageOpenMode );
+ if ( aHelper.xSignatureStorage.is() )
+ {
+ ::rtl::OUString aSIGStreamName;
+ if ( eDocSigMode == SignatureModeDocumentContent )
+ aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName();
+ else if ( eDocSigMode == SignatureModeMacros )
+ aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName();
+ else
+ aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName();
+
+ aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode );
+ }
+ }
+ catch(css::io::IOException& )
+ {
+ // Doesn't have to exist...
+ DBG_ASSERT( nOpenMode == embed::ElementModes::READ, "Error creating signature stream..." );
+ }
+
+ return aHelper;
+}
+
+//sElementList contains all files which are expected to be signed. Only those files must me signed,
+//no more, no less.
+//The DocumentSignatureAlgorithm indicates if the document was created with OOo 2.x. Then
+//the uri s in the Reference elements in the signature, were not properly encoded.
+// For example: <Reference URI="ObjectReplacements/Object 1">
+bool DocumentSignatureHelper::checkIfAllFilesAreSigned(
+ const ::std::vector< ::rtl::OUString > & sElementList,
+ const SignatureInformation & sigInfo,
+ const DocumentSignatureAlgorithm alg)
+{
+ // Can only be valid if ALL streams are signed, which means real stream count == signed stream count
+ unsigned int nRealCount = 0;
+ for ( int i = sigInfo.vSignatureReferenceInfors.size(); i; )
+ {
+ const SignatureReferenceInformation& rInf = sigInfo.vSignatureReferenceInfors[--i];
+ // There is also an extra entry of type TYPE_SAMEDOCUMENT_REFERENCE because of signature date.
+ if ( ( rInf.nType == TYPE_BINARYSTREAM_REFERENCE ) || ( rInf.nType == TYPE_XMLSTREAM_REFERENCE ) )
+ {
+ ::rtl::OUString sReferenceURI = rInf.ouURI;
+ if (alg == OOo2Document)
+ {
+ //Comparing URIs is a difficult. Therefore we kind of normalize
+ //it before comparing. We assume that our URI do not have a leading "./"
+ //and fragments at the end (...#...)
+ sReferenceURI = ::rtl::Uri::encode(
+ sReferenceURI, rtl_UriCharClassPchar,
+ rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8);
+ }
+
+ //find the file in the element list
+ typedef ::std::vector< ::rtl::OUString >::const_iterator CIT;
+ for (CIT aIter = sElementList.begin(); aIter < sElementList.end(); aIter++)
+ {
+ ::rtl::OUString sElementListURI = *aIter;
+ if (alg == OOo2Document)
+ {
+ sElementListURI =
+ ::rtl::Uri::encode(
+ sElementListURI, rtl_UriCharClassPchar,
+ rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8);
+ }
+ if (sElementListURI.equals(sReferenceURI))
+ {
+ nRealCount++;
+ break;
+ }
+ }
+ }
+ }
+ return sElementList.size() == nRealCount;
+}
+
+/*Compares the Uri which are obtained from CreateElementList with + the path obtained from the manifest.xml. + Returns true if both strings are equal. +*/ +bool DocumentSignatureHelper::equalsReferenceUriManifestPath( + const OUString & rUri, const OUString & rPath) { - for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { - ::rtl::OUString e1(getElement(version1, &i1)); - ::rtl::OUString e2(getElement(version2, &i2)); - if (e1.getLength() < e2.getLength()) { - return -1; - } else if (e1.getLength() > e2.getLength()) { - return 1; - } else if (e1 < e2) { - return -1; - } else if (e1 > e2) { - return 1; - } - } - return 0; -} -} - -void ImplFillElementList( std::vector< rtl::OUString >& rList, const uno::Reference < embed::XStorage >& rxStore, const ::rtl::OUString rRootStorageName, bool bRecursive ) -{ - ::rtl::OUString aMetaInfName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ); - ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); - - uno::Reference < container::XNameAccess > xElements( rxStore, uno::UNO_QUERY ); - uno::Sequence< ::rtl::OUString > aElements = xElements->getElementNames(); - sal_Int32 nElements = aElements.getLength(); - const ::rtl::OUString* pNames = aElements.getConstArray(); - for ( sal_Int32 n = 0; n < nElements; n++ ) - { - if ( pNames[n] != aMetaInfName ) - { - ::rtl::OUString sEncName = ::rtl::Uri::encode( - pNames[n], rtl_UriCharClassRelSegment, - rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8); - if (sEncName.getLength() == 0 && pNames[n].getLength() != 0) - throw css::uno::Exception(::rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("Failed to encode element name of XStorage")), 0); - - if ( rxStore->isStreamElement( pNames[n] ) ) - { - ::rtl::OUString aFullName( rRootStorageName + sEncName ); - rList.push_back(aFullName); - } - else if ( bRecursive && rxStore->isStorageElement( pNames[n] ) ) - { - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( pNames[n], embed::ElementModes::READ ); - rtl::OUString aFullRootName( rRootStorageName + sEncName + aSep ); - ImplFillElementList( rList, xSubStore, aFullRootName, bRecursive ); - } - } - } -} - - -bool DocumentSignatureHelper::isODFPre_1_2(const uno::Reference < embed::XStorage >& rxStore) -{ - ::rtl::OUString sVersion; - uno::Reference< beans::XPropertySet > xProps(rxStore, uno::UNO_QUERY_THROW ); - xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= sVersion; - //The property version exists only if the document is at least version 1.2 - //The constant is defined in comphelper/documentconstants.hxx - if (compareVersions(sVersion, ODFVER_012_TEXT) == -1) - return true; - return false; -} - + bool retVal = false; + //split up the uri and path into segments. Both are separated by '/'
+ std::vector<OUString> vUriSegments;
+ sal_Int32 nIndex = 0;
+ do
+ {
+ OUString aToken = rUri.getToken( 0, '/', nIndex );
+ vUriSegments.push_back(aToken);
+ }
+ while (nIndex >= 0);
+
+ std::vector<OUString> vPathSegments;
+ nIndex = 0;
+ do
+ {
+ OUString aToken = rPath.getToken( 0, '/', nIndex );
+ vPathSegments.push_back(aToken);
+ }
+ while (nIndex >= 0);
+
+ //Now compare each segment of the uri with its counterpart from the path
+ if (vUriSegments.size() == vPathSegments.size())
+ {
+ retVal = true;
+ typedef std::vector<OUString>::const_iterator CIT;
+ for (CIT i = vUriSegments.begin(), j = vPathSegments.begin();
+ i != vUriSegments.end(); i++, j++)
+ {
+ //Decode the uri segment, so that %20 becomes ' ', etc.
+ OUString sDecUri = ::rtl::Uri::decode(
+ *i, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ if (!sDecUri.equals(*j))
+ {
+ retVal = false;
+ break;
+ }
+ }
+ }
-std::vector< rtl::OUString > DocumentSignatureHelper::CreateElementList( const uno::Reference < embed::XStorage >& rxStore, const ::rtl::OUString /*rRootStorageName*/, DocumentSignatureMode eMode ) -{ - std::vector< rtl::OUString > aElements; - ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); - - bool bPre1_2 = isODFPre_1_2(rxStore); - - switch ( eMode ) - { - case SignatureModeDocumentContent: - { - if (bPre1_2) - { - // 1) Main content - ImplFillElementList( aElements, rxStore, ::rtl::OUString(), false ); - - // 2) Pictures... - rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Pictures" ) ); - try - { - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, embed::ElementModes::READ ); - ImplFillElementList( aElements, xSubStore, aSubStorageName+aSep, true ); - } - catch( com::sun::star::io::IOException& ) - { - ; // Doesn't have to exist... - } - // 3) OLE.... - aSubStorageName = rtl::OUString::createFromAscii( "ObjectReplacements" ); - try - { - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, embed::ElementModes::READ ); - ImplFillElementList( aElements, xSubStore, aSubStorageName+aSep, true ); - xSubStore.clear(); - - // Object folders... - rtl::OUString aMatchStr( rtl::OUString::createFromAscii( "Object " ) ); - uno::Reference < container::XNameAccess > xElements( rxStore, uno::UNO_QUERY ); - uno::Sequence< ::rtl::OUString > aElementNames = xElements->getElementNames(); - sal_Int32 nElements = aElementNames.getLength(); - const ::rtl::OUString* pNames = aElementNames.getConstArray(); - for ( sal_Int32 n = 0; n < nElements; n++ ) - { - if ( ( pNames[n].match( aMatchStr ) ) && rxStore->isStorageElement( pNames[n] ) ) - { - uno::Reference < embed::XStorage > xTmpSubStore = rxStore->openStorageElement( pNames[n], embed::ElementModes::READ ); - ImplFillElementList( aElements, xTmpSubStore, pNames[n]+aSep, true ); - } - } - } - catch( com::sun::star::io::IOException& ) - { - ; // Doesn't have to exist... - } - } - else - { - // Everything except META-INF - ImplFillElementList( aElements, rxStore, ::rtl::OUString(), true ); - } - } - break; - case SignatureModeMacros: - { - // 1) Macros - rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Basic" ) ); - try - { - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, embed::ElementModes::READ ); - ImplFillElementList( aElements, xSubStore, aSubStorageName+aSep, true ); - } - catch( com::sun::star::io::IOException& ) - { - ; // Doesn't have to exist... - } - - // 2) Dialogs - aSubStorageName = rtl::OUString::createFromAscii( "Dialogs") ; - try - { - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, embed::ElementModes::READ ); - ImplFillElementList( aElements, xSubStore, aSubStorageName+aSep, true ); - } - catch( com::sun::star::io::IOException& ) - { - ; // Doesn't have to exist... - } - // 3) Scripts - aSubStorageName = rtl::OUString::createFromAscii( "Scripts") ; - try - { - uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, embed::ElementModes::READ ); - ImplFillElementList( aElements, xSubStore, aSubStorageName+aSep, true ); - } - catch( com::sun::star::io::IOException& ) - { - ; // Doesn't have to exist... - } - } - break; - case SignatureModePackage: - { - // Everything except META-INF - ImplFillElementList( aElements, rxStore, ::rtl::OUString(), true ); - } - break; - } - - return aElements; -} - -SignatureStreamHelper DocumentSignatureHelper::OpenSignatureStream( const uno::Reference < embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode ) -{ - sal_Int32 nSubStorageOpenMode = embed::ElementModes::READ; - if ( nOpenMode & embed::ElementModes::WRITE ) - nSubStorageOpenMode = embed::ElementModes::WRITE; - - SignatureStreamHelper aHelper; - - try - { - ::rtl::OUString aSIGStoreName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ); - aHelper.xSignatureStorage = rxStore->openStorageElement( aSIGStoreName, nSubStorageOpenMode ); - if ( aHelper.xSignatureStorage.is() ) - { - ::rtl::OUString aSIGStreamName; - if ( eDocSigMode == SignatureModeDocumentContent ) - aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); - else if ( eDocSigMode == SignatureModeMacros ) - aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); - else - aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); - - aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode ); - } - } - catch( com::sun::star::io::IOException& ) - { - // Doesn't have to exist... - DBG_ASSERT( nOpenMode == embed::ElementModes::READ, "Error creating signature stream..." ); - } - - return aHelper; -} - -::rtl::OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName() -{ - return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "documentsignatures.xml" ) ); -} - -::rtl::OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName() -{ - return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "macrosignatures.xml" ) ); -} - -::rtl::OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName() -{ - return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "packagesignatures.xml" ) ); + return retVal; } +
+::rtl::OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()
+{
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "documentsignatures.xml" ) );
+}
+
+::rtl::OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName()
+{
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "macrosignatures.xml" ) );
+}
+
+::rtl::OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName()
+{
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "packagesignatures.xml" ) );
+}
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx index 8ef7c21dd39b..a5890544be00 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -64,6 +64,7 @@ #define NS_DOCUMENTSIGNATURES_ODF_1_2 "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0" using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx) : mxCtx(rxCtx), mbODFPre1_2(false) @@ -110,12 +111,14 @@ com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding > XMLSi return mxUriBinding; } -void XMLSignatureHelper::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStorage ) +void XMLSignatureHelper::SetStorage( + const Reference < css::embed::XStorage >& rxStorage, + ::rtl::OUString sODFVersion) { DBG_ASSERT( !mxUriBinding.is(), "SetStorage - UriBinding already set!" ); mxUriBinding = new UriBindingHelper( rxStorage ); DBG_ASSERT(rxStorage.is(), "SetStorage - empty storage!"); - mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(rxStorage); + mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion); } @@ -194,6 +197,7 @@ void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const rtl::OUStri mpXSecController->signAStream( nSecurityId, uri, objectURL, bBinary ); } + uno::Reference<xml::sax::XDocumentHandler> XMLSignatureHelper::CreateDocumentHandlerWithHeader( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xOutputStream ) { diff --git a/xmlsecurity/source/helper/xmlsignaturehelper2.cxx b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx index 24738c0b6e98..9baa6d7061c4 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper2.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx @@ -204,42 +204,17 @@ uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno { // Cloning because of I can't keep all storage references open // MBA with think about a better API... - sal_Bool bEncrypted = sal_False; - const ::rtl::OUString sName = ::rtl::Uri::decode( rURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); if (sName.getLength() == 0 && rURI.getLength() != 0) throw uno::Exception(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Could not decode URI for stream element.")), 0); - try - { - uno::Reference< io::XStream > xStream; - xStream = rxStore->cloneStreamElement( sName ); - if ( !xStream.is() ) - throw uno::RuntimeException(); - - try { - uno::Reference< beans::XPropertySet > xProps( xStream, uno::UNO_QUERY_THROW ); - xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsEncrypted" ) ) ) >>= bEncrypted; - } catch( uno::Exception ) - {} - - if ( !bEncrypted ) - xInStream = xStream->getInputStream(); - } - catch ( packages::WrongPasswordException& ) - { - bEncrypted = sal_True; - } - if ( bEncrypted ) - { - // this is an encrypted stream that should be handled accordingly - uno::Reference< embed::XStorageRawAccess > xRawStore( rxStore, uno::UNO_QUERY ); - OSL_ENSURE( xRawStore.is(), "Strange storage implementation is used for signing!\n" ); - if ( xRawStore.is() ) - xInStream = xRawStore->getPlainRawStreamElement( sName ); - } + uno::Reference< io::XStream > xStream; + xStream = rxStore->cloneStreamElement( sName ); + if ( !xStream.is() ) + throw uno::RuntimeException(); + xInStream = xStream->getInputStream(); } else { diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx index 00049d2901fc..41dbd6232bce 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -43,6 +43,7 @@ #include <rtl/locale.h> #include <osl/nlsupport.h> #include <osl/process.h> +#include <utility> //CP : end @@ -53,36 +54,130 @@ using ::rtl::OUString ; using ::com::sun::star::security::XCertificate ; using ::com::sun::star::util::DateTime ; -/* - * mmi : because MS Crypto use the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise - * it, so the 'S' tag should be changed to 'ST' tag - * - */ -OUString replaceTagSWithTagST(OUString oldDN) +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +/*Resturns the index withing rRawString where sTypeName starts and where it ends. + The starting index is pair.first. The ending index in pair.second points + one char after the last character of the type. + sTypeName can be + "S" or "CN" (without ""). Do not use spaces at the beginning of the type name. + If the type name is not found then pair.first and pair.second are -1. +*/ +std::pair< sal_Int32, sal_Int32 > +findTypeInDN(const OUString& rRawString, const OUString& sTypeName) { - - sal_Int32 nIndex = 0; - OUString newDN; - do + std::pair< sal_Int32, sal_Int32 > retVal; + bool bInEscape = false; + bool bInValue = false; + bool bFound = false; + sal_Int32 nTypeNameStart = 0; + sal_Int32 length = rRawString.getLength(); + + for (sal_Int32 i = 0; i < length; i++) { - OUString aToken = oldDN.getToken( 0, ',', nIndex ).trim(); - if (aToken.compareToAscii("S=",2) == 0) + sal_Unicode c = rRawString[i]; + + if (c == '=') { - newDN+=OUString::createFromAscii("ST="); - newDN+=aToken.copy(2); + if (! bInValue) + { + OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); + sType = sType.trim(); + if (sType.equalsIgnoreAsciiCase(sTypeName)) + { + bFound = true; + break; + } + } } - else + else if (c == '"') { - newDN+=aToken; + if (!bInEscape) + { + //If this is the quote is the first of the couple which enclose the + //whole value, because the value contains special characters + //then we just drop it. That is, this character must be followed by + //a character which is not '"'. + if ( i + 1 < length && rRawString[i+1] == '"') + bInEscape = true; + else + bInValue = !bInValue; //value is enclosed in " " + } + else + { + //This quote is escaped by a preceding quote and therefore is + //part of the value + bInEscape = false; + } } + else if (c == ',') + { + //The comma separate the attribute value pairs. + //If the comma is not part of a value (the value would then be enclosed in '"'), + //then we have reached the end of the value + if (!bInValue) + { + //The next char is the start of the new type + nTypeNameStart = i + 1; + } + } + } - if (nIndex >= 0) + //Found the Type Name, but there can still be spaces after the last comma + //and the beginning of the type. + if (bFound) + { + while (true) + { + sal_Unicode c = rRawString[nTypeNameStart]; + if (c != ' ' && c != '\t') + //found + break; + nTypeNameStart ++; + } + // search end (one after last letter) + sal_Int32 nTypeNameEnd = nTypeNameStart; + nTypeNameEnd++; + while (true) { - newDN+=OUString::createFromAscii(","); + sal_Unicode c = rRawString[nTypeNameEnd]; + if (c == ' ' || c == '\t' || c == '=') + break; + nTypeNameEnd++; } - } while ( nIndex >= 0 ); + retVal = std::make_pair(nTypeNameStart, nTypeNameEnd); + } + else + { + retVal = std::make_pair(-1, -1); + } + return retVal; +} + - return newDN; +/* + MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise + it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary + anymore, because we provide always the signers certificate when signing. So libmlsec can find + the private key based on the provided certificate (X509Certificate element) and does not need + the issuer name (X509IssuerName element). The issuer name in the xml signature has also no + effect for the signature nor the certificate validation. + In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain + strings for type names. Instead it uses OIDs. + */ + +OUString replaceTagSWithTagST(OUString oldDN) +{ + std::pair<sal_Int32, sal_Int32 > pairIndex = findTypeInDN(oldDN, OUSTR("S")); + + if (pairIndex.first != -1) + { + OUString newDN = oldDN.copy(0, pairIndex.first); + newDN += OUSTR("ST"); + newDN += oldDN.copy(pairIndex.second); + return newDN; + } + return oldDN; } /* end */ @@ -159,7 +254,7 @@ sal_Int16 SAL_CALL X509Certificate_MSCryptImpl :: getVersion() throw ( ::com::su OUString xIssuer(issuer , cbIssuer ,encoding ) ; //By CP delete issuer ; - return replaceTagSWithTagST(xIssuer) ; + return replaceTagSWithTagST(xIssuer); } else { return OUString() ; } @@ -208,7 +303,7 @@ sal_Int16 SAL_CALL X509Certificate_MSCryptImpl :: getVersion() throw ( ::com::su OUString xSubject(subject , cbSubject ,encoding ) ; //By CP delete subject ; - return replaceTagSWithTagST(xSubject) ; + return replaceTagSWithTagST(xSubject); } else { return OUString() ; } |