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 
29 #include "com/sun/star/xml/crypto/SecurityOperationStatus.hdl"
30 #include "xmlsignature_mscryptimpl.hxx"
31 
32 #ifndef _XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX_
33 #include "xmldocumentwrapper_xmlsecimpl.hxx"
34 #endif
35 
36 #ifndef _XMLELEMENTWRAPPER_XMLSECIMPL_HXX_
37 #include "xmlelementwrapper_xmlsecimpl.hxx"
38 #endif
39 
40 #ifndef _SECURITYENVIRONMENT_MSCRYPTIMPL_HXX_
41 #include "securityenvironment_mscryptimpl.hxx"
42 #endif
43 #include "xmlstreamio.hxx"
44 #include "errorcallback.hxx"
45 
46 #include "xmlsec/xmlsec.h"
47 #include "xmlsec/xmldsig.h"
48 #include "xmlsec/crypto.h"
49 
50 using namespace ::com::sun::star::uno ;
51 using namespace ::com::sun::star::lang ;
52 using ::com::sun::star::lang::XMultiServiceFactory ;
53 using ::com::sun::star::lang::XSingleServiceFactory ;
54 using ::rtl::OUString ;
55 
56 using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
57 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ;
58 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
59 using ::com::sun::star::xml::crypto::XXMLSignature ;
60 using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
61 using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
62 using ::com::sun::star::xml::crypto::XUriBinding ;
63 using ::com::sun::star::xml::crypto::XMLSignatureException ;
64 
65 
XMLSignature_MSCryptImpl(const Reference<XMultiServiceFactory> & aFactory)66 XMLSignature_MSCryptImpl :: XMLSignature_MSCryptImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_xServiceManager( aFactory ) {
67 }
68 
~XMLSignature_MSCryptImpl()69 XMLSignature_MSCryptImpl :: ~XMLSignature_MSCryptImpl() {
70 }
71 
72 /* XXMLSignature */
73 Reference< XXMLSignatureTemplate >
generate(const Reference<XXMLSignatureTemplate> & aTemplate,const Reference<XSecurityEnvironment> & aEnvironment)74 SAL_CALL XMLSignature_MSCryptImpl :: generate(
75 	const Reference< XXMLSignatureTemplate >& aTemplate ,
76 	const Reference< XSecurityEnvironment >& aEnvironment
77 ) throw( com::sun::star::xml::crypto::XMLSignatureException,
78 		 com::sun::star::uno::SecurityException )
79 {
80 	xmlSecKeysMngrPtr pMngr = NULL ;
81 	xmlSecDSigCtxPtr pDsigCtx = NULL ;
82 	xmlNodePtr pNode = NULL ;
83 
84 	if( !aTemplate.is() )
85 		throw RuntimeException() ;
86 
87 	if( !aEnvironment.is() )
88 		throw RuntimeException() ;
89 
90 	//Get Keys Manager
91 	Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ;
92 	if( !xSecTunnel.is() ) {
93 		 throw RuntimeException() ;
94 	}
95 
96 	SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ;
97 	if( pSecEnv == NULL )
98 		throw RuntimeException() ;
99 
100 	//Get the xml node
101 	Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
102 	if( !xElement.is() ) {
103 		throw RuntimeException() ;
104 	}
105 
106 	Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ;
107 	if( !xNodTunnel.is() ) {
108 		throw RuntimeException() ;
109 	}
110 
111 	XMLElementWrapper_XmlSecImpl* pElement = ( XMLElementWrapper_XmlSecImpl* )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  	setErrorRecorder( );
127 
128 	pMngr = pSecEnv->createKeysManager() ; //i39448
129 	if( !pMngr ) {
130 		throw RuntimeException() ;
131 	}
132 
133 	//Create Signature context
134 	pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
135 	if( pDsigCtx == NULL )
136 	{
137 		//throw XMLSignatureException() ;
138 		pSecEnv->destroyKeysManager( pMngr ) ; //i39448
139 		clearErrorRecorder();
140 		return aTemplate;
141 	}
142 
143 	//Sign the template
144 	if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 )
145 	{
146         if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
147             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
148         else
149             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
150 	}
151     else
152 	{
153         aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
154 	}
155 
156 
157 	xmlSecDSigCtxDestroy( pDsigCtx ) ;
158 	pSecEnv->destroyKeysManager( pMngr ) ; //i39448
159 
160 	//Unregistered the stream/URI binding
161 	if( xUriBinding.is() )
162 		xmlUnregisterStreamInputCallbacks() ;
163 
164 	clearErrorRecorder();
165 	return aTemplate ;
166 }
167 
168 /* XXMLSignature */
169 Reference< XXMLSignatureTemplate >
validate(const Reference<XXMLSignatureTemplate> & aTemplate,const Reference<XXMLSecurityContext> & aSecurityCtx)170 SAL_CALL XMLSignature_MSCryptImpl :: validate(
171 	const Reference< XXMLSignatureTemplate >& aTemplate ,
172 	const Reference< XXMLSecurityContext >& aSecurityCtx
173 ) throw( com::sun::star::uno::RuntimeException,
174 		 com::sun::star::uno::SecurityException,
175 		 com::sun::star::xml::crypto::XMLSignatureException ) {
176 	xmlSecKeysMngrPtr pMngr = NULL ;
177 	xmlSecDSigCtxPtr pDsigCtx = NULL ;
178 	xmlNodePtr pNode = NULL ;
179 	//sal_Bool valid ;
180 
181 	if( !aTemplate.is() )
182 		throw RuntimeException() ;
183 
184 	if( !aSecurityCtx.is() )
185 		throw RuntimeException() ;
186 
187 	//Get Keys Manager
188 	Reference< XSecurityEnvironment > xSecEnv
189 		= aSecurityCtx->getSecurityEnvironmentByIndex(
190 			aSecurityCtx->getDefaultSecurityEnvironmentIndex());
191 	Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY ) ;
192 	if( !xSecTunnel.is() ) {
193 		 throw RuntimeException() ;
194 	}
195 
196 	SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ;
197 	if( pSecEnv == NULL )
198 		throw RuntimeException() ;
199 
200 	//Get the xml node
201 	Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
202 	if( !xElement.is() )
203 		throw RuntimeException() ;
204 
205 	Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ;
206 	if( !xNodTunnel.is() ) {
207 		throw RuntimeException() ;
208 	}
209 
210 	XMLElementWrapper_XmlSecImpl* pElement = ( XMLElementWrapper_XmlSecImpl* )xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ;
211 	if( pElement == NULL )
212 		throw RuntimeException() ;
213 
214 	pNode = pElement->getNativeElement() ;
215 
216 	//Get the stream/URI binding
217 	Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
218 	if( xUriBinding.is() ) {
219 		//Register the stream input callbacks into libxml2
220 		if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
221 			throw RuntimeException() ;
222 	}
223 
224 	//added for test: save the result
225 	/*
226 	{
227 		FILE *dstFile = fopen( "c:\\1.txt", "w" ) ;
228 		xmlDocDump( dstFile, pNode->doc) ;
229 		fclose( dstFile ) ;
230 	}
231 	*/
232 
233  	setErrorRecorder( );
234 
235 	pMngr = pSecEnv->createKeysManager() ; //i39448
236 	if( !pMngr ) {
237 		throw RuntimeException() ;
238 	}
239 
240 	//Create Signature context
241 	pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
242 	if( pDsigCtx == NULL )
243 	{
244 		pSecEnv->destroyKeysManager( pMngr ) ; //i39448
245 		//throw XMLSignatureException() ;
246 		clearErrorRecorder();
247 		return aTemplate;
248 	}
249 
250 	//Verify signature
251     //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0)
252     //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if
253     //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the
254     //error recorder feature to get the ONE error that made the verification fail, because there is no
255     //documentation/specification as to how to interpret the number of recorded errors and what is the initial
256     //error.
257 	if( xmlSecDSigCtxVerify( pDsigCtx , pNode ) == 0 )
258     {
259         if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
260             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
261         else
262             aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
263     }
264     else
265     {
266         aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN);
267     }
268 
269     xmlSecDSigCtxDestroy( pDsigCtx ) ;
270     pSecEnv->destroyKeysManager( pMngr ) ; //i39448
271 
272     //Unregistered the stream/URI binding
273     if( xUriBinding.is() )
274         xmlUnregisterStreamInputCallbacks() ;
275 
276 
277     clearErrorRecorder();
278     return aTemplate;
279 }
280 
281 /* XInitialization */
initialize(const Sequence<Any> &)282 void SAL_CALL XMLSignature_MSCryptImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) throw( Exception, RuntimeException ) {
283 	// TBD
284 } ;
285 
286 /* XServiceInfo */
getImplementationName()287 OUString SAL_CALL XMLSignature_MSCryptImpl :: getImplementationName() throw( RuntimeException ) {
288 	return impl_getImplementationName() ;
289 }
290 
291 /* XServiceInfo */
supportsService(const OUString & serviceName)292 sal_Bool SAL_CALL XMLSignature_MSCryptImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) {
293 	Sequence< OUString > seqServiceNames = getSupportedServiceNames() ;
294 	const OUString* pArray = seqServiceNames.getConstArray() ;
295 	for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) {
296 		if( *( pArray + i ) == serviceName )
297 			return sal_True ;
298 	}
299 	return sal_False ;
300 }
301 
302 /* XServiceInfo */
getSupportedServiceNames()303 Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl :: getSupportedServiceNames() throw( RuntimeException ) {
304 	return impl_getSupportedServiceNames() ;
305 }
306 
307 //Helper for XServiceInfo
impl_getSupportedServiceNames()308 Sequence< OUString > XMLSignature_MSCryptImpl :: impl_getSupportedServiceNames() {
309 	::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
310 	Sequence< OUString > seqServiceNames( 1 ) ;
311 	seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.XMLSignature" ) ;
312 	return seqServiceNames ;
313 }
314 
impl_getImplementationName()315 OUString XMLSignature_MSCryptImpl :: impl_getImplementationName() throw( RuntimeException ) {
316 	return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_MSCryptImpl" ) ;
317 }
318 
319 //Helper for registry
impl_createInstance(const Reference<XMultiServiceFactory> & aServiceManager)320 Reference< XInterface > SAL_CALL XMLSignature_MSCryptImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) {
321 	return Reference< XInterface >( *new XMLSignature_MSCryptImpl( aServiceManager ) ) ;
322 }
323 
impl_createFactory(const Reference<XMultiServiceFactory> & aServiceManager)324 Reference< XSingleServiceFactory > XMLSignature_MSCryptImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) {
325 	//Reference< XSingleServiceFactory > xFactory ;
326 	//xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ;
327 	//return xFactory ;
328 	return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ;
329 }
330 
331