1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmlsecurity.hxx"
26 #include <sal/config.h>
27 #include <rtl/uuid.h>
28 #include "xmlsignature_nssimpl.hxx"
29 
30 #ifndef _XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX_
31 #include "xmldocumentwrapper_xmlsecimpl.hxx"
32 #endif
33 
34 #ifndef _XMLELEMENTWRAPPER_XMLSECIMPL_HXX_
35 #include "xmlelementwrapper_xmlsecimpl.hxx"
36 #endif
37 
38 #ifndef _SECURITYENVIRONMENT_NSSIMPL_HXX_
39 #include "securityenvironment_nssimpl.hxx"
40 #endif
41 
42 #ifndef _XMLSECURITYCONTEXT_NSSIMPL_HXX_
43 #include "xmlsecuritycontext_nssimpl.hxx"
44 #endif
45 #include "xmlstreamio.hxx"
46 #include "errorcallback.hxx"
47 
48 #include <sal/types.h>
49 //For reasons that escape me, this is what xmlsec does when size_t is not 4
50 #if SAL_TYPES_SIZEOFPOINTER != 4
51 #    define XMLSEC_NO_SIZE_T
52 #endif
53 #include "xmlsec/xmlsec.h"
54 #include "xmlsec/xmldsig.h"
55 #include "xmlsec/crypto.h"
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::XXMLSignature ;
67 using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
68 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
69 using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
70 using ::com::sun::star::xml::crypto::XUriBinding ;
71 using ::com::sun::star::xml::crypto::XMLSignatureException ;
72 
XMLSignature_NssImpl(const Reference<XMultiServiceFactory> & aFactory)73 XMLSignature_NssImpl :: XMLSignature_NssImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_xServiceManager( aFactory ) {
74 }
75 
~XMLSignature_NssImpl()76 XMLSignature_NssImpl :: ~XMLSignature_NssImpl() {
77 }
78 
79 /* XXMLSignature */
80 Reference< XXMLSignatureTemplate >
generate(const Reference<XXMLSignatureTemplate> & aTemplate,const Reference<XSecurityEnvironment> & aEnvironment)81 SAL_CALL XMLSignature_NssImpl :: generate(
82 	const Reference< XXMLSignatureTemplate >& aTemplate ,
83 	const Reference< XSecurityEnvironment >& aEnvironment
84 ) throw( com::sun::star::xml::crypto::XMLSignatureException,
85 		 com::sun::star::uno::SecurityException )
86 {
87 	xmlSecKeysMngrPtr pMngr = NULL ;
88 	xmlSecDSigCtxPtr pDsigCtx = NULL ;
89 	xmlNodePtr pNode = NULL ;
90 
91 	if( !aTemplate.is() )
92 		throw RuntimeException() ;
93 
94 	if( !aEnvironment.is() )
95 		throw RuntimeException() ;
96 
97 	//Get the xml node
98 	Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
99 	if( !xElement.is() ) {
100 		throw RuntimeException() ;
101 	}
102 
103 	Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ;
104 	if( !xNodTunnel.is() ) {
105 		throw RuntimeException() ;
106 	}
107 
108 	XMLElementWrapper_XmlSecImpl* pElement =
109         reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
110             sal::static_int_cast<sal_uIntPtr>(
111                 xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
112 	if( pElement == NULL ) {
113 		throw RuntimeException() ;
114 	}
115 
116 	pNode = pElement->getNativeElement() ;
117 
118 	//Get the stream/URI binding
119 	Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
120 	if( xUriBinding.is() ) {
121 		//Register the stream input callbacks into libxml2
122 		if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
123 			throw RuntimeException() ;
124 	}
125 
126 	//Get Keys Manager
127 	Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ;
128 	if( !xSecTunnel.is() ) {
129 		 throw RuntimeException() ;
130 	}
131 
132 #if 0 //i39448 : the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext
133 	XMLSecurityContext_NssImpl* pSecCtxt = ( XMLSecurityContext_NssImpl* )xSecTunnel->getSomething( XMLSecurityContext_NssImpl::getUnoTunnelId() ) ;
134 	if( pSecCtxt == NULL )
135 		throw RuntimeException() ;
136 #endif
137 
138 	SecurityEnvironment_NssImpl* pSecEnv =
139         reinterpret_cast<SecurityEnvironment_NssImpl*>(
140             sal::static_int_cast<sal_uIntPtr>(
141                 xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
142 	if( pSecEnv == NULL )
143 		throw RuntimeException() ;
144 
145  	setErrorRecorder();
146 
147 	pMngr = pSecEnv->createKeysManager() ; //i39448
148 	if( !pMngr ) {
149 		throw RuntimeException() ;
150 	}
151 
152 	//Create Signature context
153 	pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
154 	if( pDsigCtx == NULL )
155 	{
156 		pSecEnv->destroyKeysManager( pMngr ) ; //i39448
157 		//throw XMLSignatureException() ;
158 		clearErrorRecorder();
159 		return aTemplate;
160 	}
161 
162 	//Sign the template
163 	if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 )
164 	{
165         if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
166             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
167         else
168             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
169 	}
170     else
171 	{
172         aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
173 	}
174 
175 
176 	xmlSecDSigCtxDestroy( pDsigCtx ) ;
177 	pSecEnv->destroyKeysManager( pMngr ) ; //i39448
178 
179 	//Unregistered the stream/URI binding
180 	if( xUriBinding.is() )
181 		xmlUnregisterStreamInputCallbacks() ;
182 
183 	clearErrorRecorder();
184 	return aTemplate ;
185 }
186 
187 /* XXMLSignature */
188 Reference< XXMLSignatureTemplate >
validate(const Reference<XXMLSignatureTemplate> & aTemplate,const Reference<XXMLSecurityContext> & aSecurityCtx)189 SAL_CALL XMLSignature_NssImpl :: validate(
190 	const Reference< XXMLSignatureTemplate >& aTemplate ,
191 	const Reference< XXMLSecurityContext >& aSecurityCtx
192 ) throw( com::sun::star::uno::RuntimeException,
193 		 com::sun::star::uno::SecurityException,
194 		 com::sun::star::xml::crypto::XMLSignatureException ) {
195 	xmlSecKeysMngrPtr pMngr = NULL ;
196 	xmlSecDSigCtxPtr pDsigCtx = NULL ;
197 	xmlNodePtr pNode = NULL ;
198 	//sal_Bool valid ;
199 
200 	if( !aTemplate.is() )
201 		throw RuntimeException() ;
202 
203 	if( !aSecurityCtx.is() )
204 		throw RuntimeException() ;
205 
206 	//Get the xml node
207 	Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
208 	if( !xElement.is() )
209 		throw RuntimeException() ;
210 
211 	Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ;
212 	if( !xNodTunnel.is() ) {
213 		throw RuntimeException() ;
214 	}
215 
216 	XMLElementWrapper_XmlSecImpl* pElement =
217         reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
218             sal::static_int_cast<sal_uIntPtr>(
219                 xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() )));
220 	if( pElement == NULL )
221 		throw RuntimeException() ;
222 
223 	pNode = pElement->getNativeElement() ;
224 
225 	//Get the stream/URI binding
226 	Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
227 	if( xUriBinding.is() ) {
228 		//Register the stream input callbacks into libxml2
229 		if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
230 			throw RuntimeException() ;
231 	}
232 
233  	setErrorRecorder();
234 
235 	sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber();
236 	sal_Int32 i;
237 
238 	for (i=0; i<nSecurityEnvironment; ++i)
239 	{
240 		Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
241 
242 		//Get Keys Manager
243 		Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ;
244 		if( !xSecTunnel.is() ) {
245 			 throw RuntimeException() ;
246 		}
247 
248 		SecurityEnvironment_NssImpl* pSecEnv =
249             reinterpret_cast<SecurityEnvironment_NssImpl*>(
250                 sal::static_int_cast<sal_uIntPtr>(
251                     xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
252 		if( pSecEnv == NULL )
253 			throw RuntimeException() ;
254 
255 		pMngr = pSecEnv->createKeysManager() ; //i39448
256 		if( !pMngr ) {
257 			throw RuntimeException() ;
258 		}
259 
260 		//Create Signature context
261 		pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
262 		if( pDsigCtx == NULL )
263 		{
264 			pSecEnv->destroyKeysManager( pMngr ) ; //i39448
265 			//throw XMLSignatureException() ;
266 			clearErrorRecorder();
267 			return aTemplate;
268 		}
269 
270 		//Verify signature
271 		int rs = xmlSecDSigCtxVerify( pDsigCtx , pNode );
272 
273 
274 		if (rs == 0 &&
275             pDsigCtx->status == xmlSecDSigStatusSucceeded)
276 		{
277             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
278             xmlSecDSigCtxDestroy( pDsigCtx ) ;
279             pSecEnv->destroyKeysManager( pMngr );
280 			break;
281 		}
282         else
283         {
284             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
285         }
286         xmlSecDSigCtxDestroy( pDsigCtx ) ;
287 		pSecEnv->destroyKeysManager( pMngr );
288 	}
289 
290 
291 
292 	//Unregistered the stream/URI binding
293 	if( xUriBinding.is() )
294 		xmlUnregisterStreamInputCallbacks() ;
295 
296 	//return valid ;
297 	clearErrorRecorder();
298 	return aTemplate;
299 }
300 
301 /* XInitialization */
initialize(const Sequence<Any> &)302 void SAL_CALL XMLSignature_NssImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) throw( Exception, RuntimeException ) {
303 	// TBD
304 } ;
305 
306 /* XServiceInfo */
getImplementationName()307 OUString SAL_CALL XMLSignature_NssImpl :: getImplementationName() throw( RuntimeException ) {
308 	return impl_getImplementationName() ;
309 }
310 
311 /* XServiceInfo */
supportsService(const OUString & serviceName)312 sal_Bool SAL_CALL XMLSignature_NssImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) {
313 	Sequence< OUString > seqServiceNames = getSupportedServiceNames() ;
314 	const OUString* pArray = seqServiceNames.getConstArray() ;
315 	for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) {
316 		if( *( pArray + i ) == serviceName )
317 			return sal_True ;
318 	}
319 	return sal_False ;
320 }
321 
322 /* XServiceInfo */
getSupportedServiceNames()323 Sequence< OUString > SAL_CALL XMLSignature_NssImpl :: getSupportedServiceNames() throw( RuntimeException ) {
324 	return impl_getSupportedServiceNames() ;
325 }
326 
327 //Helper for XServiceInfo
impl_getSupportedServiceNames()328 Sequence< OUString > XMLSignature_NssImpl :: impl_getSupportedServiceNames() {
329 	::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
330 	Sequence< OUString > seqServiceNames( 1 ) ;
331 	seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.XMLSignature" ) ;
332 	return seqServiceNames ;
333 }
334 
impl_getImplementationName()335 OUString XMLSignature_NssImpl :: impl_getImplementationName() throw( RuntimeException ) {
336 	return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_NssImpl" ) ;
337 }
338 
339 //Helper for registry
impl_createInstance(const Reference<XMultiServiceFactory> & aServiceManager)340 Reference< XInterface > SAL_CALL XMLSignature_NssImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) {
341 	return Reference< XInterface >( *new XMLSignature_NssImpl( aServiceManager ) ) ;
342 }
343 
impl_createFactory(const Reference<XMultiServiceFactory> & aServiceManager)344 Reference< XSingleServiceFactory > XMLSignature_NssImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) {
345 	//Reference< XSingleServiceFactory > xFactory ;
346 	//xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ;
347 	//return xFactory ;
348 	return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ;
349 }
350 
351