1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
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
>
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() {
84 Reference
< XXMLSignatureTemplate
>
85 SAL_CALL
XMLSignature_NssImpl::generate(
86 const Reference
< XXMLSignatureTemplate
>& aTemplate
,
87 const Reference
< XSecurityEnvironment
>& aEnvironment
90 xmlNodePtr pNode
= nullptr ;
93 throw RuntimeException() ;
95 if( !aEnvironment
.is() )
96 throw RuntimeException() ;
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() ;
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() ;
137 std::unique_ptr
<xmlSecKeysMngr
> pMngr(pSecEnv
->createKeysManager());
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();
152 if( xmlSecDSigCtxSign( pDsigCtx
.get() , pNode
) == 0 )
154 if (pDsigCtx
->status
== xmlSecDSigStatusSucceeded
)
155 aTemplate
->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
);
157 aTemplate
->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN
);
161 aTemplate
->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN
);
164 //Unregistered the stream/URI binding
165 if( xUriBinding
.is() )
166 xmlUnregisterStreamInputCallbacks() ;
168 clearErrorRecorder();
173 Reference
< XXMLSignatureTemplate
>
174 SAL_CALL
XMLSignature_NssImpl::validate(
175 const Reference
< XXMLSignatureTemplate
>& aTemplate
,
176 const Reference
< XXMLSecurityContext
>& aSecurityCtx
178 xmlNodePtr pNode
= nullptr ;
181 if( !aTemplate
.is() )
182 throw RuntimeException() ;
184 if( !aSecurityCtx
.is() )
185 throw RuntimeException() ;
188 Reference
< XXMLElementWrapper
> xElement
= aTemplate
->getTemplate() ;
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() ;
212 sal_Int32 nSecurityEnvironment
= aSecurityCtx
->getSecurityEnvironmentNumber();
215 for (i
=0; i
<nSecurityEnvironment
; ++i
)
217 Reference
< XSecurityEnvironment
> aEnvironment
= aSecurityCtx
->getSecurityEnvironmentByIndex(i
);
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());
230 throw RuntimeException() ;
233 //Create Signature context
234 std::unique_ptr
<xmlSecDSigCtx
> pDsigCtx(xmlSecDSigCtxCreate(pMngr
.get()));
235 if( pDsigCtx
== nullptr )
237 clearErrorRecorder();
241 // We do certificate verification ourselves.
242 pDsigCtx
->keyInfoReadCtx
.flags
|= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS
;
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
));
256 if (pReference
->status
== xmlSecDSigStatusSucceeded
)
261 if (rs
== 0 && pDsigCtx
->status
== xmlSecDSigStatusSucceeded
&& nReferenceCount
== nReferenceGood
)
263 aTemplate
->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
);
268 aTemplate
->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN
);
273 //Unregistered the stream/URI binding
274 if( xUriBinding
.is() )
275 xmlUnregisterStreamInputCallbacks() ;
278 clearErrorRecorder();
283 OUString SAL_CALL
XMLSignature_NssImpl::getImplementationName()
285 return "com.sun.star.xml.crypto.XMLSignature";
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
)
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: */