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