Update ooo320-m1
[ooovba.git] / xmlsecurity / source / component / documentdigitalsignatures.cxx
blobba73b5e32eff608b5fa51ef0033f3397092bb773
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documentdigitalsignatures.cxx,v $
10 * $Revision: 1.32 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_xmlsecurity.hxx"
35 #include <documentdigitalsignatures.hxx>
36 #include <xmlsecurity/digitalsignaturesdialog.hxx>
37 #include <xmlsecurity/certificateviewer.hxx>
38 #include <xmlsecurity/macrosecurity.hxx>
39 #include <xmlsecurity/biginteger.hxx>
40 #include <xmlsecurity/global.hrc>
42 #include <xmloff/xmluconv.hxx>
44 #include <../dialogs/resourcemanager.hxx>
45 #include <com/sun/star/embed/XStorage.hpp>
46 #include <com/sun/star/embed/XTransactedObject.hpp>
47 #include <com/sun/star/embed/ElementModes.hpp>
48 #include <com/sun/star/ucb/XContent.hpp>
49 #include <com/sun/star/ucb/XContentProvider.hpp>
50 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
51 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
52 #include <com/sun/star/ucb/XCommandProcessor.hpp>
53 #include <com/sun/star/ucb/Command.hpp>
54 #include <tools/urlobj.hxx>
55 #include <vcl/msgbox.hxx>
56 #include <svtools/securityoptions.hxx>
57 #include <com/sun/star/security/CertificateValidity.hpp>
58 #include <com/sun/star/security/SerialNumberAdapter.hpp>
59 #include <ucbhelper/contentbroker.hxx>
60 #include <unotools/ucbhelper.hxx>
61 #include <comphelper/componentcontext.hxx>
62 #include "comphelper/documentconstants.hxx"
64 #include "com/sun/star/lang/IllegalArgumentException.hpp"
66 #include <stdio.h>
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 namespace css = ::com::sun::star;
73 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
75 DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ):
76 mxCtx(rxCtx),
77 m_sODFVersion(ODFVER_012_TEXT),
78 m_nArgumentsCount(0),
79 m_bHasDocumentSignature(false)
83 void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments)
84 throw (css::uno::Exception, css::uno::RuntimeException)
86 if (aArguments.getLength() == 0 || aArguments.getLength() > 2)
87 throw css::lang::IllegalArgumentException(
88 OUSTR("DocumentDigitalSignatures::initialize requires one or two arguments"),
89 Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0);
91 m_nArgumentsCount = aArguments.getLength();
93 if (!(aArguments[0] >>= m_sODFVersion))
94 throw css::lang::IllegalArgumentException(
95 OUSTR("DocumentDigitalSignatures::initialize: the first arguments must be a string"),
96 Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0);
98 if (aArguments.getLength() == 2
99 && !(aArguments[1] >>= m_bHasDocumentSignature))
100 throw css::lang::IllegalArgumentException(
101 OUSTR("DocumentDigitalSignatures::initialize: the second arguments must be a bool"),
102 Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 1);
104 //the Version is supported as of ODF1.2, so for and 1.1 document or older we will receive the
105 //an empty string. In this case we set it to ODFVER_010_TEXT. Then we can later check easily
106 //if initialize was called. Only then m_sODFVersion.getLength() is greater than 0
107 if (m_sODFVersion.getLength() == 0)
108 m_sODFVersion = ODFVER_010_TEXT;
111 sal_Bool DocumentDigitalSignatures::signDocumentContent(
112 const Reference< css::embed::XStorage >& rxStorage,
113 const Reference< css::io::XStream >& xSignStream)
114 throw (RuntimeException)
116 OSL_ENSURE(m_sODFVersion.getLength(), "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
117 return ImplViewSignatures( rxStorage, xSignStream, SignatureModeDocumentContent, false );
120 Sequence< css::security::DocumentSignatureInformation >
121 DocumentDigitalSignatures::verifyDocumentContentSignatures(
122 const Reference< css::embed::XStorage >& rxStorage,
123 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
125 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
126 return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeDocumentContent );
129 void DocumentDigitalSignatures::showDocumentContentSignatures(
130 const Reference< css::embed::XStorage >& rxStorage,
131 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
133 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
134 ImplViewSignatures( rxStorage, xSignInStream, SignatureModeDocumentContent, true );
137 ::rtl::OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName()
138 throw (css::uno::RuntimeException)
140 return DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName();
143 sal_Bool DocumentDigitalSignatures::signScriptingContent(
144 const Reference< css::embed::XStorage >& rxStorage,
145 const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException)
147 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
148 OSL_ENSURE(m_nArgumentsCount == 2, "DocumentDigitalSignatures: Service was not initialized properly");
149 return ImplViewSignatures( rxStorage, xSignStream, SignatureModeMacros, false );
152 Sequence< css::security::DocumentSignatureInformation >
153 DocumentDigitalSignatures::verifyScriptingContentSignatures(
154 const Reference< css::embed::XStorage >& rxStorage,
155 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
157 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
158 return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeMacros );
161 void DocumentDigitalSignatures::showScriptingContentSignatures(
162 const Reference< css::embed::XStorage >& rxStorage,
163 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
165 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
166 ImplViewSignatures( rxStorage, xSignInStream, SignatureModeMacros, true );
169 ::rtl::OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName()
170 throw (css::uno::RuntimeException)
172 return DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName();
176 sal_Bool DocumentDigitalSignatures::signPackage(
177 const Reference< css::embed::XStorage >& rxStorage,
178 const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException)
180 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
181 return ImplViewSignatures( rxStorage, xSignStream, SignatureModePackage, false );
184 Sequence< css::security::DocumentSignatureInformation >
185 DocumentDigitalSignatures::verifyPackageSignatures(
186 const Reference< css::embed::XStorage >& rxStorage,
187 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
189 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
190 return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModePackage );
193 void DocumentDigitalSignatures::showPackageSignatures(
194 const Reference< css::embed::XStorage >& rxStorage,
195 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
197 OSL_ENSURE(m_sODFVersion.getLength(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
198 ImplViewSignatures( rxStorage, xSignInStream, SignatureModePackage, true );
201 ::rtl::OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName( )
202 throw (::com::sun::star::uno::RuntimeException)
204 return DocumentSignatureHelper::GetPackageSignatureDefaultStreamName();
208 sal_Bool DocumentDigitalSignatures::ImplViewSignatures(
209 const Reference< css::embed::XStorage >& rxStorage,
210 const Reference< css::io::XInputStream >& xSignStream,
211 DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException)
213 Reference< io::XStream > xStream;
214 if ( xSignStream.is() )
215 xStream = Reference< io::XStream >( xSignStream, UNO_QUERY );
216 return ImplViewSignatures( rxStorage, xStream, eMode, bReadOnly );
219 sal_Bool DocumentDigitalSignatures::ImplViewSignatures(
220 const Reference< css::embed::XStorage >& rxStorage, const Reference< css::io::XStream >& xSignStream,
221 DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException)
223 sal_Bool bChanges = sal_False;
224 DigitalSignaturesDialog aSignaturesDialog(
225 NULL, mxCtx, eMode, bReadOnly, m_sODFVersion, m_bHasDocumentSignature);
226 bool bInit = aSignaturesDialog.Init( rtl::OUString() );
227 DBG_ASSERT( bInit, "Error initializing security context!" );
228 if ( bInit )
230 aSignaturesDialog.SetStorage( rxStorage );
231 aSignaturesDialog.SetSignatureStream( xSignStream );
232 if ( aSignaturesDialog.Execute() )
234 if ( aSignaturesDialog.SignaturesChanged() )
236 bChanges = TRUE;
237 // If we have a storage and no stream, we are responsible for commit
238 if ( rxStorage.is() && !xSignStream.is() )
240 uno::Reference< embed::XTransactedObject > xTrans( rxStorage, uno::UNO_QUERY );
241 xTrans->commit();
246 else
248 WarningBox aBox( NULL, XMLSEC_RES( RID_XMLSECWB_NO_MOZILLA_PROFILE ) );
249 aBox.Execute();
252 return bChanges;
255 Sequence< css::security::DocumentSignatureInformation >
256 DocumentDigitalSignatures::ImplVerifySignatures(
257 const Reference< css::embed::XStorage >& rxStorage,
258 const Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode ) throw (RuntimeException)
260 if (!rxStorage.is())
262 DBG_ASSERT(0, "Error, no XStorage provided");
263 return Sequence<css::security::DocumentSignatureInformation>();
265 // First check for the InputStream, to avoid unnecessary initialization of the security environemnt...
266 SignatureStreamHelper aStreamHelper;
267 Reference< io::XInputStream > xInputStream = xSignStream;
269 if ( !xInputStream.is() )
271 aStreamHelper = DocumentSignatureHelper::OpenSignatureStream( rxStorage, embed::ElementModes::READ, eMode );
272 if ( aStreamHelper.xSignatureStream.is() )
273 xInputStream = Reference< io::XInputStream >( aStreamHelper.xSignatureStream, UNO_QUERY );
276 if ( !xInputStream.is() )
277 return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0);
280 XMLSignatureHelper aSignatureHelper( mxCtx );
282 bool bInit = aSignatureHelper.Init( rtl::OUString() );
284 DBG_ASSERT( bInit, "Error initializing security context!" );
286 if ( !bInit )
287 return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0);
289 aSignatureHelper.SetStorage(rxStorage, m_sODFVersion);
291 aSignatureHelper.StartMission();
293 aSignatureHelper.ReadAndVerifySignature( xInputStream );
295 aSignatureHelper.EndMission();
297 Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = aSignatureHelper.GetSecurityEnvironment();
299 SignatureInformations aSignInfos = aSignatureHelper.GetSignatureInformations();
300 int nInfos = aSignInfos.size();
301 Sequence< css::security::DocumentSignatureInformation > aInfos(nInfos);
302 css::security::DocumentSignatureInformation* arInfos = aInfos.getArray();
304 if ( nInfos )
306 Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
307 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
309 for( int n = 0; n < nInfos; ++n )
311 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
312 m_sODFVersion, aSignInfos[n]);
313 const std::vector< rtl::OUString > aElementsToBeVerified =
314 DocumentSignatureHelper::CreateElementList(
315 rxStorage, ::rtl::OUString(), eMode, mode);
317 const SignatureInformation& rInfo = aSignInfos[n];
318 css::security::DocumentSignatureInformation& rSigInfo = arInfos[n];
320 if (rInfo.ouX509Certificate.getLength())
321 rSigInfo.Signer = xSecEnv->createCertificateFromAscii( rInfo.ouX509Certificate ) ;
322 if (!rSigInfo.Signer.is())
323 rSigInfo.Signer = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
325 // --> PB 2004-12-14 #i38744# time support again
326 Date aDate( rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year );
327 Time aTime( rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes,
328 rInfo.stDateTime.Seconds, rInfo.stDateTime.HundredthSeconds );
329 rSigInfo.SignatureDate = aDate.GetDate();
330 rSigInfo.SignatureTime = aTime.GetTime();
332 // Verify certificate
333 //We have patched our version of libxmlsec, so that it does not verify the certificates. This has two
334 //reasons. First we want two separate status for signature and certificate. Second libxmlsec calls
335 //CERT_VerifyCertificate (solaris, linux) falsly, so that it always regards the certificate as valid.
336 //On Window the checking of the certificate path is buggy. It does name matching (issuer, subject name)
337 //to find the parent certificate. It does not take into account that there can be several certificates
338 //with the same subject name.
339 if (rSigInfo.Signer.is())
341 try {
342 rSigInfo.CertificateStatus = xSecEnv->verifyCertificate(rSigInfo.Signer,
343 Sequence<Reference<css::security::XCertificate> >());
344 } catch (SecurityException& ) {
345 OSL_ENSURE(0, "Verification of certificate failed");
346 rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
349 else
351 //We should always be aible to get the certificates because it is contained in the document,
352 //unless the document is damaged so that signature xml file could not be parsed.
353 rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
356 rSigInfo.SignatureIsValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
359 if ( rSigInfo.SignatureIsValid )
361 rSigInfo.SignatureIsValid =
362 DocumentSignatureHelper::checkIfAllFilesAreSigned(
363 aElementsToBeVerified, rInfo, mode);
365 if (eMode == SignatureModeDocumentContent)
366 rSigInfo.PartialDocumentSignature =
367 ! DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]);
371 return aInfos;
375 void DocumentDigitalSignatures::manageTrustedSources( ) throw (RuntimeException)
377 // MT: i45295
378 // SecEnv is only needed to display certificate information from trusted sources.
379 // Macro Security also has some options where no security environment is needed, so raise dialog anyway.
380 // Later I should change the code so the Dialog creates the SecEnv on demand...
382 Reference< dcss::xml::crypto::XSecurityEnvironment > xSecEnv;
384 XMLSignatureHelper aSignatureHelper( mxCtx );
385 if ( aSignatureHelper.Init( rtl::OUString() ) )
386 xSecEnv = aSignatureHelper.GetSecurityEnvironment();
388 MacroSecurity aDlg( NULL, mxCtx, xSecEnv );
389 aDlg.Execute();
392 void DocumentDigitalSignatures::showCertificate(
393 const Reference< css::security::XCertificate >& _Certificate ) throw (RuntimeException)
395 XMLSignatureHelper aSignatureHelper( mxCtx );
397 bool bInit = aSignatureHelper.Init( rtl::OUString() );
399 DBG_ASSERT( bInit, "Error initializing security context!" );
401 if ( bInit )
403 CertificateViewer aViewer( NULL, aSignatureHelper.GetSecurityEnvironment(), _Certificate, FALSE );
404 aViewer.Execute();
409 ::sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
410 const Reference< css::security::XCertificate >& Author ) throw (RuntimeException)
412 sal_Bool bFound = sal_False;
414 Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
415 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
417 ::rtl::OUString sSerialNum = xSerialNumberAdapter->toString( Author->getSerialNumber() );
419 Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors();
420 const SvtSecurityOptions::Certificate* pAuthors = aTrustedAuthors.getConstArray();
421 const SvtSecurityOptions::Certificate* pAuthorsEnd = pAuthors + aTrustedAuthors.getLength();
422 for ( ; pAuthors != pAuthorsEnd; ++pAuthors )
424 SvtSecurityOptions::Certificate aAuthor = *pAuthors;
425 if ( ( aAuthor[0] == Author->getIssuerName() ) && ( aAuthor[1] == sSerialNum ) )
427 bFound = sal_True;
428 break;
432 return bFound;
435 ::sal_Bool DocumentDigitalSignatures::isLocationTrusted( const ::rtl::OUString& Location ) throw (RuntimeException)
437 sal_Bool bFound = sal_False;
438 INetURLObject aLocObj( Location );
439 INetURLObject aLocObjLowCase( Location.toAsciiLowerCase() ); // will be used for case insensitive comparing
441 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProvider > xContentProvider;
442 ::ucbhelper::ContentBroker* pBroker = NULL;
444 //warning free code
445 //if ( aLocObj.GetProtocol() == INET_PROT_FILE && ( pBroker = ::ucbhelper::ContentBroker::get() ) )
446 // xContentProvider = pBroker->getContentProviderInterface();
447 if ( aLocObj.GetProtocol() == INET_PROT_FILE)
449 pBroker = ::ucbhelper::ContentBroker::get();
450 if (pBroker)
451 xContentProvider = pBroker->getContentProviderInterface();
454 Sequence< ::rtl::OUString > aSecURLs = SvtSecurityOptions().GetSecureURLs();
455 const ::rtl::OUString* pSecURLs = aSecURLs.getConstArray();
456 const ::rtl::OUString* pSecURLsEnd = pSecURLs + aSecURLs.getLength();
457 for ( ; pSecURLs != pSecURLsEnd && !bFound; ++pSecURLs )
458 bFound = ::utl::UCBContentHelper::IsSubPath( *pSecURLs, Location, xContentProvider );
460 return bFound;
463 void DocumentDigitalSignatures::addAuthorToTrustedSources(
464 const Reference< css::security::XCertificate >& Author ) throw (RuntimeException)
466 SvtSecurityOptions aSecOpts;
468 Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
469 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
471 SvtSecurityOptions::Certificate aNewCert( 3 );
472 aNewCert[ 0 ] = Author->getIssuerName();
473 aNewCert[ 1 ] = xSerialNumberAdapter->toString( Author->getSerialNumber() );
475 rtl::OUStringBuffer aStrBuffer;
476 SvXMLUnitConverter::encodeBase64(aStrBuffer, Author->getEncoded());
477 aNewCert[ 2 ] = aStrBuffer.makeStringAndClear();
480 Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = aSecOpts.GetTrustedAuthors();
481 sal_Int32 nCnt = aTrustedAuthors.getLength();
482 aTrustedAuthors.realloc( nCnt + 1 );
483 aTrustedAuthors[ nCnt ] = aNewCert;
485 aSecOpts.SetTrustedAuthors( aTrustedAuthors );
488 void DocumentDigitalSignatures::addLocationToTrustedSources( const ::rtl::OUString& Location ) throw (RuntimeException)
490 SvtSecurityOptions aSecOpt;
492 Sequence< ::rtl::OUString > aSecURLs = aSecOpt.GetSecureURLs();
493 sal_Int32 nCnt = aSecURLs.getLength();
494 aSecURLs.realloc( nCnt + 1 );
495 aSecURLs[ nCnt ] = Location;
497 aSecOpt.SetSecureURLs( aSecURLs );
500 rtl::OUString DocumentDigitalSignatures::GetImplementationName() throw (RuntimeException)
502 return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) );
505 Sequence< rtl::OUString > DocumentDigitalSignatures::GetSupportedServiceNames() throw (cssu::RuntimeException)
507 Sequence < rtl::OUString > aRet(1);
508 rtl::OUString* pArray = aRet.getArray();
509 pArray[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) );
510 return aRet;
514 Reference< XInterface > DocumentDigitalSignatures_CreateInstance(
515 const Reference< XComponentContext >& rCtx) throw ( Exception )
517 return (cppu::OWeakObject*) new DocumentDigitalSignatures( rCtx );