xref: /trunk/main/xmlsecurity/source/xmlsec/nss/xmlencryption_nssimpl.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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