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 <xsecctl.hxx>
32 #include <tools/debug.hxx>
33 
34 #include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
35 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
36 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
37 #include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp>
38 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
39 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp>
40 #include <com/sun/star/io/XActiveDataSource.hpp>
41 #include <rtl/uuid.h>
42 
43 #include <stdio.h>
44 
45 namespace cssu = com::sun::star::uno;
46 namespace cssl = com::sun::star::lang;
47 namespace cssxc = com::sun::star::xml::crypto;
48 namespace cssxs = com::sun::star::xml::sax;
49 
50 /* xml security framework components */
51 #define SIGNATURECREATOR_COMPONENT "com.sun.star.xml.crypto.sax.SignatureCreator"
52 
53 /* protected: for signature generation */
54 rtl::OUString XSecController::createId()
55 {
56 	cssu::Sequence< sal_Int8 > aSeq( 16 );
57 	rtl_createUuid ((sal_uInt8 *)aSeq.getArray(), 0, sal_True);
58 
59 	char str[68]="ID_";
60 	int length = 3;
61 	for (int i=0; i<16; ++i)
62 	{
63 		length += sprintf(str+length, "%04x", (unsigned char)aSeq[i]);
64 	}
65 
66 	return rtl::OUString::createFromAscii(str);
67 }
68 
69 cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite(
70 	InternalSignatureInformation& internalSignatureInfor )
71 {
72 	sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId;
73 	SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors;
74 
75 	sal_Int32 nIdOfSignatureElementCollector;
76 	cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener;
77 
78 	nIdOfSignatureElementCollector =
79 		m_xSAXEventKeeper->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_AFTERMODIFY, sal_True );
80 
81 	m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId);
82 
83         /*
84          * create a SignatureCreator
85          */
86 	cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
87 	xReferenceResolvedListener = cssu::Reference< cssxc::sax::XReferenceResolvedListener >(
88 		xMCF->createInstanceWithContext(
89 			rtl::OUString::createFromAscii(SIGNATURECREATOR_COMPONENT), mxCtx),
90 		cssu::UNO_QUERY);
91 
92 	cssu::Reference<cssl::XInitialization> xInitialization(xReferenceResolvedListener, cssu::UNO_QUERY);
93 
94 	cssu::Sequence<cssu::Any> args(5);
95 	args[0] = cssu::makeAny(rtl::OUString::valueOf(nSecurityId));
96 	args[1] = cssu::makeAny(m_xSAXEventKeeper);
97 	args[2] = cssu::makeAny(rtl::OUString::valueOf(nIdOfSignatureElementCollector));
98 
99 	//i39448 : for nss, the internal module is used for signing, which needs to be improved later
100 	sal_Int32 nEnvIndex = internalSignatureInfor.signatureInfor.nSecurityEnvironmentIndex;
101 	if( nEnvIndex < 0 || nEnvIndex >= m_xSecurityContext->getSecurityEnvironmentNumber())
102 	{// set defaultEnv
103 		args[3] = cssu::makeAny(m_xSecurityContext->getSecurityEnvironment());
104 	}
105 	else
106 	{
107 		args[3] = cssu::makeAny(m_xSecurityContext->getSecurityEnvironmentByIndex(nEnvIndex));
108 	}
109 
110 	args[4] = cssu::makeAny(m_xXMLSignature);
111 	xInitialization->initialize(args);
112 
113 	sal_Int32 nBlockerId = m_xSAXEventKeeper->addBlocker();
114 	m_xSAXEventKeeper->setSecurityId(nBlockerId, nSecurityId);
115 
116 	cssu::Reference<cssxc::sax::XBlockerMonitor> xBlockerMonitor(xReferenceResolvedListener, cssu::UNO_QUERY);
117 	xBlockerMonitor->setBlockerId(nBlockerId);
118 
119 	cssu::Reference< cssxc::sax::XSignatureCreationResultBroadcaster >
120 		xSignatureCreationResultBroadcaster(xReferenceResolvedListener, cssu::UNO_QUERY);
121 
122 	xSignatureCreationResultBroadcaster->addSignatureCreationResultListener( this );
123 
124 	cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster>
125 		xReferenceResolvedBroadcaster
126 		(m_xSAXEventKeeper,
127 		cssu::UNO_QUERY);
128 
129 	xReferenceResolvedBroadcaster->addReferenceResolvedListener(
130 		nIdOfSignatureElementCollector,
131 		xReferenceResolvedListener);
132 
133 	cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector
134 		(xReferenceResolvedListener, cssu::UNO_QUERY);
135 
136 	int i;
137 	int size = vReferenceInfors.size();
138 	sal_Int32 nReferenceCount = 0;
139 
140 	for(i=0; i<size; ++i)
141 	{
142 		sal_Int32 keeperId = internalSignatureInfor.vKeeperIds[i];
143 
144 		if ( keeperId != -1)
145 		{
146 			m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId);
147 			xReferenceResolvedBroadcaster->addReferenceResolvedListener( keeperId, xReferenceResolvedListener);
148 			xReferenceCollector->setReferenceId( keeperId );
149 			nReferenceCount++;
150 		}
151 	}
152 
153 	xReferenceCollector->setReferenceCount( nReferenceCount );
154 
155 	/*
156 	 * adds all URI binding
157 	 */
158 	cssu::Reference<cssxc::XUriBinding> xUriBinding
159 		(xReferenceResolvedListener, cssu::UNO_QUERY);
160 
161 	for(i=0; i<size; ++i)
162 	{
163 		const SignatureReferenceInformation& refInfor = vReferenceInfors[i];
164 
165 		cssu::Reference< com::sun::star::io::XInputStream > xInputStream
166 			= getObjectInputStream( refInfor.ouURI );
167 
168 		if (xInputStream.is())
169 		{
170 			xUriBinding->setUriBinding(refInfor.ouURI,xInputStream);
171 		}
172 	}
173 
174 	cssu::Reference<cssxc::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, cssu::UNO_QUERY);
175 	keyCollector->setKeyId(0);
176 
177 	internalSignatureInfor.signatureInfor.ouSignatureId = createId();
178 	internalSignatureInfor.signatureInfor.ouPropertyId = createId();
179 	internalSignatureInfor.addReference(TYPE_SAMEDOCUMENT_REFERENCE, internalSignatureInfor.signatureInfor.ouPropertyId, -1 );
180 	size++;
181 
182 	/*
183 	 * replace both digestValues and signatueValue to " "
184 	 */
185 	for(i=0; i<size; ++i)
186 	{
187 		SignatureReferenceInformation& refInfor = vReferenceInfors[i];
188 		refInfor.ouDigestValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CHAR_BLANK));
189 	}
190 
191 	internalSignatureInfor.signatureInfor.ouSignatureValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CHAR_BLANK));
192 
193 	return xReferenceResolvedListener;
194 }
195 
196 /* public: for signature generation */
197 void XSecController::collectToSign( sal_Int32 securityId, const rtl::OUString& referenceId )
198 {
199 	/* DBG_ASSERT( m_xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" ); */
200 
201 	chainOn(true);
202 
203 	if ( m_nStatusOfSecurityComponents == INITIALIZED )
204 	/*
205 	 * if all security components are ready, add a signature.
206 	 */
207 	{
208 		sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector(
209 			cssxc::sax::ElementMarkPriority_AFTERMODIFY, sal_False);
210 
211 		int index = findSignatureInfor( securityId );
212 
213 		if ( index == -1 )
214 		{
215 			InternalSignatureInformation isi(securityId, NULL);
216 			isi.addReference(TYPE_SAMEDOCUMENT_REFERENCE, referenceId, nKeeperId );
217 			m_vInternalSignatureInformations.push_back( isi );
218 		}
219 		else
220 		{
221 			m_vInternalSignatureInformations[index].addReference(TYPE_SAMEDOCUMENT_REFERENCE, referenceId, nKeeperId );
222 		}
223 	}
224 }
225 
226 void XSecController::signAStream( sal_Int32 securityId, const rtl::OUString& uri, const rtl::OUString& /*objectURL*/, sal_Bool isBinary)
227 {
228         sal_Int32 type = ((isBinary==sal_True)?TYPE_BINARYSTREAM_REFERENCE:TYPE_XMLSTREAM_REFERENCE);
229 
230 	int index = findSignatureInfor( securityId );
231 
232 	if (index == -1)
233 	{
234 		InternalSignatureInformation isi(securityId, NULL);
235 		isi.addReference(type, uri, -1);
236 		m_vInternalSignatureInformations.push_back( isi );
237 	}
238 	else
239 	{
240 		m_vInternalSignatureInformations[index].addReference(type, uri, -1);
241 	}
242 }
243 
244 void XSecController::setX509Certificate(
245 	sal_Int32 nSecurityId,
246 	const rtl::OUString& ouX509IssuerName,
247 	const rtl::OUString& ouX509SerialNumber,
248 	const rtl::OUString& ouX509Cert)
249 {
250 	setX509Certificate(nSecurityId, -1, ouX509IssuerName, ouX509SerialNumber, ouX509Cert);
251 }
252 
253 void XSecController::setX509Certificate(
254 	sal_Int32 nSecurityId,
255 	const sal_Int32	nSecurityEnvironmentIndex,
256 	const rtl::OUString& ouX509IssuerName,
257 	const rtl::OUString& ouX509SerialNumber,
258 	const rtl::OUString& ouX509Cert)
259 {
260 	int index = findSignatureInfor( nSecurityId );
261 
262 	if ( index == -1 )
263 	{
264 		InternalSignatureInformation isi(nSecurityId, NULL);
265 		isi.signatureInfor.nSecurityEnvironmentIndex = nSecurityEnvironmentIndex;
266 		isi.signatureInfor.ouX509IssuerName = ouX509IssuerName;
267 		isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber;
268 		isi.signatureInfor.ouX509Certificate = ouX509Cert;
269 		m_vInternalSignatureInformations.push_back( isi );
270 	}
271 	else
272 	{
273 		SignatureInformation &si
274 			= m_vInternalSignatureInformations[index].signatureInfor;
275 		si.ouX509IssuerName = ouX509IssuerName;
276 		si.ouX509SerialNumber = ouX509SerialNumber;
277 		si.ouX509Certificate = ouX509Cert;
278 		si.nSecurityEnvironmentIndex = nSecurityEnvironmentIndex;
279 	}
280 }
281 
282 void XSecController::setDate(
283 	sal_Int32 nSecurityId,
284 	const ::com::sun::star::util::DateTime& rDateTime )
285 {
286 	int index = findSignatureInfor( nSecurityId );
287 
288 	if ( index == -1 )
289 	{
290 		InternalSignatureInformation isi(nSecurityId, NULL);
291 		isi.signatureInfor.stDateTime = rDateTime;
292 		m_vInternalSignatureInformations.push_back( isi );
293 	}
294 	else
295 	{
296 		SignatureInformation &si
297 			= m_vInternalSignatureInformations[index].signatureInfor;
298 		si.stDateTime = rDateTime;
299 	}
300 }
301 
302 bool XSecController::WriteSignature(
303 	const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler )
304 {
305 	bool rc = false;
306 
307 	DBG_ASSERT( xDocumentHandler.is(), "I really need a document handler!" );
308 
309 	/*
310 	 * chain the SAXEventKeeper to the SAX chain
311 	 */
312 	chainOn(true);
313 
314 	if ( m_nStatusOfSecurityComponents == INITIALIZED )
315 	/*
316 	 * if all security components are ready, add the signature
317 	 * stream.
318 	 */
319 	{
320 		m_bIsSAXEventKeeperSticky = true;
321 		m_xSAXEventKeeper->setNextHandler(xDocumentHandler);
322 
323 		try
324 		{
325 			/*
326 			 * export the signature template
327 			 */
328 			cssu::Reference<cssxs::XDocumentHandler> xSEKHandler( m_xSAXEventKeeper,cssu::UNO_QUERY);
329 
330 			int i;
331 			int sigNum = m_vInternalSignatureInformations.size();
332 
333 			for (i=0; i<sigNum; ++i)
334 			{
335 				InternalSignatureInformation &isi = m_vInternalSignatureInformations[i];
336 
337 				/*
338 				 * prepare the signature creator
339 				 */
340 				isi.xReferenceResolvedListener
341 					= prepareSignatureToWrite( isi );
342 
343 				exportSignature( xSEKHandler, isi.signatureInfor );
344 			}
345 
346 			m_bIsSAXEventKeeperSticky = false;
347 			chainOff();
348 
349 			rc = true;
350 		}
351 		catch( cssxs::SAXException& )
352 		{
353 			m_pErrorMessage = ERROR_SAXEXCEPTIONDURINGCREATION;
354 		}
355 		catch( com::sun::star::io::IOException& )
356 		{
357 			m_pErrorMessage = ERROR_IOEXCEPTIONDURINGCREATION;
358 		}
359 		catch( cssu::Exception& )
360 		{
361 			m_pErrorMessage = ERROR_EXCEPTIONDURINGCREATION;
362 		}
363 
364 		m_xSAXEventKeeper->setNextHandler( NULL );
365 		m_bIsSAXEventKeeperSticky = false;
366 	}
367 	else
368 	{
369 		m_pErrorMessage = ERROR_CANNOTCREATEXMLSECURITYCOMPONENT;
370 	}
371 
372 	return rc;
373 }
374 
375