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