1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include "xmlencryption_mscryptimpl.hxx"
24 #include "xmldocumentwrapper_xmlsecimpl.hxx"
26 #include "xmlelementwrapper_xmlsecimpl.hxx"
28 #include "securityenvironment_mscryptimpl.hxx"
29 #include "errorcallback.hxx"
31 #include "xmlsecurity/xmlsec-wrapper.h"
34 #define stricmp strcasecmp
37 using namespace ::com::sun::star::uno
;
38 using namespace ::com::sun::star::lang
;
39 using ::com::sun::star::lang::XMultiServiceFactory
;
40 using ::com::sun::star::lang::XSingleServiceFactory
;
42 using ::com::sun::star::xml::wrapper::XXMLElementWrapper
;
43 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper
;
44 using ::com::sun::star::xml::crypto::XSecurityEnvironment
;
45 using ::com::sun::star::xml::crypto::XXMLEncryption
;
46 using ::com::sun::star::xml::crypto::XXMLEncryptionTemplate
;
47 using ::com::sun::star::xml::crypto::XXMLSecurityContext
;
48 using ::com::sun::star::xml::crypto::XMLEncryptionException
;
50 XMLEncryption_MSCryptImpl :: XMLEncryption_MSCryptImpl( const Reference
< XMultiServiceFactory
>& aFactory
) : m_xServiceManager( aFactory
) {
53 XMLEncryption_MSCryptImpl :: ~XMLEncryption_MSCryptImpl() {
57 Reference
< XXMLEncryptionTemplate
>
58 SAL_CALL
XMLEncryption_MSCryptImpl :: encrypt(
59 const Reference
< XXMLEncryptionTemplate
>& aTemplate
,
60 const Reference
< XSecurityEnvironment
>& aEnvironment
61 ) throw( com::sun::star::xml::crypto::XMLEncryptionException
,
62 com::sun::star::uno::SecurityException
)
64 xmlSecKeysMngrPtr pMngr
= NULL
;
65 xmlSecEncCtxPtr pEncCtx
= NULL
;
66 xmlNodePtr pEncryptedData
= NULL
;
67 xmlNodePtr pContent
= NULL
;
70 throw RuntimeException() ;
72 if( !aEnvironment
.is() )
73 throw RuntimeException() ;
76 Reference
< XUnoTunnel
> xSecTunnel( aEnvironment
, UNO_QUERY
) ;
77 if( !xSecTunnel
.is() ) {
78 throw RuntimeException() ;
81 SecurityEnvironment_MSCryptImpl
* pSecEnv
= ( SecurityEnvironment_MSCryptImpl
* )xSecTunnel
->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ;
83 throw RuntimeException() ;
85 //Get the encryption template
86 Reference
< XXMLElementWrapper
> xTemplate
= aTemplate
->getTemplate() ;
87 if( !xTemplate
.is() ) {
88 throw RuntimeException() ;
91 Reference
< XUnoTunnel
> xTplTunnel( xTemplate
, UNO_QUERY
) ;
92 if( !xTplTunnel
.is() ) {
93 throw RuntimeException() ;
96 XMLElementWrapper_XmlSecImpl
* pTemplate
= ( XMLElementWrapper_XmlSecImpl
* )xTplTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ;
97 if( pTemplate
== NULL
) {
98 throw RuntimeException() ;
101 pEncryptedData
= pTemplate
->getNativeElement() ;
103 //Find the element to be encrypted.
104 //This element is wrapped in the CipherValue sub-element.
105 xmlNodePtr pCipherData
= pEncryptedData
->children
;
106 while (pCipherData
!= NULL
&& stricmp((const char *)(pCipherData
->name
), "CipherData"))
108 pCipherData
= pCipherData
->next
;
111 if( pCipherData
== NULL
) {
112 throw XMLEncryptionException() ;
115 xmlNodePtr pCipherValue
= pCipherData
->children
;
116 while (pCipherValue
!= NULL
&& stricmp((const char *)(pCipherValue
->name
), "CipherValue"))
118 pCipherValue
= pCipherValue
->next
;
121 if( pCipherValue
== NULL
) {
122 throw XMLEncryptionException() ;
125 pContent
= pCipherValue
->children
;
127 if( pContent
== NULL
) {
128 throw XMLEncryptionException() ;
131 xmlUnlinkNode(pContent
);
132 xmlAddNextSibling(pEncryptedData
, pContent
);
134 //remember the position of the element to be signed
135 sal_Bool isParentRef
= sal_True
;
136 xmlNodePtr pParent
= pEncryptedData
->parent
;
137 xmlNodePtr referenceNode
;
139 if (pEncryptedData
== pParent
->children
)
141 referenceNode
= pParent
;
145 referenceNode
= pEncryptedData
->prev
;
146 isParentRef
= sal_False
;
151 pMngr
= pSecEnv
->createKeysManager();
153 throw RuntimeException() ;
156 //Create Encryption context
157 pEncCtx
= xmlSecEncCtxCreate( pMngr
) ;
158 if( pEncCtx
== NULL
)
160 pSecEnv
->destroyKeysManager( pMngr
);
161 //throw XMLEncryptionException() ;
162 clearErrorRecorder();
166 //Encrypt the template
167 if( xmlSecEncCtxXmlEncrypt( pEncCtx
, pEncryptedData
, pContent
) < 0 ) {
168 aTemplate
->setStatus(::com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN
);
169 xmlSecEncCtxDestroy( pEncCtx
) ;
170 pSecEnv
->destroyKeysManager( pMngr
);
171 clearErrorRecorder();
174 aTemplate
->setStatus(::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
);
175 xmlSecEncCtxDestroy( pEncCtx
) ;
176 pSecEnv
->destroyKeysManager( pMngr
);
178 //get the new EncryptedData element
181 pTemplate
->setNativeElement(referenceNode
->children
) ;
185 pTemplate
->setNativeElement(referenceNode
->next
);
188 clearErrorRecorder();
193 Reference
< XXMLEncryptionTemplate
> SAL_CALL
194 XMLEncryption_MSCryptImpl :: decrypt(
195 const Reference
< XXMLEncryptionTemplate
>& aTemplate
,
196 const Reference
< XXMLSecurityContext
>& aSecurityCtx
197 ) throw( com::sun::star::xml::crypto::XMLEncryptionException
,
198 com::sun::star::uno::SecurityException
) {
199 xmlSecKeysMngrPtr pMngr
= NULL
;
200 xmlSecEncCtxPtr pEncCtx
= NULL
;
201 xmlNodePtr pEncryptedData
= NULL
;
203 if( !aTemplate
.is() )
204 throw RuntimeException() ;
206 if( !aSecurityCtx
.is() )
207 throw RuntimeException() ;
210 Reference
< XSecurityEnvironment
> xSecEnv
211 = aSecurityCtx
->getSecurityEnvironmentByIndex(
212 aSecurityCtx
->getDefaultSecurityEnvironmentIndex());
213 Reference
< XUnoTunnel
> xSecTunnel( xSecEnv
, UNO_QUERY
) ;
214 if( !xSecTunnel
.is() ) {
215 throw RuntimeException() ;
218 SecurityEnvironment_MSCryptImpl
* pSecEnv
= ( SecurityEnvironment_MSCryptImpl
* )xSecTunnel
->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ;
219 if( pSecEnv
== NULL
)
220 throw RuntimeException() ;
222 //Get the encryption template
223 Reference
< XXMLElementWrapper
> xTemplate
= aTemplate
->getTemplate() ;
224 if( !xTemplate
.is() ) {
225 throw RuntimeException() ;
228 Reference
< XUnoTunnel
> xTplTunnel( xTemplate
, UNO_QUERY
) ;
229 if( !xTplTunnel
.is() ) {
230 throw RuntimeException() ;
233 XMLElementWrapper_XmlSecImpl
* pTemplate
= ( XMLElementWrapper_XmlSecImpl
* )xTplTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ;
234 if( pTemplate
== NULL
) {
235 throw RuntimeException() ;
238 pEncryptedData
= pTemplate
->getNativeElement() ;
240 //remember the position of the element to be signed
241 sal_Bool isParentRef
= sal_True
;
242 xmlNodePtr pParent
= pEncryptedData
->parent
;
243 xmlNodePtr referenceNode
;
245 if (pEncryptedData
== pParent
->children
)
247 referenceNode
= pParent
;
251 referenceNode
= pEncryptedData
->prev
;
252 isParentRef
= sal_False
;
257 pMngr
= pSecEnv
->createKeysManager();
259 throw RuntimeException() ;
262 //Create Encryption context
263 pEncCtx
= xmlSecEncCtxCreate( pMngr
) ;
264 if( pEncCtx
== NULL
)
266 pSecEnv
->destroyKeysManager( pMngr
);
267 //throw XMLEncryptionException() ;
268 clearErrorRecorder();
272 //Decrypt the template
273 if( xmlSecEncCtxDecrypt( pEncCtx
, pEncryptedData
) < 0 || pEncCtx
->result
== NULL
) {
274 aTemplate
->setStatus(::com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN
);
275 xmlSecEncCtxDestroy( pEncCtx
) ;
276 pSecEnv
->destroyKeysManager( pMngr
);
278 //throw XMLEncryptionException() ;
279 clearErrorRecorder();
282 aTemplate
->setStatus(::com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
);
283 #if 0 // This code block has been commented out since 2004,
284 // but let's keep it here in case it contains some useful hints
286 if( pEncCtx
->resultReplaced
!= 0 ) {
287 pContent
= pEncryptedData
;
289 Reference
< XUnoTunnel
> xTunnel( ret
, UNO_QUERY
) ;
290 if( !xTunnel
.is() ) {
291 xmlSecEncCtxDestroy( pEncCtx
) ;
292 throw RuntimeException() ;
294 XMLElementWrapper_XmlSecImpl
* pNode
= ( XMLElementWrapper_XmlSecImpl
* )xTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ;
295 if( pNode
== NULL
) {
296 xmlSecEncCtxDestroy( pEncCtx
) ;
297 throw RuntimeException() ;
300 pNode
->setNativeElement( pContent
) ;
302 xmlSecEncCtxDestroy( pEncCtx
) ;
303 throw RuntimeException() ;
307 //Destroy the encryption context
308 xmlSecEncCtxDestroy( pEncCtx
) ;
309 pSecEnv
->destroyKeysManager( pMngr
);
311 //get the decrypted element
312 XMLElementWrapper_XmlSecImpl
* ret
= new XMLElementWrapper_XmlSecImpl(isParentRef
?
313 (referenceNode
->children
):(referenceNode
->next
));
316 aTemplate
->setTemplate(ret
);
318 clearErrorRecorder();
323 OUString SAL_CALL
XMLEncryption_MSCryptImpl :: getImplementationName() throw( RuntimeException
) {
324 return impl_getImplementationName() ;
328 sal_Bool SAL_CALL
XMLEncryption_MSCryptImpl :: supportsService( const OUString
& serviceName
) throw( RuntimeException
) {
329 Sequence
< OUString
> seqServiceNames
= getSupportedServiceNames() ;
330 const OUString
* pArray
= seqServiceNames
.getConstArray() ;
331 for( sal_Int32 i
= 0 ; i
< seqServiceNames
.getLength() ; i
++ ) {
332 if( *( pArray
+ i
) == serviceName
)
339 Sequence
< OUString
> SAL_CALL
XMLEncryption_MSCryptImpl :: getSupportedServiceNames() throw( RuntimeException
) {
340 return impl_getSupportedServiceNames() ;
343 //Helper for XServiceInfo
344 Sequence
< OUString
> XMLEncryption_MSCryptImpl :: impl_getSupportedServiceNames() {
345 ::osl::Guard
< ::osl::Mutex
> aGuard( ::osl::Mutex::getGlobalMutex() ) ;
346 Sequence
< OUString
> seqServiceNames( 1 ) ;
347 seqServiceNames
[0] = "com.sun.star.xml.crypto.XMLEncryption";
348 return seqServiceNames
;
351 OUString
XMLEncryption_MSCryptImpl :: impl_getImplementationName() throw( RuntimeException
) {
352 return OUString("com.sun.star.xml.security.bridge.xmlsec.XMLEncryption_MSCryptImpl") ;
355 //Helper for registry
356 Reference
< XInterface
> SAL_CALL
XMLEncryption_MSCryptImpl :: impl_createInstance( const Reference
< XMultiServiceFactory
>& aServiceManager
) throw( RuntimeException
) {
357 return Reference
< XInterface
>( *new XMLEncryption_MSCryptImpl( aServiceManager
) ) ;
360 Reference
< XSingleServiceFactory
> XMLEncryption_MSCryptImpl :: impl_createFactory( const Reference
< XMultiServiceFactory
>& aServiceManager
) {
361 //Reference< XSingleServiceFactory > xFactory ;
362 //xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ;
364 return ::cppu::createSingleFactory( aServiceManager
, impl_getImplementationName() , impl_createInstance
, impl_getSupportedServiceNames() ) ;
367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */