1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21
22 #include <xmlelementwrapper_xmlsecimpl.hxx>
23 #include <xmlsec/xmlstreamio.hxx>
24 #include <xmlsec/errorcallback.hxx>
25
26 #include "securityenvironment_nssimpl.hxx"
27
28 #include <xmlsec-wrapper.h>
29 #include <com/sun/star/xml/crypto/XXMLSignature.hpp>
30 #include <memory>
31
32 namespace com::sun::star::uno { class XComponentContext; }
33
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno ;
36 using namespace ::com::sun::star::lang ;
37
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 ;
44
45 namespace std
46 {
47 template <> struct default_delete<xmlSecKeysMngr>
48 {
operator ()std::default_delete49 void operator()(xmlSecKeysMngrPtr ptr) { SecurityEnvironment_NssImpl::destroyKeysManager(ptr); }
50 };
51 template <> struct default_delete<xmlSecDSigCtx>
52 {
operator ()std::default_delete53 void operator()(xmlSecDSigCtxPtr ptr) { xmlSecDSigCtxDestroy(ptr); }
54 };
55 }
56
57 class XMLSignature_NssImpl
58 : public ::cppu::WeakImplHelper<xml::crypto::XXMLSignature, lang::XServiceInfo>
59 {
60 public:
61 explicit XMLSignature_NssImpl();
62
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;
67
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;
71
72 //Methods from XServiceInfo
73 virtual OUString SAL_CALL getImplementationName() override;
74
75 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
76
77 virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
78 };
79
XMLSignature_NssImpl()80 XMLSignature_NssImpl::XMLSignature_NssImpl() {
81 }
82
83 /* XXMLSignature */
84 Reference< XXMLSignatureTemplate >
generate(const Reference<XXMLSignatureTemplate> & aTemplate,const Reference<XSecurityEnvironment> & aEnvironment)85 SAL_CALL XMLSignature_NssImpl::generate(
86 const Reference< XXMLSignatureTemplate >& aTemplate ,
87 const Reference< XSecurityEnvironment >& aEnvironment
88 )
89 {
90 xmlNodePtr pNode = nullptr ;
91
92 if( !aTemplate.is() )
93 throw RuntimeException() ;
94
95 if( !aEnvironment.is() )
96 throw RuntimeException() ;
97
98 //Get the xml node
99 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
100 if( !xElement.is() ) {
101 throw RuntimeException() ;
102 }
103
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() ;
111 }
112
113 pNode = pElement->getNativeElement() ;
114
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() ;
121 }
122
123 //Get Keys Manager
124 Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
125
126 // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext
127
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() ;
134
135 setErrorRecorder();
136
137 std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager());
138 if( !pMngr ) {
139 throw RuntimeException() ;
140 }
141
142 //Create Signature context
143 std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get()));
144 if( pDsigCtx == nullptr )
145 {
146 //throw XMLSignatureException() ;
147 clearErrorRecorder();
148 return aTemplate;
149 }
150
151 //Sign the template
152 if( xmlSecDSigCtxSign( pDsigCtx.get() , pNode ) == 0 )
153 {
154 if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
155 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
156 else
157 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
158 }
159 else
160 {
161 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
162 }
163
164 //Unregistered the stream/URI binding
165 if( xUriBinding.is() )
166 xmlUnregisterStreamInputCallbacks() ;
167
168 clearErrorRecorder();
169 return aTemplate ;
170 }
171
172 /* XXMLSignature */
173 Reference< XXMLSignatureTemplate >
validate(const Reference<XXMLSignatureTemplate> & aTemplate,const Reference<XXMLSecurityContext> & aSecurityCtx)174 SAL_CALL XMLSignature_NssImpl::validate(
175 const Reference< XXMLSignatureTemplate >& aTemplate ,
176 const Reference< XXMLSecurityContext >& aSecurityCtx
177 ) {
178 xmlNodePtr pNode = nullptr ;
179 //sal_Bool valid ;
180
181 if( !aTemplate.is() )
182 throw RuntimeException() ;
183
184 if( !aSecurityCtx.is() )
185 throw RuntimeException() ;
186
187 //Get the xml node
188 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
189 if( !xElement.is() )
190 throw RuntimeException() ;
191
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() ;
199
200 pNode = pElement->getNativeElement() ;
201
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() ;
208 }
209
210 setErrorRecorder();
211
212 sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber();
213 sal_Int32 i;
214
215 for (i=0; i<nSecurityEnvironment; ++i)
216 {
217 Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
218
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() ;
227
228 std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager());
229 if( !pMngr ) {
230 throw RuntimeException() ;
231 }
232
233 //Create Signature context
234 std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get()));
235 if( pDsigCtx == nullptr )
236 {
237 clearErrorRecorder();
238 return aTemplate;
239 }
240
241 // We do certificate verification ourselves.
242 pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
243
244 //Verify signature
245 int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode );
246
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)
252 {
253 xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
254 if (pReference)
255 {
256 if (pReference->status == xmlSecDSigStatusSucceeded)
257 ++nReferenceGood;
258 }
259 }
260
261 if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood)
262 {
263 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
264 break;
265 }
266 else
267 {
268 aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
269 }
270 }
271
272
273 //Unregistered the stream/URI binding
274 if( xUriBinding.is() )
275 xmlUnregisterStreamInputCallbacks() ;
276
277 //return valid ;
278 clearErrorRecorder();
279 return aTemplate;
280 }
281
282 /* XServiceInfo */
getImplementationName()283 OUString SAL_CALL XMLSignature_NssImpl::getImplementationName()
284 {
285 return "com.sun.star.xml.crypto.XMLSignature";
286 }
287
288 /* XServiceInfo */
supportsService(const OUString & rServiceName)289 sal_Bool SAL_CALL XMLSignature_NssImpl::supportsService(const OUString& rServiceName)
290 {
291 const css::uno::Sequence<OUString> aServiceNames = getSupportedServiceNames();
292 for (OUString const & rCurrentServiceName : aServiceNames)
293 {
294 if (rCurrentServiceName == rServiceName)
295 return true;
296 }
297 return false;
298 }
299
300 /* XServiceInfo */
getSupportedServiceNames()301 Sequence<OUString> SAL_CALL XMLSignature_NssImpl::getSupportedServiceNames()
302 {
303 Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" };
304 return seqServiceNames;
305 }
306
307 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext *,uno::Sequence<uno::Any> const &)308 com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/,
309 uno::Sequence<uno::Any> const& /*rSeq*/)
310 {
311 return cppu::acquire(new XMLSignature_NssImpl);
312 }
313
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
315