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