xref: /AOO41X/main/xmlsecurity/source/helper/documentsignaturehelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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