xref: /AOO41X/main/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
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>
51 
52 
53 #include <rtl/ustrbuf.hxx>
54 #include <rtl/uri.hxx>
55 
56 #include <tools/date.hxx>
57 #include <tools/time.hxx>
58 
59 #include "dialogs.hrc"
60 #include "digitalsignaturesdialog.hrc"
61 #include "helpids.hrc"
62 #include "resourcemanager.hxx"
63 
64 #include <vcl/msgbox.hxx> // Until encrypted docs work...
65 #include <unotools/configitem.hxx>
66 #include <comphelper/componentcontext.hxx>
67 
68 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
69 
70 
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
75 
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;
81 
82 namespace
83 {
84     class SaveODFItem: public utl::ConfigItem
85     {
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()
93         {
94             return m_nODF < 3;
95         }
96     };
97 
98 void SaveODFItem::Commit() {}
99 void SaveODFItem::Notify( const ::com::sun::star::uno::Sequence< rtl::OUString >& ) {}
100 
101     SaveODFItem::SaveODFItem(): utl::ConfigItem(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
102         "Office.Common/Save"))), m_nODF(0)
103     {
104         OUString sDef(RTL_CONSTASCII_USTRINGPARAM("ODF/DefaultVersion"));
105         Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
106         if ( aValues.getLength() == 1)
107         {
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 );
115 
116         }
117         else
118             throw uno::RuntimeException(
119                 OUString(RTL_CONSTASCII_USTRINGPARAM(
120                     "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion")), 0);
121     }
122 }
123 
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.
128 */
129 bool DigitalSignaturesDialog::isXML(const rtl::OUString& rURI )
130 {
131     OSL_ASSERT(mxStore.is());
132 
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"));
138 
139     for (int i = 0; i < m_manifest.getLength(); i++)
140     {
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++)
146         {
147             const css::beans::PropertyValue & prop = entry[j];
148 
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;
155         }
156         if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
157         {
158             bIsXML = sMediaType.equals(OUSTR("text/xml")) && ! bEncrypted;
159             bPropsAvailable = true;
160             break;
161         }
162     }
163     if (!bPropsAvailable)
164     {
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) )
173         {
174             OUString aExt = rURI.copy( nSep+1 );
175             if (aExt.equalsIgnoreAsciiCase(aXMLExt ))
176                 bIsXML = true;
177         }
178      }
179     return bIsXML;
180 }
181 
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)
210 {
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 ) ) );
220 
221     maSigsNotvalidatedFI.SetText( String( XMLSEC_RES( STR_NO_INFO_TO_VERIFY ) ) );
222 
223     if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
224     {
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 ) ) );
229     }
230 
231     FreeResource();
232 
233 	mbVerifySignatures = true;
234 	mbSignaturesChanged = false;
235 
236 	maSignaturesLB.SetSelectHdl( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
237 	maSignaturesLB.SetDoubleClickHdl( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
238 
239 	maViewBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
240 	maViewBtn.Disable();
241 
242 	maAddBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
243 	if ( bReadOnly  )
244 	    maAddBtn.Disable();
245 
246 	maRemoveBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
247 	maRemoveBtn.Disable();
248 
249     maOKBtn.SetClickHdl( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
250 
251 	switch( meSignatureMode )
252 	{
253 		case SignatureModeDocumentContent:	maHintDocFT.Show();		break;
254 		case SignatureModeMacros:		    maHintBasicFT.Show();	break;
255 		case SignatureModePackage:	        maHintPackageFT.Show();	break;
256 	}
257 
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 );
263 }
264 
265 DigitalSignaturesDialog::~DigitalSignaturesDialog()
266 {
267 }
268 
269 sal_Bool DigitalSignaturesDialog::Init()
270 {
271     bool bInit = maSignatureHelper.Init();
272 
273     DBG_ASSERT( bInit, "Error initializing security context!" );
274 
275     if ( bInit )
276     {
277         maSignatureHelper.SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
278     }
279 
280     return bInit;
281 }
282 
283 void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore )
284 {
285     mxStore = rxStore;
286     maSignatureHelper.SetStorage( mxStore, m_sODFVersion);
287 
288     Reference < css::packages::manifest::XManifestReader > xReader(
289         mxCtx->getServiceManager()->createInstanceWithContext(
290         OUSTR("com.sun.star.packages.manifest.ManifestReader"), mxCtx), UNO_QUERY_THROW);
291 
292 	//Get the manifest.xml
293     Reference < css::embed::XStorage > xSubStore(rxStore->openStorageElement(
294                 OUSTR("META-INF"), css::embed::ElementModes::READ), UNO_QUERY_THROW);
295 
296     Reference< css::io::XInputStream > xStream(
297         xSubStore->openStreamElement(OUSTR("manifest.xml"), css::embed::ElementModes::READ),
298         UNO_QUERY_THROW);
299 
300     m_manifest = xReader->readManifestSequence(xStream);
301 }
302 
303 void DigitalSignaturesDialog::SetSignatureStream( const cssu::Reference < css::io::XStream >& rxStream )
304 {
305     mxSignatureStream = rxStream;
306 }
307 
308 bool DigitalSignaturesDialog::canAddRemove()
309 {
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();
316 
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) )
322     {
323         //#4
324         ErrorBox err(NULL, XMLSEC_RES(RID_XMLSECDLG_OLD_ODF_FORMAT));
325         err.Execute();
326         ret = false;
327     }
328 
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)
334     {
335         if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
336         {
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;
347 
348         }
349     }
350     return ret;
351 }
352 
353 bool DigitalSignaturesDialog::canAdd()
354 {
355     if (canAddRemove())
356         return true;
357     return false;
358 }
359 
360 bool DigitalSignaturesDialog::canRemove()
361 {
362     if (canAddRemove())
363         return true;
364     return false;
365 }
366 
367 short DigitalSignaturesDialog::Execute()
368 {
369     // Verify Signatures and add certificates to ListBox...
370     mbVerifySignatures = true;
371     ImplGetSignatureInformations(false);
372     ImplFillSignaturesBox();
373 
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;
377 
378     return Dialog::Execute();
379 }
380 
381 IMPL_LINK( DigitalSignaturesDialog, SignatureHighlightHdl, void*, EMPTYARG )
382 {
383 	bool bSel = maSignaturesLB.FirstSelected() ? true : false;
384     maViewBtn.Enable( bSel );
385     if ( maAddBtn.IsEnabled() ) // not read only
386 	    maRemoveBtn.Enable( bSel );
387 
388     return 0;
389 }
390 
391 IMPL_LINK( DigitalSignaturesDialog, OKButtonHdl, void*, EMPTYARG )
392 {
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 );
400 
401     int nInfos = maCurrentSignatureInformations.size();
402     for( int n = 0 ; n < nInfos ; ++n )
403         maSignatureHelper.ExportSignature(
404         xDocumentHandler, maCurrentSignatureInformations[ n ] );
405 
406     maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
407 
408     // If stream was not provided, we are responsible for committing it....
409     if ( !mxSignatureStream.is() )
410     {
411         uno::Reference< embed::XTransactedObject > xTrans(
412             aStreamHelper.xSignatureStorage, uno::UNO_QUERY );
413         xTrans->commit();
414     }
415 
416     EndDialog(RET_OK);
417     return 0;
418 }
419 
420 IMPL_LINK( DigitalSignaturesDialog, SignatureSelectHdl, void*, EMPTYARG )
421 {
422     ImplShowSignaturesDetails();
423     return 0;
424 }
425 
426 IMPL_LINK( DigitalSignaturesDialog, ViewButtonHdl, Button*, EMPTYARG )
427 {
428     ImplShowSignaturesDetails();
429     return 0;
430 }
431 
432 IMPL_LINK( DigitalSignaturesDialog, AddButtonHdl, Button*, EMPTYARG )
433 {
434     if( ! canAdd())
435         return 0;
436     try
437     {
438         uno::Reference<com::sun::star::xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureHelper.GetSecurityEnvironment();
439 
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 )
444         {
445             uno::Reference< ::com::sun::star::security::XCertificate > xCert = aChooser.GetSelectedCertificate();
446             if ( !xCert.is() )
447             {
448                 DBG_ERRORFILE( "no certificate selected" );
449                 return -1;
450             }
451             rtl::OUString aCertSerial = xSerialNumberAdapter->toString( xCert->getSerialNumber() );
452             if ( !aCertSerial.getLength() )
453             {
454                 DBG_ERROR( "Error in Certificate, problem with serial number!" );
455                 return -1;
456             }
457 
458             maSignatureHelper.StartMission();
459 
460             sal_Int32 nSecurityId = maSignatureHelper.GetNewSecurityId();
461 
462             rtl::OUStringBuffer aStrBuffer;
463             SvXMLUnitConverter::encodeBase64(aStrBuffer, xCert->getEncoded());
464 
465             maSignatureHelper.SetX509Certificate( nSecurityId,
466                 xCert->getIssuerName(), aCertSerial,
467                 aStrBuffer.makeStringAndClear());
468 
469             std::vector< rtl::OUString > aElements =
470                 DocumentSignatureHelper::CreateElementList(
471                     mxStore, rtl::OUString(), meSignatureMode, OOo3_2Document);
472 
473             sal_Int32 nElements = aElements.size();
474             for ( sal_Int32 n = 0; n < nElements; n++ )
475             {
476                 bool bBinaryMode = !isXML(aElements[n]);
477                 maSignatureHelper.AddForSigning( nSecurityId, aElements[n], aElements[n], bBinaryMode );
478             }
479 
480             maSignatureHelper.SetDateTime( nSecurityId, Date(), Time() );
481 
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 );
493 
494             // Export old signatures...
495  	        int nInfos = maCurrentSignatureInformations.size();
496             for ( int n = 0; n < nInfos; n++ )
497 	            maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[n]);
498 
499             // Create a new one...
500 	        maSignatureHelper.CreateAndWriteSignature( xDocumentHandler );
501 
502             // That's it...
503 	        maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
504 
505             maSignatureHelper.EndMission();
506 
507 			aStreamHelper = SignatureStreamHelper();	// release objects...
508 
509             mbSignaturesChanged = true;
510 
511             sal_Int32 nStatus = maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus;
512 
513             if ( nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
514             {
515                 mbSignaturesChanged = true;
516 
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();
524             }
525         }
526     }
527 	catch ( uno::Exception& )
528 	{
529 	    DBG_ERROR( "Exception while adding a signature!" );
530 		// Don't keep invalid entries...
531 		ImplGetSignatureInformations(true);
532         ImplFillSignaturesBox();
533 	}
534 
535     return 0;
536 }
537 
538 IMPL_LINK( DigitalSignaturesDialog, RemoveButtonHdl, Button*, EMPTYARG )
539 {
540     if (!canRemove())
541         return 0;
542 	if( maSignaturesLB.FirstSelected() )
543 	{
544 	    try
545 	    {
546             sal_uInt16 nSelected = (sal_uInt16) (sal_uIntPtr) maSignaturesLB.FirstSelected()->GetUserData();
547     		maCurrentSignatureInformations.erase( maCurrentSignatureInformations.begin()+nSelected );
548 
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 );
556 
557             int nInfos = maCurrentSignatureInformations.size();
558     		for( int n = 0 ; n < nInfos ; ++n )
559     			maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[ n ] );
560 
561     	    maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
562 
563             mbSignaturesChanged = true;
564 
565 			aStreamHelper = SignatureStreamHelper();	// release objects...
566 
567             ImplFillSignaturesBox();
568         }
569     	catch ( uno::Exception& )
570     	{
571     	    DBG_ERROR( "Exception while removing a signature!" );
572 			// Don't keep invalid entries...
573 			ImplGetSignatureInformations(true);
574 			ImplFillSignaturesBox();
575     	}
576 	}
577 
578     return 0;
579 }
580 
581 IMPL_LINK( DigitalSignaturesDialog, StartVerifySignatureHdl, void*, EMPTYARG )
582 {
583     return mbVerifySignatures ? 1 : 0;
584 }
585 
586 void DigitalSignaturesDialog::ImplFillSignaturesBox()
587 {
588     maSignaturesLB.Clear();
589 
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);
593 
594     uno::Reference< ::com::sun::star::security::XCertificate > xCert;
595 
596 	String aNullStr;
597 	int nInfos = maCurrentSignatureInformations.size();
598     int nValidSigs = 0, nValidCerts = 0;
599     bool bAllNewSignatures = true;
600 
601     if( nInfos )
602     {
603         for( int n = 0; n < nInfos; ++n )
604         {
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);
610 
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!");
623             }
624 
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 ) );
629 
630 		    DBG_ASSERT( xCert.is(), "Certificate not found and can't be created!" );
631 
632 		    String	aSubject;
633 		    String	aIssuer;
634 		    String	aDateTimeStr;
635 
636             bool bSigValid = false;
637             bool bCertValid = false;
638             if( xCert.is() )
639 		    {
640                 //check the validity of the cert
641                 try {
642                     sal_Int32 certResult = xSecEnv->verifyCertificate(xCert,
643                         Sequence<css::uno::Reference<css::security::XCertificate> >());
644 
645                     bCertValid = certResult == css::security::CertificateValidity::VALID ? true : false;
646                     if ( bCertValid )
647                         nValidCerts++;
648 
649                 } catch (css::uno::SecurityException& ) {
650                     OSL_ENSURE(0, "Verification of certificate failed");
651                     bCertValid = false;
652                 }
653 
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 );
658             }
659             bSigValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
660 
661             if ( bSigValid )
662             {
663                  bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
664                       aElementsToBeVerified, rInfo, mode);
665 
666                 if( bSigValid )
667 			        nValidSigs++;
668             }
669 
670             Image aImage;
671             if (!bSigValid)
672             {
673                 aImage = maSigsInvalidImg.GetImage();
674             }
675             else if (bSigValid && !bCertValid)
676             {
677                 aImage = maSigsNotvalidatedImg.GetImage();
678             }
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]))
684             {
685                 aImage = maSigsNotvalidatedImg.GetImage();
686                 bAllNewSignatures &= false;
687             }
688             else if (meSignatureMode == SignatureModeDocumentContent
689                 && bSigValid && bCertValid && DocumentSignatureHelper::isOOo3_2_Signature(
690                 maCurrentSignatureInformations[n]))
691             {
692                 aImage = maSigsValidImg.GetImage();
693             }
694             else if (meSignatureMode == SignatureModeMacros
695                 && bSigValid && bCertValid)
696             {
697                 aImage = aImage = maSigsValidImg.GetImage();
698             }
699 
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
705         }
706     }
707 
708     bool bAllSigsValid = (nValidSigs == nInfos);
709     bool bAllCertsValid = (nValidCerts == nInfos);
710     bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
711 
712     bool bShowNotValidatedState = nInfos && (bAllSigsValid && (!bAllCertsValid || !bAllNewSignatures));
713     bool bShowInvalidState = nInfos && !bAllSigsValid;
714 
715 	maSigsValidImg.Show( bShowValidState);
716 	maSigsValidFI.Show( bShowValidState );
717 	maSigsInvalidImg.Show( bShowInvalidState );
718 	maSigsInvalidFI.Show( bShowInvalidState );
719 
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);
724 
725 	SignatureHighlightHdl( NULL );
726 }
727 
728 
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)
732 {
733     maCurrentSignatureInformations.clear();
734 
735     maSignatureHelper.StartMission();
736 
737     SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
738         css::embed::ElementModes::READ, bUseTempStream);
739     if ( aStreamHelper.xSignatureStream.is() )
740     {
741         uno::Reference< io::XInputStream > xInputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY );
742 	    maSignatureHelper.ReadAndVerifySignature( xInputStream );
743     }
744     maSignatureHelper.EndMission();
745 
746     maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
747 
748     mbVerifySignatures = false;
749 }
750 
751 void DigitalSignaturesDialog::ImplShowSignaturesDetails()
752 {
753 	if( maSignaturesLB.FirstSelected() )
754 	{
755         sal_uInt16 nSelected = (sal_uInt16) (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 ) );
768 
769 		DBG_ASSERT( xCert.is(), "Error getting cCertificate!" );
770 		if ( xCert.is() )
771 		{
772 			CertificateViewer aViewer( this, maSignatureHelper.GetSecurityEnvironment(), xCert, sal_False );
773 			aViewer.Execute();
774 		}
775 	}
776 }
777 
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)
786 {
787 	SignatureStreamHelper aHelper;
788     if (bTempStream)
789     {
790         if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
791         {
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;
798         }
799         else
800         {
801             //When we read from the temp stream, then we must have previously
802             //created one.
803             OSL_ASSERT(mxTempSignatureStream.is());
804         }
805         aHelper.xSignatureStream = mxTempSignatureStream;
806     }
807     else
808     {
809         //No temporary stream
810         if (!mxSignatureStream.is())
811         {
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 );
819         }
820         else
821         {
822             aHelper.xSignatureStream = mxSignatureStream;
823         }
824     }
825 
826     if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
827     {
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();
832     }
833     else if ( bTempStream || mxSignatureStream.is())
834     {
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 );
842     }
843 
844 	return aHelper;
845 }
846 
847