1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlencryption_nssimpl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmlsecurity.hxx"
33 #include <sal/config.h>
35 #include "xmlencryption_nssimpl.hxx"
37 #ifndef _XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX_
38 #include "xmldocumentwrapper_xmlsecimpl.hxx"
41 #ifndef _XMLELEMENTWRAPPER_XMLSECIMPL_HXX_
42 #include "xmlelementwrapper_xmlsecimpl.hxx"
45 #ifndef _SECURITYENVIRONMENT_NSSIMPL_HXX_
46 #include "securityenvironment_nssimpl.hxx"
48 #include "errorcallback.hxx"
50 #include <sal/types.h>
51 //For reasons that escape me, this is what xmlsec does when size_t is not 4
52 #if SAL_TYPES_SIZEOFPOINTER != 4
53 # define XMLSEC_NO_SIZE_T
55 #include "xmlsec/xmlsec.h"
56 #include "xmlsec/xmltree.h"
57 #include "xmlsec/xmlenc.h"
58 #include "xmlsec/crypto.h"
61 #define stricmp strcasecmp
64 using namespace ::com::sun::star::uno
;
65 using namespace ::com::sun::star::lang
;
66 using ::com::sun::star::lang::XMultiServiceFactory
;
67 using ::com::sun::star::lang::XSingleServiceFactory
;
68 using ::rtl::OUString
;
70 using ::com::sun::star::xml::wrapper::XXMLElementWrapper
;
71 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper
;
72 using ::com::sun::star::xml::crypto::XSecurityEnvironment
;
73 using ::com::sun::star::xml::crypto::XXMLEncryption
;
74 using ::com::sun::star::xml::crypto::XXMLEncryptionTemplate
;
75 using ::com::sun::star::xml::crypto::XXMLSecurityContext
;
76 using ::com::sun::star::xml::crypto::XSecurityEnvironment
;
77 using ::com::sun::star::xml::crypto::XMLEncryptionException
;
79 XMLEncryption_NssImpl :: XMLEncryption_NssImpl( const Reference
< XMultiServiceFactory
>& aFactory
) : m_xServiceManager( aFactory
) {
82 XMLEncryption_NssImpl :: ~XMLEncryption_NssImpl() {
86 Reference
< XXMLEncryptionTemplate
>
87 SAL_CALL
XMLEncryption_NssImpl :: encrypt(
88 const Reference
< XXMLEncryptionTemplate
>& aTemplate
,
89 const Reference
< XSecurityEnvironment
>& aEnvironment
90 ) throw( com::sun::star::xml::crypto::XMLEncryptionException
,
91 com::sun::star::uno::SecurityException
)
93 xmlSecKeysMngrPtr pMngr
= NULL
;
94 xmlSecEncCtxPtr pEncCtx
= NULL
;
95 xmlNodePtr pEncryptedData
= NULL
;
96 xmlNodePtr pContent
= NULL
;
99 throw RuntimeException() ;
101 if( !aEnvironment
.is() )
102 throw RuntimeException() ;
105 Reference
< XUnoTunnel
> xSecTunnel( aEnvironment
, UNO_QUERY
) ;
106 if( !xSecTunnel
.is() ) {
107 throw RuntimeException() ;
111 XMLSecurityContext_NssImpl
* pSecCtxt
= ( XMLSecurityContext_NssImpl
* )xSecTunnel
->getSomething( XMLSecurityContext_NssImpl::getUnoTunnelId() ) ;
112 if( pSecCtxt
== NULL
)
113 throw RuntimeException() ;
116 SecurityEnvironment_NssImpl
* pSecEnv
=
117 reinterpret_cast<SecurityEnvironment_NssImpl
*>(
118 sal::static_int_cast
<sal_uIntPtr
>(xSecTunnel
->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() ))) ;
119 if( pSecEnv
== NULL
)
120 throw RuntimeException() ;
122 //Get the encryption template
123 Reference
< XXMLElementWrapper
> xTemplate
= aTemplate
->getTemplate() ;
124 if( !xTemplate
.is() ) {
125 throw RuntimeException() ;
128 Reference
< XUnoTunnel
> xTplTunnel( xTemplate
, UNO_QUERY
) ;
129 if( !xTplTunnel
.is() ) {
130 throw RuntimeException() ;
133 XMLElementWrapper_XmlSecImpl
* pTemplate
=
134 reinterpret_cast<XMLElementWrapper_XmlSecImpl
*>(
135 sal::static_int_cast
<sal_uIntPtr
>(
136 xTplTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
137 if( pTemplate
== NULL
) {
138 throw RuntimeException() ;
141 //MM : Get the element to be encrypted
142 Reference
< XXMLElementWrapper
> xTarget
= aTemplate
->getTarget() ;
143 if( !xTarget
.is() ) {
144 throw XMLEncryptionException() ;
147 Reference
< XUnoTunnel
> xTgtTunnel( xTarget
, UNO_QUERY
) ;
148 if( !xTgtTunnel
.is() ) {
149 throw XMLEncryptionException() ;
152 XMLElementWrapper_XmlSecImpl
* pTarget
=
153 reinterpret_cast<XMLElementWrapper_XmlSecImpl
*>(
154 sal::static_int_cast
<sal_uIntPtr
>(
155 xTgtTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
156 if( pTarget
== NULL
) {
157 throw RuntimeException() ;
160 pContent
= pTarget
->getNativeElement() ;
163 if( pContent
== NULL
) {
164 throw XMLEncryptionException() ;
167 /* MM : remove the following 2 lines
168 xmlUnlinkNode(pContent);
169 xmlAddNextSibling(pEncryptedData, pContent);
172 //remember the position of the element to be signed
173 sal_Bool isParentRef
= sal_True
;
174 xmlNodePtr pParent
= pEncryptedData
->parent
;
175 xmlNodePtr referenceNode
;
177 if (pEncryptedData
== pParent
->children
)
179 referenceNode
= pParent
;
183 referenceNode
= pEncryptedData
->prev
;
184 isParentRef
= sal_False
;
189 pMngr
= pSecEnv
->createKeysManager() ; //i39448
191 throw RuntimeException() ;
194 //Create Encryption context
195 pEncCtx
= xmlSecEncCtxCreate( pMngr
) ;
196 if( pEncCtx
== NULL
)
198 pSecEnv
->destroyKeysManager( pMngr
) ; //i39448
199 //throw XMLEncryptionException() ;
200 clearErrorRecorder();
204 pEncryptedData
= pTemplate
->getNativeElement() ;
206 //Find the element to be encrypted.
207 /* MM : remove the old method to get the target element
208 //This element is wrapped in the CipherValue sub-element.
209 xmlNodePtr pCipherData = pEncryptedData->children;
210 while (pCipherData != NULL && stricmp((const char *)(pCipherData->name), "CipherData"))
212 pCipherData = pCipherData->next;
215 if( pCipherData == NULL ) {
216 xmlSecEncCtxDestroy( pEncCtx ) ;
217 throw XMLEncryptionException() ;
220 xmlNodePtr pCipherValue = pCipherData->children;
221 while (pCipherValue != NULL && stricmp((const char *)(pCipherValue->name), "CipherValue"))
223 pCipherValue = pCipherValue->next;
226 if( pCipherValue == NULL ) {
227 xmlSecEncCtxDestroy( pEncCtx ) ;
228 throw XMLEncryptionException() ;
231 pContent = pCipherValue->children;
234 //Encrypt the template
235 if( xmlSecEncCtxXmlEncrypt( pEncCtx
, pEncryptedData
, pContent
) < 0 )
237 xmlSecEncCtxDestroy( pEncCtx
) ;
238 pSecEnv
->destroyKeysManager( pMngr
) ; //i39448
240 //throw XMLEncryptionException() ;
241 clearErrorRecorder();
245 xmlSecEncCtxDestroy( pEncCtx
) ;
246 pSecEnv
->destroyKeysManager( pMngr
) ; //i39448
248 //get the new EncryptedData element
251 pTemplate
->setNativeElement(referenceNode
->children
) ;
255 pTemplate
->setNativeElement(referenceNode
->next
);
262 Reference
< XXMLEncryptionTemplate
>
263 SAL_CALL
XMLEncryption_NssImpl :: decrypt(
264 const Reference
< XXMLEncryptionTemplate
>& aTemplate
,
265 const Reference
< XXMLSecurityContext
>& aSecurityCtx
266 ) throw( com::sun::star::xml::crypto::XMLEncryptionException
,
267 com::sun::star::uno::SecurityException
) {
268 xmlSecKeysMngrPtr pMngr
= NULL
;
269 xmlSecEncCtxPtr pEncCtx
= NULL
;
270 xmlNodePtr pEncryptedData
= NULL
;
272 if( !aTemplate
.is() )
273 throw RuntimeException() ;
275 if( !aSecurityCtx
.is() )
276 throw RuntimeException() ;
278 //Get the encryption template
279 Reference
< XXMLElementWrapper
> xTemplate
= aTemplate
->getTemplate() ;
280 if( !xTemplate
.is() ) {
281 throw RuntimeException() ;
284 Reference
< XUnoTunnel
> xTplTunnel( xTemplate
, UNO_QUERY
) ;
285 if( !xTplTunnel
.is() ) {
286 throw RuntimeException() ;
289 XMLElementWrapper_XmlSecImpl
* pTemplate
=
290 reinterpret_cast<XMLElementWrapper_XmlSecImpl
*>(
291 sal::static_int_cast
<sal_uIntPtr
>(
292 xTplTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
293 if( pTemplate
== NULL
) {
294 throw RuntimeException() ;
297 pEncryptedData
= pTemplate
->getNativeElement() ;
299 //remember the position of the element to be signed
300 sal_Bool isParentRef
= sal_True
;
301 xmlNodePtr pParent
= pEncryptedData
->parent
;
302 xmlNodePtr referenceNode
;
304 if (pEncryptedData
== pParent
->children
)
306 referenceNode
= pParent
;
310 referenceNode
= pEncryptedData
->prev
;
311 isParentRef
= sal_False
;
316 sal_Int32 nSecurityEnvironment
= aSecurityCtx
->getSecurityEnvironmentNumber();
319 for (i
=0; i
<nSecurityEnvironment
; ++i
)
321 Reference
< XSecurityEnvironment
> aEnvironment
= aSecurityCtx
->getSecurityEnvironmentByIndex(i
);
324 Reference
< XUnoTunnel
> xSecTunnel( aEnvironment
, UNO_QUERY
) ;
325 if( !aEnvironment
.is() ) {
326 throw RuntimeException() ;
329 SecurityEnvironment_NssImpl
* pSecEnv
=
330 reinterpret_cast<SecurityEnvironment_NssImpl
*>(
331 sal::static_int_cast
<sal_uIntPtr
>(
332 xSecTunnel
->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
333 if( pSecEnv
== NULL
)
334 throw RuntimeException() ;
336 pMngr
= pSecEnv
->createKeysManager() ; //i39448
338 throw RuntimeException() ;
341 //Create Encryption context
342 pEncCtx
= xmlSecEncCtxCreate( pMngr
) ;
343 if( pEncCtx
== NULL
)
345 pSecEnv
->destroyKeysManager( pMngr
) ; //i39448
346 //throw XMLEncryptionException() ;
347 clearErrorRecorder();
351 //Decrypt the template
352 if(!( xmlSecEncCtxDecrypt( pEncCtx
, pEncryptedData
) < 0 || pEncCtx
->result
== NULL
))
354 //The decryption succeeds
356 //Destroy the encryption context
357 xmlSecEncCtxDestroy( pEncCtx
) ;
358 pSecEnv
->destroyKeysManager( pMngr
) ; //i39448
360 //get the decrypted element
361 XMLElementWrapper_XmlSecImpl
* ret
= new XMLElementWrapper_XmlSecImpl(isParentRef
?
362 (referenceNode
->children
):(referenceNode
->next
));
365 aTemplate
->setTemplate(ret
);
370 //The decryption fails, continue with the next security environment
371 xmlSecEncCtxDestroy( pEncCtx
) ;
372 pSecEnv
->destroyKeysManager( pMngr
) ; //i39448
376 clearErrorRecorder();
380 /* XInitialization */
381 void SAL_CALL
XMLEncryption_NssImpl :: initialize( const Sequence
< Any
>& /*aArguments*/ ) throw( Exception
, RuntimeException
) {
386 OUString SAL_CALL
XMLEncryption_NssImpl :: getImplementationName() throw( RuntimeException
) {
387 return impl_getImplementationName() ;
391 sal_Bool SAL_CALL
XMLEncryption_NssImpl :: supportsService( const OUString
& serviceName
) throw( RuntimeException
) {
392 Sequence
< OUString
> seqServiceNames
= getSupportedServiceNames() ;
393 const OUString
* pArray
= seqServiceNames
.getConstArray() ;
394 for( sal_Int32 i
= 0 ; i
< seqServiceNames
.getLength() ; i
++ ) {
395 if( *( pArray
+ i
) == serviceName
)
402 Sequence
< OUString
> SAL_CALL
XMLEncryption_NssImpl :: getSupportedServiceNames() throw( RuntimeException
) {
403 return impl_getSupportedServiceNames() ;
406 //Helper for XServiceInfo
407 Sequence
< OUString
> XMLEncryption_NssImpl :: impl_getSupportedServiceNames() {
408 ::osl::Guard
< ::osl::Mutex
> aGuard( ::osl::Mutex::getGlobalMutex() ) ;
409 Sequence
< OUString
> seqServiceNames( 1 ) ;
410 seqServiceNames
.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.XMLEncryption" ) ;
411 return seqServiceNames
;
414 OUString
XMLEncryption_NssImpl :: impl_getImplementationName() throw( RuntimeException
) {
415 return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.XMLEncryption_NssImpl" ) ;
418 //Helper for registry
419 Reference
< XInterface
> SAL_CALL
XMLEncryption_NssImpl :: impl_createInstance( const Reference
< XMultiServiceFactory
>& aServiceManager
) throw( RuntimeException
) {
420 return Reference
< XInterface
>( *new XMLEncryption_NssImpl( aServiceManager
) ) ;
423 Reference
< XSingleServiceFactory
> XMLEncryption_NssImpl :: impl_createFactory( const Reference
< XMultiServiceFactory
>& aServiceManager
) {
424 //Reference< XSingleServiceFactory > xFactory ;
425 //xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ;
427 return ::cppu::createSingleFactory( aServiceManager
, impl_getImplementationName() , impl_createInstance
, impl_getSupportedServiceNames() ) ;