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>
23 #include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
24 #include "xmlsignature_mscryptimpl.hxx"
25 #include "xmldocumentwrapper_xmlsecimpl.hxx"
26 #include "xmlelementwrapper_xmlsecimpl.hxx"
27 #include "securityenvironment_mscryptimpl.hxx"
28 #include "xmlstreamio.hxx"
29 #include "errorcallback.hxx"
30 #include "xmlsecurity/xmlsec-wrapper.h"
32 using namespace ::com::sun::star::uno
;
33 using namespace ::com::sun::star::lang
;
34 using ::com::sun::star::lang::XMultiServiceFactory
;
35 using ::com::sun::star::lang::XSingleServiceFactory
;
37 using ::com::sun::star::xml::wrapper::XXMLElementWrapper
;
38 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper
;
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 using ::com::sun::star::xml::crypto::XMLSignatureException
;
47 XMLSignature_MSCryptImpl :: XMLSignature_MSCryptImpl( const Reference
< XMultiServiceFactory
>& aFactory
) : m_xServiceManager( aFactory
) {
50 XMLSignature_MSCryptImpl :: ~XMLSignature_MSCryptImpl() {
54 Reference
< XXMLSignatureTemplate
>
55 SAL_CALL
XMLSignature_MSCryptImpl :: generate(
56 const Reference
< XXMLSignatureTemplate
>& aTemplate
,
57 const Reference
< XSecurityEnvironment
>& aEnvironment
58 ) throw( com::sun::star::xml::crypto::XMLSignatureException
,
59 com::sun::star::uno::SecurityException
)
61 xmlSecKeysMngrPtr pMngr
= NULL
;
62 xmlSecDSigCtxPtr pDsigCtx
= NULL
;
63 xmlNodePtr pNode
= NULL
;
66 throw RuntimeException() ;
68 if( !aEnvironment
.is() )
69 throw RuntimeException() ;
72 Reference
< XUnoTunnel
> xSecTunnel( aEnvironment
, UNO_QUERY
) ;
73 if( !xSecTunnel
.is() ) {
74 throw RuntimeException() ;
77 SecurityEnvironment_MSCryptImpl
* pSecEnv
= ( SecurityEnvironment_MSCryptImpl
* )xSecTunnel
->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ;
79 throw RuntimeException() ;
82 Reference
< XXMLElementWrapper
> xElement
= aTemplate
->getTemplate() ;
83 if( !xElement
.is() ) {
84 throw RuntimeException() ;
87 Reference
< XUnoTunnel
> xNodTunnel( xElement
, UNO_QUERY
) ;
88 if( !xNodTunnel
.is() ) {
89 throw RuntimeException() ;
92 XMLElementWrapper_XmlSecImpl
* pElement
= ( XMLElementWrapper_XmlSecImpl
* )xNodTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ;
93 if( pElement
== NULL
) {
94 throw RuntimeException() ;
97 pNode
= pElement
->getNativeElement() ;
99 //Get the stream/URI binding
100 Reference
< XUriBinding
> xUriBinding
= aTemplate
->getBinding() ;
101 if( xUriBinding
.is() ) {
102 //Register the stream input callbacks into libxml2
103 if( xmlRegisterStreamInputCallbacks( xUriBinding
) < 0 )
104 throw RuntimeException() ;
109 pMngr
= pSecEnv
->createKeysManager();
111 throw RuntimeException() ;
114 //Create Signature context
115 pDsigCtx
= xmlSecDSigCtxCreate( pMngr
) ;
116 if( pDsigCtx
== NULL
)
118 //throw XMLSignatureException() ;
119 pSecEnv
->destroyKeysManager( pMngr
);
120 clearErrorRecorder();
125 if( xmlSecDSigCtxSign( pDsigCtx
, pNode
) == 0 )
127 if (pDsigCtx
->status
== xmlSecDSigStatusSucceeded
)
128 aTemplate
->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
);
130 aTemplate
->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN
);
134 aTemplate
->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN
);
138 xmlSecDSigCtxDestroy( pDsigCtx
) ;
139 pSecEnv
->destroyKeysManager( pMngr
);
141 //Unregistered the stream/URI binding
142 if( xUriBinding
.is() )
143 xmlUnregisterStreamInputCallbacks() ;
145 clearErrorRecorder();
150 Reference
< XXMLSignatureTemplate
>
151 SAL_CALL
XMLSignature_MSCryptImpl :: validate(
152 const Reference
< XXMLSignatureTemplate
>& aTemplate
,
153 const Reference
< XXMLSecurityContext
>& aSecurityCtx
154 ) throw( com::sun::star::uno::RuntimeException
,
155 com::sun::star::uno::SecurityException
,
156 com::sun::star::xml::crypto::XMLSignatureException
) {
157 xmlSecKeysMngrPtr pMngr
= NULL
;
158 xmlSecDSigCtxPtr pDsigCtx
= NULL
;
159 xmlNodePtr pNode
= NULL
;
161 if( !aTemplate
.is() )
162 throw RuntimeException() ;
164 if( !aSecurityCtx
.is() )
165 throw RuntimeException() ;
168 Reference
< XSecurityEnvironment
> xSecEnv
169 = aSecurityCtx
->getSecurityEnvironmentByIndex(
170 aSecurityCtx
->getDefaultSecurityEnvironmentIndex());
171 Reference
< XUnoTunnel
> xSecTunnel( xSecEnv
, UNO_QUERY
) ;
172 if( !xSecTunnel
.is() ) {
173 throw RuntimeException() ;
176 SecurityEnvironment_MSCryptImpl
* pSecEnv
= ( SecurityEnvironment_MSCryptImpl
* )xSecTunnel
->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ;
177 if( pSecEnv
== NULL
)
178 throw RuntimeException() ;
181 Reference
< XXMLElementWrapper
> xElement
= aTemplate
->getTemplate() ;
183 throw RuntimeException() ;
185 Reference
< XUnoTunnel
> xNodTunnel( xElement
, UNO_QUERY
) ;
186 if( !xNodTunnel
.is() ) {
187 throw RuntimeException() ;
190 XMLElementWrapper_XmlSecImpl
* pElement
= ( XMLElementWrapper_XmlSecImpl
* )xNodTunnel
->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ;
191 if( pElement
== NULL
)
192 throw RuntimeException() ;
194 pNode
= pElement
->getNativeElement() ;
196 //Get the stream/URI binding
197 Reference
< XUriBinding
> xUriBinding
= aTemplate
->getBinding() ;
198 if( xUriBinding
.is() ) {
199 //Register the stream input callbacks into libxml2
200 if( xmlRegisterStreamInputCallbacks( xUriBinding
) < 0 )
201 throw RuntimeException() ;
206 pMngr
= pSecEnv
->createKeysManager();
208 throw RuntimeException() ;
211 //Create Signature context
212 pDsigCtx
= xmlSecDSigCtxCreate( pMngr
) ;
213 if( pDsigCtx
== NULL
)
215 pSecEnv
->destroyKeysManager( pMngr
);
216 clearErrorRecorder();
221 //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0)
222 //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if
223 //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the
224 //error recorder feature to get the ONE error that made the verification fail, because there is no
225 //documentation/specification as to how to interpret the number of recorded errors and what is the initial
227 if( xmlSecDSigCtxVerify( pDsigCtx
, pNode
) == 0 )
229 if (pDsigCtx
->status
== xmlSecDSigStatusSucceeded
)
230 aTemplate
->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
);
232 aTemplate
->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN
);
236 aTemplate
->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN
);
239 xmlSecDSigCtxDestroy( pDsigCtx
) ;
240 pSecEnv
->destroyKeysManager( pMngr
);
242 //Unregistered the stream/URI binding
243 if( xUriBinding
.is() )
244 xmlUnregisterStreamInputCallbacks() ;
247 clearErrorRecorder();
252 OUString SAL_CALL
XMLSignature_MSCryptImpl :: getImplementationName() throw( RuntimeException
) {
253 return impl_getImplementationName() ;
257 sal_Bool SAL_CALL
XMLSignature_MSCryptImpl :: supportsService( const OUString
& serviceName
) throw( RuntimeException
) {
258 Sequence
< OUString
> seqServiceNames
= getSupportedServiceNames() ;
259 const OUString
* pArray
= seqServiceNames
.getConstArray() ;
260 for( sal_Int32 i
= 0 ; i
< seqServiceNames
.getLength() ; i
++ ) {
261 if( *( pArray
+ i
) == serviceName
)
268 Sequence
< OUString
> SAL_CALL
XMLSignature_MSCryptImpl :: getSupportedServiceNames() throw( RuntimeException
) {
269 return impl_getSupportedServiceNames() ;
272 //Helper for XServiceInfo
273 Sequence
< OUString
> XMLSignature_MSCryptImpl :: impl_getSupportedServiceNames() {
274 ::osl::Guard
< ::osl::Mutex
> aGuard( ::osl::Mutex::getGlobalMutex() ) ;
275 Sequence
< OUString
> seqServiceNames( 1 ) ;
276 seqServiceNames
[0] = "com.sun.star.xml.crypto.XMLSignature";
277 return seqServiceNames
;
280 OUString
XMLSignature_MSCryptImpl :: impl_getImplementationName() throw( RuntimeException
) {
281 return OUString("com.sun.star.xml.security.bridge.xmlsec.XMLSignature_MSCryptImpl") ;
284 //Helper for registry
285 Reference
< XInterface
> SAL_CALL
XMLSignature_MSCryptImpl :: impl_createInstance( const Reference
< XMultiServiceFactory
>& aServiceManager
) throw( RuntimeException
) {
286 return Reference
< XInterface
>( *new XMLSignature_MSCryptImpl( aServiceManager
) ) ;
289 Reference
< XSingleServiceFactory
> XMLSignature_MSCryptImpl :: impl_createFactory( const Reference
< XMultiServiceFactory
>& aServiceManager
) {
290 return ::cppu::createSingleFactory( aServiceManager
, impl_getImplementationName() , impl_createInstance
, impl_getSupportedServiceNames() ) ;
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */