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