merged tag ooo/OOO330_m14
[LibreOffice.git] / xmlsecurity / source / dialogs / digitalsignaturesdialog.cxx
blobdf032dcbe5ef2b52c972cb536a2aa763bf79a666
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
30 #include <xmlsecurity/digitalsignaturesdialog.hxx>
31 #include <xmlsecurity/certificatechooser.hxx>
32 #include <xmlsecurity/certificateviewer.hxx>
33 #include <xmlsecurity/biginteger.hxx>
34 #include <xmloff/xmluconv.hxx>
35 #include <com/sun/star/embed/XStorage.hpp>
36 #include <com/sun/star/embed/ElementModes.hpp>
37 #include <com/sun/star/io/XSeekable.hpp>
38 #include <com/sun/star/io/XTruncate.hpp>
39 #include <com/sun/star/embed/XTransactedObject.hpp>
40 #include <com/sun/star/container/XNameAccess.hpp>
41 #include <com/sun/star/lang/XComponent.hpp>
42 #include <com/sun/star/security/NoPasswordException.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/security/CertificateValidity.hdl>
46 #include <com/sun/star/packages/WrongPasswordException.hpp>
47 #include <com/sun/star/security/SerialNumberAdapter.hpp>
48 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
49 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
50 #include <com/sun/star/packages/manifest/XManifestReader.hpp>
53 #include <rtl/ustrbuf.hxx>
54 #include <rtl/uri.hxx>
56 #include <tools/date.hxx>
57 #include <tools/time.hxx>
59 #include "dialogs.hrc"
60 #include "digitalsignaturesdialog.hrc"
61 #include "helpids.hrc"
62 #include "resourcemanager.hxx"
64 #include <vcl/msgbox.hxx> // Until encrypted docs work...
65 #include <unotools/configitem.hxx>
66 #include <comphelper/componentcontext.hxx>
68 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
71 /* HACK: disable some warnings for MS-C */
72 #ifdef _MSC_VER
73 #pragma warning (disable : 4355) // 4355: this used in initializer-list
74 #endif
76 using namespace ::com::sun::star::security;
77 using namespace ::com::sun::star::uno;
78 using namespace ::com::sun::star;
79 namespace css = ::com::sun::star;
80 using ::rtl::OUString;
82 namespace
84 class SaveODFItem: public utl::ConfigItem
86 sal_Int16 m_nODF;
87 public:
88 virtual void Commit();
89 virtual void Notify( const ::com::sun::star::uno::Sequence< rtl::OUString >& aPropertyNames );
90 SaveODFItem();
91 //See group ODF in Common.xcs
92 bool isLessODF1_2()
94 return m_nODF < 3;
98 void SaveODFItem::Commit() {}
99 void SaveODFItem::Notify( const ::com::sun::star::uno::Sequence< rtl::OUString >& ) {}
101 SaveODFItem::SaveODFItem(): utl::ConfigItem(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
102 "Office.Common/Save"))), m_nODF(0)
104 OUString sDef(RTL_CONSTASCII_USTRINGPARAM("ODF/DefaultVersion"));
105 Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
106 if ( aValues.getLength() == 1)
108 sal_Int16 nTmp = 0;
109 if ( aValues[0] >>= nTmp )
110 m_nODF = nTmp;
111 else
112 throw uno::RuntimeException(
113 OUString(RTL_CONSTASCII_USTRINGPARAM(
114 "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!")), 0 );
117 else
118 throw uno::RuntimeException(
119 OUString(RTL_CONSTASCII_USTRINGPARAM(
120 "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion")), 0);
124 /* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
125 We use the manifest to find out if a file is xml and if it is encrypted.
126 The parameter is an encoded uri. However, the manifest contains paths. Therefore
127 the path is encoded as uri, so they can be compared.
129 bool DigitalSignaturesDialog::isXML(const rtl::OUString& rURI )
131 OSL_ASSERT(mxStore.is());
133 bool bIsXML = false;
134 bool bPropsAvailable = false;
135 const OUString sPropFullPath(RTL_CONSTASCII_USTRINGPARAM("FullPath"));
136 const OUString sPropMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
137 const OUString sPropDigest(RTL_CONSTASCII_USTRINGPARAM("Digest"));
139 for (int i = 0; i < m_manifest.getLength(); i++)
141 Any digest;
142 const Sequence< css::beans::PropertyValue >& entry = m_manifest[i];
143 OUString sPath, sMediaType;
144 bool bEncrypted = false;
145 for (int j = 0; j < entry.getLength(); j++)
147 const css::beans::PropertyValue & prop = entry[j];
149 if (prop.Name.equals( sPropFullPath ) )
150 prop.Value >>= sPath;
151 else if (prop.Name.equals( sPropMediaType ) )
152 prop.Value >>= sMediaType;
153 else if (prop.Name.equals( sPropDigest ) )
154 bEncrypted = true;
156 if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
158 bIsXML = sMediaType.equals(OUSTR("text/xml")) && ! bEncrypted;
159 bPropsAvailable = true;
160 break;
163 if (!bPropsAvailable)
165 //This would be the case for at least mimetype, META-INF/manifest.xml
166 //META-INF/macrosignatures.xml.
167 //Files can only be encrypted if they are in the manifest.xml.
168 //That is, the current file cannot be encrypted, otherwise bPropsAvailable
169 //would be true.
170 OUString aXMLExt( RTL_CONSTASCII_USTRINGPARAM( "XML" ) );
171 sal_Int32 nSep = rURI.lastIndexOf( '.' );
172 if ( nSep != (-1) )
174 OUString aExt = rURI.copy( nSep+1 );
175 if (aExt.equalsIgnoreAsciiCase(aXMLExt ))
176 bIsXML = true;
179 return bIsXML;
182 DigitalSignaturesDialog::DigitalSignaturesDialog(
183 Window* pParent,
184 uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
185 sal_Bool bReadOnly, const ::rtl::OUString& sODFVersion, bool bHasDocumentSignature)
186 :ModalDialog ( pParent, XMLSEC_RES( RID_XMLSECDLG_DIGSIG ) )
187 ,mxCtx ( rxCtx )
188 ,maSignatureHelper ( rxCtx )
189 ,meSignatureMode ( eMode )
190 ,maHintDocFT ( this, XMLSEC_RES( FT_HINT_DOC ) )
191 ,maHintBasicFT ( this, XMLSEC_RES( FT_HINT_BASIC ) )
192 ,maHintPackageFT ( this, XMLSEC_RES( FT_HINT_PACK ) )
193 ,maSignaturesLB ( this, XMLSEC_RES( LB_SIGNATURES ) )
194 ,maSigsValidImg ( this, XMLSEC_RES( IMG_STATE_VALID ) )
195 ,maSigsValidFI ( this, XMLSEC_RES( FI_STATE_VALID ) )
196 ,maSigsInvalidImg ( this, XMLSEC_RES( IMG_STATE_BROKEN ) )
197 ,maSigsInvalidFI ( this, XMLSEC_RES( FI_STATE_BROKEN ) )
198 ,maSigsNotvalidatedImg( this, XMLSEC_RES( IMG_STATE_NOTVALIDATED ) )
199 ,maSigsNotvalidatedFI ( this, XMLSEC_RES( FI_STATE_NOTVALIDATED ) )
200 ,maSigsOldSignatureFI ( this, XMLSEC_RES( FI_STATE_OLDSIGNATURE) )
201 ,maViewBtn ( this, XMLSEC_RES( BTN_VIEWCERT ) )
202 ,maAddBtn ( this, XMLSEC_RES( BTN_ADDCERT ) )
203 ,maRemoveBtn ( this, XMLSEC_RES( BTN_REMOVECERT ) )
204 ,maBottomSepFL ( this, XMLSEC_RES( FL_BOTTOM_SEP ) )
205 ,maOKBtn ( this, XMLSEC_RES( BTN_OK ) )
206 ,maHelpBtn ( this, XMLSEC_RES( BTN_HELP ) )
207 ,m_sODFVersion (sODFVersion)
208 ,m_bHasDocumentSignature(bHasDocumentSignature)
209 ,m_bWarningShowSignMacro(false)
211 // --> PB #i48253 the tablistbox needs its own unique id
212 maSignaturesLB.Window::SetUniqueId( HID_XMLSEC_TREE_SIGNATURESDLG );
213 // <--
214 Size aControlSize( maSignaturesLB.GetSizePixel() );
215 aControlSize = maSignaturesLB.PixelToLogic( aControlSize, MapMode( MAP_APPFONT ) );
216 const long nControlWidth = aControlSize.Width();
217 static long nTabs[] = { 4, 0, 6*nControlWidth/100, 36*nControlWidth/100, 74*nControlWidth/100 };
218 maSignaturesLB.SetTabs( &nTabs[ 0 ] );
219 maSignaturesLB.InsertHeaderEntry( String( XMLSEC_RES( STR_HEADERBAR ) ) );
221 maSigsNotvalidatedFI.SetText( String( XMLSEC_RES( STR_NO_INFO_TO_VERIFY ) ) );
223 if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
225 // high contrast mode needs other images
226 maSigsValidImg.SetImage( Image( XMLSEC_RES( IMG_STATE_VALID_HC ) ) );
227 maSigsInvalidImg.SetImage( Image( XMLSEC_RES( IMG_STATE_BROKEN_HC ) ) );
228 maSigsNotvalidatedImg.SetImage( Image( XMLSEC_RES( IMG_STATE_NOTVALIDATED_HC ) ) );
231 FreeResource();
233 mbVerifySignatures = true;
234 mbSignaturesChanged = false;
236 maSignaturesLB.SetSelectHdl( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
237 maSignaturesLB.SetDoubleClickHdl( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
239 maViewBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
240 maViewBtn.Disable();
242 maAddBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
243 if ( bReadOnly )
244 maAddBtn.Disable();
246 maRemoveBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
247 maRemoveBtn.Disable();
249 maOKBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
251 switch( meSignatureMode )
253 case SignatureModeDocumentContent: maHintDocFT.Show(); break;
254 case SignatureModeMacros: maHintBasicFT.Show(); break;
255 case SignatureModePackage: maHintPackageFT.Show(); break;
258 // adjust fixed text to images
259 XmlSec::AlignAndFitImageAndControl( maSigsValidImg, maSigsValidFI, 5 );
260 XmlSec::AlignAndFitImageAndControl( maSigsInvalidImg, maSigsInvalidFI, 5 );
261 XmlSec::AlignAndFitImageAndControl( maSigsNotvalidatedImg, maSigsNotvalidatedFI, 5 );
262 XmlSec::AlignAndFitImageAndControl( maSigsNotvalidatedImg, maSigsOldSignatureFI, 5 );
265 DigitalSignaturesDialog::~DigitalSignaturesDialog()
269 BOOL DigitalSignaturesDialog::Init( const rtl::OUString& rTokenName )
271 bool bInit = maSignatureHelper.Init( rTokenName );
273 DBG_ASSERT( bInit, "Error initializing security context!" );
275 if ( bInit )
277 maSignatureHelper.SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
280 return bInit;
283 void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore )
285 mxStore = rxStore;
286 maSignatureHelper.SetStorage( mxStore, m_sODFVersion);
288 Reference < css::packages::manifest::XManifestReader > xReader(
289 mxCtx->getServiceManager()->createInstanceWithContext(
290 OUSTR("com.sun.star.packages.manifest.ManifestReader"), mxCtx), UNO_QUERY_THROW);
292 //Get the manifest.xml
293 Reference < css::embed::XStorage > xSubStore(rxStore->openStorageElement(
294 OUSTR("META-INF"), css::embed::ElementModes::READ), UNO_QUERY_THROW);
296 Reference< css::io::XInputStream > xStream(
297 xSubStore->openStreamElement(OUSTR("manifest.xml"), css::embed::ElementModes::READ),
298 UNO_QUERY_THROW);
300 m_manifest = xReader->readManifestSequence(xStream);
303 void DigitalSignaturesDialog::SetSignatureStream( const cssu::Reference < css::io::XStream >& rxStream )
305 mxSignatureStream = rxStream;
308 bool DigitalSignaturesDialog::canAddRemove()
310 //m56
311 bool ret = true;
312 OSL_ASSERT(mxStore.is());
313 bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
314 SaveODFItem item;
315 bool bSave1_1 = item.isLessODF1_2();
317 // see specification
318 //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
319 //Paragraph 'Behavior with regard to ODF 1.2'
320 //For both, macro and document
321 if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
323 //#4
324 ErrorBox err(NULL, XMLSEC_RES(RID_XMLSECDLG_OLD_ODF_FORMAT));
325 err.Execute();
326 ret = false;
329 //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
330 //adding a macro signature will break an existing document signature.
331 //The sfx2 will remove the documentsignature when the user adds a macro signature
332 if (meSignatureMode == SignatureModeMacros
333 && ret)
335 if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
337 //The warning says that the document signatures will be removed if the user
338 //continues. He can then either press 'OK' or 'NO'
339 //It the user presses 'Add' or 'Remove' several times then, then the warning
340 //is shown every time until the user presses 'OK'. From then on, the warning
341 //is not displayed anymore as long as the signatures dialog is alive.
342 if (QueryBox(
343 NULL, XMLSEC_RES(MSG_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)).Execute() == RET_NO)
344 ret = false;
345 else
346 m_bWarningShowSignMacro = true;
350 return ret;
353 bool DigitalSignaturesDialog::canAdd()
355 if (canAddRemove())
356 return true;
357 return false;
360 bool DigitalSignaturesDialog::canRemove()
362 if (canAddRemove())
363 return true;
364 return false;
367 short DigitalSignaturesDialog::Execute()
369 // Verify Signatures and add certificates to ListBox...
370 mbVerifySignatures = true;
371 ImplGetSignatureInformations(false);
372 ImplFillSignaturesBox();
374 // Only verify once, content will not change.
375 // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
376 mbVerifySignatures = false;
378 return Dialog::Execute();
381 IMPL_LINK( DigitalSignaturesDialog, SignatureHighlightHdl, void*, EMPTYARG )
383 bool bSel = maSignaturesLB.FirstSelected() ? true : false;
384 maViewBtn.Enable( bSel );
385 if ( maAddBtn.IsEnabled() ) // not read only
386 maRemoveBtn.Enable( bSel );
388 return 0;
391 IMPL_LINK( DigitalSignaturesDialog, OKButtonHdl, void*, EMPTYARG )
393 // Export all other signatures...
394 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
395 embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE, false );
396 uno::Reference< io::XOutputStream > xOutputStream(
397 aStreamHelper.xSignatureStream, uno::UNO_QUERY );
398 uno::Reference< com::sun::star::xml::sax::XDocumentHandler> xDocumentHandler =
399 maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
401 int nInfos = maCurrentSignatureInformations.size();
402 for( int n = 0 ; n < nInfos ; ++n )
403 maSignatureHelper.ExportSignature(
404 xDocumentHandler, maCurrentSignatureInformations[ n ] );
406 maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
408 // If stream was not provided, we are responsible for committing it....
409 if ( !mxSignatureStream.is() )
411 uno::Reference< embed::XTransactedObject > xTrans(
412 aStreamHelper.xSignatureStorage, uno::UNO_QUERY );
413 xTrans->commit();
416 EndDialog(RET_OK);
417 return 0;
420 IMPL_LINK( DigitalSignaturesDialog, SignatureSelectHdl, void*, EMPTYARG )
422 ImplShowSignaturesDetails();
423 return 0;
426 IMPL_LINK( DigitalSignaturesDialog, ViewButtonHdl, Button*, EMPTYARG )
428 ImplShowSignaturesDetails();
429 return 0;
432 IMPL_LINK( DigitalSignaturesDialog, AddButtonHdl, Button*, EMPTYARG )
434 if( ! canAdd())
435 return 0;
438 uno::Reference<com::sun::star::xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureHelper.GetSecurityEnvironment();
440 uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
441 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
442 CertificateChooser aChooser( this, mxCtx, xSecEnv, maCurrentSignatureInformations );
443 if ( aChooser.Execute() == RET_OK )
445 uno::Reference< ::com::sun::star::security::XCertificate > xCert = aChooser.GetSelectedCertificate();
446 if ( !xCert.is() )
448 DBG_ERRORFILE( "no certificate selected" );
449 return -1;
451 rtl::OUString aCertSerial = xSerialNumberAdapter->toString( xCert->getSerialNumber() );
452 if ( !aCertSerial.getLength() )
454 DBG_ERROR( "Error in Certificate, problem with serial number!" );
455 return -1;
458 maSignatureHelper.StartMission();
460 sal_Int32 nSecurityId = maSignatureHelper.GetNewSecurityId();
462 rtl::OUStringBuffer aStrBuffer;
463 SvXMLUnitConverter::encodeBase64(aStrBuffer, xCert->getEncoded());
465 maSignatureHelper.SetX509Certificate( nSecurityId,
466 xCert->getIssuerName(), aCertSerial,
467 aStrBuffer.makeStringAndClear());
469 std::vector< rtl::OUString > aElements =
470 DocumentSignatureHelper::CreateElementList(
471 mxStore, rtl::OUString(), meSignatureMode, OOo3_2Document);
473 sal_Int32 nElements = aElements.size();
474 for ( sal_Int32 n = 0; n < nElements; n++ )
476 bool bBinaryMode = !isXML(aElements[n]);
477 maSignatureHelper.AddForSigning( nSecurityId, aElements[n], aElements[n], bBinaryMode );
480 maSignatureHelper.SetDateTime( nSecurityId, Date(), Time() );
482 // We open a signature stream in which the existing and the new
483 //signature is written. ImplGetSignatureInformation (later in this function) will
484 //then read the stream an will fill maCurrentSignatureInformations. The final signature
485 //is written when the user presses OK. Then only maCurrentSignatureInformation and
486 //a sax writer are used to write the information.
487 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
488 css::embed::ElementModes::WRITE|css::embed::ElementModes::TRUNCATE, true);
489 Reference< css::io::XOutputStream > xOutputStream(
490 aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
491 Reference< css::xml::sax::XDocumentHandler> xDocumentHandler =
492 maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
494 // Export old signatures...
495 int nInfos = maCurrentSignatureInformations.size();
496 for ( int n = 0; n < nInfos; n++ )
497 maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[n]);
499 // Create a new one...
500 maSignatureHelper.CreateAndWriteSignature( xDocumentHandler );
502 // That's it...
503 maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
505 maSignatureHelper.EndMission();
507 aStreamHelper = SignatureStreamHelper(); // release objects...
509 mbSignaturesChanged = true;
511 sal_Int32 nStatus = maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus;
513 if ( nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
515 mbSignaturesChanged = true;
517 // Can't simply remember current information, need parsing for getting full information :(
518 // We need to verify the signatures again, otherwise the status in the signature information
519 // will not contain
520 // SecurityOperationStatus_OPERATION_SUCCEEDED
521 mbVerifySignatures = true;
522 ImplGetSignatureInformations(true);
523 ImplFillSignaturesBox();
527 catch ( uno::Exception& )
529 DBG_ERROR( "Exception while adding a signature!" );
530 // Don't keep invalid entries...
531 ImplGetSignatureInformations(true);
532 ImplFillSignaturesBox();
535 return 0;
538 IMPL_LINK( DigitalSignaturesDialog, RemoveButtonHdl, Button*, EMPTYARG )
540 if (!canRemove())
541 return 0;
542 if( maSignaturesLB.FirstSelected() )
546 USHORT nSelected = (USHORT) (sal_uIntPtr) maSignaturesLB.FirstSelected()->GetUserData();
547 maCurrentSignatureInformations.erase( maCurrentSignatureInformations.begin()+nSelected );
549 // Export all other signatures...
550 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
551 css::embed::ElementModes::WRITE | css::embed::ElementModes::TRUNCATE, true);
552 Reference< css::io::XOutputStream > xOutputStream(
553 aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
554 Reference< css::xml::sax::XDocumentHandler> xDocumentHandler =
555 maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
557 int nInfos = maCurrentSignatureInformations.size();
558 for( int n = 0 ; n < nInfos ; ++n )
559 maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[ n ] );
561 maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
563 mbSignaturesChanged = true;
565 aStreamHelper = SignatureStreamHelper(); // release objects...
567 ImplFillSignaturesBox();
569 catch ( uno::Exception& )
571 DBG_ERROR( "Exception while removing a signature!" );
572 // Don't keep invalid entries...
573 ImplGetSignatureInformations(true);
574 ImplFillSignaturesBox();
578 return 0;
581 IMPL_LINK( DigitalSignaturesDialog, StartVerifySignatureHdl, void*, EMPTYARG )
583 return mbVerifySignatures ? 1 : 0;
586 void DigitalSignaturesDialog::ImplFillSignaturesBox()
588 maSignaturesLB.Clear();
590 uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = maSignatureHelper.GetSecurityEnvironment();
591 uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
592 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
594 uno::Reference< ::com::sun::star::security::XCertificate > xCert;
596 String aNullStr;
597 int nInfos = maCurrentSignatureInformations.size();
598 int nValidSigs = 0, nValidCerts = 0;
599 bool bAllNewSignatures = true;
601 if( nInfos )
603 for( int n = 0; n < nInfos; ++n )
605 DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
606 m_sODFVersion, maCurrentSignatureInformations[n]);
607 std::vector< rtl::OUString > aElementsToBeVerified =
608 DocumentSignatureHelper::CreateElementList(
609 mxStore, ::rtl::OUString(), meSignatureMode, mode);
611 const SignatureInformation& rInfo = maCurrentSignatureInformations[n];
612 //First we try to get the certificate which is embedded in the XML Signature
613 if (rInfo.ouX509Certificate.getLength())
614 xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
615 else {
616 //There must be an embedded certificate because we use it to get the
617 //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
618 //because it could be modified by an attacker. The issuer is displayed
619 //in the digital signature dialog.
620 //Comparing the X509IssuerName with the one from the X509Certificate in order
621 //to find out if the X509IssuerName was modified does not work. See #i62684
622 DBG_ASSERT(sal_False, "Could not find embedded certificate!");
625 //In case there is no embedded certificate we try to get it from a local store
626 //Todo: This probably could be removed, see above.
627 if (!xCert.is())
628 xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
630 DBG_ASSERT( xCert.is(), "Certificate not found and can't be created!" );
632 String aSubject;
633 String aIssuer;
634 String aDateTimeStr;
636 bool bSigValid = false;
637 bool bCertValid = false;
638 if( xCert.is() )
640 //check the validity of the cert
641 try {
642 sal_Int32 certResult = xSecEnv->verifyCertificate(xCert,
643 Sequence<css::uno::Reference<css::security::XCertificate> >());
645 bCertValid = certResult == css::security::CertificateValidity::VALID ? true : false;
646 if ( bCertValid )
647 nValidCerts++;
649 } catch (css::uno::SecurityException& ) {
650 OSL_ENSURE(0, "Verification of certificate failed");
651 bCertValid = false;
654 aSubject = XmlSec::GetContentPart( xCert->getSubjectName() );
655 aIssuer = XmlSec::GetContentPart( xCert->getIssuerName() );
656 // --> PB 2004-10-12 #i20172# String with date and time information
657 aDateTimeStr = XmlSec::GetDateTimeString( rInfo.stDateTime );
659 bSigValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
661 if ( bSigValid )
663 bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
664 aElementsToBeVerified, rInfo, mode);
666 if( bSigValid )
667 nValidSigs++;
670 Image aImage;
671 if (!bSigValid)
673 aImage = maSigsInvalidImg.GetImage();
675 else if (bSigValid && !bCertValid)
677 aImage = maSigsNotvalidatedImg.GetImage();
679 //Check if the signature is a "old" document signature, that is, which was created
680 //by an version of OOo previous to 3.2
681 else if (meSignatureMode == SignatureModeDocumentContent
682 && bSigValid && bCertValid && !DocumentSignatureHelper::isOOo3_2_Signature(
683 maCurrentSignatureInformations[n]))
685 aImage = maSigsNotvalidatedImg.GetImage();
686 bAllNewSignatures &= false;
688 else if (meSignatureMode == SignatureModeDocumentContent
689 && bSigValid && bCertValid && DocumentSignatureHelper::isOOo3_2_Signature(
690 maCurrentSignatureInformations[n]))
692 aImage = maSigsValidImg.GetImage();
694 else if (meSignatureMode == SignatureModeMacros
695 && bSigValid && bCertValid)
697 aImage = aImage = maSigsValidImg.GetImage();
700 SvLBoxEntry* pEntry = maSignaturesLB.InsertEntry( aNullStr, aImage, aImage );
701 maSignaturesLB.SetEntryText( aSubject, pEntry, 1 );
702 maSignaturesLB.SetEntryText( aIssuer, pEntry, 2 );
703 maSignaturesLB.SetEntryText( aDateTimeStr, pEntry, 3 );
704 pEntry->SetUserData( ( void* ) n ); // missuse user data as index
708 bool bAllSigsValid = (nValidSigs == nInfos);
709 bool bAllCertsValid = (nValidCerts == nInfos);
710 bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
712 bool bShowNotValidatedState = nInfos && (bAllSigsValid && (!bAllCertsValid || !bAllNewSignatures));
713 bool bShowInvalidState = nInfos && !bAllSigsValid;
715 maSigsValidImg.Show( bShowValidState);
716 maSigsValidFI.Show( bShowValidState );
717 maSigsInvalidImg.Show( bShowInvalidState );
718 maSigsInvalidFI.Show( bShowInvalidState );
720 maSigsNotvalidatedImg.Show(bShowNotValidatedState);
721 //bAllNewSignatures is always true if we are not in document mode
722 maSigsNotvalidatedFI.Show(nInfos && bAllSigsValid && ! bAllCertsValid);
723 maSigsOldSignatureFI.Show(nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures);
725 SignatureHighlightHdl( NULL );
729 //If bUseTempStream is true then the temporary signature stream is used.
730 //Otherwise the real signature stream is used.
731 void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream)
733 maCurrentSignatureInformations.clear();
735 maSignatureHelper.StartMission();
737 SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
738 css::embed::ElementModes::READ, bUseTempStream);
739 if ( aStreamHelper.xSignatureStream.is() )
741 uno::Reference< io::XInputStream > xInputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY );
742 maSignatureHelper.ReadAndVerifySignature( xInputStream );
744 maSignatureHelper.EndMission();
746 maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
748 mbVerifySignatures = false;
751 void DigitalSignaturesDialog::ImplShowSignaturesDetails()
753 if( maSignaturesLB.FirstSelected() )
755 USHORT nSelected = (USHORT) (sal_uIntPtr) maSignaturesLB.FirstSelected()->GetUserData();
756 const SignatureInformation& rInfo = maCurrentSignatureInformations[ nSelected ];
757 css::uno::Reference<css::xml::crypto::XSecurityEnvironment > xSecEnv =
758 maSignatureHelper.GetSecurityEnvironment();
759 css::uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
760 ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
761 // Use Certificate from doc, not from key store
762 uno::Reference< dcss::security::XCertificate > xCert;
763 if (rInfo.ouX509Certificate.getLength())
764 xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
765 //fallback if no certificate is embedded, get if from store
766 if (!xCert.is())
767 xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
769 DBG_ASSERT( xCert.is(), "Error getting cCertificate!" );
770 if ( xCert.is() )
772 CertificateViewer aViewer( this, maSignatureHelper.GetSecurityEnvironment(), xCert, FALSE );
773 aViewer.Execute();
778 //If bTempStream is true, then a temporary stream is return. If it is false then, the actual
779 //signature stream is used.
780 //Everytime the user presses Add a new temporary stream is created.
781 //We keep the temporary stream as member because ImplGetSignatureInformations
782 //will later access the stream to create DocumentSignatureInformation objects
783 //which are stored in maCurrentSignatureInformations.
784 SignatureStreamHelper DigitalSignaturesDialog::ImplOpenSignatureStream(
785 sal_Int32 nStreamOpenMode, bool bTempStream)
787 SignatureStreamHelper aHelper;
788 if (bTempStream)
790 if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
792 //We write always into a new temporary stream.
793 mxTempSignatureStream = Reference < css::io::XStream >(
794 mxCtx->getServiceManager()->createInstanceWithContext(
795 OUSTR( "com.sun.star.io.TempFile" ), mxCtx) ,
796 UNO_QUERY_THROW);
797 aHelper.xSignatureStream = mxTempSignatureStream;
799 else
801 //When we read from the temp stream, then we must have previously
802 //created one.
803 OSL_ASSERT(mxTempSignatureStream.is());
805 aHelper.xSignatureStream = mxTempSignatureStream;
807 else
809 //No temporary stream
810 if (!mxSignatureStream.is())
812 //We may not have a dedicated stream for writing the signature
813 //So we take one directly from the storage
814 //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
815 //in which case Add/Remove is not allowed. This is done, for example, if the
816 //document is readonly
817 aHelper = DocumentSignatureHelper::OpenSignatureStream(
818 mxStore, nStreamOpenMode, meSignatureMode );
820 else
822 aHelper.xSignatureStream = mxSignatureStream;
826 if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
828 css::uno::Reference < css::io::XTruncate > xTruncate(
829 aHelper.xSignatureStream, UNO_QUERY_THROW);
830 DBG_ASSERT( xTruncate.is(), "ImplOpenSignatureStream - Stream does not support xTruncate!" );
831 xTruncate->truncate();
833 else if ( bTempStream || mxSignatureStream.is())
835 //In case we read the signature stream from the storage directly,
836 //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
837 //then XSeakable is not supported
838 css::uno::Reference < css::io::XSeekable > xSeek(
839 aHelper.xSignatureStream, UNO_QUERY_THROW);
840 DBG_ASSERT( xSeek.is(), "ImplOpenSignatureStream - Stream does not support xSeekable!" );
841 xSeek->seek( 0 );
844 return aHelper;