LCOV - code coverage report
Current view: top level - xmlsecurity/source/dialogs - digitalsignaturesdialog.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 386 0.3 %
Date: 2015-06-13 12:38:46 Functions: 2 38 5.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11