Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / xmlsecurity / source / xmlsec / mscrypt / xmlsignature_mscryptimpl.cxx
bloba0acd81786d76e2f779f2a4bb0d1eee8d71588fe
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <rtl/uuid.h>
23 #include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
24 #include <com/sun/star/xml/crypto/XXMLSignature.hpp>
26 #include "securityenvironment_mscryptimpl.hxx"
28 #include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
29 #include <xmlelementwrapper_xmlsecimpl.hxx>
30 #include <xmlsec/xmlstreamio.hxx>
31 #include <xmlsec/errorcallback.hxx>
33 #include <xmlsec-wrapper.h>
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno ;
37 using namespace ::com::sun::star::lang ;
38 using ::com::sun::star::lang::XMultiServiceFactory ;
39 using ::com::sun::star::lang::XSingleServiceFactory ;
41 using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
42 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ;
43 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
44 using ::com::sun::star::xml::crypto::XXMLSignature ;
45 using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
46 using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
47 using ::com::sun::star::xml::crypto::XUriBinding ;
49 class XMLSignature_MSCryptImpl : public ::cppu::WeakImplHelper<
50 css::xml::crypto::XXMLSignature ,
51 css::lang::XServiceInfo >
53 public:
54 explicit XMLSignature_MSCryptImpl();
56 //Methods from XXMLSignature
57 virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate(
58 const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
59 const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment
60 ) override;
62 virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate(
63 const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
64 const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext
65 ) override;
67 //Methods from XServiceInfo
68 virtual OUString SAL_CALL getImplementationName() override;
70 virtual sal_Bool SAL_CALL supportsService(
71 const OUString& ServiceName
72 ) override;
74 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
75 } ;
77 XMLSignature_MSCryptImpl::XMLSignature_MSCryptImpl() {
80 /* XXMLSignature */
81 Reference< XXMLSignatureTemplate >
82 SAL_CALL XMLSignature_MSCryptImpl::generate(
83 const Reference< XXMLSignatureTemplate >& aTemplate ,
84 const Reference< XSecurityEnvironment >& aEnvironment
87 xmlSecKeysMngrPtr pMngr = nullptr ;
88 xmlSecDSigCtxPtr pDsigCtx = nullptr ;
89 xmlNodePtr pNode = nullptr ;
91 if( !aTemplate.is() )
92 throw RuntimeException() ;
94 if( !aEnvironment.is() )
95 throw RuntimeException() ;
97 //Get Keys Manager
98 Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
99 SecurityEnvironment_MSCryptImpl* pSecEnv = reinterpret_cast<SecurityEnvironment_MSCryptImpl*>(xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ));
100 if( pSecEnv == nullptr )
101 throw RuntimeException() ;
103 //Get the xml node
104 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
105 if( !xElement.is() ) {
106 throw RuntimeException() ;
109 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
110 XMLElementWrapper_XmlSecImpl* pElement = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() ));
111 if( pElement == nullptr ) {
112 throw RuntimeException() ;
115 pNode = pElement->getNativeElement() ;
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() ;
125 setErrorRecorder( );
127 pMngr = pSecEnv->createKeysManager();
128 if( !pMngr ) {
129 throw RuntimeException() ;
132 //Create Signature context
133 pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
134 if( pDsigCtx == nullptr )
136 //throw XMLSignatureException() ;
137 SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
138 clearErrorRecorder();
139 return aTemplate;
142 //Sign the template
143 if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 )
145 if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
146 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
147 else
148 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
150 else
152 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
156 xmlSecDSigCtxDestroy( pDsigCtx ) ;
157 SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
159 //Unregistered the stream/URI binding
160 if( xUriBinding.is() )
161 xmlUnregisterStreamInputCallbacks() ;
163 clearErrorRecorder();
164 return aTemplate ;
167 /* XXMLSignature */
168 Reference< XXMLSignatureTemplate >
169 SAL_CALL XMLSignature_MSCryptImpl::validate(
170 const Reference< XXMLSignatureTemplate >& aTemplate ,
171 const Reference< XXMLSecurityContext >& aSecurityCtx
173 xmlSecKeysMngrPtr pMngr = nullptr ;
174 xmlSecDSigCtxPtr pDsigCtx = nullptr ;
175 xmlNodePtr pNode = nullptr ;
177 if( !aTemplate.is() )
178 throw RuntimeException() ;
180 if( !aSecurityCtx.is() )
181 throw RuntimeException() ;
183 //Get Keys Manager
184 Reference< XSecurityEnvironment > xSecEnv
185 = aSecurityCtx->getSecurityEnvironmentByIndex(
186 aSecurityCtx->getDefaultSecurityEnvironmentIndex());
187 Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY_THROW ) ;
188 SecurityEnvironment_MSCryptImpl* pSecEnv = reinterpret_cast<SecurityEnvironment_MSCryptImpl*>(xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ));
189 if( pSecEnv == nullptr )
190 throw RuntimeException() ;
192 //Get the xml node
193 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
194 if( !xElement.is() )
195 throw RuntimeException() ;
197 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
198 XMLElementWrapper_XmlSecImpl* pElement = reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() ));
199 if( pElement == nullptr )
200 throw RuntimeException() ;
202 pNode = pElement->getNativeElement() ;
204 //Get the stream/URI binding
205 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
206 if( xUriBinding.is() ) {
207 //Register the stream input callbacks into libxml2
208 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
209 throw RuntimeException() ;
212 setErrorRecorder( );
214 pMngr = pSecEnv->createKeysManager();
215 if( !pMngr ) {
216 throw RuntimeException() ;
219 //Create Signature context
220 pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
221 if( pDsigCtx == nullptr )
223 SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
224 clearErrorRecorder();
225 return aTemplate;
228 // We do certificate verification ourselves.
229 pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
231 //Verify signature
232 //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0)
233 //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if
234 //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the
235 //error recorder feature to get the ONE error that made the verification fail, because there is no
236 //documentation/specification as to how to interpret the number of recorded errors and what is the initial
237 //error.
238 int rs = xmlSecDSigCtxVerify(pDsigCtx , pNode);
240 // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
241 xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
242 // Require that all manifest references are also good.
243 xmlSecSize nReferenceGood = 0;
244 for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
246 xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
247 if (pReference)
249 if (pReference->status == xmlSecDSigStatusSucceeded)
250 ++nReferenceGood;
254 if (rs == 0 && nReferenceCount == nReferenceGood)
256 if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
257 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
258 else
259 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
261 else
263 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
266 xmlSecDSigCtxDestroy( pDsigCtx ) ;
267 SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
269 //Unregistered the stream/URI binding
270 if( xUriBinding.is() )
271 xmlUnregisterStreamInputCallbacks() ;
274 clearErrorRecorder();
275 return aTemplate;
278 /* XServiceInfo */
279 OUString SAL_CALL XMLSignature_MSCryptImpl::getImplementationName() {
280 return "com.sun.star.xml.crypto.XMLSignature";
283 /* XServiceInfo */
284 sal_Bool SAL_CALL XMLSignature_MSCryptImpl::supportsService( const OUString& serviceName) {
285 Sequence< OUString > seqServiceNames = getSupportedServiceNames() ;
286 const OUString* pArray = seqServiceNames.getConstArray() ;
287 for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) {
288 if( *( pArray + i ) == serviceName )
289 return true ;
291 return false ;
294 /* XServiceInfo */
295 Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl::getSupportedServiceNames() {
296 Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" };
297 return seqServiceNames ;
300 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
301 com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/,
302 uno::Sequence<uno::Any> const& /*rSeq*/)
304 return cppu::acquire(new XMLSignature_MSCryptImpl);
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */