Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / xmlsecurity / source / xmlsec / nss / xmlsignature_nssimpl.cxx
blobc39f6cc72f763e87e0b378a23fa93b83d4e703b6
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>
22 #include <xmlelementwrapper_xmlsecimpl.hxx>
23 #include <xmlsec/xmlstreamio.hxx>
24 #include <xmlsec/errorcallback.hxx>
26 #include "securityenvironment_nssimpl.hxx"
28 #include <xmlsec-wrapper.h>
29 #include <com/sun/star/xml/crypto/XXMLSignature.hpp>
30 #include <memory>
32 namespace com::sun::star::uno { class XComponentContext; }
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno ;
36 using namespace ::com::sun::star::lang ;
38 using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
39 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
40 using ::com::sun::star::xml::crypto::XXMLSignature ;
41 using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
42 using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
43 using ::com::sun::star::xml::crypto::XUriBinding ;
45 namespace std
47 template <> struct default_delete<xmlSecKeysMngr>
49 void operator()(xmlSecKeysMngrPtr ptr) { SecurityEnvironment_NssImpl::destroyKeysManager(ptr); }
51 template <> struct default_delete<xmlSecDSigCtx>
53 void operator()(xmlSecDSigCtxPtr ptr) { xmlSecDSigCtxDestroy(ptr); }
57 class XMLSignature_NssImpl
58 : public ::cppu::WeakImplHelper<xml::crypto::XXMLSignature, lang::XServiceInfo>
60 public:
61 explicit XMLSignature_NssImpl();
63 //Methods from XXMLSignature
64 virtual uno::Reference<xml::crypto::XXMLSignatureTemplate> SAL_CALL
65 generate(const uno::Reference<xml::crypto::XXMLSignatureTemplate>& aTemplate,
66 const uno::Reference<xml::crypto::XSecurityEnvironment>& aEnvironment) override;
68 virtual uno::Reference<xml::crypto::XXMLSignatureTemplate> SAL_CALL
69 validate(const uno::Reference<xml::crypto::XXMLSignatureTemplate>& aTemplate,
70 const uno::Reference<xml::crypto::XXMLSecurityContext>& aContext) override;
72 //Methods from XServiceInfo
73 virtual OUString SAL_CALL getImplementationName() override;
75 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
77 virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
80 XMLSignature_NssImpl::XMLSignature_NssImpl() {
83 /* XXMLSignature */
84 Reference< XXMLSignatureTemplate >
85 SAL_CALL XMLSignature_NssImpl::generate(
86 const Reference< XXMLSignatureTemplate >& aTemplate ,
87 const Reference< XSecurityEnvironment >& aEnvironment
90 xmlNodePtr pNode = nullptr ;
92 if( !aTemplate.is() )
93 throw RuntimeException() ;
95 if( !aEnvironment.is() )
96 throw RuntimeException() ;
98 //Get the xml node
99 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
100 if( !xElement.is() ) {
101 throw RuntimeException() ;
104 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
105 XMLElementWrapper_XmlSecImpl* pElement =
106 reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
107 sal::static_int_cast<sal_uIntPtr>(
108 xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() )));
109 if( pElement == nullptr ) {
110 throw RuntimeException() ;
113 pNode = pElement->getNativeElement() ;
115 //Get the stream/URI binding
116 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
117 if( xUriBinding.is() ) {
118 //Register the stream input callbacks into libxml2
119 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
120 throw RuntimeException() ;
123 //Get Keys Manager
124 Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
126 // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext
128 SecurityEnvironment_NssImpl* pSecEnv =
129 reinterpret_cast<SecurityEnvironment_NssImpl*>(
130 sal::static_int_cast<sal_uIntPtr>(
131 xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
132 if( pSecEnv == nullptr )
133 throw RuntimeException() ;
135 setErrorRecorder();
137 std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager());
138 if( !pMngr ) {
139 throw RuntimeException() ;
142 //Create Signature context
143 std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get()));
144 if( pDsigCtx == nullptr )
146 //throw XMLSignatureException() ;
147 clearErrorRecorder();
148 return aTemplate;
151 //Sign the template
152 if( xmlSecDSigCtxSign( pDsigCtx.get() , pNode ) == 0 )
154 if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
155 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
156 else
157 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
159 else
161 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
164 //Unregistered the stream/URI binding
165 if( xUriBinding.is() )
166 xmlUnregisterStreamInputCallbacks() ;
168 clearErrorRecorder();
169 return aTemplate ;
172 /* XXMLSignature */
173 Reference< XXMLSignatureTemplate >
174 SAL_CALL XMLSignature_NssImpl::validate(
175 const Reference< XXMLSignatureTemplate >& aTemplate ,
176 const Reference< XXMLSecurityContext >& aSecurityCtx
178 xmlNodePtr pNode = nullptr ;
179 //sal_Bool valid ;
181 if( !aTemplate.is() )
182 throw RuntimeException() ;
184 if( !aSecurityCtx.is() )
185 throw RuntimeException() ;
187 //Get the xml node
188 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
189 if( !xElement.is() )
190 throw RuntimeException() ;
192 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
193 XMLElementWrapper_XmlSecImpl* pElement =
194 reinterpret_cast<XMLElementWrapper_XmlSecImpl*>(
195 sal::static_int_cast<sal_uIntPtr>(
196 xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() )));
197 if( pElement == nullptr )
198 throw RuntimeException() ;
200 pNode = pElement->getNativeElement() ;
202 //Get the stream/URI binding
203 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
204 if( xUriBinding.is() ) {
205 //Register the stream input callbacks into libxml2
206 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
207 throw RuntimeException() ;
210 setErrorRecorder();
212 sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber();
213 sal_Int32 i;
215 for (i=0; i<nSecurityEnvironment; ++i)
217 Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
219 //Get Keys Manager
220 Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
221 SecurityEnvironment_NssImpl* pSecEnv =
222 reinterpret_cast<SecurityEnvironment_NssImpl*>(
223 sal::static_int_cast<sal_uIntPtr>(
224 xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
225 if( pSecEnv == nullptr )
226 throw RuntimeException() ;
228 std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager());
229 if( !pMngr ) {
230 throw RuntimeException() ;
233 //Create Signature context
234 std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get()));
235 if( pDsigCtx == nullptr )
237 clearErrorRecorder();
238 return aTemplate;
241 // We do certificate verification ourselves.
242 pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
244 //Verify signature
245 int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode );
247 // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
248 xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
249 // Require that all manifest references are also good.
250 xmlSecSize nReferenceGood = 0;
251 for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
253 xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
254 if (pReference)
256 if (pReference->status == xmlSecDSigStatusSucceeded)
257 ++nReferenceGood;
261 if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood)
263 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
264 break;
266 else
268 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
273 //Unregistered the stream/URI binding
274 if( xUriBinding.is() )
275 xmlUnregisterStreamInputCallbacks() ;
277 //return valid ;
278 clearErrorRecorder();
279 return aTemplate;
282 /* XServiceInfo */
283 OUString SAL_CALL XMLSignature_NssImpl::getImplementationName()
285 return "com.sun.star.xml.crypto.XMLSignature";
288 /* XServiceInfo */
289 sal_Bool SAL_CALL XMLSignature_NssImpl::supportsService(const OUString& rServiceName)
291 const css::uno::Sequence<OUString> aServiceNames = getSupportedServiceNames();
292 for (OUString const & rCurrentServiceName : aServiceNames)
294 if (rCurrentServiceName == rServiceName)
295 return true;
297 return false;
300 /* XServiceInfo */
301 Sequence<OUString> SAL_CALL XMLSignature_NssImpl::getSupportedServiceNames()
303 Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" };
304 return seqServiceNames;
307 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
308 com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/,
309 uno::Sequence<uno::Any> const& /*rSeq*/)
311 return cppu::acquire(new XMLSignature_NssImpl);
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */