1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
30 
31 #include <xmlsecurity/xmlsignaturehelper.hxx>
32 #include <xmlsecurity/documentsignaturehelper.hxx>
33 #include <xsecctl.hxx>
34 
35 #include <xmlsignaturehelper2.hxx>
36 
37 #include <tools/stream.hxx>
38 #include <tools/debug.hxx>
39 
40 #include <xmloff/attrlist.hxx>
41 
42 #include <com/sun/star/io/XOutputStream.hpp>
43 #include <com/sun/star/io/XInputStream.hpp>
44 #include <com/sun/star/io/XActiveDataSource.hpp>
45 #include <com/sun/star/lang/XComponent.hpp>
46 #include <com/sun/star/security/SerialNumberAdapter.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 
49 #include <tools/date.hxx>
50 #include <tools/time.hxx>
51 
52 //MM : search for the default profile
53 //#include <unotools/streamhelper.hxx>
54 //MM : end
55 
56 /* SEInitializer component */
57 #define SEINITIALIZER_COMPONENT "com.sun.star.xml.crypto.SEInitializer"
58 
59 #define TAG_DOCUMENTSIGNATURES	"document-signatures"
60 #define NS_DOCUMENTSIGNATURES	"http://openoffice.org/2004/documentsignatures"
61 #define NS_DOCUMENTSIGNATURES_ODF_1_2 "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0"
62 
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65 
66 XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx)
67     : mxCtx(rxCtx), mbODFPre1_2(false)
68 {
69     mpXSecController = new XSecController(rxCtx);
70     mxSecurityController = mpXSecController;
71     mbError = false;
72 }
73 
74 XMLSignatureHelper::~XMLSignatureHelper()
75 {
76 }
77 
78 bool XMLSignatureHelper::Init()
79 {
80     DBG_ASSERT( !mxSEInitializer.is(), "XMLSignatureHelper::Init - mxSEInitializer already set!" );
81     DBG_ASSERT( !mxSecurityContext.is(), "XMLSignatureHelper::Init - mxSecurityContext already set!" );
82 
83     ImplCreateSEInitializer();
84 
85 	if ( mxSEInitializer.is() )
86 		mxSecurityContext = mxSEInitializer->createSecurityContext( ::rtl::OUString() );
87 
88     return mxSecurityContext.is();
89 }
90 
91 void XMLSignatureHelper::ImplCreateSEInitializer()
92 {
93     rtl::OUString sSEInitializer(rtl::OUString::createFromAscii( SEINITIALIZER_COMPONENT ));
94     uno::Reference< lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
95     mxSEInitializer = uno::Reference< com::sun::star::xml::crypto::XSEInitializer > (
96         xMCF->createInstanceWithContext( sSEInitializer,  mxCtx ), uno::UNO_QUERY );
97 }
98 
99 void XMLSignatureHelper::SetUriBinding( com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding >& rxUriBinding )
100 {
101     mxUriBinding = rxUriBinding;
102 }
103 
104 com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding > XMLSignatureHelper::GetUriBinding() const
105 {
106     return mxUriBinding;
107 }
108 
109 void XMLSignatureHelper::SetStorage(
110     const Reference < css::embed::XStorage >& rxStorage,
111     ::rtl::OUString sODFVersion)
112 {
113     DBG_ASSERT( !mxUriBinding.is(), "SetStorage - UriBinding already set!" );
114     mxUriBinding = new UriBindingHelper( rxStorage );
115     DBG_ASSERT(rxStorage.is(), "SetStorage - empty storage!");
116     mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion);
117 }
118 
119 
120 void XMLSignatureHelper::SetStartVerifySignatureHdl( const Link& rLink )
121 {
122     maStartVerifySignatureHdl = rLink;
123 }
124 
125 
126 void XMLSignatureHelper::StartMission()
127 {
128     if ( !mxUriBinding.is() )
129         mxUriBinding = new UriBindingHelper();
130 
131     mpXSecController->startMission( mxUriBinding, mxSecurityContext );
132 }
133 
134 void XMLSignatureHelper::EndMission()
135 {
136     mpXSecController->endMission();
137 }
138 
139 sal_Int32 XMLSignatureHelper::GetNewSecurityId()
140 {
141     return mpXSecController->getNewSecurityId();
142 }
143 
144 void XMLSignatureHelper::SetX509Certificate(
145 		sal_Int32 nSecurityId,
146 		const rtl::OUString& ouX509IssuerName,
147 		const rtl::OUString& ouX509SerialNumber,
148 		const rtl::OUString& ouX509Cert)
149 {
150 	mpXSecController->setX509Certificate(
151 		nSecurityId,
152 		ouX509IssuerName,
153 		ouX509SerialNumber,
154 		ouX509Cert);
155 }
156 
157 void XMLSignatureHelper::SetX509Certificate(
158 		sal_Int32 nSecurityId,
159 		sal_Int32 nSecurityEnvironmentIndex,
160 		const rtl::OUString& ouX509IssuerName,
161 		const rtl::OUString& ouX509SerialNumber,
162 		const rtl::OUString& ouX509Cert)
163 {
164 	mpXSecController->setX509Certificate(
165 		nSecurityId,
166 		nSecurityEnvironmentIndex,
167 		ouX509IssuerName,
168 		ouX509SerialNumber,
169 		ouX509Cert);
170 }
171 
172 void XMLSignatureHelper::SetDateTime( sal_Int32 nSecurityId, const Date& rDate, const Time& rTime )
173 {
174 	/*
175     rtl::OUString aDate = String::CreateFromInt32( rDate.GetDate() );
176     rtl::OUString aTime = String::CreateFromInt32( rTime.GetTime() );
177 	mpXSecController->setDateTime( nSecurityId, aDate, aTime );
178 	*/
179 	::com::sun::star::util::DateTime stDateTime;
180 	stDateTime.HundredthSeconds = (::sal_uInt16)rTime.Get100Sec();
181 	stDateTime.Seconds = (::sal_uInt16)rTime.GetSec();
182 	stDateTime.Minutes = (::sal_uInt16)rTime.GetMin();
183 	stDateTime.Hours = (::sal_uInt16)rTime.GetHour();
184 	stDateTime.Day = (::sal_uInt16)rDate.GetDay();
185 	stDateTime.Month = (::sal_uInt16)rDate.GetMonth();
186 	stDateTime.Year = (::sal_uInt16)rDate.GetYear();
187 	mpXSecController->setDate( nSecurityId, stDateTime );
188 }
189 
190 void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const rtl::OUString& uri, const rtl::OUString& objectURL, sal_Bool bBinary )
191 {
192 	mpXSecController->signAStream( nSecurityId, uri, objectURL, bBinary );
193 }
194 
195 
196 uno::Reference<xml::sax::XDocumentHandler> XMLSignatureHelper::CreateDocumentHandlerWithHeader(
197 	const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xOutputStream )
198 {
199 	/*
200 	 * get SAX writer component
201 	 */
202 	uno::Reference< lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
203 	uno::Reference< io::XActiveDataSource > xSaxWriter(
204 		xMCF->createInstanceWithContext(rtl::OUString::createFromAscii(
205 			"com.sun.star.xml.sax.Writer"), mxCtx ), uno::UNO_QUERY );
206 
207 	DBG_ASSERT( xSaxWriter.is(), "can't instantiate XML writer" );
208 
209 	/*
210 	 * connect XML writer to output stream
211 	 */
212 	xSaxWriter->setOutputStream( xOutputStream );
213 
214 	/*
215 	 * prepare document handler
216 	 */
217 	uno::Reference<xml::sax::XDocumentHandler>
218 		xDocHandler( xSaxWriter,uno::UNO_QUERY);
219 
220 	/*
221 	 * write the xml context for signatures
222 	 */
223 	rtl::OUString tag_AllSignatures(RTL_CONSTASCII_USTRINGPARAM(TAG_DOCUMENTSIGNATURES));
224 
225 	SvXMLAttributeList *pAttributeList = new SvXMLAttributeList();
226     rtl::OUString sNamespace;
227     if (mbODFPre1_2)
228         sNamespace = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NS_DOCUMENTSIGNATURES));
229     else
230         sNamespace = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NS_DOCUMENTSIGNATURES_ODF_1_2));
231 
232 	pAttributeList->AddAttribute(
233 		rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_XMLNS)),
234 		sNamespace);
235 
236 	xDocHandler->startDocument();
237 	xDocHandler->startElement(
238 		tag_AllSignatures,
239 		uno::Reference< com::sun::star::xml::sax::XAttributeList > (pAttributeList));
240 
241 	return xDocHandler;
242 }
243 
244 void XMLSignatureHelper::CloseDocumentHandler( const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler )
245 {
246 	rtl::OUString tag_AllSignatures(RTL_CONSTASCII_USTRINGPARAM(TAG_DOCUMENTSIGNATURES));
247 	xDocumentHandler->endElement( tag_AllSignatures );
248 	xDocumentHandler->endDocument();
249 }
250 
251 void XMLSignatureHelper::ExportSignature(
252 	const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler,
253 	const SignatureInformation& signatureInfo )
254 {
255 	mpXSecController->exportSignature(xDocumentHandler, signatureInfo);
256 }
257 
258 bool XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler )
259 {
260 	mbError = false;
261 
262 	/*
263 	 * create a signature listener
264 	 */
265 /*
266 	ImplXMLSignatureListener* pSignatureListener = new ImplXMLSignatureListener(
267 	                                                LINK( this, XMLSignatureHelper, SignatureCreationResultListener ),
268 	                                                LINK( this, XMLSignatureHelper, SignatureVerifyResultListener ),
269 	                                                LINK( this, XMLSignatureHelper, StartVerifySignatureElement ) );
270 */
271 	/*
272 	 * configure the signature creation listener
273 	 */
274 	//mpXSecController->setSignatureCreationResultListener( pSignatureListener );
275 
276 	/*
277 	 * write signatures
278 	 */
279 	if ( !mpXSecController->WriteSignature( xDocumentHandler ) )
280 	{
281 		mbError = true;
282 	}
283 
284 	/*
285 	 * clear up the signature creation listener
286 	 */
287 	//mpXSecController->setSignatureCreationResultListener( NULL );
288 
289 	return !mbError;
290 }
291 
292 bool XMLSignatureHelper::CreateAndWriteSignature( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xOutputStream )
293 {
294 	uno::Reference<xml::sax::XDocumentHandler> xDocHandler
295 		= CreateDocumentHandlerWithHeader(xOutputStream);
296 
297 	bool rc = CreateAndWriteSignature( xDocHandler );
298 
299 	CloseDocumentHandler(xDocHandler);
300 
301 	return rc;
302 }
303 
304 bool XMLSignatureHelper::ReadAndVerifySignature( const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& xInputStream )
305 {
306 	mbError = false;
307 
308 	DBG_ASSERT(xInputStream.is(), "input stream missing");
309 
310 	/*
311 	 * prepare ParserInputSrouce
312 	 */
313 	xml::sax::InputSource aParserInput;
314 	// aParserInput.sSystemId = ouName;
315 	aParserInput.aInputStream = xInputStream;
316 
317 	/*
318 	 * get SAX parser component
319 	 */
320 	uno::Reference< lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
321 	uno::Reference< xml::sax::XParser > xParser(
322 		xMCF->createInstanceWithContext(
323 			rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser"), mxCtx ),
324 		uno::UNO_QUERY );
325 
326 	DBG_ASSERT( xParser.is(), "Can't create parser" );
327 
328 	/*
329 	 * create a signature reader
330 	 */
331 	uno::Reference< xml::sax::XDocumentHandler > xHandler
332 		= mpXSecController->createSignatureReader( );
333 
334 	/*
335 	 * create a signature listener
336 	 */
337 	ImplXMLSignatureListener* pSignatureListener = new ImplXMLSignatureListener(
338 	                                                LINK( this, XMLSignatureHelper, SignatureCreationResultListener ),
339 	                                                LINK( this, XMLSignatureHelper, SignatureVerifyResultListener ),
340 	                                                LINK( this, XMLSignatureHelper, StartVerifySignatureElement ) );
341 
342 	/*
343 	 * configure the signature verify listener
344 	 */
345 	//mpXSecController->setSignatureVerifyResultListener( pSignatureListener );
346 
347 	/*
348 	 * setup the connection:
349 	 * Parser -> SignatureListener -> SignatureReader
350 	 */
351 	pSignatureListener->setNextHandler(xHandler);
352 	xParser->setDocumentHandler( pSignatureListener );
353 
354 	/*
355 	 * parser the stream
356 	 */
357 	try
358 	{
359 		xParser->parseStream( aParserInput );
360 	}
361 	catch( xml::sax::SAXParseException& )
362 	{
363 		mbError = true;
364 	}
365 	catch( xml::sax::SAXException& )
366 	{
367 		mbError = true;
368 	}
369 	catch( com::sun::star::io::IOException& )
370 	{
371 		mbError = true;
372 	}
373 	catch( uno::Exception& )
374 	{
375 		mbError = true;
376 	}
377 
378 	/*
379 	 * clear up the connection
380 	 */
381 	pSignatureListener->setNextHandler( NULL );
382 
383 	/*
384 	 * clear up the signature verify listener
385 	 */
386 	//mpXSecController->setSignatureVerifyResultListener( NULL );
387 
388 	/*
389 	 * release the signature reader
390 	 */
391 	mpXSecController->releaseSignatureReader( );
392 
393 	return !mbError;
394 }
395 
396 SignatureInformation XMLSignatureHelper::GetSignatureInformation( sal_Int32 nSecurityId ) const
397 {
398 	return mpXSecController->getSignatureInformation( nSecurityId );
399 }
400 
401 SignatureInformations XMLSignatureHelper::GetSignatureInformations() const
402 {
403 	return mpXSecController->getSignatureInformations();
404 }
405 
406 uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > XMLSignatureHelper::GetSecurityEnvironment()
407 {
408 	return (mxSecurityContext.is()?(mxSecurityContext->getSecurityEnvironment()): uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment >());
409 }
410 
411 uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > XMLSignatureHelper::GetSecurityEnvironmentByIndex(sal_Int32 nId)
412 {
413 	return (mxSecurityContext.is()?(mxSecurityContext->getSecurityEnvironmentByIndex(nId)): uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment >());
414 }
415 
416 sal_Int32 XMLSignatureHelper::GetSecurityEnvironmentNumber()
417 {
418 	return (mxSecurityContext.is()?(mxSecurityContext->getSecurityEnvironmentNumber()): 0);
419 }
420 
421 IMPL_LINK( XMLSignatureHelper, SignatureCreationResultListener, XMLSignatureCreationResult*, pResult )
422 {
423     maCreationResults.insert( maCreationResults.begin() + maCreationResults.size(), *pResult );
424     if ( pResult->nSignatureCreationResult != com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
425         mbError = true;
426     return 0;
427 }
428 
429 IMPL_LINK( XMLSignatureHelper, SignatureVerifyResultListener, XMLSignatureVerifyResult*, pResult )
430 {
431     maVerifyResults.insert( maVerifyResults.begin() + maVerifyResults.size(), *pResult );
432     if ( pResult->nSignatureVerifyResult != com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
433         mbError = true;
434     return 0;
435 }
436 
437 IMPL_LINK( XMLSignatureHelper, StartVerifySignatureElement, const uno::Reference< com::sun::star::xml::sax::XAttributeList >*, pAttrs )
438 {
439     if ( !maStartVerifySignatureHdl.IsSet() || maStartVerifySignatureHdl.Call( (void*)pAttrs ) )
440 	{
441 		sal_Int32 nSignatureId = mpXSecController->getNewSecurityId();
442 		mpXSecController->addSignature( nSignatureId );
443 	}
444 
445     return 0;
446 }
447