1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmlsecurity.hxx" 30 #include <sal/config.h> 31 #include <rtl/uuid.h> 32 33 #include "com/sun/star/xml/crypto/SecurityOperationStatus.hdl" 34 #include "xmlsignature_mscryptimpl.hxx" 35 36 #ifndef _XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX_ 37 #include "xmldocumentwrapper_xmlsecimpl.hxx" 38 #endif 39 40 #ifndef _XMLELEMENTWRAPPER_XMLSECIMPL_HXX_ 41 #include "xmlelementwrapper_xmlsecimpl.hxx" 42 #endif 43 44 #ifndef _SECURITYENVIRONMENT_MSCRYPTIMPL_HXX_ 45 #include "securityenvironment_mscryptimpl.hxx" 46 #endif 47 #include "xmlstreamio.hxx" 48 #include "errorcallback.hxx" 49 50 #include "xmlsec/xmlsec.h" 51 #include "xmlsec/xmldsig.h" 52 #include "xmlsec/crypto.h" 53 54 using namespace ::com::sun::star::uno ; 55 using namespace ::com::sun::star::lang ; 56 using ::com::sun::star::lang::XMultiServiceFactory ; 57 using ::com::sun::star::lang::XSingleServiceFactory ; 58 using ::rtl::OUString ; 59 60 using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; 61 using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ; 62 using ::com::sun::star::xml::crypto::XSecurityEnvironment ; 63 using ::com::sun::star::xml::crypto::XXMLSignature ; 64 using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ; 65 using ::com::sun::star::xml::crypto::XXMLSecurityContext ; 66 using ::com::sun::star::xml::crypto::XUriBinding ; 67 using ::com::sun::star::xml::crypto::XMLSignatureException ; 68 69 70 XMLSignature_MSCryptImpl :: XMLSignature_MSCryptImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_xServiceManager( aFactory ) { 71 } 72 73 XMLSignature_MSCryptImpl :: ~XMLSignature_MSCryptImpl() { 74 } 75 76 /* XXMLSignature */ 77 Reference< XXMLSignatureTemplate > 78 SAL_CALL XMLSignature_MSCryptImpl :: generate( 79 const Reference< XXMLSignatureTemplate >& aTemplate , 80 const Reference< XSecurityEnvironment >& aEnvironment 81 ) throw( com::sun::star::xml::crypto::XMLSignatureException, 82 com::sun::star::uno::SecurityException ) 83 { 84 xmlSecKeysMngrPtr pMngr = NULL ; 85 xmlSecDSigCtxPtr pDsigCtx = NULL ; 86 xmlNodePtr pNode = NULL ; 87 88 if( !aTemplate.is() ) 89 throw RuntimeException() ; 90 91 if( !aEnvironment.is() ) 92 throw RuntimeException() ; 93 94 //Get Keys Manager 95 Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ; 96 if( !xSecTunnel.is() ) { 97 throw RuntimeException() ; 98 } 99 100 SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ; 101 if( pSecEnv == NULL ) 102 throw RuntimeException() ; 103 104 //Get the xml node 105 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; 106 if( !xElement.is() ) { 107 throw RuntimeException() ; 108 } 109 110 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ; 111 if( !xNodTunnel.is() ) { 112 throw RuntimeException() ; 113 } 114 115 XMLElementWrapper_XmlSecImpl* pElement = ( XMLElementWrapper_XmlSecImpl* )xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ; 116 if( pElement == NULL ) { 117 throw RuntimeException() ; 118 } 119 120 pNode = pElement->getNativeElement() ; 121 122 //Get the stream/URI binding 123 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; 124 if( xUriBinding.is() ) { 125 //Register the stream input callbacks into libxml2 126 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) 127 throw RuntimeException() ; 128 } 129 130 setErrorRecorder( ); 131 132 pMngr = pSecEnv->createKeysManager() ; //i39448 133 if( !pMngr ) { 134 throw RuntimeException() ; 135 } 136 137 //Create Signature context 138 pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; 139 if( pDsigCtx == NULL ) 140 { 141 //throw XMLSignatureException() ; 142 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 143 clearErrorRecorder(); 144 return aTemplate; 145 } 146 147 //Sign the template 148 if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 ) 149 { 150 if (pDsigCtx->status == xmlSecDSigStatusSucceeded) 151 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); 152 else 153 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 154 } 155 else 156 { 157 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 158 } 159 160 161 xmlSecDSigCtxDestroy( pDsigCtx ) ; 162 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 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 > 174 SAL_CALL XMLSignature_MSCryptImpl :: validate( 175 const Reference< XXMLSignatureTemplate >& aTemplate , 176 const Reference< XXMLSecurityContext >& aSecurityCtx 177 ) throw( com::sun::star::uno::RuntimeException, 178 com::sun::star::uno::SecurityException, 179 com::sun::star::xml::crypto::XMLSignatureException ) { 180 xmlSecKeysMngrPtr pMngr = NULL ; 181 xmlSecDSigCtxPtr pDsigCtx = NULL ; 182 xmlNodePtr pNode = NULL ; 183 //sal_Bool valid ; 184 185 if( !aTemplate.is() ) 186 throw RuntimeException() ; 187 188 if( !aSecurityCtx.is() ) 189 throw RuntimeException() ; 190 191 //Get Keys Manager 192 Reference< XSecurityEnvironment > xSecEnv 193 = aSecurityCtx->getSecurityEnvironmentByIndex( 194 aSecurityCtx->getDefaultSecurityEnvironmentIndex()); 195 Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY ) ; 196 if( !xSecTunnel.is() ) { 197 throw RuntimeException() ; 198 } 199 200 SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ; 201 if( pSecEnv == NULL ) 202 throw RuntimeException() ; 203 204 //Get the xml node 205 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; 206 if( !xElement.is() ) 207 throw RuntimeException() ; 208 209 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ; 210 if( !xNodTunnel.is() ) { 211 throw RuntimeException() ; 212 } 213 214 XMLElementWrapper_XmlSecImpl* pElement = ( XMLElementWrapper_XmlSecImpl* )xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ; 215 if( pElement == NULL ) 216 throw RuntimeException() ; 217 218 pNode = pElement->getNativeElement() ; 219 220 //Get the stream/URI binding 221 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; 222 if( xUriBinding.is() ) { 223 //Register the stream input callbacks into libxml2 224 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) 225 throw RuntimeException() ; 226 } 227 228 //added for test: save the result 229 /* 230 { 231 FILE *dstFile = fopen( "c:\\1.txt", "w" ) ; 232 xmlDocDump( dstFile, pNode->doc) ; 233 fclose( dstFile ) ; 234 } 235 */ 236 237 setErrorRecorder( ); 238 239 pMngr = pSecEnv->createKeysManager() ; //i39448 240 if( !pMngr ) { 241 throw RuntimeException() ; 242 } 243 244 //Create Signature context 245 pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; 246 if( pDsigCtx == NULL ) 247 { 248 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 249 //throw XMLSignatureException() ; 250 clearErrorRecorder(); 251 return aTemplate; 252 } 253 254 //Verify signature 255 //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0) 256 //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if 257 //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the 258 //error recorder feature to get the ONE error that made the verification fail, because there is no 259 //documentation/specification as to how to interpret the number of recorded errors and what is the initial 260 //error. 261 if( xmlSecDSigCtxVerify( pDsigCtx , pNode ) == 0 ) 262 { 263 if (pDsigCtx->status == xmlSecDSigStatusSucceeded) 264 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); 265 else 266 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 267 } 268 else 269 { 270 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 271 } 272 273 xmlSecDSigCtxDestroy( pDsigCtx ) ; 274 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 275 276 //Unregistered the stream/URI binding 277 if( xUriBinding.is() ) 278 xmlUnregisterStreamInputCallbacks() ; 279 280 281 clearErrorRecorder(); 282 return aTemplate; 283 } 284 285 /* XInitialization */ 286 void SAL_CALL XMLSignature_MSCryptImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) throw( Exception, RuntimeException ) { 287 // TBD 288 } ; 289 290 /* XServiceInfo */ 291 OUString SAL_CALL XMLSignature_MSCryptImpl :: getImplementationName() throw( RuntimeException ) { 292 return impl_getImplementationName() ; 293 } 294 295 /* XServiceInfo */ 296 sal_Bool SAL_CALL XMLSignature_MSCryptImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) { 297 Sequence< OUString > seqServiceNames = getSupportedServiceNames() ; 298 const OUString* pArray = seqServiceNames.getConstArray() ; 299 for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) { 300 if( *( pArray + i ) == serviceName ) 301 return sal_True ; 302 } 303 return sal_False ; 304 } 305 306 /* XServiceInfo */ 307 Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl :: getSupportedServiceNames() throw( RuntimeException ) { 308 return impl_getSupportedServiceNames() ; 309 } 310 311 //Helper for XServiceInfo 312 Sequence< OUString > XMLSignature_MSCryptImpl :: impl_getSupportedServiceNames() { 313 ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ; 314 Sequence< OUString > seqServiceNames( 1 ) ; 315 seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.XMLSignature" ) ; 316 return seqServiceNames ; 317 } 318 319 OUString XMLSignature_MSCryptImpl :: impl_getImplementationName() throw( RuntimeException ) { 320 return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_MSCryptImpl" ) ; 321 } 322 323 //Helper for registry 324 Reference< XInterface > SAL_CALL XMLSignature_MSCryptImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) { 325 return Reference< XInterface >( *new XMLSignature_MSCryptImpl( aServiceManager ) ) ; 326 } 327 328 Reference< XSingleServiceFactory > XMLSignature_MSCryptImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) { 329 //Reference< XSingleServiceFactory > xFactory ; 330 //xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ; 331 //return xFactory ; 332 return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ; 333 } 334 335