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 #include <sal/config.h>
31 #include <rtl/uuid.h>
32 #include "xmlencryption_nssimpl.hxx"
33 
34 #ifndef _XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX_
35 #include "xmldocumentwrapper_xmlsecimpl.hxx"
36 #endif
37 
38 #ifndef _XMLELEMENTWRAPPER_XMLSECIMPL_HXX_
39 #include "xmlelementwrapper_xmlsecimpl.hxx"
40 #endif
41 
42 #ifndef _SECURITYENVIRONMENT_NSSIMPL_HXX_
43 #include "securityenvironment_nssimpl.hxx"
44 #endif
45 #include "errorcallback.hxx"
46 
47 #include <sal/types.h>
48 //For reasons that escape me, this is what xmlsec does when size_t is not 4
49 #if SAL_TYPES_SIZEOFPOINTER != 4
50 #    define XMLSEC_NO_SIZE_T
51 #endif
52 #include "xmlsec/xmlsec.h"
53 #include "xmlsec/xmltree.h"
54 #include "xmlsec/xmlenc.h"
55 #include "xmlsec/crypto.h"
56 
57 #ifdef UNX
58 #define stricmp strcasecmp
59 #endif
60 
61 using namespace ::com::sun::star::uno ;
62 using namespace ::com::sun::star::lang ;
63 using ::com::sun::star::lang::XMultiServiceFactory ;
64 using ::com::sun::star::lang::XSingleServiceFactory ;
65 using ::rtl::OUString ;
66 
67 using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
68 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ;
69 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
70 using ::com::sun::star::xml::crypto::XXMLEncryption ;
71 using ::com::sun::star::xml::crypto::XXMLEncryptionTemplate ;
72 using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
73 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
74 using ::com::sun::star::xml::crypto::XMLEncryptionException ;
75 
76 XMLEncryption_NssImpl :: XMLEncryption_NssImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_xServiceManager( aFactory ) {
77 }
78 
79 XMLEncryption_NssImpl :: ~XMLEncryption_NssImpl() {
80 }
81 
82 /* XXMLEncryption */
83 Reference< XXMLEncryptionTemplate >
84 SAL_CALL XMLEncryption_NssImpl :: encrypt(
85 	const Reference< XXMLEncryptionTemplate >& aTemplate ,
86 	const Reference< XSecurityEnvironment >& aEnvironment
87 ) throw( com::sun::star::xml::crypto::XMLEncryptionException,
88 		 com::sun::star::uno::SecurityException )
89 {
90 	xmlSecKeysMngrPtr pMngr = NULL ;
91 	xmlSecEncCtxPtr pEncCtx = NULL ;
92 	xmlNodePtr pEncryptedData = NULL ;
93 	xmlNodePtr pContent = NULL ;
94 
95 	if( !aTemplate.is() )
96 		throw RuntimeException() ;
97 
98 	if( !aEnvironment.is() )
99 		throw RuntimeException() ;
100 
101 	//Get Keys Manager
102 	Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ;
103 	if( !xSecTunnel.is() ) {
104 		 throw RuntimeException() ;
105 	}
106 
107 #if 0
108 	XMLSecurityContext_NssImpl* pSecCtxt = ( XMLSecurityContext_NssImpl* )xSecTunnel->getSomething( XMLSecurityContext_NssImpl::getUnoTunnelId() ) ;
109 	if( pSecCtxt == NULL )
110 		throw RuntimeException() ;
111 #endif
112 
113 	SecurityEnvironment_NssImpl* pSecEnv =
114         reinterpret_cast<SecurityEnvironment_NssImpl*>(
115             sal::static_int_cast<sal_uIntPtr>(xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() ))) ;
116 	if( pSecEnv == NULL )
117 		throw RuntimeException() ;
118 
119 	//Get the encryption template
120 	Reference< XXMLElementWrapper > xTemplate = aTemplate->getTemplate() ;
121 	if( !xTemplate.is() ) {
122 		throw RuntimeException() ;
123 	}
124 
125 	Reference< XUnoTunnel > xTplTunnel( xTemplate , UNO_QUERY ) ;
126 	if( !xTplTunnel.is() ) {
127 		throw RuntimeException() ;
128 	}
129 
130 	XMLElementWrapper_XmlSecImpl* pTemplate =
131         reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
132             sal::static_int_cast<sal_uIntPtr>(
133                 xTplTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
134 	if( pTemplate == NULL ) {
135 		throw RuntimeException() ;
136 	}
137 
138 	//MM : Get the element to be encrypted
139 	Reference< XXMLElementWrapper > xTarget = aTemplate->getTarget() ;
140 	if( !xTarget.is() ) {
141 		throw XMLEncryptionException() ;
142 	}
143 
144 	Reference< XUnoTunnel > xTgtTunnel( xTarget , UNO_QUERY ) ;
145 	if( !xTgtTunnel.is() ) {
146 		throw XMLEncryptionException() ;
147 	}
148 
149 	XMLElementWrapper_XmlSecImpl* pTarget =
150         reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
151             sal::static_int_cast<sal_uIntPtr>(
152                 xTgtTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
153 	if( pTarget == NULL ) {
154 		throw RuntimeException() ;
155 	}
156 
157 	pContent = pTarget->getNativeElement() ;
158 	//MM : end
159 
160 	if( pContent == NULL ) {
161 		throw XMLEncryptionException() ;
162 	}
163 
164 	/* MM : remove the following 2 lines
165 	xmlUnlinkNode(pContent);
166 	xmlAddNextSibling(pEncryptedData, pContent);
167 	*/
168 
169 	//remember the position of the element to be signed
170 	sal_Bool isParentRef = sal_True;
171 	xmlNodePtr pParent = pEncryptedData->parent;
172 	xmlNodePtr referenceNode;
173 
174 	if (pEncryptedData == pParent->children)
175 	{
176 		referenceNode = pParent;
177 	}
178 	else
179 	{
180 		referenceNode = pEncryptedData->prev;
181 		isParentRef = sal_False;
182 	}
183 
184  	setErrorRecorder( );
185 
186 	pMngr = pSecEnv->createKeysManager() ; //i39448
187 	if( !pMngr ) {
188 		throw RuntimeException() ;
189 	}
190 
191 	//Create Encryption context
192 	pEncCtx = xmlSecEncCtxCreate( pMngr ) ;
193 	if( pEncCtx == NULL )
194 	{
195 		pSecEnv->destroyKeysManager( pMngr ) ; //i39448
196 		//throw XMLEncryptionException() ;
197 		clearErrorRecorder();
198 		return aTemplate;
199 	}
200 
201 	pEncryptedData = pTemplate->getNativeElement() ;
202 
203 	//Find the element to be encrypted.
204 	/* MM : remove the old method to get the target element
205 	//This element is wrapped in the CipherValue sub-element.
206 	xmlNodePtr pCipherData = pEncryptedData->children;
207 	while (pCipherData != NULL && stricmp((const char *)(pCipherData->name), "CipherData"))
208 	{
209 		pCipherData = pCipherData->next;
210 	}
211 
212 	if( pCipherData == NULL ) {
213 		xmlSecEncCtxDestroy( pEncCtx ) ;
214 		throw XMLEncryptionException() ;
215 	}
216 
217 	xmlNodePtr pCipherValue = pCipherData->children;
218 	while (pCipherValue != NULL && stricmp((const char *)(pCipherValue->name), "CipherValue"))
219 	{
220 		pCipherValue = pCipherValue->next;
221 	}
222 
223 	if( pCipherValue == NULL ) {
224 		xmlSecEncCtxDestroy( pEncCtx ) ;
225 		throw XMLEncryptionException() ;
226 	}
227 
228 	pContent = pCipherValue->children;
229 	*/
230 
231 	//Encrypt the template
232 	if( xmlSecEncCtxXmlEncrypt( pEncCtx , pEncryptedData , pContent ) < 0 )
233 	{
234 		xmlSecEncCtxDestroy( pEncCtx ) ;
235 		pSecEnv->destroyKeysManager( pMngr ) ; //i39448
236 
237 		//throw XMLEncryptionException() ;
238 		clearErrorRecorder();
239 		return aTemplate;
240 	}
241 
242 	xmlSecEncCtxDestroy( pEncCtx ) ;
243 	pSecEnv->destroyKeysManager( pMngr ) ; //i39448
244 
245 	//get the new EncryptedData element
246 	if (isParentRef)
247 	{
248 		pTemplate->setNativeElement(referenceNode->children) ;
249 	}
250 	else
251 	{
252 		pTemplate->setNativeElement(referenceNode->next);
253 	}
254 
255 	return aTemplate ;
256 }
257 
258 /* XXMLEncryption */
259 Reference< XXMLEncryptionTemplate >
260 SAL_CALL XMLEncryption_NssImpl :: decrypt(
261 	const Reference< XXMLEncryptionTemplate >& aTemplate ,
262 	const Reference< XXMLSecurityContext >& aSecurityCtx
263 ) throw( com::sun::star::xml::crypto::XMLEncryptionException ,
264 		 com::sun::star::uno::SecurityException) {
265 	xmlSecKeysMngrPtr pMngr = NULL ;
266 	xmlSecEncCtxPtr pEncCtx = NULL ;
267 	xmlNodePtr pEncryptedData = NULL ;
268 
269 	if( !aTemplate.is() )
270 		throw RuntimeException() ;
271 
272 	if( !aSecurityCtx.is() )
273 		throw RuntimeException() ;
274 
275 	//Get the encryption template
276 	Reference< XXMLElementWrapper > xTemplate = aTemplate->getTemplate() ;
277 	if( !xTemplate.is() ) {
278 		throw RuntimeException() ;
279 	}
280 
281 	Reference< XUnoTunnel > xTplTunnel( xTemplate , UNO_QUERY ) ;
282 	if( !xTplTunnel.is() ) {
283 		throw RuntimeException() ;
284 	}
285 
286 	XMLElementWrapper_XmlSecImpl* pTemplate =
287         reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
288             sal::static_int_cast<sal_uIntPtr>(
289                 xTplTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
290 	if( pTemplate == NULL ) {
291 		throw RuntimeException() ;
292 	}
293 
294 	pEncryptedData = pTemplate->getNativeElement() ;
295 
296 	//remember the position of the element to be signed
297 	sal_Bool isParentRef = sal_True;
298 	xmlNodePtr pParent = pEncryptedData->parent;
299 	xmlNodePtr referenceNode;
300 
301 	if (pEncryptedData == pParent->children)
302 	{
303 		referenceNode = pParent;
304 	}
305 	else
306 	{
307 		referenceNode = pEncryptedData->prev;
308 		isParentRef = sal_False;
309 	}
310 
311  	setErrorRecorder( );
312 
313 	sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber();
314 	sal_Int32 i;
315 
316 	for (i=0; i<nSecurityEnvironment; ++i)
317 	{
318 		Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
319 
320 		//Get Keys Manager
321 		Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ;
322 		if( !aEnvironment.is() ) {
323 			 throw RuntimeException() ;
324 		}
325 
326 		SecurityEnvironment_NssImpl* pSecEnv =
327             reinterpret_cast<SecurityEnvironment_NssImpl*>(
328                 sal::static_int_cast<sal_uIntPtr>(
329                     xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
330 		if( pSecEnv == NULL )
331 			throw RuntimeException() ;
332 
333 		pMngr = pSecEnv->createKeysManager() ; //i39448
334 		if( !pMngr ) {
335 			throw RuntimeException() ;
336 		}
337 
338 		//Create Encryption context
339 		pEncCtx = xmlSecEncCtxCreate( pMngr ) ;
340 		if( pEncCtx == NULL )
341 		{
342 			pSecEnv->destroyKeysManager( pMngr ) ; //i39448
343 			//throw XMLEncryptionException() ;
344 			clearErrorRecorder();
345 			return aTemplate;
346 		}
347 
348 		//Decrypt the template
349 		if(!( xmlSecEncCtxDecrypt( pEncCtx , pEncryptedData ) < 0 || pEncCtx->result == NULL ))
350 		{
351 			//The decryption succeeds
352 
353 			//Destroy the encryption context
354 			xmlSecEncCtxDestroy( pEncCtx ) ;
355 			pSecEnv->destroyKeysManager( pMngr ) ; //i39448
356 
357 			//get the decrypted element
358 			XMLElementWrapper_XmlSecImpl * ret = new XMLElementWrapper_XmlSecImpl(isParentRef?
359 				(referenceNode->children):(referenceNode->next));
360 
361 			//return ret;
362 			aTemplate->setTemplate(ret);
363 			break;
364 		}
365 		else
366 		{
367 			//The decryption fails, continue with the next security environment
368 			xmlSecEncCtxDestroy( pEncCtx ) ;
369 			pSecEnv->destroyKeysManager( pMngr ) ; //i39448
370 		}
371 	}
372 
373 	clearErrorRecorder();
374 	return aTemplate;
375 }
376 
377 /* XInitialization */
378 void SAL_CALL XMLEncryption_NssImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) throw( Exception, RuntimeException ) {
379 	// TBD
380 } ;
381 
382 /* XServiceInfo */
383 OUString SAL_CALL XMLEncryption_NssImpl :: getImplementationName() throw( RuntimeException ) {
384 	return impl_getImplementationName() ;
385 }
386 
387 /* XServiceInfo */
388 sal_Bool SAL_CALL XMLEncryption_NssImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) {
389 	Sequence< OUString > seqServiceNames = getSupportedServiceNames() ;
390 	const OUString* pArray = seqServiceNames.getConstArray() ;
391 	for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) {
392 		if( *( pArray + i ) == serviceName )
393 			return sal_True ;
394 	}
395 	return sal_False ;
396 }
397 
398 /* XServiceInfo */
399 Sequence< OUString > SAL_CALL XMLEncryption_NssImpl :: getSupportedServiceNames() throw( RuntimeException ) {
400 	return impl_getSupportedServiceNames() ;
401 }
402 
403 //Helper for XServiceInfo
404 Sequence< OUString > XMLEncryption_NssImpl :: impl_getSupportedServiceNames() {
405 	::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
406 	Sequence< OUString > seqServiceNames( 1 ) ;
407 	seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.XMLEncryption" ) ;
408 	return seqServiceNames ;
409 }
410 
411 OUString XMLEncryption_NssImpl :: impl_getImplementationName() throw( RuntimeException ) {
412 	return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.XMLEncryption_NssImpl" ) ;
413 }
414 
415 //Helper for registry
416 Reference< XInterface > SAL_CALL XMLEncryption_NssImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) {
417 	return Reference< XInterface >( *new XMLEncryption_NssImpl( aServiceManager ) ) ;
418 }
419 
420 Reference< XSingleServiceFactory > XMLEncryption_NssImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) {
421 	//Reference< XSingleServiceFactory > xFactory ;
422 	//xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ;
423 	//return xFactory ;
424 	return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ;
425 }
426 
427