| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmlsecurity.hxx" |
| |
| #ifdef _MSC_VER |
| #pragma warning(push,1) |
| #endif |
| #include "Windows.h" |
| #include "WinCrypt.h" |
| #ifdef _MSC_VER |
| #pragma warning(pop) |
| #endif |
| #include <sal/config.h> |
| #include <osl/thread.h> |
| #include "securityenvironment_mscryptimpl.hxx" |
| |
| #ifndef _X509CERTIFICATE_NSSIMPL_HXX_ |
| #include "x509certificate_mscryptimpl.hxx" |
| #endif |
| #include <rtl/uuid.h> |
| |
| #include <xmlsec/xmlsec.h> |
| #include <xmlsec/keysmngr.h> |
| #include <xmlsec/crypto.h> |
| #include <xmlsec/base64.h> |
| |
| #include <xmlsecurity/biginteger.hxx> |
| |
| #include "xmlsec/keysmngr.h" |
| #include "xmlsec/mscrypto/akmngr.h" |
| |
| //CP : added by CP |
| #include <rtl/locale.h> |
| #include <osl/nlsupport.h> |
| #include <osl/process.h> |
| |
| //CP : end |
| #include <rtl/memory.h> |
| |
| #include "../diagnose.hxx" |
| |
| using namespace xmlsecurity; |
| using namespace ::com::sun::star::uno ; |
| using namespace ::com::sun::star::lang ; |
| using ::com::sun::star::lang::XMultiServiceFactory ; |
| using ::com::sun::star::lang::XSingleServiceFactory ; |
| using ::rtl::OUString ; |
| |
| using ::com::sun::star::xml::crypto::XSecurityEnvironment ; |
| using ::com::sun::star::security::XCertificate ; |
| namespace css = ::com::sun::star; |
| |
| extern X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ; |
| |
| struct CertErrorToString{ |
| DWORD error; |
| char * name; |
| }; |
| |
| CertErrorToString arErrStrings[] = |
| { |
| { 0x00000000, "CERT_TRUST_NO_ERROR"}, |
| { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"}, |
| { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"}, |
| { 0x00000004, "CERT_TRUST_IS_REVOKED" }, |
| { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" }, |
| { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"}, |
| { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"}, |
| { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"}, |
| { 0x00000080, "CERT_TRUST_IS_CYCLIC"}, |
| { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"}, |
| { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"}, |
| { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"}, |
| { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"}, |
| { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"}, |
| { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"}, |
| { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"}, |
| { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"}, |
| { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"}, |
| { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"}, |
| { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"}, |
| { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"}, |
| //Chain errors |
| { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"}, |
| { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"}, |
| { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"}, |
| { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"} |
| }; |
| |
| void traceTrustStatus(DWORD err) |
| { |
| int numErrors = sizeof(arErrStrings) / sizeof(CertErrorToString); |
| xmlsec_trace("The certificate error status is: "); |
| if (err == 0) |
| xmlsec_trace("%s", arErrStrings[0].name); |
| for (int i = 1; i < numErrors; i++) |
| { |
| if (arErrStrings[i].error & err) |
| xmlsec_trace("%s", arErrStrings[i].name); |
| } |
| } |
| |
| SecurityEnvironment_MSCryptImpl :: SecurityEnvironment_MSCryptImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_hProv( NULL ) , m_pszContainer( NULL ) , m_hKeyStore( NULL ), m_hCertStore( NULL ), m_tSymKeyList() , m_tPubKeyList() , m_tPriKeyList(), m_xServiceManager( aFactory ), m_bEnableDefault( sal_False ), m_hMySystemStore(NULL), m_hRootSystemStore(NULL), m_hTrustSystemStore(NULL), m_hCaSystemStore(NULL){ |
| |
| } |
| |
| SecurityEnvironment_MSCryptImpl :: ~SecurityEnvironment_MSCryptImpl() { |
| |
| if( m_hProv != NULL ) { |
| CryptReleaseContext( m_hProv, 0 ) ; |
| m_hProv = NULL ; |
| } |
| |
| if( m_pszContainer != NULL ) { |
| //TODO: Don't know whether or not it should be released now. |
| m_pszContainer = NULL ; |
| } |
| |
| if( m_hCertStore != NULL ) { |
| CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; |
| m_hCertStore = NULL ; |
| } |
| |
| if( m_hKeyStore != NULL ) { |
| CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; |
| m_hKeyStore = NULL ; |
| } |
| |
| //i120675, close the store handles |
| if( m_hMySystemStore != NULL ) { |
| CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hMySystemStore = NULL ; |
| } |
| |
| if( m_hRootSystemStore != NULL ) { |
| CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hRootSystemStore = NULL ; |
| } |
| |
| if( m_hTrustSystemStore != NULL ) { |
| CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hTrustSystemStore = NULL ; |
| } |
| |
| if( m_hCaSystemStore != NULL ) { |
| CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hCaSystemStore = NULL ; |
| } |
| |
| if( !m_tSymKeyList.empty() ) { |
| std::list< HCRYPTKEY >::iterator symKeyIt ; |
| |
| for( symKeyIt = m_tSymKeyList.begin() ; symKeyIt != m_tSymKeyList.end() ; symKeyIt ++ ) |
| CryptDestroyKey( *symKeyIt ) ; |
| } |
| |
| if( !m_tPubKeyList.empty() ) { |
| std::list< HCRYPTKEY >::iterator pubKeyIt ; |
| |
| for( pubKeyIt = m_tPubKeyList.begin() ; pubKeyIt != m_tPubKeyList.end() ; pubKeyIt ++ ) |
| CryptDestroyKey( *pubKeyIt ) ; |
| } |
| |
| if( !m_tPriKeyList.empty() ) { |
| std::list< HCRYPTKEY >::iterator priKeyIt ; |
| |
| for( priKeyIt = m_tPriKeyList.begin() ; priKeyIt != m_tPriKeyList.end() ; priKeyIt ++ ) |
| CryptDestroyKey( *priKeyIt ) ; |
| } |
| |
| } |
| |
| /* XInitialization */ |
| void SAL_CALL SecurityEnvironment_MSCryptImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) throw( Exception, RuntimeException ) { |
| //TODO |
| } ; |
| |
| /* XServiceInfo */ |
| OUString SAL_CALL SecurityEnvironment_MSCryptImpl :: getImplementationName() throw( RuntimeException ) { |
| return impl_getImplementationName() ; |
| } |
| |
| /* XServiceInfo */ |
| sal_Bool SAL_CALL SecurityEnvironment_MSCryptImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) { |
| Sequence< OUString > seqServiceNames = getSupportedServiceNames() ; |
| const OUString* pArray = seqServiceNames.getConstArray() ; |
| for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) { |
| if( *( pArray + i ) == serviceName ) |
| return sal_True ; |
| } |
| return sal_False ; |
| } |
| |
| /* XServiceInfo */ |
| Sequence< OUString > SAL_CALL SecurityEnvironment_MSCryptImpl :: getSupportedServiceNames() throw( RuntimeException ) { |
| return impl_getSupportedServiceNames() ; |
| } |
| |
| //Helper for XServiceInfo |
| Sequence< OUString > SecurityEnvironment_MSCryptImpl :: impl_getSupportedServiceNames() { |
| ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ; |
| Sequence< OUString > seqServiceNames( 1 ) ; |
| seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.SecurityEnvironment" ) ; |
| return seqServiceNames ; |
| } |
| |
| OUString SecurityEnvironment_MSCryptImpl :: impl_getImplementationName() throw( RuntimeException ) { |
| return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.SecurityEnvironment_MSCryptImpl" ) ; |
| } |
| |
| //Helper for registry |
| Reference< XInterface > SAL_CALL SecurityEnvironment_MSCryptImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) { |
| return Reference< XInterface >( *new SecurityEnvironment_MSCryptImpl( aServiceManager ) ) ; |
| } |
| |
| Reference< XSingleServiceFactory > SecurityEnvironment_MSCryptImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) { |
| return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ; |
| } |
| |
| /* XUnoTunnel */ |
| sal_Int64 SAL_CALL SecurityEnvironment_MSCryptImpl :: getSomething( const Sequence< sal_Int8 >& aIdentifier ) |
| throw( RuntimeException ) |
| { |
| if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) { |
| return ( sal_Int64 )this ; |
| } |
| return 0 ; |
| } |
| |
| /* XUnoTunnel extension */ |
| const Sequence< sal_Int8>& SecurityEnvironment_MSCryptImpl :: getUnoTunnelId() { |
| static Sequence< sal_Int8 >* pSeq = 0 ; |
| if( !pSeq ) { |
| ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ; |
| if( !pSeq ) { |
| static Sequence< sal_Int8> aSeq( 16 ) ; |
| rtl_createUuid( ( sal_uInt8* )aSeq.getArray() , 0 , sal_True ) ; |
| pSeq = &aSeq ; |
| } |
| } |
| return *pSeq ; |
| } |
| |
| /* XUnoTunnel extension */ |
| SecurityEnvironment_MSCryptImpl* SecurityEnvironment_MSCryptImpl :: getImplementation( const Reference< XInterface > xObj ) { |
| Reference< XUnoTunnel > xUT( xObj , UNO_QUERY ) ; |
| if( xUT.is() ) { |
| return ( SecurityEnvironment_MSCryptImpl* )xUT->getSomething( getUnoTunnelId() ) ; |
| } else |
| return NULL ; |
| } |
| |
| /* Native methods */ |
| HCRYPTPROV SecurityEnvironment_MSCryptImpl :: getCryptoProvider() throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) { |
| return m_hProv ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: setCryptoProvider( HCRYPTPROV aProv ) throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) { |
| if( m_hProv != NULL ) { |
| CryptReleaseContext( m_hProv, 0 ) ; |
| m_hProv = NULL ; |
| } |
| |
| if( aProv != NULL ) { |
| /*- Replaced by direct adopt for WINNT support ---- |
| if( !CryptContextAddRef( aProv, NULL, NULL ) ) |
| throw Exception() ; |
| else |
| m_hProv = aProv ; |
| ----*/ |
| m_hProv = aProv ; |
| } |
| } |
| |
| LPCTSTR SecurityEnvironment_MSCryptImpl :: getKeyContainer() throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) { |
| return m_pszContainer ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: setKeyContainer( LPCTSTR aKeyContainer ) throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) { |
| //TODO: Don't know whether or not it should be copied. |
| m_pszContainer = aKeyContainer ; |
| } |
| |
| |
| HCERTSTORE SecurityEnvironment_MSCryptImpl :: getCryptoSlot() throw( Exception , RuntimeException ) { |
| return m_hKeyStore ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: setCryptoSlot( HCERTSTORE aSlot) throw( Exception , RuntimeException ) { |
| if( m_hKeyStore != NULL ) { |
| CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; |
| m_hKeyStore = NULL ; |
| } |
| |
| if( aSlot != NULL ) { |
| m_hKeyStore = CertDuplicateStore( aSlot ) ; |
| } |
| } |
| |
| HCERTSTORE SecurityEnvironment_MSCryptImpl :: getCertDb() throw( Exception , RuntimeException ) { |
| return m_hCertStore ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: setCertDb( HCERTSTORE aCertDb ) throw( Exception , RuntimeException ) { |
| if( m_hCertStore != NULL ) { |
| CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; |
| m_hCertStore = NULL ; |
| } |
| |
| if( aCertDb != NULL ) { |
| m_hCertStore = CertDuplicateStore( aCertDb ) ; |
| } |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: adoptSymKey( HCRYPTKEY aSymKey ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY symkey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| |
| if( aSymKey != NULL ) { |
| //First try to find the key in the list |
| for( keyIt = m_tSymKeyList.begin() ; keyIt != m_tSymKeyList.end() ; keyIt ++ ) { |
| if( *keyIt == aSymKey ) |
| return ; |
| } |
| |
| //If we do not find the key in the list, add a new node |
| /*- Replaced with directly adopt for WINNT 4.0 support ---- |
| if( !CryptDuplicateKey( aSymKey, NULL, 0, &symkey ) ) |
| throw RuntimeException() ; |
| ----*/ |
| symkey = aSymKey ; |
| |
| try { |
| m_tSymKeyList.push_back( symkey ) ; |
| } catch ( Exception& ) { |
| CryptDestroyKey( symkey ) ; |
| } |
| } |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: rejectSymKey( HCRYPTKEY aSymKey ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY symkey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| |
| if( aSymKey != NULL ) { |
| for( keyIt = m_tSymKeyList.begin() ; keyIt != m_tSymKeyList.end() ; keyIt ++ ) { |
| if( *keyIt == aSymKey ) { |
| symkey = *keyIt ; |
| CryptDestroyKey( symkey ) ; |
| m_tSymKeyList.erase( keyIt ) ; |
| break ; |
| } |
| } |
| } |
| } |
| |
| HCRYPTKEY SecurityEnvironment_MSCryptImpl :: getSymKey( unsigned int position ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY symkey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| unsigned int pos ; |
| |
| symkey = NULL ; |
| for( pos = 0, keyIt = m_tSymKeyList.begin() ; pos < position && keyIt != m_tSymKeyList.end() ; pos ++ , keyIt ++ ) ; |
| |
| if( pos == position && keyIt != m_tSymKeyList.end() ) |
| symkey = *keyIt ; |
| |
| return symkey ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: adoptPubKey( HCRYPTKEY aPubKey ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY pubkey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| |
| if( aPubKey != NULL ) { |
| //First try to find the key in the list |
| for( keyIt = m_tPubKeyList.begin() ; keyIt != m_tPubKeyList.end() ; keyIt ++ ) { |
| if( *keyIt == aPubKey ) |
| return ; |
| } |
| |
| //If we do not find the key in the list, add a new node |
| /*- Replaced with directly adopt for WINNT 4.0 support ---- |
| if( !CryptDuplicateKey( aPubKey, NULL, 0, &pubkey ) ) |
| throw RuntimeException() ; |
| ----*/ |
| pubkey = aPubKey ; |
| |
| try { |
| m_tPubKeyList.push_back( pubkey ) ; |
| } catch ( Exception& ) { |
| CryptDestroyKey( pubkey ) ; |
| } |
| } |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: rejectPubKey( HCRYPTKEY aPubKey ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY pubkey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| |
| if( aPubKey != NULL ) { |
| for( keyIt = m_tPubKeyList.begin() ; keyIt != m_tPubKeyList.end() ; keyIt ++ ) { |
| if( *keyIt == aPubKey ) { |
| pubkey = *keyIt ; |
| CryptDestroyKey( pubkey ) ; |
| m_tPubKeyList.erase( keyIt ) ; |
| break ; |
| } |
| } |
| } |
| } |
| |
| HCRYPTKEY SecurityEnvironment_MSCryptImpl :: getPubKey( unsigned int position ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY pubkey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| unsigned int pos ; |
| |
| pubkey = NULL ; |
| for( pos = 0, keyIt = m_tPubKeyList.begin() ; pos < position && keyIt != m_tPubKeyList.end() ; pos ++ , keyIt ++ ) ; |
| |
| if( pos == position && keyIt != m_tPubKeyList.end() ) |
| pubkey = *keyIt ; |
| |
| return pubkey ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: adoptPriKey( HCRYPTKEY aPriKey ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY prikey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| |
| if( aPriKey != NULL ) { |
| //First try to find the key in the list |
| for( keyIt = m_tPriKeyList.begin() ; keyIt != m_tPriKeyList.end() ; keyIt ++ ) { |
| if( *keyIt == aPriKey ) |
| return ; |
| } |
| |
| //If we do not find the key in the list, add a new node |
| /*- Replaced with directly adopt for WINNT 4.0 support ---- |
| if( !CryptDuplicateKey( aPriKey, NULL, 0, &prikey ) ) |
| throw RuntimeException() ; |
| ----*/ |
| prikey = aPriKey ; |
| |
| try { |
| m_tPriKeyList.push_back( prikey ) ; |
| } catch ( Exception& ) { |
| CryptDestroyKey( prikey ) ; |
| } |
| } |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: rejectPriKey( HCRYPTKEY aPriKey ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY prikey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| |
| if( aPriKey != NULL ) { |
| for( keyIt = m_tPriKeyList.begin() ; keyIt != m_tPriKeyList.end() ; keyIt ++ ) { |
| if( *keyIt == aPriKey ) { |
| prikey = *keyIt ; |
| CryptDestroyKey( prikey ) ; |
| m_tPriKeyList.erase( keyIt ) ; |
| break ; |
| } |
| } |
| } |
| } |
| |
| HCRYPTKEY SecurityEnvironment_MSCryptImpl :: getPriKey( unsigned int position ) throw( Exception , RuntimeException ) { |
| HCRYPTKEY prikey ; |
| std::list< HCRYPTKEY >::iterator keyIt ; |
| unsigned int pos ; |
| |
| prikey = NULL ; |
| for( pos = 0, keyIt = m_tPriKeyList.begin() ; pos < position && keyIt != m_tPriKeyList.end() ; pos ++ , keyIt ++ ) ; |
| |
| if( pos == position && keyIt != m_tPriKeyList.end() ) |
| prikey = *keyIt ; |
| |
| return prikey ; |
| } |
| |
| //Methods from XSecurityEnvironment |
| Sequence< Reference < XCertificate > > SecurityEnvironment_MSCryptImpl :: getPersonalCertificates() throw( SecurityException , RuntimeException ) |
| { |
| sal_Int32 length ; |
| X509Certificate_MSCryptImpl* xcert ; |
| std::list< X509Certificate_MSCryptImpl* > certsList ; |
| PCCERT_CONTEXT pCertContext = NULL; |
| |
| //firstly, we try to find private keys in given key store. |
| if( m_hKeyStore != NULL ) { |
| pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext ); |
| while (pCertContext) |
| { |
| xcert = MswcryCertContextToXCert( pCertContext ) ; |
| if( xcert != NULL ) |
| certsList.push_back( xcert ) ; |
| pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext ); |
| } |
| } |
| |
| //secondly, we try to find certificate from registered private keys. |
| if( !m_tPriKeyList.empty() ) { |
| //TODO: Don't know whether or not it is necessary ans possible. |
| } |
| |
| //Thirdly, we try to find certificate from system default key store. |
| if( m_bEnableDefault ) { |
| HCERTSTORE hSystemKeyStore ; |
| DWORD dwKeySpec; |
| HCRYPTPROV hCryptProv; |
| |
| /* |
| hSystemKeyStore = CertOpenStore( |
| CERT_STORE_PROV_SYSTEM , |
| 0 , |
| NULL , |
| CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG , |
| L"MY" |
| ) ; |
| */ |
| hSystemKeyStore = CertOpenSystemStore( 0, "MY" ) ; |
| if( hSystemKeyStore != NULL ) { |
| pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext ); |
| while (pCertContext) |
| { |
| // Add By CP for checking whether the certificate is a personal certificate or not. |
| if(!(CryptAcquireCertificatePrivateKey(pCertContext, |
| CRYPT_ACQUIRE_COMPARE_KEY_FLAG, |
| NULL, |
| &hCryptProv, |
| &dwKeySpec, |
| NULL))) |
| { |
| // Not Privatekey found. SKIP this one; By CP |
| pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext ); |
| continue; |
| } |
| // then TODO : Check the personal cert is valid or not. |
| |
| // end CP |
| xcert = MswcryCertContextToXCert( pCertContext ) ; |
| if( xcert != NULL ) |
| certsList.push_back( xcert ) ; |
| pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext ); |
| } |
| } |
| |
| CertCloseStore( hSystemKeyStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| } |
| |
| length = certsList.size() ; |
| if( length != 0 ) { |
| int i ; |
| std::list< X509Certificate_MSCryptImpl* >::iterator xcertIt ; |
| Sequence< Reference< XCertificate > > certSeq( length ) ; |
| |
| for( i = 0, xcertIt = certsList.begin(); xcertIt != certsList.end(); xcertIt ++, i++ ) { |
| certSeq[i] = *xcertIt ; |
| } |
| |
| return certSeq ; |
| } |
| |
| return Sequence< Reference< XCertificate > >() ; |
| } |
| |
| |
| Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& serialNumber ) throw( SecurityException , RuntimeException ) { |
| unsigned int i ; |
| // sal_Int8 found = 0 ; |
| LPSTR pszName ; |
| X509Certificate_MSCryptImpl *xcert = NULL ; |
| PCCERT_CONTEXT pCertContext = NULL ; |
| HCERTSTORE hCertStore = NULL ; |
| CRYPT_INTEGER_BLOB cryptSerialNumber ; |
| CERT_INFO certInfo ; |
| |
| // By CP , for correct encoding |
| sal_uInt16 encoding ; |
| rtl_Locale *pLocale = NULL ; |
| osl_getProcessLocale( &pLocale ) ; |
| encoding = osl_getTextEncodingFromLocale( pLocale ) ; |
| // CP end |
| |
| //Create cert info from issue and serial |
| rtl::OString oissuer = rtl::OUStringToOString( issuerName , encoding ) ; |
| pszName = ( char* )oissuer.getStr() ; |
| |
| if( ! ( CertStrToName( |
| X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , |
| pszName , |
| CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, |
| NULL , |
| NULL , |
| &certInfo.Issuer.cbData, NULL ) ) |
| ) { |
| return NULL ; |
| } |
| |
| certInfo.Issuer.pbData = ( BYTE* )malloc( certInfo.Issuer.cbData ); |
| if(!certInfo.Issuer.pbData) |
| throw RuntimeException() ; |
| |
| if( ! ( CertStrToName( |
| X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , |
| pszName , |
| CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, |
| NULL , |
| ( BYTE* )certInfo.Issuer.pbData , |
| &certInfo.Issuer.cbData, NULL ) ) |
| ) { |
| free( certInfo.Issuer.pbData ) ; |
| return NULL ; |
| } |
| |
| //Get the SerialNumber |
| cryptSerialNumber.cbData = serialNumber.getLength() ; |
| cryptSerialNumber.pbData = ( BYTE* )malloc( cryptSerialNumber.cbData); |
| if (!cryptSerialNumber.pbData) |
| { |
| free( certInfo.Issuer.pbData ) ; |
| throw RuntimeException() ; |
| } |
| for( i = 0; i < cryptSerialNumber.cbData; i ++ ) |
| cryptSerialNumber.pbData[i] = serialNumber[ cryptSerialNumber.cbData - i - 1 ] ; |
| |
| certInfo.SerialNumber.cbData = cryptSerialNumber.cbData ; |
| certInfo.SerialNumber.pbData = cryptSerialNumber.pbData ; |
| |
| // Get the Cert from all store. |
| for( i = 0 ; i < 6 ; i ++ ) |
| { |
| switch(i) |
| { |
| case 0: |
| if(m_hKeyStore == NULL) continue ; |
| hCertStore = m_hKeyStore ; |
| break; |
| case 1: |
| if(m_hCertStore == NULL) continue ; |
| hCertStore = m_hCertStore ; |
| break; |
| case 2: |
| hCertStore = CertOpenSystemStore( 0, "MY" ) ; |
| if(hCertStore == NULL || !m_bEnableDefault) continue ; |
| break; |
| case 3: |
| hCertStore = CertOpenSystemStore( 0, "Root" ) ; |
| if(hCertStore == NULL || !m_bEnableDefault) continue ; |
| break; |
| case 4: |
| hCertStore = CertOpenSystemStore( 0, "Trust" ) ; |
| if(hCertStore == NULL || !m_bEnableDefault) continue ; |
| break; |
| case 5: |
| hCertStore = CertOpenSystemStore( 0, "CA" ) ; |
| if(hCertStore == NULL || !m_bEnableDefault) continue ; |
| break; |
| default: |
| i=6; |
| continue; |
| } |
| |
| /******************************************************************************* |
| * This code reserved for remind us there are another way to find one cert by |
| * IssuerName&serialnumber. You can use the code to replaced the function |
| * CertFindCertificateInStore IF and ONLY IF you must find one special cert in |
| * certStore but can not be found by CertFindCertificateInStore , then , you |
| * should also change the same part in libxmlsec/.../src/mscrypto/x509vfy.c#875. |
| * By Chandler Peng(chandler.peng@sun.com) |
| *****/ |
| /******************************************************************************* |
| pCertContext = NULL ; |
| found = 0; |
| do{ |
| // 1. enum the certs has same string in the issuer string. |
| pCertContext = CertEnumCertificatesInStore( hCertStore , pCertContext ) ; |
| if( pCertContext != NULL ) |
| { |
| // 2. check the cert's issuer name . |
| char* issuer = NULL ; |
| DWORD cbIssuer = 0 ; |
| |
| cbIssuer = CertNameToStr( |
| X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , |
| &( pCertContext->pCertInfo->Issuer ), |
| CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , |
| NULL, 0 |
| ) ; |
| |
| if( cbIssuer == 0 ) continue ; // discard this cert; |
| |
| issuer = (char *)malloc( cbIssuer ) ; |
| if( issuer == NULL ) // discard this cert; |
| { |
| free( cryptSerialNumber.pbData) ; |
| free( certInfo.Issuer.pbData ) ; |
| CertFreeCertificateContext( pCertContext ) ; |
| if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| throw RuntimeException() ; |
| } |
| |
| cbIssuer = CertNameToStr( |
| X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , |
| &( pCertContext->pCertInfo->Issuer ), |
| CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , |
| issuer, cbIssuer |
| ) ; |
| |
| if( cbIssuer <= 0 ) |
| { |
| free( issuer ) ; |
| continue ;// discard this cert; |
| } |
| |
| if(strncmp(pszName , issuer , cbIssuer) != 0) |
| { |
| free( issuer ) ; |
| continue ;// discard this cert; |
| } |
| free( issuer ) ; |
| |
| // 3. check the serial number. |
| if( memcmp( cryptSerialNumber.pbData , pCertContext->pCertInfo->SerialNumber.pbData , cryptSerialNumber.cbData ) != 0 ) |
| { |
| continue ;// discard this cert; |
| } |
| |
| // 4. confirm and break; |
| found = 1; |
| break ; |
| } |
| |
| }while(pCertContext); |
| |
| if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| if( found != 0 ) break; // Found the certificate. |
| ********************************************************************************/ |
| |
| pCertContext = CertFindCertificateInStore( |
| hCertStore, |
| X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| 0, |
| CERT_FIND_SUBJECT_CERT, |
| &certInfo, |
| NULL |
| ) ; |
| |
| if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| if( pCertContext != NULL ) break ; // Found the certificate. |
| |
| } |
| |
| if( cryptSerialNumber.pbData ) free( cryptSerialNumber.pbData ) ; |
| if( certInfo.Issuer.pbData ) free( certInfo.Issuer.pbData ) ; |
| |
| if( pCertContext != NULL ) { |
| xcert = MswcryCertContextToXCert( pCertContext ) ; |
| if( pCertContext ) CertFreeCertificateContext( pCertContext ) ; |
| } else { |
| xcert = NULL ; |
| } |
| |
| return xcert ; |
| } |
| |
| Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: getCertificate( const OUString& issuerName, const OUString& serialNumber ) throw( SecurityException , RuntimeException ) { |
| Sequence< sal_Int8 > serial = numericStringToBigInteger( serialNumber ) ; |
| return getCertificate( issuerName, serial ) ; |
| } |
| |
| Sequence< Reference < XCertificate > > SecurityEnvironment_MSCryptImpl :: buildCertificatePath( const Reference< XCertificate >& begin ) throw( SecurityException , RuntimeException ) { |
| PCCERT_CHAIN_CONTEXT pChainContext ; |
| PCCERT_CONTEXT pCertContext ; |
| const X509Certificate_MSCryptImpl* xcert ; |
| |
| CERT_ENHKEY_USAGE enhKeyUsage ; |
| CERT_USAGE_MATCH certUsage ; |
| CERT_CHAIN_PARA chainPara ; |
| |
| enhKeyUsage.cUsageIdentifier = 0 ; |
| enhKeyUsage.rgpszUsageIdentifier = NULL ; |
| certUsage.dwType = USAGE_MATCH_TYPE_AND ; |
| certUsage.Usage = enhKeyUsage ; |
| chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; |
| chainPara.RequestedUsage = certUsage ; |
| |
| Reference< XUnoTunnel > xCertTunnel( begin, UNO_QUERY ) ; |
| if( !xCertTunnel.is() ) { |
| throw RuntimeException() ; |
| } |
| |
| xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ; |
| if( xcert == NULL ) { |
| throw RuntimeException() ; |
| } |
| |
| pCertContext = xcert->getMswcryCert() ; |
| |
| pChainContext = NULL ; |
| |
| BOOL bChain = FALSE; |
| if( pCertContext != NULL ) |
| { |
| HCERTSTORE hAdditionalStore = NULL; |
| HCERTSTORE hCollectionStore = NULL; |
| if (m_hCertStore && m_hKeyStore) |
| { |
| //Merge m_hCertStore and m_hKeyStore into one store. |
| hCollectionStore = CertOpenStore( |
| CERT_STORE_PROV_COLLECTION , |
| 0 , |
| NULL , |
| 0 , |
| NULL |
| ) ; |
| if (hCollectionStore != NULL) |
| { |
| CertAddStoreToCollection ( |
| hCollectionStore , |
| m_hCertStore , |
| CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , |
| 0) ; |
| CertAddStoreToCollection ( |
| hCollectionStore , |
| m_hCertStore , |
| CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , |
| 0) ; |
| hAdditionalStore = hCollectionStore; |
| } |
| |
| } |
| |
| //if the merge of both stores failed then we add only m_hCertStore |
| if (hAdditionalStore == NULL && m_hCertStore) |
| hAdditionalStore = m_hCertStore; |
| else if (hAdditionalStore == NULL && m_hKeyStore) |
| hAdditionalStore = m_hKeyStore; |
| else |
| hAdditionalStore = NULL; |
| |
| //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST |
| bChain = CertGetCertificateChain( |
| NULL , |
| pCertContext , |
| NULL , //use current system time |
| hAdditionalStore, |
| &chainPara , |
| CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME , |
| NULL , |
| &pChainContext); |
| if (!bChain) |
| pChainContext = NULL; |
| |
| //Close the additional store |
| CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); |
| } |
| |
| if(bChain && pChainContext != NULL && pChainContext->cChain > 0 ) |
| { |
| PCCERT_CONTEXT pCertInChain ; |
| PCERT_SIMPLE_CHAIN pCertChain ; |
| X509Certificate_MSCryptImpl* pCert ; |
| |
| pCertChain = pChainContext->rgpChain[0] ; |
| if( pCertChain->cElement ) { |
| Sequence< Reference< XCertificate > > xCertChain( pCertChain->cElement ) ; |
| |
| for( unsigned int i = 0 ; i < pCertChain->cElement ; i ++ ) { |
| if( pCertChain->rgpElement[i] ) |
| pCertInChain = pCertChain->rgpElement[i]->pCertContext ; |
| else |
| pCertInChain = NULL ; |
| |
| if( pCertInChain != NULL ) { |
| pCert = MswcryCertContextToXCert( pCertInChain ) ; |
| if( pCert != NULL ) |
| xCertChain[i] = pCert ; |
| } |
| } |
| |
| CertFreeCertificateChain( pChainContext ) ; |
| pChainContext = NULL ; |
| |
| return xCertChain ; |
| } |
| } |
| if (pChainContext) |
| CertFreeCertificateChain(pChainContext); |
| |
| return Sequence< Reference < XCertificate > >(); |
| } |
| |
| Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: createCertificateFromRaw( const Sequence< sal_Int8 >& rawCertificate ) throw( SecurityException , RuntimeException ) { |
| X509Certificate_MSCryptImpl* xcert ; |
| |
| if( rawCertificate.getLength() > 0 ) { |
| xcert = new X509Certificate_MSCryptImpl() ; |
| if( xcert == NULL ) |
| throw RuntimeException() ; |
| |
| xcert->setRawCert( rawCertificate ) ; |
| } else { |
| xcert = NULL ; |
| } |
| |
| return xcert ; |
| } |
| |
| Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: createCertificateFromAscii( const OUString& asciiCertificate ) throw( SecurityException , RuntimeException ) { |
| xmlChar* chCert ; |
| xmlSecSize certSize ; |
| |
| rtl::OString oscert = rtl::OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ; |
| |
| chCert = xmlStrndup( ( const xmlChar* )oscert.getStr(), ( int )oscert.getLength() ) ; |
| |
| certSize = xmlSecBase64Decode( chCert, ( xmlSecByte* )chCert, xmlStrlen( chCert ) ) ; |
| |
| Sequence< sal_Int8 > rawCert( certSize ) ; |
| for( unsigned int i = 0 ; i < certSize ; i ++ ) |
| rawCert[i] = *( chCert + i ) ; |
| |
| xmlFree( chCert ) ; |
| |
| return createCertificateFromRaw( rawCert ) ; |
| } |
| |
| |
| HCERTSTORE getCertStoreForIntermediatCerts( |
| const Sequence< Reference< ::com::sun::star::security::XCertificate > >& seqCerts) |
| { |
| HCERTSTORE store = NULL; |
| store = CertOpenStore( |
| CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); |
| if (store == NULL) |
| return NULL; |
| |
| for (int i = 0; i < seqCerts.getLength(); i++) |
| { |
| xmlsec_trace("Added temporary certificate: \n%s", |
| OUStringToOString(seqCerts[i]->getSubjectName(), |
| osl_getThreadTextEncoding()).getStr()); |
| |
| |
| Sequence<sal_Int8> data = seqCerts[i]->getEncoded(); |
| PCCERT_CONTEXT cert = CertCreateCertificateContext( |
| X509_ASN_ENCODING, ( const BYTE* )&data[0], data.getLength()); |
| //Adding the certificate creates a copy and not just increases the ref count |
| //Therefore we free later the certificate that we now add |
| CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_ALWAYS, NULL); |
| CertFreeCertificateContext(cert); |
| } |
| return store; |
| } |
| |
| //We return only valid or invalid, as long as the API documentation expresses |
| //explicitly that all validation steps are carried out even if one or several |
| //errors occur. See also |
| //http://wiki.services.openoffice.org/wiki/Certificate_Path_Validation#Validation_status |
| sal_Int32 SecurityEnvironment_MSCryptImpl :: verifyCertificate( |
| const Reference< ::com::sun::star::security::XCertificate >& aCert, |
| const Sequence< Reference< ::com::sun::star::security::XCertificate > >& seqCerts) |
| throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException ) |
| { |
| sal_Int32 validity = 0; |
| PCCERT_CHAIN_CONTEXT pChainContext = NULL; |
| PCCERT_CONTEXT pCertContext = NULL; |
| const X509Certificate_MSCryptImpl* xcert = NULL; |
| |
| Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ; |
| if( !xCertTunnel.is() ) { |
| throw RuntimeException() ; |
| } |
| |
| xmlsec_trace("Start verification of certificate: \n %s", |
| OUStringToOString( |
| aCert->getSubjectName(), osl_getThreadTextEncoding()).getStr()); |
| |
| xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ; |
| if( xcert == NULL ) { |
| throw RuntimeException() ; |
| } |
| |
| pCertContext = xcert->getMswcryCert() ; |
| |
| CERT_ENHKEY_USAGE enhKeyUsage ; |
| CERT_USAGE_MATCH certUsage ; |
| CERT_CHAIN_PARA chainPara ; |
| rtl_zeroMemory(&chainPara, sizeof(CERT_CHAIN_PARA)); |
| |
| //Prepare parameter for CertGetCertificateChain |
| enhKeyUsage.cUsageIdentifier = 0 ; |
| enhKeyUsage.rgpszUsageIdentifier = NULL ; |
| certUsage.dwType = USAGE_MATCH_TYPE_AND ; |
| certUsage.Usage = enhKeyUsage ; |
| chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; |
| chainPara.RequestedUsage = certUsage ; |
| |
| |
| HCERTSTORE hCollectionStore = NULL; |
| HCERTSTORE hIntermediateCertsStore = NULL; |
| BOOL bChain = FALSE; |
| if( pCertContext != NULL ) |
| { |
| hIntermediateCertsStore = |
| getCertStoreForIntermediatCerts(seqCerts); |
| |
| //Merge m_hCertStore and m_hKeyStore and the store of the intermediate |
| //certificates into one store. |
| hCollectionStore = CertOpenStore( |
| CERT_STORE_PROV_COLLECTION , |
| 0 , |
| NULL , |
| 0 , |
| NULL |
| ) ; |
| if (hCollectionStore != NULL) |
| { |
| CertAddStoreToCollection ( |
| hCollectionStore , |
| m_hCertStore , |
| CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , |
| 0) ; |
| CertAddStoreToCollection ( |
| hCollectionStore , |
| m_hCertStore , |
| CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , |
| 0) ; |
| CertAddStoreToCollection ( |
| hCollectionStore, |
| hIntermediateCertsStore, |
| CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, |
| 0); |
| |
| } |
| |
| //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST |
| //We do not check revocation of the root. In most cases there are none. |
| //Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
| xmlsec_trace("Verifying cert using revocation information."); |
| bChain = CertGetCertificateChain( |
| NULL , |
| pCertContext , |
| NULL , //use current system time |
| hCollectionStore, |
| &chainPara , |
| CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, |
| NULL , |
| &pChainContext); |
| |
| if (bChain && pChainContext->cChain > 0) |
| { |
| xmlsec_trace("Overall error status (all chains):"); |
| traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus); |
| //highest quality chains come first |
| PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0]; |
| xmlsec_trace("Error status of first chain: "); |
| traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus); |
| |
| //CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate |
| //has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed. |
| DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN | |
| CERT_TRUST_IS_OFFLINE_REVOCATION; |
| DWORD otherErrorsMask = ~revocationFlags; |
| if( !(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask)) |
| |
| { |
| //No errors except maybe those caused by missing revocation information |
| //Check if there are errors |
| if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags) |
| { |
| //No revocation information. Because MSDN documentation is not |
| //clear about if all other tests are performed if an error occurrs, |
| //we test again, without requiring revocation checking. |
| CertFreeCertificateChain(pChainContext); |
| pChainContext = NULL; |
| xmlsec_trace("Checking again but without requiring revocation information."); |
| bChain = CertGetCertificateChain( |
| NULL , |
| pCertContext , |
| NULL , //use current system time |
| hCollectionStore, |
| &chainPara , |
| 0, |
| NULL , |
| &pChainContext); |
| if (bChain |
| && pChainContext->cChain > 0 |
| && pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR) |
| { |
| xmlsec_trace("Certificate is valid.\n"); |
| validity = ::com::sun::star::security::CertificateValidity::VALID; |
| } |
| else |
| { |
| xmlsec_trace("Certificate is invalid.\n"); |
| } |
| } |
| else |
| { |
| //valid and revocation information available |
| xmlsec_trace("Certificate is valid.\n"); |
| validity = ::com::sun::star::security::CertificateValidity::VALID; |
| } |
| } |
| else |
| { |
| //invalid |
| xmlsec_trace("Certificate is invalid.\n"); |
| validity = ::com::sun::star::security::CertificateValidity::INVALID ; |
| } |
| } |
| else |
| { |
| xmlsec_trace("CertGetCertificateChaine failed.\n"); |
| } |
| } |
| |
| if (pChainContext) |
| { |
| CertFreeCertificateChain(pChainContext); |
| pChainContext = NULL; |
| } |
| |
| //Close the additional store, do not destroy the contained certs |
| CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); |
| //Close the temporary store containing the intermediate certificates and make |
| //sure all certificates are deleted. |
| CertCloseStore(hIntermediateCertsStore, CERT_CLOSE_STORE_CHECK_FLAG); |
| |
| return validity ; |
| } |
| |
| sal_Int32 SecurityEnvironment_MSCryptImpl :: getCertificateCharacters( const ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificate >& aCert ) throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException ) { |
| sal_Int32 characters ; |
| PCCERT_CONTEXT pCertContext ; |
| const X509Certificate_MSCryptImpl* xcert ; |
| |
| Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ; |
| if( !xCertTunnel.is() ) { |
| throw RuntimeException() ; |
| } |
| |
| xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ; |
| if( xcert == NULL ) { |
| throw RuntimeException() ; |
| } |
| |
| pCertContext = xcert->getMswcryCert() ; |
| |
| characters = 0x00000000 ; |
| |
| //Firstly, make sentence whether or not the cert is self-signed. |
| if( CertCompareCertificateName( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->Subject), &(pCertContext->pCertInfo->Issuer) ) ) { |
| characters |= ::com::sun::star::security::CertificateCharacters::SELF_SIGNED ; |
| } else { |
| characters &= ~ ::com::sun::star::security::CertificateCharacters::SELF_SIGNED ; |
| } |
| |
| //Secondly, make sentence whether or not the cert has a private key. |
| { |
| BOOL fCallerFreeProv ; |
| DWORD dwKeySpec ; |
| HCRYPTPROV hProv ; |
| if( CryptAcquireCertificatePrivateKey( pCertContext , |
| 0 , |
| NULL , |
| &( hProv ) , |
| &( dwKeySpec ) , |
| &( fCallerFreeProv ) ) |
| ) { |
| characters |= ::com::sun::star::security::CertificateCharacters::HAS_PRIVATE_KEY ; |
| |
| if( hProv != NULL && fCallerFreeProv ) |
| CryptReleaseContext( hProv, 0 ) ; |
| } else { |
| characters &= ~ ::com::sun::star::security::CertificateCharacters::HAS_PRIVATE_KEY ; |
| } |
| } |
| return characters ; |
| } |
| |
| void SecurityEnvironment_MSCryptImpl :: enableDefaultCrypt( sal_Bool enable ) throw( Exception, RuntimeException ) { |
| m_bEnableDefault = enable ; |
| } |
| |
| sal_Bool SecurityEnvironment_MSCryptImpl :: defaultEnabled() throw( Exception, RuntimeException ) { |
| return m_bEnableDefault ; |
| } |
| |
| X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert ) |
| { |
| X509Certificate_MSCryptImpl* xcert ; |
| |
| if( cert != NULL ) { |
| xcert = new X509Certificate_MSCryptImpl() ; |
| if( xcert != NULL ) { |
| xcert->setMswcryCert( cert ) ; |
| } |
| } else { |
| xcert = NULL ; |
| } |
| |
| return xcert ; |
| } |
| |
| ::rtl::OUString SecurityEnvironment_MSCryptImpl::getSecurityEnvironmentInformation() throw( ::com::sun::star::uno::RuntimeException ) |
| { |
| return rtl::OUString::createFromAscii("Microsoft Crypto API"); |
| } |
| |
| /* Native methods */ |
| xmlSecKeysMngrPtr SecurityEnvironment_MSCryptImpl :: createKeysManager() throw( Exception, RuntimeException ) { |
| |
| unsigned int i ; |
| HCRYPTKEY symKey ; |
| HCRYPTKEY pubKey ; |
| HCRYPTKEY priKey ; |
| xmlSecKeysMngrPtr pKeysMngr = NULL ; |
| |
| /*- |
| * The following lines is based on the of xmlsec-mscrypto crypto engine |
| */ |
| pKeysMngr = xmlSecMSCryptoAppliedKeysMngrCreate( m_hKeyStore , m_hCertStore ) ; |
| if( pKeysMngr == NULL ) |
| throw RuntimeException() ; |
| |
| /*- |
| * Adopt symmetric key into keys manager |
| */ |
| for( i = 0 ; ( symKey = getSymKey( i ) ) != NULL ; i ++ ) { |
| if( xmlSecMSCryptoAppliedKeysMngrSymKeyLoad( pKeysMngr, symKey ) < 0 ) { |
| throw RuntimeException() ; |
| } |
| } |
| |
| /*- |
| * Adopt asymmetric public key into keys manager |
| */ |
| for( i = 0 ; ( pubKey = getPubKey( i ) ) != NULL ; i ++ ) { |
| if( xmlSecMSCryptoAppliedKeysMngrPubKeyLoad( pKeysMngr, pubKey ) < 0 ) { |
| throw RuntimeException() ; |
| } |
| } |
| |
| /*- |
| * Adopt asymmetric private key into keys manager |
| */ |
| for( i = 0 ; ( priKey = getPriKey( i ) ) != NULL ; i ++ ) { |
| if( xmlSecMSCryptoAppliedKeysMngrPriKeyLoad( pKeysMngr, priKey ) < 0 ) { |
| throw RuntimeException() ; |
| } |
| } |
| |
| /*- |
| * Adopt system default certificate store. |
| */ |
| if( defaultEnabled() ) { |
| //Add system key store into the keys manager. |
| m_hMySystemStore = CertOpenSystemStore( 0, "MY" ) ; |
| if( m_hMySystemStore != NULL ) { |
| if( xmlSecMSCryptoAppliedKeysMngrAdoptKeyStore( pKeysMngr, m_hMySystemStore ) < 0 ) { |
| CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hMySystemStore = NULL; |
| throw RuntimeException() ; |
| } |
| } |
| |
| //Add system root store into the keys manager. |
| m_hRootSystemStore = CertOpenSystemStore( 0, "Root" ) ; |
| if( m_hRootSystemStore != NULL ) { |
| if( xmlSecMSCryptoAppliedKeysMngrAdoptTrustedStore( pKeysMngr, m_hRootSystemStore ) < 0 ) { |
| CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hRootSystemStore = NULL; |
| throw RuntimeException() ; |
| } |
| } |
| |
| //Add system trusted store into the keys manager. |
| m_hTrustSystemStore = CertOpenSystemStore( 0, "Trust" ) ; |
| if( m_hTrustSystemStore != NULL ) { |
| if( xmlSecMSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hTrustSystemStore ) < 0 ) { |
| CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hTrustSystemStore = NULL; |
| throw RuntimeException() ; |
| } |
| } |
| |
| //Add system CA store into the keys manager. |
| m_hCaSystemStore = CertOpenSystemStore( 0, "CA" ) ; |
| if( m_hCaSystemStore != NULL ) { |
| if( xmlSecMSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hCaSystemStore ) < 0 ) { |
| CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; |
| m_hCaSystemStore = NULL; |
| throw RuntimeException() ; |
| } |
| } |
| } |
| |
| return pKeysMngr ; |
| } |
| void SecurityEnvironment_MSCryptImpl :: destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) throw( Exception, RuntimeException ) { |
| if( pKeysMngr != NULL ) { |
| xmlSecKeysMngrDestroy( pKeysMngr ) ; |
| } |
| } |