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