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