1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_xmlsecurity.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <xmlsecurity/documentsignaturehelper.hxx> 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp> 34*cdf0e10cSrcweir #include <com/sun/star/lang/XComponent.hpp> 35*cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp> 36*cdf0e10cSrcweir #include <com/sun/star/embed/XStorage.hpp> 37*cdf0e10cSrcweir #include <com/sun/star/embed/ElementModes.hpp> 38*cdf0e10cSrcweir #include "com/sun/star/beans/XPropertySet.hpp" 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir #include "comphelper/documentconstants.hxx" 41*cdf0e10cSrcweir #include <tools/debug.hxx> 42*cdf0e10cSrcweir #include "rtl/uri.hxx" 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 45*cdf0e10cSrcweir //using namespace ::com::sun::star; 46*cdf0e10cSrcweir namespace css = ::com::sun::star; 47*cdf0e10cSrcweir using rtl::OUString; 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir namespace 51*cdf0e10cSrcweir { 52*cdf0e10cSrcweir ::rtl::OUString getElement(::rtl::OUString const & version, ::sal_Int32 * index) 53*cdf0e10cSrcweir { 54*cdf0e10cSrcweir while (*index < version.getLength() && version[*index] == '0') { 55*cdf0e10cSrcweir ++*index; 56*cdf0e10cSrcweir } 57*cdf0e10cSrcweir return version.getToken(0, '.', *index); 58*cdf0e10cSrcweir } 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir // Return 1 if version1 is greater then version 2, 0 if they are equal 63*cdf0e10cSrcweir //and -1 if version1 is less version 2 64*cdf0e10cSrcweir int compareVersions( 65*cdf0e10cSrcweir ::rtl::OUString const & version1, ::rtl::OUString const & version2) 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { 68*cdf0e10cSrcweir ::rtl::OUString e1(getElement(version1, &i1)); 69*cdf0e10cSrcweir ::rtl::OUString e2(getElement(version2, &i2)); 70*cdf0e10cSrcweir if (e1.getLength() < e2.getLength()) { 71*cdf0e10cSrcweir return -1; 72*cdf0e10cSrcweir } else if (e1.getLength() > e2.getLength()) { 73*cdf0e10cSrcweir return 1; 74*cdf0e10cSrcweir } else if (e1 < e2) { 75*cdf0e10cSrcweir return -1; 76*cdf0e10cSrcweir } else if (e1 > e2) { 77*cdf0e10cSrcweir return 1; 78*cdf0e10cSrcweir } 79*cdf0e10cSrcweir } 80*cdf0e10cSrcweir return 0; 81*cdf0e10cSrcweir } 82*cdf0e10cSrcweir } 83*cdf0e10cSrcweir //If the OOo 3.0 mode is used then we exclude 84*cdf0e10cSrcweir //'mimetype' and all content of 'META-INF'. 85*cdf0e10cSrcweir //If the argument 'bSigning' is true then the element list is created for a signing 86*cdf0e10cSrcweir //operation in which case we use the latest signing algorithm. That is all elements 87*cdf0e10cSrcweir //we find in the zip storage are added to the list. We do not support the old signatures 88*cdf0e10cSrcweir //which did not contain all files. 89*cdf0e10cSrcweir //If 'bSigning' is false, then we validate. If the user enabled validating according to OOo 3.0 90*cdf0e10cSrcweir //then mimetype and all content of META-INF must be excluded. 91*cdf0e10cSrcweir void ImplFillElementList( 92*cdf0e10cSrcweir std::vector< rtl::OUString >& rList, const Reference < css::embed::XStorage >& rxStore, 93*cdf0e10cSrcweir const ::rtl::OUString rRootStorageName, const bool bRecursive, 94*cdf0e10cSrcweir const DocumentSignatureAlgorithm mode) 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir ::rtl::OUString aMetaInfName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ); 97*cdf0e10cSrcweir ::rtl::OUString sMimeTypeName (RTL_CONSTASCII_USTRINGPARAM("mimetype")); 98*cdf0e10cSrcweir ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 99*cdf0e10cSrcweir 100*cdf0e10cSrcweir Reference < css::container::XNameAccess > xElements( rxStore, UNO_QUERY ); 101*cdf0e10cSrcweir Sequence< ::rtl::OUString > aElements = xElements->getElementNames(); 102*cdf0e10cSrcweir sal_Int32 nElements = aElements.getLength(); 103*cdf0e10cSrcweir const ::rtl::OUString* pNames = aElements.getConstArray(); 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir for ( sal_Int32 n = 0; n < nElements; n++ ) 106*cdf0e10cSrcweir { 107*cdf0e10cSrcweir if (mode != OOo3_2Document 108*cdf0e10cSrcweir && (pNames[n] == aMetaInfName 109*cdf0e10cSrcweir || pNames[n] == sMimeTypeName)) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir continue; 112*cdf0e10cSrcweir } 113*cdf0e10cSrcweir else 114*cdf0e10cSrcweir { 115*cdf0e10cSrcweir ::rtl::OUString sEncName = ::rtl::Uri::encode( 116*cdf0e10cSrcweir pNames[n], rtl_UriCharClassRelSegment, 117*cdf0e10cSrcweir rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8); 118*cdf0e10cSrcweir if (sEncName.getLength() == 0 && pNames[n].getLength() != 0) 119*cdf0e10cSrcweir throw css::uno::Exception(::rtl::OUString( 120*cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("Failed to encode element name of XStorage")), 0); 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir if ( rxStore->isStreamElement( pNames[n] ) ) 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir //Exclude documentsignatures.xml! 125*cdf0e10cSrcweir if (pNames[n].equals( 126*cdf0e10cSrcweir DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName())) 127*cdf0e10cSrcweir continue; 128*cdf0e10cSrcweir ::rtl::OUString aFullName( rRootStorageName + sEncName ); 129*cdf0e10cSrcweir rList.push_back(aFullName); 130*cdf0e10cSrcweir } 131*cdf0e10cSrcweir else if ( bRecursive && rxStore->isStorageElement( pNames[n] ) ) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( pNames[n], css::embed::ElementModes::READ ); 134*cdf0e10cSrcweir rtl::OUString aFullRootName( rRootStorageName + sEncName + aSep ); 135*cdf0e10cSrcweir ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode); 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir } 139*cdf0e10cSrcweir } 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir bool DocumentSignatureHelper::isODFPre_1_2(const ::rtl::OUString & sVersion) 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir //The property version exists only if the document is at least version 1.2 145*cdf0e10cSrcweir //That is, if the document has version 1.1 and sVersion is empty. 146*cdf0e10cSrcweir //The constant is defined in comphelper/documentconstants.hxx 147*cdf0e10cSrcweir if (compareVersions(sVersion, ODFVER_012_TEXT) == -1) 148*cdf0e10cSrcweir return true; 149*cdf0e10cSrcweir return false; 150*cdf0e10cSrcweir } 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir ::rtl::OUString sManifestURI(RTL_CONSTASCII_USTRINGPARAM("META-INF/manifest.xml")); 155*cdf0e10cSrcweir bool bOOo3_2 = false; 156*cdf0e10cSrcweir typedef ::std::vector< SignatureReferenceInformation >::const_iterator CIT; 157*cdf0e10cSrcweir for (CIT i = sigInfo.vSignatureReferenceInfors.begin(); 158*cdf0e10cSrcweir i < sigInfo.vSignatureReferenceInfors.end(); i++) 159*cdf0e10cSrcweir { 160*cdf0e10cSrcweir if (i->ouURI.equals(sManifestURI)) 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir bOOo3_2 = true; 163*cdf0e10cSrcweir break; 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir } 166*cdf0e10cSrcweir return bOOo3_2; 167*cdf0e10cSrcweir } 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir DocumentSignatureAlgorithm 170*cdf0e10cSrcweir DocumentSignatureHelper::getDocumentAlgorithm( 171*cdf0e10cSrcweir const ::rtl::OUString & sODFVersion, const SignatureInformation & sigInfo) 172*cdf0e10cSrcweir { 173*cdf0e10cSrcweir OSL_ASSERT(sODFVersion.getLength()); 174*cdf0e10cSrcweir DocumentSignatureAlgorithm mode = OOo3_2Document; 175*cdf0e10cSrcweir if (!isOOo3_2_Signature(sigInfo)) 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir if (isODFPre_1_2(sODFVersion)) 178*cdf0e10cSrcweir mode = OOo2Document; 179*cdf0e10cSrcweir else 180*cdf0e10cSrcweir mode = OOo3_0Document; 181*cdf0e10cSrcweir } 182*cdf0e10cSrcweir return mode; 183*cdf0e10cSrcweir } 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir //The function creates a list of files which are to be signed or for which 186*cdf0e10cSrcweir //the signature is to be validated. The strings are UTF8 encoded URIs which 187*cdf0e10cSrcweir //contain '/' as path separators. 188*cdf0e10cSrcweir // 189*cdf0e10cSrcweir //The algorithm how document signatures are created and validated has 190*cdf0e10cSrcweir //changed over time. The change affects only which files within the document 191*cdf0e10cSrcweir //are changed. Document signatures created by OOo 2.x only used particular files. Since 192*cdf0e10cSrcweir //OOo 3.0 everything except "mimetype" and "META-INF" are signed. As of OOo 3.2 everything 193*cdf0e10cSrcweir //except META-INF/documentsignatures.xml is signed. 194*cdf0e10cSrcweir //Signatures are validated according to the algorithm which was then used for validation. 195*cdf0e10cSrcweir //That is, when validating a signature which was created by OOo 3.0, then mimetype and 196*cdf0e10cSrcweir //META-INF are not used. 197*cdf0e10cSrcweir // 198*cdf0e10cSrcweir //When a signature is created then we always use the latest algorithm. That is, we use 199*cdf0e10cSrcweir //that of OOo 3.2 200*cdf0e10cSrcweir std::vector< rtl::OUString > 201*cdf0e10cSrcweir DocumentSignatureHelper::CreateElementList( 202*cdf0e10cSrcweir const Reference < css::embed::XStorage >& rxStore, 203*cdf0e10cSrcweir const ::rtl::OUString /*rRootStorageName*/, DocumentSignatureMode eMode, 204*cdf0e10cSrcweir const DocumentSignatureAlgorithm mode) 205*cdf0e10cSrcweir { 206*cdf0e10cSrcweir std::vector< rtl::OUString > aElements; 207*cdf0e10cSrcweir ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir switch ( eMode ) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir case SignatureModeDocumentContent: 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir if (mode == OOo2Document) //that is, ODF 1.0, 1.1 214*cdf0e10cSrcweir { 215*cdf0e10cSrcweir // 1) Main content 216*cdf0e10cSrcweir ImplFillElementList(aElements, rxStore, ::rtl::OUString(), false, mode); 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir // 2) Pictures... 219*cdf0e10cSrcweir rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Pictures" ) ); 220*cdf0e10cSrcweir try 221*cdf0e10cSrcweir { 222*cdf0e10cSrcweir Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); 223*cdf0e10cSrcweir ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir catch(css::io::IOException& ) 226*cdf0e10cSrcweir { 227*cdf0e10cSrcweir ; // Doesn't have to exist... 228*cdf0e10cSrcweir } 229*cdf0e10cSrcweir // 3) OLE.... 230*cdf0e10cSrcweir aSubStorageName = rtl::OUString::createFromAscii( "ObjectReplacements" ); 231*cdf0e10cSrcweir try 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); 234*cdf0e10cSrcweir ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); 235*cdf0e10cSrcweir xSubStore.clear(); 236*cdf0e10cSrcweir 237*cdf0e10cSrcweir // Object folders... 238*cdf0e10cSrcweir rtl::OUString aMatchStr( rtl::OUString::createFromAscii( "Object " ) ); 239*cdf0e10cSrcweir Reference < css::container::XNameAccess > xElements( rxStore, UNO_QUERY ); 240*cdf0e10cSrcweir Sequence< ::rtl::OUString > aElementNames = xElements->getElementNames(); 241*cdf0e10cSrcweir sal_Int32 nElements = aElementNames.getLength(); 242*cdf0e10cSrcweir const ::rtl::OUString* pNames = aElementNames.getConstArray(); 243*cdf0e10cSrcweir for ( sal_Int32 n = 0; n < nElements; n++ ) 244*cdf0e10cSrcweir { 245*cdf0e10cSrcweir if ( ( pNames[n].match( aMatchStr ) ) && rxStore->isStorageElement( pNames[n] ) ) 246*cdf0e10cSrcweir { 247*cdf0e10cSrcweir Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( pNames[n], css::embed::ElementModes::READ ); 248*cdf0e10cSrcweir ImplFillElementList(aElements, xTmpSubStore, pNames[n]+aSep, true, mode); 249*cdf0e10cSrcweir } 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir } 252*cdf0e10cSrcweir catch( com::sun::star::io::IOException& ) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir ; // Doesn't have to exist... 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir } 257*cdf0e10cSrcweir else 258*cdf0e10cSrcweir { 259*cdf0e10cSrcweir // Everything except META-INF 260*cdf0e10cSrcweir ImplFillElementList(aElements, rxStore, ::rtl::OUString(), true, mode); 261*cdf0e10cSrcweir } 262*cdf0e10cSrcweir } 263*cdf0e10cSrcweir break; 264*cdf0e10cSrcweir case SignatureModeMacros: 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir // 1) Macros 267*cdf0e10cSrcweir rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Basic" ) ); 268*cdf0e10cSrcweir try 269*cdf0e10cSrcweir { 270*cdf0e10cSrcweir Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); 271*cdf0e10cSrcweir ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); 272*cdf0e10cSrcweir } 273*cdf0e10cSrcweir catch( com::sun::star::io::IOException& ) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir ; // Doesn't have to exist... 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir // 2) Dialogs 279*cdf0e10cSrcweir aSubStorageName = rtl::OUString::createFromAscii( "Dialogs") ; 280*cdf0e10cSrcweir try 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); 283*cdf0e10cSrcweir ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir catch( com::sun::star::io::IOException& ) 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir ; // Doesn't have to exist... 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir // 3) Scripts 290*cdf0e10cSrcweir aSubStorageName = rtl::OUString::createFromAscii( "Scripts") ; 291*cdf0e10cSrcweir try 292*cdf0e10cSrcweir { 293*cdf0e10cSrcweir Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); 294*cdf0e10cSrcweir ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); 295*cdf0e10cSrcweir } 296*cdf0e10cSrcweir catch( css::io::IOException& ) 297*cdf0e10cSrcweir { 298*cdf0e10cSrcweir ; // Doesn't have to exist... 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir } 301*cdf0e10cSrcweir break; 302*cdf0e10cSrcweir case SignatureModePackage: 303*cdf0e10cSrcweir { 304*cdf0e10cSrcweir // Everything except META-INF 305*cdf0e10cSrcweir ImplFillElementList(aElements, rxStore, ::rtl::OUString(), true, mode); 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir break; 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir return aElements; 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir SignatureStreamHelper DocumentSignatureHelper::OpenSignatureStream( 314*cdf0e10cSrcweir const Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode ) 315*cdf0e10cSrcweir { 316*cdf0e10cSrcweir sal_Int32 nSubStorageOpenMode = css::embed::ElementModes::READ; 317*cdf0e10cSrcweir if ( nOpenMode & css::embed::ElementModes::WRITE ) 318*cdf0e10cSrcweir nSubStorageOpenMode = css::embed::ElementModes::WRITE; 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir SignatureStreamHelper aHelper; 321*cdf0e10cSrcweir 322*cdf0e10cSrcweir try 323*cdf0e10cSrcweir { 324*cdf0e10cSrcweir ::rtl::OUString aSIGStoreName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ); 325*cdf0e10cSrcweir aHelper.xSignatureStorage = rxStore->openStorageElement( aSIGStoreName, nSubStorageOpenMode ); 326*cdf0e10cSrcweir if ( aHelper.xSignatureStorage.is() ) 327*cdf0e10cSrcweir { 328*cdf0e10cSrcweir ::rtl::OUString aSIGStreamName; 329*cdf0e10cSrcweir if ( eDocSigMode == SignatureModeDocumentContent ) 330*cdf0e10cSrcweir aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); 331*cdf0e10cSrcweir else if ( eDocSigMode == SignatureModeMacros ) 332*cdf0e10cSrcweir aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); 333*cdf0e10cSrcweir else 334*cdf0e10cSrcweir aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode ); 337*cdf0e10cSrcweir } 338*cdf0e10cSrcweir } 339*cdf0e10cSrcweir catch(css::io::IOException& ) 340*cdf0e10cSrcweir { 341*cdf0e10cSrcweir // Doesn't have to exist... 342*cdf0e10cSrcweir DBG_ASSERT( nOpenMode == css::embed::ElementModes::READ, "Error creating signature stream..." ); 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir return aHelper; 346*cdf0e10cSrcweir } 347*cdf0e10cSrcweir 348*cdf0e10cSrcweir //sElementList contains all files which are expected to be signed. Only those files must me signed, 349*cdf0e10cSrcweir //no more, no less. 350*cdf0e10cSrcweir //The DocumentSignatureAlgorithm indicates if the document was created with OOo 2.x. Then 351*cdf0e10cSrcweir //the uri s in the Reference elements in the signature, were not properly encoded. 352*cdf0e10cSrcweir // For example: <Reference URI="ObjectReplacements/Object 1"> 353*cdf0e10cSrcweir bool DocumentSignatureHelper::checkIfAllFilesAreSigned( 354*cdf0e10cSrcweir const ::std::vector< ::rtl::OUString > & sElementList, 355*cdf0e10cSrcweir const SignatureInformation & sigInfo, 356*cdf0e10cSrcweir const DocumentSignatureAlgorithm alg) 357*cdf0e10cSrcweir { 358*cdf0e10cSrcweir // Can only be valid if ALL streams are signed, which means real stream count == signed stream count 359*cdf0e10cSrcweir unsigned int nRealCount = 0; 360*cdf0e10cSrcweir for ( int i = sigInfo.vSignatureReferenceInfors.size(); i; ) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir const SignatureReferenceInformation& rInf = sigInfo.vSignatureReferenceInfors[--i]; 363*cdf0e10cSrcweir // There is also an extra entry of type TYPE_SAMEDOCUMENT_REFERENCE because of signature date. 364*cdf0e10cSrcweir if ( ( rInf.nType == TYPE_BINARYSTREAM_REFERENCE ) || ( rInf.nType == TYPE_XMLSTREAM_REFERENCE ) ) 365*cdf0e10cSrcweir { 366*cdf0e10cSrcweir ::rtl::OUString sReferenceURI = rInf.ouURI; 367*cdf0e10cSrcweir if (alg == OOo2Document) 368*cdf0e10cSrcweir { 369*cdf0e10cSrcweir //Comparing URIs is a difficult. Therefore we kind of normalize 370*cdf0e10cSrcweir //it before comparing. We assume that our URI do not have a leading "./" 371*cdf0e10cSrcweir //and fragments at the end (...#...) 372*cdf0e10cSrcweir sReferenceURI = ::rtl::Uri::encode( 373*cdf0e10cSrcweir sReferenceURI, rtl_UriCharClassPchar, 374*cdf0e10cSrcweir rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8); 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir //find the file in the element list 378*cdf0e10cSrcweir typedef ::std::vector< ::rtl::OUString >::const_iterator CIT; 379*cdf0e10cSrcweir for (CIT aIter = sElementList.begin(); aIter < sElementList.end(); aIter++) 380*cdf0e10cSrcweir { 381*cdf0e10cSrcweir ::rtl::OUString sElementListURI = *aIter; 382*cdf0e10cSrcweir if (alg == OOo2Document) 383*cdf0e10cSrcweir { 384*cdf0e10cSrcweir sElementListURI = 385*cdf0e10cSrcweir ::rtl::Uri::encode( 386*cdf0e10cSrcweir sElementListURI, rtl_UriCharClassPchar, 387*cdf0e10cSrcweir rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8); 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir if (sElementListURI.equals(sReferenceURI)) 390*cdf0e10cSrcweir { 391*cdf0e10cSrcweir nRealCount++; 392*cdf0e10cSrcweir break; 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir } 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir return sElementList.size() == nRealCount; 398*cdf0e10cSrcweir } 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir /*Compares the Uri which are obtained from CreateElementList with 401*cdf0e10cSrcweir the path obtained from the manifest.xml. 402*cdf0e10cSrcweir Returns true if both strings are equal. 403*cdf0e10cSrcweir */ 404*cdf0e10cSrcweir bool DocumentSignatureHelper::equalsReferenceUriManifestPath( 405*cdf0e10cSrcweir const OUString & rUri, const OUString & rPath) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir bool retVal = false; 408*cdf0e10cSrcweir //split up the uri and path into segments. Both are separated by '/' 409*cdf0e10cSrcweir std::vector<OUString> vUriSegments; 410*cdf0e10cSrcweir sal_Int32 nIndex = 0; 411*cdf0e10cSrcweir do 412*cdf0e10cSrcweir { 413*cdf0e10cSrcweir OUString aToken = rUri.getToken( 0, '/', nIndex ); 414*cdf0e10cSrcweir vUriSegments.push_back(aToken); 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir while (nIndex >= 0); 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir std::vector<OUString> vPathSegments; 419*cdf0e10cSrcweir nIndex = 0; 420*cdf0e10cSrcweir do 421*cdf0e10cSrcweir { 422*cdf0e10cSrcweir OUString aToken = rPath.getToken( 0, '/', nIndex ); 423*cdf0e10cSrcweir vPathSegments.push_back(aToken); 424*cdf0e10cSrcweir } 425*cdf0e10cSrcweir while (nIndex >= 0); 426*cdf0e10cSrcweir 427*cdf0e10cSrcweir //Now compare each segment of the uri with its counterpart from the path 428*cdf0e10cSrcweir if (vUriSegments.size() == vPathSegments.size()) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir retVal = true; 431*cdf0e10cSrcweir typedef std::vector<OUString>::const_iterator CIT; 432*cdf0e10cSrcweir for (CIT i = vUriSegments.begin(), j = vPathSegments.begin(); 433*cdf0e10cSrcweir i != vUriSegments.end(); i++, j++) 434*cdf0e10cSrcweir { 435*cdf0e10cSrcweir //Decode the uri segment, so that %20 becomes ' ', etc. 436*cdf0e10cSrcweir OUString sDecUri = ::rtl::Uri::decode( 437*cdf0e10cSrcweir *i, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); 438*cdf0e10cSrcweir if (!sDecUri.equals(*j)) 439*cdf0e10cSrcweir { 440*cdf0e10cSrcweir retVal = false; 441*cdf0e10cSrcweir break; 442*cdf0e10cSrcweir } 443*cdf0e10cSrcweir } 444*cdf0e10cSrcweir } 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir return retVal; 447*cdf0e10cSrcweir } 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir ::rtl::OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName() 450*cdf0e10cSrcweir { 451*cdf0e10cSrcweir return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "documentsignatures.xml" ) ); 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir ::rtl::OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName() 455*cdf0e10cSrcweir { 456*cdf0e10cSrcweir return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "macrosignatures.xml" ) ); 457*cdf0e10cSrcweir } 458*cdf0e10cSrcweir 459*cdf0e10cSrcweir ::rtl::OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName() 460*cdf0e10cSrcweir { 461*cdf0e10cSrcweir return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "packagesignatures.xml" ) ); 462*cdf0e10cSrcweir } 463