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 ) 78 { 79 xmlSecKeysMngrPtr pMngr = NULL ; 80 xmlSecDSigCtxPtr pDsigCtx = NULL ; 81 xmlNodePtr pNode = NULL ; 82 83 if( !aTemplate.is() ) 84 throw RuntimeException() ; 85 86 if( !aEnvironment.is() ) 87 throw RuntimeException() ; 88 89 //Get Keys Manager 90 Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY ) ; 91 if( !xSecTunnel.is() ) { 92 throw RuntimeException() ; 93 } 94 95 SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ; 96 if( pSecEnv == NULL ) 97 throw RuntimeException() ; 98 99 //Get the xml node 100 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; 101 if( !xElement.is() ) { 102 throw RuntimeException() ; 103 } 104 105 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ; 106 if( !xNodTunnel.is() ) { 107 throw RuntimeException() ; 108 } 109 110 XMLElementWrapper_XmlSecImpl* pElement = ( XMLElementWrapper_XmlSecImpl* )xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ; 111 if( pElement == NULL ) { 112 throw RuntimeException() ; 113 } 114 115 pNode = pElement->getNativeElement() ; 116 117 //Get the stream/URI binding 118 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; 119 if( xUriBinding.is() ) { 120 //Register the stream input callbacks into libxml2 121 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) 122 throw RuntimeException() ; 123 } 124 125 setErrorRecorder( ); 126 127 pMngr = pSecEnv->createKeysManager() ; //i39448 128 if( !pMngr ) { 129 throw RuntimeException() ; 130 } 131 132 //Create Signature context 133 pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; 134 if( pDsigCtx == NULL ) 135 { 136 //throw XMLSignatureException() ; 137 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 138 clearErrorRecorder(); 139 return aTemplate; 140 } 141 142 //Sign the template 143 if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 ) 144 { 145 if (pDsigCtx->status == xmlSecDSigStatusSucceeded) 146 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); 147 else 148 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 149 } 150 else 151 { 152 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 153 } 154 155 156 xmlSecDSigCtxDestroy( pDsigCtx ) ; 157 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 158 159 //Unregistered the stream/URI binding 160 if( xUriBinding.is() ) 161 xmlUnregisterStreamInputCallbacks() ; 162 163 clearErrorRecorder(); 164 return aTemplate ; 165 } 166 167 /* XXMLSignature */ 168 Reference< XXMLSignatureTemplate > 169 SAL_CALL XMLSignature_MSCryptImpl :: validate( 170 const Reference< XXMLSignatureTemplate >& aTemplate , 171 const Reference< XXMLSecurityContext >& aSecurityCtx 172 ) { 173 xmlSecKeysMngrPtr pMngr = NULL ; 174 xmlSecDSigCtxPtr pDsigCtx = NULL ; 175 xmlNodePtr pNode = NULL ; 176 //sal_Bool valid ; 177 178 if( !aTemplate.is() ) 179 throw RuntimeException() ; 180 181 if( !aSecurityCtx.is() ) 182 throw RuntimeException() ; 183 184 //Get Keys Manager 185 Reference< XSecurityEnvironment > xSecEnv 186 = aSecurityCtx->getSecurityEnvironmentByIndex( 187 aSecurityCtx->getDefaultSecurityEnvironmentIndex()); 188 Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY ) ; 189 if( !xSecTunnel.is() ) { 190 throw RuntimeException() ; 191 } 192 193 SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ; 194 if( pSecEnv == NULL ) 195 throw RuntimeException() ; 196 197 //Get the xml node 198 Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; 199 if( !xElement.is() ) 200 throw RuntimeException() ; 201 202 Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY ) ; 203 if( !xNodTunnel.is() ) { 204 throw RuntimeException() ; 205 } 206 207 XMLElementWrapper_XmlSecImpl* pElement = ( XMLElementWrapper_XmlSecImpl* )xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelImplementationId() ) ; 208 if( pElement == NULL ) 209 throw RuntimeException() ; 210 211 pNode = pElement->getNativeElement() ; 212 213 //Get the stream/URI binding 214 Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; 215 if( xUriBinding.is() ) { 216 //Register the stream input callbacks into libxml2 217 if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) 218 throw RuntimeException() ; 219 } 220 221 //added for test: save the result 222 /* 223 { 224 FILE *dstFile = fopen( "c:\\1.txt", "w" ) ; 225 xmlDocDump( dstFile, pNode->doc) ; 226 fclose( dstFile ) ; 227 } 228 */ 229 230 setErrorRecorder( ); 231 232 pMngr = pSecEnv->createKeysManager() ; //i39448 233 if( !pMngr ) { 234 throw RuntimeException() ; 235 } 236 237 //Create Signature context 238 pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; 239 if( pDsigCtx == NULL ) 240 { 241 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 242 //throw XMLSignatureException() ; 243 clearErrorRecorder(); 244 return aTemplate; 245 } 246 247 //Verify signature 248 //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0) 249 //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if 250 //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the 251 //error recorder feature to get the ONE error that made the verification fail, because there is no 252 //documentation/specification as to how to interpret the number of recorded errors and what is the initial 253 //error. 254 if( xmlSecDSigCtxVerify( pDsigCtx , pNode ) == 0 ) 255 { 256 if (pDsigCtx->status == xmlSecDSigStatusSucceeded) 257 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); 258 else 259 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 260 } 261 else 262 { 263 aTemplate->setStatus(com::sun::star::xml::crypto::SecurityOperationStatus_UNKNOWN); 264 } 265 266 xmlSecDSigCtxDestroy( pDsigCtx ) ; 267 pSecEnv->destroyKeysManager( pMngr ) ; //i39448 268 269 //Unregistered the stream/URI binding 270 if( xUriBinding.is() ) 271 xmlUnregisterStreamInputCallbacks() ; 272 273 274 clearErrorRecorder(); 275 return aTemplate; 276 } 277 278 /* XInitialization */ 279 void SAL_CALL XMLSignature_MSCryptImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) { 280 // TBD 281 } ; 282 283 /* XServiceInfo */ 284 OUString SAL_CALL XMLSignature_MSCryptImpl :: getImplementationName() { 285 return impl_getImplementationName() ; 286 } 287 288 /* XServiceInfo */ 289 sal_Bool SAL_CALL XMLSignature_MSCryptImpl :: supportsService( const OUString& serviceName) { 290 Sequence< OUString > seqServiceNames = getSupportedServiceNames() ; 291 const OUString* pArray = seqServiceNames.getConstArray() ; 292 for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) { 293 if( *( pArray + i ) == serviceName ) 294 return sal_True ; 295 } 296 return sal_False ; 297 } 298 299 /* XServiceInfo */ 300 Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl :: getSupportedServiceNames() { 301 return impl_getSupportedServiceNames() ; 302 } 303 304 //Helper for XServiceInfo 305 Sequence< OUString > XMLSignature_MSCryptImpl :: impl_getSupportedServiceNames() { 306 ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ; 307 Sequence< OUString > seqServiceNames( 1 ) ; 308 seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.XMLSignature" ) ; 309 return seqServiceNames ; 310 } 311 312 OUString XMLSignature_MSCryptImpl :: impl_getImplementationName() { 313 return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_MSCryptImpl" ) ; 314 } 315 316 //Helper for registry 317 Reference< XInterface > SAL_CALL XMLSignature_MSCryptImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) { 318 return Reference< XInterface >( *new XMLSignature_MSCryptImpl( aServiceManager ) ) ; 319 } 320 321 Reference< XSingleServiceFactory > XMLSignature_MSCryptImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) { 322 //Reference< XSingleServiceFactory > xFactory ; 323 //xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ; 324 //return xFactory ; 325 return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ; 326 } 327