bump product version to 4.1.6.2
[LibreOffice.git] / xmlsecurity / source / component / documentdigitalsignatures.cxx
blob5993122837cb6d3e4628cee47d10c221439cd7c1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <documentdigitalsignatures.hxx>
21 #include <xmlsecurity/digitalsignaturesdialog.hxx>
22 #include <xmlsecurity/certificatechooser.hxx>
23 #include <xmlsecurity/certificateviewer.hxx>
24 #include <xmlsecurity/macrosecurity.hxx>
25 #include <xmlsecurity/biginteger.hxx>
26 #include <xmlsecurity/global.hrc>
28 #include <sax/tools/converter.hxx>
30 #include <../dialogs/resourcemanager.hxx>
31 #include <com/sun/star/embed/XStorage.hpp>
32 #include <com/sun/star/embed/XTransactedObject.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/ucb/XContent.hpp>
35 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
36 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
37 #include <com/sun/star/ucb/XCommandProcessor.hpp>
38 #include <com/sun/star/ucb/Command.hpp>
39 #include <tools/urlobj.hxx>
40 #include <vcl/msgbox.hxx>
41 #include <unotools/securityoptions.hxx>
42 #include <com/sun/star/security/CertificateValidity.hpp>
43 #include <com/sun/star/security/SerialNumberAdapter.hpp>
44 #include <unotools/ucbhelper.hxx>
45 #include <comphelper/componentcontext.hxx>
46 #include "comphelper/documentconstants.hxx"
48 #include "com/sun/star/lang/IllegalArgumentException.hpp"
50 #include <stdio.h>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
56 DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ):
57 mxCtx(rxCtx),
58 m_sODFVersion(ODFVER_012_TEXT),
59 m_nArgumentsCount(0),
60 m_bHasDocumentSignature(false)
64 void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments)
65 throw (css::uno::Exception, css::uno::RuntimeException)
67 if (aArguments.getLength() > 2)
68 throw css::lang::IllegalArgumentException(
69 "DocumentDigitalSignatures::initialize requires zero, one, or two arguments",
70 Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0);
72 m_nArgumentsCount = aArguments.getLength();
74 if (aArguments.getLength() > 0)
76 if (!(aArguments[0] >>= m_sODFVersion))
77 throw css::lang::IllegalArgumentException(
78 "DocumentDigitalSignatures::initialize: the first arguments must be a string",
79 Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 0);
81 if (aArguments.getLength() == 2
82 && !(aArguments[1] >>= m_bHasDocumentSignature))
83 throw css::lang::IllegalArgumentException(
84 "DocumentDigitalSignatures::initialize: the second arguments must be a bool",
85 Reference<XInterface>(static_cast<XInitialization*>(this), UNO_QUERY), 1);
87 //the Version is supported as of ODF1.2, so for and 1.1 document or older we will receive the
88 //an empty string. In this case we set it to ODFVER_010_TEXT. Then we can later check easily
89 //if initialize was called. Only then m_sODFVersion.getLength() is greater than 0
90 if (m_sODFVersion.isEmpty())
91 m_sODFVersion = ODFVER_010_TEXT;
95 sal_Bool DocumentDigitalSignatures::signDocumentContent(
96 const Reference< css::embed::XStorage >& rxStorage,
97 const Reference< css::io::XStream >& xSignStream)
98 throw (RuntimeException)
100 OSL_ENSURE(!m_sODFVersion.isEmpty(), "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
101 return ImplViewSignatures( rxStorage, xSignStream, SignatureModeDocumentContent, false );
104 Sequence< css::security::DocumentSignatureInformation >
105 DocumentDigitalSignatures::verifyDocumentContentSignatures(
106 const Reference< css::embed::XStorage >& rxStorage,
107 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
109 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
110 return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeDocumentContent );
113 void DocumentDigitalSignatures::showDocumentContentSignatures(
114 const Reference< css::embed::XStorage >& rxStorage,
115 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
117 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
118 ImplViewSignatures( rxStorage, xSignInStream, SignatureModeDocumentContent, true );
121 OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName()
122 throw (css::uno::RuntimeException)
124 return DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName();
127 sal_Bool DocumentDigitalSignatures::signScriptingContent(
128 const Reference< css::embed::XStorage >& rxStorage,
129 const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException)
131 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
132 OSL_ENSURE(m_nArgumentsCount == 2, "DocumentDigitalSignatures: Service was not initialized properly");
133 return ImplViewSignatures( rxStorage, xSignStream, SignatureModeMacros, false );
136 Sequence< css::security::DocumentSignatureInformation >
137 DocumentDigitalSignatures::verifyScriptingContentSignatures(
138 const Reference< css::embed::XStorage >& rxStorage,
139 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
141 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
142 return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModeMacros );
145 void DocumentDigitalSignatures::showScriptingContentSignatures(
146 const Reference< css::embed::XStorage >& rxStorage,
147 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
149 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
150 ImplViewSignatures( rxStorage, xSignInStream, SignatureModeMacros, true );
153 OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName()
154 throw (css::uno::RuntimeException)
156 return DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName();
160 sal_Bool DocumentDigitalSignatures::signPackage(
161 const Reference< css::embed::XStorage >& rxStorage,
162 const Reference< css::io::XStream >& xSignStream ) throw (RuntimeException)
164 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
165 return ImplViewSignatures( rxStorage, xSignStream, SignatureModePackage, false );
168 Sequence< css::security::DocumentSignatureInformation >
169 DocumentDigitalSignatures::verifyPackageSignatures(
170 const Reference< css::embed::XStorage >& rxStorage,
171 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
173 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
174 return ImplVerifySignatures( rxStorage, xSignInStream, SignatureModePackage );
177 void DocumentDigitalSignatures::showPackageSignatures(
178 const Reference< css::embed::XStorage >& rxStorage,
179 const Reference< css::io::XInputStream >& xSignInStream ) throw (RuntimeException)
181 OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
182 ImplViewSignatures( rxStorage, xSignInStream, SignatureModePackage, true );
185 OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName( )
186 throw (::com::sun::star::uno::RuntimeException)
188 return DocumentSignatureHelper::GetPackageSignatureDefaultStreamName();
192 sal_Bool DocumentDigitalSignatures::ImplViewSignatures(
193 const Reference< css::embed::XStorage >& rxStorage,
194 const Reference< css::io::XInputStream >& xSignStream,
195 DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException)
197 Reference< io::XStream > xStream;
198 if ( xSignStream.is() )
199 xStream = Reference< io::XStream >( xSignStream, UNO_QUERY );
200 return ImplViewSignatures( rxStorage, xStream, eMode, bReadOnly );
203 sal_Bool DocumentDigitalSignatures::ImplViewSignatures(
204 const Reference< css::embed::XStorage >& rxStorage, const Reference< css::io::XStream >& xSignStream,
205 DocumentSignatureMode eMode, bool bReadOnly ) throw (RuntimeException)
207 sal_Bool bChanges = sal_False;
208 DigitalSignaturesDialog aSignaturesDialog(
209 NULL, mxCtx, eMode, bReadOnly, m_sODFVersion, m_bHasDocumentSignature);
210 bool bInit = aSignaturesDialog.Init();
211 DBG_ASSERT( bInit, "Error initializing security context!" );
212 if ( bInit )
214 aSignaturesDialog.SetStorage( rxStorage );
215 aSignaturesDialog.SetSignatureStream( xSignStream );
216 if ( aSignaturesDialog.Execute() )
218 if ( aSignaturesDialog.SignaturesChanged() )
220 bChanges = sal_True;
221 // If we have a storage and no stream, we are responsible for commit
222 if ( rxStorage.is() && !xSignStream.is() )
224 uno::Reference< embed::XTransactedObject > xTrans( rxStorage, uno::UNO_QUERY );
225 xTrans->commit();
230 else
232 WarningBox aBox( NULL, XMLSEC_RES( RID_XMLSECWB_NO_MOZILLA_PROFILE ) );
233 aBox.Execute();
236 return bChanges;
239 Sequence< css::security::DocumentSignatureInformation >
240 DocumentDigitalSignatures::ImplVerifySignatures(
241 const Reference< css::embed::XStorage >& rxStorage,
242 const Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode ) throw (RuntimeException)
244 if (!rxStorage.is())
246 DBG_ASSERT(0, "Error, no XStorage provided");
247 return Sequence<css::security::DocumentSignatureInformation>();
249 // First check for the InputStream, to avoid unnecessary initialization of the security environemnt...
250 SignatureStreamHelper aStreamHelper;
251 Reference< io::XInputStream > xInputStream = xSignStream;
253 if ( !xInputStream.is() )
255 aStreamHelper = DocumentSignatureHelper::OpenSignatureStream( rxStorage, embed::ElementModes::READ, eMode );
256 if ( aStreamHelper.xSignatureStream.is() )
257 xInputStream = Reference< io::XInputStream >( aStreamHelper.xSignatureStream, UNO_QUERY );
260 if ( !xInputStream.is() )
261 return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0);
264 XMLSignatureHelper aSignatureHelper( mxCtx );
266 bool bInit = aSignatureHelper.Init();
268 DBG_ASSERT( bInit, "Error initializing security context!" );
270 if ( !bInit )
271 return Sequence< ::com::sun::star::security::DocumentSignatureInformation >(0);
273 aSignatureHelper.SetStorage(rxStorage, m_sODFVersion);
275 aSignatureHelper.StartMission();
277 aSignatureHelper.ReadAndVerifySignature( xInputStream );
279 aSignatureHelper.EndMission();
281 Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = aSignatureHelper.GetSecurityEnvironment();
283 SignatureInformations aSignInfos = aSignatureHelper.GetSignatureInformations();
284 int nInfos = aSignInfos.size();
285 Sequence< css::security::DocumentSignatureInformation > aInfos(nInfos);
286 css::security::DocumentSignatureInformation* arInfos = aInfos.getArray();
288 if ( nInfos )
290 Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
291 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
293 for( int n = 0; n < nInfos; ++n )
295 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
296 m_sODFVersion, aSignInfos[n]);
297 const std::vector< OUString > aElementsToBeVerified =
298 DocumentSignatureHelper::CreateElementList(
299 rxStorage, OUString(), eMode, mode);
301 const SignatureInformation& rInfo = aSignInfos[n];
302 css::security::DocumentSignatureInformation& rSigInfo = arInfos[n];
304 if (!rInfo.ouX509Certificate.isEmpty())
305 rSigInfo.Signer = xSecEnv->createCertificateFromAscii( rInfo.ouX509Certificate ) ;
306 if (!rSigInfo.Signer.is())
307 rSigInfo.Signer = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
309 // Time support again (#i38744#)
310 Date aDate( rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year );
311 Time aTime( rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes,
312 rInfo.stDateTime.Seconds, rInfo.stDateTime.NanoSeconds );
313 rSigInfo.SignatureDate = aDate.GetDate();
314 rSigInfo.SignatureTime = aTime.GetTime();
316 // Verify certificate
317 //We have patched our version of libxmlsec, so that it does not verify the certificates. This has two
318 //reasons. First we want two separate status for signature and certificate. Second libxmlsec calls
319 //CERT_VerifyCertificate (solaris, linux) falsly, so that it always regards the certificate as valid.
320 //On Window the checking of the certificate path is buggy. It does name matching (issuer, subject name)
321 //to find the parent certificate. It does not take into account that there can be several certificates
322 //with the same subject name.
323 if (rSigInfo.Signer.is())
325 try {
326 rSigInfo.CertificateStatus = xSecEnv->verifyCertificate(rSigInfo.Signer,
327 Sequence<Reference<css::security::XCertificate> >());
328 } catch (SecurityException& ) {
329 OSL_FAIL("Verification of certificate failed");
330 rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
333 else
335 //We should always be aible to get the certificates because it is contained in the document,
336 //unless the document is damaged so that signature xml file could not be parsed.
337 rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
340 rSigInfo.SignatureIsValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
343 if ( rSigInfo.SignatureIsValid )
345 rSigInfo.SignatureIsValid =
346 DocumentSignatureHelper::checkIfAllFilesAreSigned(
347 aElementsToBeVerified, rInfo, mode);
349 if (eMode == SignatureModeDocumentContent)
350 rSigInfo.PartialDocumentSignature =
351 ! DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]);
355 return aInfos;
359 void DocumentDigitalSignatures::manageTrustedSources( ) throw (RuntimeException)
361 // MT: i45295
362 // SecEnv is only needed to display certificate information from trusted sources.
363 // Macro Security also has some options where no security environment is needed, so raise dialog anyway.
364 // Later I should change the code so the Dialog creates the SecEnv on demand...
366 Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv;
368 XMLSignatureHelper aSignatureHelper( mxCtx );
369 if ( aSignatureHelper.Init() )
370 xSecEnv = aSignatureHelper.GetSecurityEnvironment();
372 MacroSecurity aDlg( NULL, mxCtx, xSecEnv );
373 aDlg.Execute();
376 void DocumentDigitalSignatures::showCertificate(
377 const Reference< css::security::XCertificate >& _Certificate ) throw (RuntimeException)
379 XMLSignatureHelper aSignatureHelper( mxCtx );
381 bool bInit = aSignatureHelper.Init();
383 DBG_ASSERT( bInit, "Error initializing security context!" );
385 if ( bInit )
387 CertificateViewer aViewer( NULL, aSignatureHelper.GetSecurityEnvironment(), _Certificate, sal_False );
388 aViewer.Execute();
393 ::sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
394 const Reference< css::security::XCertificate >& Author ) throw (RuntimeException)
396 sal_Bool bFound = sal_False;
398 Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
399 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
401 OUString sSerialNum = xSerialNumberAdapter->toString( Author->getSerialNumber() );
403 Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors();
404 const SvtSecurityOptions::Certificate* pAuthors = aTrustedAuthors.getConstArray();
405 const SvtSecurityOptions::Certificate* pAuthorsEnd = pAuthors + aTrustedAuthors.getLength();
406 for ( ; pAuthors != pAuthorsEnd; ++pAuthors )
408 SvtSecurityOptions::Certificate aAuthor = *pAuthors;
409 if ( ( aAuthor[0] == Author->getIssuerName() ) && ( aAuthor[1] == sSerialNum ) )
411 bFound = sal_True;
412 break;
416 return bFound;
419 Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificate() throw (RuntimeException)
421 Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv;
423 XMLSignatureHelper aSignatureHelper( mxCtx );
424 if ( aSignatureHelper.Init() )
425 xSecEnv = aSignatureHelper.GetSecurityEnvironment();
427 CertificateChooser aChooser( NULL, mxCtx, xSecEnv, aSignatureHelper.GetSignatureInformations());
429 if (aChooser.Execute() != RET_OK)
430 return Reference< css::security::XCertificate >(0);
432 Reference< css::security::XCertificate > xCert = aChooser.GetSelectedCertificate();
434 if ( !xCert.is() )
435 return Reference< css::security::XCertificate >(0);
437 return xCert;
441 ::sal_Bool DocumentDigitalSignatures::isLocationTrusted( const OUString& Location ) throw (RuntimeException)
443 sal_Bool bFound = sal_False;
444 INetURLObject aLocObj( Location );
445 INetURLObject aLocObjLowCase( Location.toAsciiLowerCase() ); // will be used for case insensitive comparing
447 Sequence< OUString > aSecURLs = SvtSecurityOptions().GetSecureURLs();
448 const OUString* pSecURLs = aSecURLs.getConstArray();
449 const OUString* pSecURLsEnd = pSecURLs + aSecURLs.getLength();
450 for ( ; pSecURLs != pSecURLsEnd && !bFound; ++pSecURLs )
451 bFound = ::utl::UCBContentHelper::IsSubPath( *pSecURLs, Location );
453 return bFound;
456 void DocumentDigitalSignatures::addAuthorToTrustedSources(
457 const Reference< css::security::XCertificate >& Author ) throw (RuntimeException)
459 SvtSecurityOptions aSecOpts;
461 Reference<security::XSerialNumberAdapter> xSerialNumberAdapter =
462 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
464 SvtSecurityOptions::Certificate aNewCert( 3 );
465 aNewCert[ 0 ] = Author->getIssuerName();
466 aNewCert[ 1 ] = xSerialNumberAdapter->toString( Author->getSerialNumber() );
468 OUStringBuffer aStrBuffer;
469 ::sax::Converter::encodeBase64(aStrBuffer, Author->getEncoded());
470 aNewCert[ 2 ] = aStrBuffer.makeStringAndClear();
473 Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = aSecOpts.GetTrustedAuthors();
474 sal_Int32 nCnt = aTrustedAuthors.getLength();
475 aTrustedAuthors.realloc( nCnt + 1 );
476 aTrustedAuthors[ nCnt ] = aNewCert;
478 aSecOpts.SetTrustedAuthors( aTrustedAuthors );
481 void DocumentDigitalSignatures::addLocationToTrustedSources( const OUString& Location ) throw (RuntimeException)
483 SvtSecurityOptions aSecOpt;
485 Sequence< OUString > aSecURLs = aSecOpt.GetSecureURLs();
486 sal_Int32 nCnt = aSecURLs.getLength();
487 aSecURLs.realloc( nCnt + 1 );
488 aSecURLs[ nCnt ] = Location;
490 aSecOpt.SetSecureURLs( aSecURLs );
493 OUString DocumentDigitalSignatures::GetImplementationName() throw (RuntimeException)
495 return OUString( "com.sun.star.security.DocumentDigitalSignatures" );
498 Sequence< OUString > DocumentDigitalSignatures::GetSupportedServiceNames() throw (css::uno::RuntimeException)
500 Sequence < OUString > aRet(1);
501 OUString* pArray = aRet.getArray();
502 pArray[0] = OUString( "com.sun.star.security.DocumentDigitalSignatures" );
503 return aRet;
507 Reference< XInterface > DocumentDigitalSignatures_CreateInstance(
508 const Reference< XComponentContext >& rCtx) throw ( Exception )
510 return (cppu::OWeakObject*) new DocumentDigitalSignatures( rCtx );
513 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */