Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <xmlsecurity/digitalsignaturesdialog.hxx>
21 : #include <xmlsecurity/certificatechooser.hxx>
22 : #include <xmlsecurity/certificateviewer.hxx>
23 : #include <xmlsecurity/biginteger.hxx>
24 : #include <sax/tools/converter.hxx>
25 :
26 : #include <com/sun/star/embed/XStorage.hpp>
27 : #include <com/sun/star/embed/ElementModes.hpp>
28 : #include <com/sun/star/io/XSeekable.hpp>
29 : #include <com/sun/star/io/XTruncate.hpp>
30 : #include <com/sun/star/io/TempFile.hpp>
31 : #include <com/sun/star/embed/XTransactedObject.hpp>
32 : #include <com/sun/star/container/XNameAccess.hpp>
33 : #include <com/sun/star/lang/XComponent.hpp>
34 : #include <com/sun/star/security/NoPasswordException.hpp>
35 : #include <com/sun/star/lang/DisposedException.hpp>
36 : #include <com/sun/star/beans/XPropertySet.hpp>
37 : #include <com/sun/star/security/CertificateValidity.hpp>
38 : #include <com/sun/star/packages/WrongPasswordException.hpp>
39 : #include <com/sun/star/security/SerialNumberAdapter.hpp>
40 : #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
41 : #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
42 : #include <com/sun/star/packages/manifest/ManifestReader.hpp>
43 :
44 :
45 : #include <rtl/ustrbuf.hxx>
46 : #include <rtl/uri.hxx>
47 :
48 : #include <tools/date.hxx>
49 : #include <tools/time.hxx>
50 : #include "svtools/treelistentry.hxx"
51 :
52 : #include "dialogs.hrc"
53 : #include "digitalsignaturesdialog.hrc"
54 : #include "helpids.hrc"
55 : #include "resourcemanager.hxx"
56 :
57 : #include <vcl/msgbox.hxx> // Until encrypted docs work...
58 : #include <unotools/configitem.hxx>
59 :
60 :
61 : /* HACK: disable some warnings for MS-C */
62 : #ifdef _MSC_VER
63 : #pragma warning (disable : 4355) // 4355: this used in initializer-list
64 : #endif
65 :
66 : using namespace ::com::sun::star::security;
67 : using namespace ::com::sun::star::uno;
68 : using namespace ::com::sun::star;
69 :
70 : namespace
71 : {
72 0 : class SaveODFItem: public utl::ConfigItem
73 : {
74 : sal_Int16 m_nODF;
75 : public:
76 : virtual void Commit();
77 : virtual void Notify( const ::com::sun::star::uno::Sequence< OUString >& aPropertyNames );
78 : SaveODFItem();
79 : //See group ODF in Common.xcs
80 0 : bool isLessODF1_2()
81 : {
82 0 : return m_nODF < 3;
83 : }
84 : };
85 :
86 0 : void SaveODFItem::Commit() {}
87 0 : void SaveODFItem::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {}
88 :
89 0 : SaveODFItem::SaveODFItem(): utl::ConfigItem(OUString(
90 0 : "Office.Common/Save")), m_nODF(0)
91 : {
92 0 : OUString sDef("ODF/DefaultVersion");
93 0 : Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
94 0 : if ( aValues.getLength() == 1)
95 : {
96 0 : sal_Int16 nTmp = 0;
97 0 : if ( aValues[0] >>= nTmp )
98 0 : m_nODF = nTmp;
99 : else
100 : throw uno::RuntimeException(
101 : OUString("[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!"),
102 0 : 0 );
103 :
104 : }
105 : else
106 : throw uno::RuntimeException(
107 : OUString("[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion"),
108 0 : 0);
109 0 : }
110 : }
111 :
112 : /* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
113 : We use the manifest to find out if a file is xml and if it is encrypted.
114 : The parameter is an encoded uri. However, the manifest contains paths. Therefore
115 : the path is encoded as uri, so they can be compared.
116 : */
117 0 : bool DigitalSignaturesDialog::isXML(const OUString& rURI )
118 : {
119 : OSL_ASSERT(mxStore.is());
120 :
121 0 : bool bIsXML = false;
122 0 : bool bPropsAvailable = false;
123 0 : const OUString sPropFullPath("FullPath");
124 0 : const OUString sPropMediaType("MediaType");
125 0 : const OUString sPropDigest("Digest");
126 :
127 0 : for (int i = 0; i < m_manifest.getLength(); i++)
128 : {
129 0 : Any digest;
130 0 : const Sequence< css::beans::PropertyValue >& entry = m_manifest[i];
131 0 : OUString sPath, sMediaType;
132 0 : bool bEncrypted = false;
133 0 : for (int j = 0; j < entry.getLength(); j++)
134 : {
135 0 : const css::beans::PropertyValue & prop = entry[j];
136 :
137 0 : if (prop.Name.equals( sPropFullPath ) )
138 0 : prop.Value >>= sPath;
139 0 : else if (prop.Name.equals( sPropMediaType ) )
140 0 : prop.Value >>= sMediaType;
141 0 : else if (prop.Name.equals( sPropDigest ) )
142 0 : bEncrypted = true;
143 : }
144 0 : if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
145 : {
146 0 : bIsXML = sMediaType.equals("text/xml") && ! bEncrypted;
147 0 : bPropsAvailable = true;
148 0 : break;
149 : }
150 0 : }
151 0 : if (!bPropsAvailable)
152 : {
153 : //This would be the case for at least mimetype, META-INF/manifest.xml
154 : //META-INF/macrosignatures.xml.
155 : //Files can only be encrypted if they are in the manifest.xml.
156 : //That is, the current file cannot be encrypted, otherwise bPropsAvailable
157 : //would be true.
158 0 : OUString aXMLExt( "XML" );
159 0 : sal_Int32 nSep = rURI.lastIndexOf( '.' );
160 0 : if ( nSep != (-1) )
161 : {
162 0 : OUString aExt = rURI.copy( nSep+1 );
163 0 : if (aExt.equalsIgnoreAsciiCase(aXMLExt ))
164 0 : bIsXML = true;
165 0 : }
166 : }
167 0 : return bIsXML;
168 : }
169 :
170 0 : DigitalSignaturesDialog::DigitalSignaturesDialog(
171 : Window* pParent,
172 : uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
173 : sal_Bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature)
174 : : ModalDialog(pParent, "DigitalSignaturesDialog", "xmlsec/ui/digitalsignaturesdialog.ui")
175 : , mxCtx(rxCtx)
176 : , maSignatureHelper(rxCtx)
177 : , meSignatureMode(eMode)
178 : , m_sODFVersion (sODFVersion)
179 : , m_bHasDocumentSignature(bHasDocumentSignature)
180 0 : , m_bWarningShowSignMacro(false)
181 : {
182 0 : get(m_pHintDocFT, "dochint");
183 0 : get(m_pHintBasicFT, "macrohint");
184 0 : get(m_pHintPackageFT, "packagehint");
185 0 : get(m_pViewBtn, "view");
186 0 : get(m_pAddBtn, "sign");
187 0 : get(m_pRemoveBtn, "remove");
188 0 : get(m_pCloseBtn, "close");
189 0 : get(m_pSigsValidImg, "validimg");
190 0 : get(m_pSigsValidFI, "validft");
191 0 : get(m_pSigsInvalidImg, "invalidimg");
192 0 : get(m_pSigsInvalidFI, "invalidft");
193 0 : get(m_pSigsNotvalidatedImg, "notvalidatedimg");
194 0 : get(m_pSigsNotvalidatedFI, "notvalidatedft");
195 0 : get(m_pSigsOldSignatureImg, "oldsignatureimg");
196 0 : get(m_pSigsOldSignatureFI, "oldsignatureft");
197 :
198 0 : Size aControlSize(275, 109);
199 0 : const long nControlWidth = aControlSize.Width();
200 0 : aControlSize = LogicToPixel(aControlSize, MAP_APPFONT);
201 0 : SvxSimpleTableContainer *pSignatures = get<SvxSimpleTableContainer>("signatures");
202 0 : pSignatures->set_width_request(aControlSize.Width());
203 0 : pSignatures->set_height_request(aControlSize.Height());
204 :
205 0 : m_pSignaturesLB = new SvxSimpleTable(*pSignatures);
206 : // #i48253# the tablistbox needs its own unique id
207 0 : m_pSignaturesLB->Window::SetUniqueId( HID_XMLSEC_TREE_SIGNATURESDLG );
208 0 : static long aTabs[] = { 4, 0, 6*nControlWidth/100, 36*nControlWidth/100, 74*nControlWidth/100 };
209 0 : m_pSignaturesLB->SetTabs(aTabs);
210 :
211 0 : OUStringBuffer sHeader;
212 0 : sHeader.append("\t").append(get<FixedText>("signed")->GetText())
213 0 : .append("\t").append(get<FixedText>("issued")->GetText())
214 0 : .append("\t").append(get<FixedText>("date")->GetText());
215 0 : m_pSignaturesLB->InsertHeaderEntry(sHeader.makeStringAndClear());
216 :
217 0 : mbVerifySignatures = true;
218 0 : mbSignaturesChanged = false;
219 :
220 0 : m_pSignaturesLB->SetSelectHdl( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
221 0 : m_pSignaturesLB->SetDoubleClickHdl( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
222 :
223 0 : m_pViewBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
224 0 : m_pViewBtn->Disable();
225 :
226 0 : m_pAddBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
227 0 : if ( bReadOnly )
228 0 : m_pAddBtn->Disable();
229 :
230 0 : m_pRemoveBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
231 0 : m_pRemoveBtn->Disable();
232 :
233 0 : m_pCloseBtn->SetClickHdl( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
234 :
235 0 : switch( meSignatureMode )
236 : {
237 0 : case SignatureModeDocumentContent: m_pHintDocFT->Show(); break;
238 0 : case SignatureModeMacros: m_pHintBasicFT->Show(); break;
239 0 : case SignatureModePackage: m_pHintPackageFT->Show(); break;
240 0 : }
241 0 : }
242 :
243 0 : DigitalSignaturesDialog::~DigitalSignaturesDialog()
244 : {
245 0 : delete m_pSignaturesLB;
246 0 : }
247 :
248 0 : sal_Bool DigitalSignaturesDialog::Init()
249 : {
250 0 : bool bInit = maSignatureHelper.Init();
251 :
252 : DBG_ASSERT( bInit, "Error initializing security context!" );
253 :
254 0 : if ( bInit )
255 : {
256 0 : maSignatureHelper.SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
257 : }
258 :
259 0 : return bInit;
260 : }
261 :
262 0 : void DigitalSignaturesDialog::SetStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore )
263 : {
264 0 : mxStore = rxStore;
265 0 : maSignatureHelper.SetStorage( mxStore, m_sODFVersion);
266 :
267 : Reference < css::packages::manifest::XManifestReader > xReader =
268 0 : css::packages::manifest::ManifestReader::create(mxCtx);
269 :
270 : //Get the manifest.xml
271 0 : Reference < css::embed::XStorage > xSubStore(rxStore->openStorageElement(
272 0 : "META-INF", css::embed::ElementModes::READ), UNO_QUERY_THROW);
273 :
274 : Reference< css::io::XInputStream > xStream(
275 0 : xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ),
276 0 : UNO_QUERY_THROW);
277 :
278 0 : m_manifest = xReader->readManifestSequence(xStream);
279 0 : }
280 :
281 0 : void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
282 : {
283 0 : mxSignatureStream = rxStream;
284 0 : }
285 :
286 0 : bool DigitalSignaturesDialog::canAddRemove()
287 : {
288 : //m56
289 0 : bool ret = true;
290 : OSL_ASSERT(mxStore.is());
291 0 : bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
292 0 : SaveODFItem item;
293 0 : bool bSave1_1 = item.isLessODF1_2();
294 :
295 : // see specification
296 : //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
297 : //Paragraph 'Behavior with regard to ODF 1.2'
298 : //For both, macro and document
299 0 : if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
300 : {
301 : //#4
302 0 : ErrorBox err(NULL, XMLSEC_RES(RID_XMLSECDLG_OLD_ODF_FORMAT));
303 0 : err.Execute();
304 0 : ret = false;
305 : }
306 :
307 : //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
308 : //adding a macro signature will break an existing document signature.
309 : //The sfx2 will remove the documentsignature when the user adds a macro signature
310 0 : if (meSignatureMode == SignatureModeMacros
311 0 : && ret)
312 : {
313 0 : if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
314 : {
315 : //The warning says that the document signatures will be removed if the user
316 : //continues. He can then either press 'OK' or 'NO'
317 : //It the user presses 'Add' or 'Remove' several times then, then the warning
318 : //is shown every time until the user presses 'OK'. From then on, the warning
319 : //is not displayed anymore as long as the signatures dialog is alive.
320 0 : if (QueryBox(
321 0 : NULL, XMLSEC_RES(MSG_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)).Execute() == RET_NO)
322 0 : ret = false;
323 : else
324 0 : m_bWarningShowSignMacro = true;
325 :
326 : }
327 : }
328 0 : return ret;
329 : }
330 :
331 0 : bool DigitalSignaturesDialog::canAdd()
332 : {
333 0 : if (canAddRemove())
334 0 : return true;
335 0 : return false;
336 : }
337 :
338 0 : bool DigitalSignaturesDialog::canRemove()
339 : {
340 0 : if (canAddRemove())
341 0 : return true;
342 0 : return false;
343 : }
344 :
345 0 : short DigitalSignaturesDialog::Execute()
346 : {
347 : // Verify Signatures and add certificates to ListBox...
348 0 : mbVerifySignatures = true;
349 0 : ImplGetSignatureInformations(false);
350 0 : ImplFillSignaturesBox();
351 :
352 : // Only verify once, content will not change.
353 : // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
354 0 : mbVerifySignatures = false;
355 :
356 0 : return Dialog::Execute();
357 : }
358 :
359 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl)
360 : {
361 0 : bool bSel = m_pSignaturesLB->FirstSelected() ? true : false;
362 0 : m_pViewBtn->Enable( bSel );
363 0 : if ( m_pAddBtn->IsEnabled() ) // not read only
364 0 : m_pRemoveBtn->Enable( bSel );
365 :
366 0 : return 0;
367 : }
368 :
369 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl)
370 : {
371 : // Export all other signatures...
372 : SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
373 0 : embed::ElementModes::WRITE|embed::ElementModes::TRUNCATE, false );
374 : uno::Reference< io::XOutputStream > xOutputStream(
375 0 : aStreamHelper.xSignatureStream, uno::UNO_QUERY );
376 : uno::Reference< com::sun::star::xml::sax::XWriter> xSaxWriter =
377 0 : maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
378 :
379 0 : uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
380 0 : size_t nInfos = maCurrentSignatureInformations.size();
381 0 : for( size_t n = 0 ; n < nInfos ; ++n )
382 : maSignatureHelper.ExportSignature(
383 0 : xDocumentHandler, maCurrentSignatureInformations[ n ] );
384 :
385 0 : maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
386 :
387 : // If stream was not provided, we are responsible for committing it....
388 0 : if ( !mxSignatureStream.is() )
389 : {
390 : uno::Reference< embed::XTransactedObject > xTrans(
391 0 : aStreamHelper.xSignatureStorage, uno::UNO_QUERY );
392 0 : xTrans->commit();
393 : }
394 :
395 0 : EndDialog(RET_OK);
396 0 : return 0;
397 : }
398 :
399 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl)
400 : {
401 0 : ImplShowSignaturesDetails();
402 0 : return 0;
403 : }
404 :
405 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl)
406 : {
407 0 : ImplShowSignaturesDetails();
408 0 : return 0;
409 : }
410 :
411 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl)
412 : {
413 0 : if( ! canAdd())
414 0 : return 0;
415 : try
416 : {
417 0 : uno::Reference<com::sun::star::xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureHelper.GetSecurityEnvironment();
418 :
419 : uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
420 0 : ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
421 0 : CertificateChooser aChooser( this, mxCtx, xSecEnv, maCurrentSignatureInformations );
422 0 : if ( aChooser.Execute() == RET_OK )
423 : {
424 0 : uno::Reference< ::com::sun::star::security::XCertificate > xCert = aChooser.GetSelectedCertificate();
425 0 : if ( !xCert.is() )
426 : {
427 : SAL_WARN( "xmlsecurity.dialogs", "no certificate selected" );
428 0 : return -1;
429 : }
430 0 : OUString aCertSerial = xSerialNumberAdapter->toString( xCert->getSerialNumber() );
431 0 : if ( aCertSerial.isEmpty() )
432 : {
433 : OSL_FAIL( "Error in Certificate, problem with serial number!" );
434 0 : return -1;
435 : }
436 :
437 0 : maSignatureHelper.StartMission();
438 :
439 0 : sal_Int32 nSecurityId = maSignatureHelper.GetNewSecurityId();
440 :
441 0 : OUStringBuffer aStrBuffer;
442 0 : ::sax::Converter::encodeBase64(aStrBuffer, xCert->getEncoded());
443 :
444 : maSignatureHelper.SetX509Certificate( nSecurityId,
445 0 : xCert->getIssuerName(), aCertSerial,
446 0 : aStrBuffer.makeStringAndClear());
447 :
448 : std::vector< OUString > aElements =
449 : DocumentSignatureHelper::CreateElementList(
450 0 : mxStore, OUString(), meSignatureMode, OOo3_2Document);
451 :
452 0 : sal_Int32 nElements = aElements.size();
453 0 : for ( sal_Int32 n = 0; n < nElements; n++ )
454 : {
455 0 : bool bBinaryMode = !isXML(aElements[n]);
456 0 : maSignatureHelper.AddForSigning( nSecurityId, aElements[n], aElements[n], bBinaryMode );
457 : }
458 :
459 0 : maSignatureHelper.SetDateTime( nSecurityId, Date( Date::SYSTEM ), Time( Time::SYSTEM ) );
460 :
461 : // We open a signature stream in which the existing and the new
462 : //signature is written. ImplGetSignatureInformation (later in this function) will
463 : //then read the stream an will fill maCurrentSignatureInformations. The final signature
464 : //is written when the user presses OK. Then only maCurrentSignatureInformation and
465 : //a sax writer are used to write the information.
466 : SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
467 0 : css::embed::ElementModes::WRITE|css::embed::ElementModes::TRUNCATE, true);
468 : Reference< css::io::XOutputStream > xOutputStream(
469 0 : aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
470 : Reference< css::xml::sax::XWriter> xSaxWriter =
471 0 : maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
472 :
473 : // Export old signatures...
474 0 : uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
475 0 : size_t nInfos = maCurrentSignatureInformations.size();
476 0 : for ( size_t n = 0; n < nInfos; n++ )
477 0 : maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[n]);
478 :
479 : // Create a new one...
480 0 : maSignatureHelper.CreateAndWriteSignature( xDocumentHandler );
481 :
482 : // That's it...
483 0 : maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
484 :
485 0 : maSignatureHelper.EndMission();
486 :
487 0 : aStreamHelper = SignatureStreamHelper(); // release objects...
488 :
489 0 : mbSignaturesChanged = true;
490 :
491 0 : sal_Int32 nStatus = maSignatureHelper.GetSignatureInformation( nSecurityId ).nStatus;
492 :
493 0 : if ( nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
494 : {
495 0 : mbSignaturesChanged = true;
496 :
497 : // Can't simply remember current information, need parsing for getting full information :(
498 : // We need to verify the signatures again, otherwise the status in the signature information
499 : // will not contain
500 : // SecurityOperationStatus_OPERATION_SUCCEEDED
501 0 : mbVerifySignatures = true;
502 0 : ImplGetSignatureInformations(true);
503 0 : ImplFillSignaturesBox();
504 0 : }
505 0 : }
506 : }
507 0 : catch ( uno::Exception& )
508 : {
509 : OSL_FAIL( "Exception while adding a signature!" );
510 : // Don't keep invalid entries...
511 0 : ImplGetSignatureInformations(true);
512 0 : ImplFillSignaturesBox();
513 : }
514 :
515 0 : return 0;
516 : }
517 :
518 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl)
519 : {
520 0 : if (!canRemove())
521 0 : return 0;
522 0 : if( m_pSignaturesLB->FirstSelected() )
523 : {
524 : try
525 : {
526 0 : sal_uInt16 nSelected = (sal_uInt16) (sal_uIntPtr) m_pSignaturesLB->FirstSelected()->GetUserData();
527 0 : maCurrentSignatureInformations.erase( maCurrentSignatureInformations.begin()+nSelected );
528 :
529 : // Export all other signatures...
530 : SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
531 0 : css::embed::ElementModes::WRITE | css::embed::ElementModes::TRUNCATE, true);
532 : Reference< css::io::XOutputStream > xOutputStream(
533 0 : aStreamHelper.xSignatureStream, UNO_QUERY_THROW);
534 : Reference< css::xml::sax::XWriter> xSaxWriter =
535 0 : maSignatureHelper.CreateDocumentHandlerWithHeader( xOutputStream );
536 :
537 0 : uno::Reference< xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, UNO_QUERY_THROW);
538 0 : size_t nInfos = maCurrentSignatureInformations.size();
539 0 : for( size_t n = 0 ; n < nInfos ; ++n )
540 0 : maSignatureHelper.ExportSignature( xDocumentHandler, maCurrentSignatureInformations[ n ] );
541 :
542 0 : maSignatureHelper.CloseDocumentHandler( xDocumentHandler);
543 :
544 0 : mbSignaturesChanged = true;
545 :
546 0 : aStreamHelper = SignatureStreamHelper(); // release objects...
547 :
548 0 : ImplFillSignaturesBox();
549 : }
550 0 : catch ( uno::Exception& )
551 : {
552 : OSL_FAIL( "Exception while removing a signature!" );
553 : // Don't keep invalid entries...
554 0 : ImplGetSignatureInformations(true);
555 0 : ImplFillSignaturesBox();
556 : }
557 : }
558 :
559 0 : return 0;
560 : }
561 :
562 0 : IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl)
563 : {
564 0 : return mbVerifySignatures ? 1 : 0;
565 : }
566 :
567 0 : void DigitalSignaturesDialog::ImplFillSignaturesBox()
568 : {
569 0 : m_pSignaturesLB->Clear();
570 :
571 0 : uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > xSecEnv = maSignatureHelper.GetSecurityEnvironment();
572 : uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
573 0 : ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
574 :
575 0 : uno::Reference< ::com::sun::star::security::XCertificate > xCert;
576 :
577 0 : size_t nInfos = maCurrentSignatureInformations.size();
578 0 : size_t nValidSigs = 0, nValidCerts = 0;
579 0 : bool bAllNewSignatures = true;
580 :
581 0 : if( nInfos )
582 : {
583 0 : for( size_t n = 0; n < nInfos; ++n )
584 : {
585 : DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
586 0 : m_sODFVersion, maCurrentSignatureInformations[n]);
587 : std::vector< OUString > aElementsToBeVerified =
588 : DocumentSignatureHelper::CreateElementList(
589 0 : mxStore, OUString(), meSignatureMode, mode);
590 :
591 0 : const SignatureInformation& rInfo = maCurrentSignatureInformations[n];
592 : //First we try to get the certificate which is embedded in the XML Signature
593 0 : if (!rInfo.ouX509Certificate.isEmpty())
594 0 : xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
595 : else {
596 : //There must be an embedded certificate because we use it to get the
597 : //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
598 : //because it could be modified by an attacker. The issuer is displayed
599 : //in the digital signature dialog.
600 : //Comparing the X509IssuerName with the one from the X509Certificate in order
601 : //to find out if the X509IssuerName was modified does not work. See #i62684
602 : DBG_ASSERT(sal_False, "Could not find embedded certificate!");
603 : }
604 :
605 : //In case there is no embedded certificate we try to get it from a local store
606 : //Todo: This probably could be removed, see above.
607 0 : if (!xCert.is())
608 0 : xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
609 :
610 : DBG_ASSERT( xCert.is(), "Certificate not found and can't be created!" );
611 :
612 0 : OUString aSubject;
613 0 : OUString aIssuer;
614 0 : OUString aDateTimeStr;
615 :
616 0 : bool bSigValid = false;
617 0 : bool bCertValid = false;
618 0 : if( xCert.is() )
619 : {
620 : //check the validity of the cert
621 : try {
622 0 : sal_Int32 certResult = xSecEnv->verifyCertificate(xCert,
623 0 : Sequence<css::uno::Reference<css::security::XCertificate> >());
624 :
625 0 : bCertValid = certResult == css::security::CertificateValidity::VALID ? true : false;
626 0 : if ( bCertValid )
627 0 : nValidCerts++;
628 :
629 0 : } catch (css::uno::SecurityException& ) {
630 : OSL_FAIL("Verification of certificate failed");
631 0 : bCertValid = false;
632 : }
633 :
634 0 : aSubject = XmlSec::GetContentPart( xCert->getSubjectName() );
635 0 : aIssuer = XmlSec::GetContentPart( xCert->getIssuerName() );
636 : // String with date and time information (#i20172#)
637 0 : aDateTimeStr = XmlSec::GetDateTimeString( rInfo.stDateTime );
638 : }
639 0 : bSigValid = ( rInfo.nStatus == ::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
640 :
641 0 : if ( bSigValid )
642 : {
643 : bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
644 0 : aElementsToBeVerified, rInfo, mode);
645 :
646 0 : if( bSigValid )
647 0 : nValidSigs++;
648 : }
649 :
650 0 : Image aImage;
651 0 : if (!bSigValid)
652 : {
653 0 : aImage = m_pSigsInvalidImg->GetImage();
654 : }
655 0 : else if (bSigValid && !bCertValid)
656 : {
657 0 : aImage = m_pSigsNotvalidatedImg->GetImage();
658 : }
659 : //Check if the signature is a "old" document signature, that is, which was created
660 : //by an version of OOo previous to 3.2
661 0 : else if (meSignatureMode == SignatureModeDocumentContent
662 0 : && bSigValid && bCertValid && !DocumentSignatureHelper::isOOo3_2_Signature(
663 0 : maCurrentSignatureInformations[n]))
664 : {
665 0 : aImage = m_pSigsNotvalidatedImg->GetImage();
666 0 : bAllNewSignatures &= false;
667 : }
668 0 : else if (meSignatureMode == SignatureModeDocumentContent
669 0 : && bSigValid && bCertValid && DocumentSignatureHelper::isOOo3_2_Signature(
670 0 : maCurrentSignatureInformations[n]))
671 : {
672 0 : aImage = m_pSigsValidImg->GetImage();
673 : }
674 0 : else if (meSignatureMode == SignatureModeMacros
675 0 : && bSigValid && bCertValid)
676 : {
677 0 : aImage = m_pSigsValidImg->GetImage();
678 : }
679 :
680 0 : SvTreeListEntry* pEntry = m_pSignaturesLB->InsertEntry( OUString(), aImage, aImage );
681 0 : m_pSignaturesLB->SetEntryText( aSubject, pEntry, 1 );
682 0 : m_pSignaturesLB->SetEntryText( aIssuer, pEntry, 2 );
683 0 : m_pSignaturesLB->SetEntryText( aDateTimeStr, pEntry, 3 );
684 0 : pEntry->SetUserData( ( void* ) n ); // missuse user data as index
685 0 : }
686 : }
687 :
688 0 : bool bAllSigsValid = (nValidSigs == nInfos);
689 0 : bool bAllCertsValid = (nValidCerts == nInfos);
690 0 : bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
691 :
692 0 : m_pSigsValidImg->Show( bShowValidState);
693 0 : m_pSigsValidFI->Show( bShowValidState );
694 :
695 0 : bool bShowInvalidState = nInfos && !bAllSigsValid;
696 :
697 0 : m_pSigsInvalidImg->Show( bShowInvalidState );
698 0 : m_pSigsInvalidFI->Show( bShowInvalidState );
699 :
700 0 : bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
701 :
702 0 : m_pSigsNotvalidatedImg->Show(bShowNotValidatedState);
703 0 : m_pSigsNotvalidatedFI->Show(bShowNotValidatedState);
704 :
705 : //bAllNewSignatures is always true if we are not in document mode
706 0 : bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
707 0 : m_pSigsOldSignatureImg->Show(bShowOldSignature);
708 0 : m_pSigsOldSignatureFI->Show(bShowOldSignature);
709 :
710 0 : SignatureHighlightHdl( NULL );
711 0 : }
712 :
713 : //If bUseTempStream is true then the temporary signature stream is used.
714 : //Otherwise the real signature stream is used.
715 0 : void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream)
716 : {
717 0 : maCurrentSignatureInformations.clear();
718 :
719 0 : maSignatureHelper.StartMission();
720 :
721 : SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
722 0 : css::embed::ElementModes::READ, bUseTempStream);
723 0 : if ( aStreamHelper.xSignatureStream.is() )
724 : {
725 0 : uno::Reference< io::XInputStream > xInputStream( aStreamHelper.xSignatureStream, uno::UNO_QUERY );
726 0 : maSignatureHelper.ReadAndVerifySignature( xInputStream );
727 : }
728 0 : maSignatureHelper.EndMission();
729 :
730 0 : maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
731 :
732 0 : mbVerifySignatures = false;
733 0 : }
734 :
735 0 : void DigitalSignaturesDialog::ImplShowSignaturesDetails()
736 : {
737 0 : if( m_pSignaturesLB->FirstSelected() )
738 : {
739 0 : sal_uInt16 nSelected = (sal_uInt16) (sal_uIntPtr) m_pSignaturesLB->FirstSelected()->GetUserData();
740 0 : const SignatureInformation& rInfo = maCurrentSignatureInformations[ nSelected ];
741 : css::uno::Reference<css::xml::crypto::XSecurityEnvironment > xSecEnv =
742 0 : maSignatureHelper.GetSecurityEnvironment();
743 : css::uno::Reference<com::sun::star::security::XSerialNumberAdapter> xSerialNumberAdapter =
744 0 : ::com::sun::star::security::SerialNumberAdapter::create(mxCtx);
745 : // Use Certificate from doc, not from key store
746 0 : uno::Reference< css::security::XCertificate > xCert;
747 0 : if (!rInfo.ouX509Certificate.isEmpty())
748 0 : xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate);
749 : //fallback if no certificate is embedded, get if from store
750 0 : if (!xCert.is())
751 0 : xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xSerialNumberAdapter->toSequence( rInfo.ouX509SerialNumber ) );
752 :
753 : DBG_ASSERT( xCert.is(), "Error getting cCertificate!" );
754 0 : if ( xCert.is() )
755 : {
756 0 : CertificateViewer aViewer( this, maSignatureHelper.GetSecurityEnvironment(), xCert, false );
757 0 : aViewer.Execute();
758 0 : }
759 : }
760 0 : }
761 :
762 : //If bTempStream is true, then a temporary stream is return. If it is false then, the actual
763 : //signature stream is used.
764 : //Everytime the user presses Add a new temporary stream is created.
765 : //We keep the temporary stream as member because ImplGetSignatureInformations
766 : //will later access the stream to create DocumentSignatureInformation objects
767 : //which are stored in maCurrentSignatureInformations.
768 0 : SignatureStreamHelper DigitalSignaturesDialog::ImplOpenSignatureStream(
769 : sal_Int32 nStreamOpenMode, bool bTempStream)
770 : {
771 0 : SignatureStreamHelper aHelper;
772 0 : if (bTempStream)
773 : {
774 0 : if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
775 : {
776 : //We write always into a new temporary stream.
777 0 : mxTempSignatureStream = Reference < css::io::XStream >(css::io::TempFile::create(mxCtx), UNO_QUERY_THROW);
778 0 : aHelper.xSignatureStream = mxTempSignatureStream;
779 : }
780 : else
781 : {
782 : //When we read from the temp stream, then we must have previously
783 : //created one.
784 : OSL_ASSERT(mxTempSignatureStream.is());
785 : }
786 0 : aHelper.xSignatureStream = mxTempSignatureStream;
787 : }
788 : else
789 : {
790 : //No temporary stream
791 0 : if (!mxSignatureStream.is())
792 : {
793 : //We may not have a dedicated stream for writing the signature
794 : //So we take one directly from the storage
795 : //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
796 : //in which case Add/Remove is not allowed. This is done, for example, if the
797 : //document is readonly
798 0 : aHelper = DocumentSignatureHelper::OpenSignatureStream(
799 0 : mxStore, nStreamOpenMode, meSignatureMode );
800 : }
801 : else
802 : {
803 0 : aHelper.xSignatureStream = mxSignatureStream;
804 : }
805 : }
806 :
807 0 : if (nStreamOpenMode & css::embed::ElementModes::TRUNCATE)
808 : {
809 : css::uno::Reference < css::io::XTruncate > xTruncate(
810 0 : aHelper.xSignatureStream, UNO_QUERY_THROW);
811 : DBG_ASSERT( xTruncate.is(), "ImplOpenSignatureStream - Stream does not support xTruncate!" );
812 0 : xTruncate->truncate();
813 : }
814 0 : else if ( bTempStream || mxSignatureStream.is())
815 : {
816 : //In case we read the signature stream from the storage directly,
817 : //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
818 : //then XSeakable is not supported
819 : css::uno::Reference < css::io::XSeekable > xSeek(
820 0 : aHelper.xSignatureStream, UNO_QUERY_THROW);
821 : DBG_ASSERT( xSeek.is(), "ImplOpenSignatureStream - Stream does not support xSeekable!" );
822 0 : xSeek->seek( 0 );
823 : }
824 :
825 0 : return aHelper;
826 60 : }
827 :
828 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|