From c1ea20979cdeb36ba3b0899fefcc12e3735cf7eb Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Wed, 23 Aug 2006 04:41:08 +0000 Subject: [PATCH] Address certificate object lifetime with wrapper class. --- .../security/impl/ExplicitKeyTrustEngine.cpp | 7 ++-- xmltooling/signature/KeyResolver.h | 48 ++++++++++++++++++++-- .../impl/FilesystemCredentialResolver.cpp | 14 ++++--- xmltooling/signature/impl/InlineKeyResolver.cpp | 30 ++++++++------ xmltooling/signature/impl/KeyResolver.cpp | 4 +- xmltoolingtest/InlineKeyResolverTest.h | 2 +- 6 files changed, 75 insertions(+), 30 deletions(-) diff --git a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp index 69c381a..f0833a4 100644 --- a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp +++ b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp @@ -136,20 +136,19 @@ bool ExplicitKeyTrustEngine::validate( // role interface to verify the EE certificate. log.debug("attempting to match key information from peer with end-entity certificate"); - vector resolvedCerts; while (keyInfoSource.hasNext()) { - resolvedCerts.clear(); + KeyResolver::ResolvedCertificates resolvedCerts; if (0 == (keyResolver ? keyResolver : m_keyResolver)->resolveCertificates(keyInfoSource.next(),resolvedCerts)) { log.debug("key information does not resolve to a certificate, skipping it"); continue; } log.debug("checking if certificates contained within key information match end-entity certificate"); - if (resolvedCerts.front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + if (resolvedCerts.v().front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { log.error("only the OpenSSL XSEC provider is supported"); continue; } - else if (!X509_cmp(static_cast(certEE)->getOpenSSLX509(),static_cast(resolvedCerts.front())->getOpenSSLX509())) { + else if (!X509_cmp(static_cast(certEE)->getOpenSSLX509(),static_cast(resolvedCerts.v().front())->getOpenSSLX509())) { log.info("end-entity certificate matches certificate from peer key information"); return true; } diff --git a/xmltooling/signature/KeyResolver.h b/xmltooling/signature/KeyResolver.h index b75ab2b..b874bff 100644 --- a/xmltooling/signature/KeyResolver.h +++ b/xmltooling/signature/KeyResolver.h @@ -79,15 +79,35 @@ namespace xmlsignature { } /** + * A wrapper that handles disposal of certificates when required. + */ + class XMLTOOL_API ResolvedCertificates { + MAKE_NONCOPYABLE(ResolvedCertificates); + bool m_owned; + std::vector m_certs; + public: + ResolvedCertificates() : m_owned(false) {} + ~ResolvedCertificates() { + if (m_owned) { + std::for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup()); + } + } + const std::vector& v() const { + return m_certs; + } + friend class XMLTOOL_API KeyResolver; + }; + + /** * Returns a set of certificates based on the supplied KeyInfo information. * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. * * @param keyInfo the key information - * @param certs reference to vector to store certificates + * @param certs reference to object to hold certificates * @return number of certificates returned */ virtual std::vector::size_type resolveCertificates( - const KeyInfo* keyInfo, std::vector& certs + const KeyInfo* keyInfo, ResolvedCertificates& certs ) const; /** @@ -95,11 +115,11 @@ namespace xmlsignature { * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. * * @param keyInfo the key information - * @param certs reference to vector to store certificates + * @param certs reference to object to hold certificates * @return number of certificates returned */ virtual std::vector::size_type resolveCertificates( - DSIGKeyInfoList* keyInfo, std::vector& certs + DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs ) const; /** @@ -122,6 +142,26 @@ namespace xmlsignature { protected: XSECCryptoKey* m_key; + + /** + * Accessor for certificate vector from derived KeyResolver classes. + * + * @param certs certificate wrapper to access + * @return modifiable reference to vector inside wrapper + */ + std::vector& accessCertificates(ResolvedCertificates& certs) const { + return certs.m_certs; + } + + /** + * Accessor for certificate ownership flag from derived KeyResolver classes. + * + * @param certs certificate wrapper to access + * @return modifiable reference to ownership flag inside wrapper + */ + bool& accessOwned(ResolvedCertificates& certs) const { + return certs.m_owned; + } }; /** diff --git a/xmltooling/signature/impl/FilesystemCredentialResolver.cpp b/xmltooling/signature/impl/FilesystemCredentialResolver.cpp index c4362d5..2389c14 100644 --- a/xmltooling/signature/impl/FilesystemCredentialResolver.cpp +++ b/xmltooling/signature/impl/FilesystemCredentialResolver.cpp @@ -73,13 +73,15 @@ namespace xmlsignature { XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const { return m_key ? m_key->clone() : NULL; } XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const { return m_key ? m_key->clone() : NULL; } - vector::size_type resolveCertificates(const KeyInfo* keyInfo, vector& certs) const { - certs.assign(m_xseccerts.begin(), m_xseccerts.end()); - return certs.size(); + vector::size_type resolveCertificates(const KeyInfo* keyInfo, ResolvedCertificates& certs) const { + accessCertificates(certs).assign(m_xseccerts.begin(), m_xseccerts.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); } - vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, vector& certs) const { - certs.assign(m_xseccerts.begin(), m_xseccerts.end()); - return certs.size(); + vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs) const { + accessCertificates(certs).assign(m_xseccerts.begin(), m_xseccerts.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); } private: diff --git a/xmltooling/signature/impl/InlineKeyResolver.cpp b/xmltooling/signature/impl/InlineKeyResolver.cpp index 82f0433..897af8e 100644 --- a/xmltooling/signature/impl/InlineKeyResolver.cpp +++ b/xmltooling/signature/impl/InlineKeyResolver.cpp @@ -50,8 +50,8 @@ namespace xmlsignature { XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const; XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const; - vector::size_type resolveCertificates(const KeyInfo* keyInfo, vector& certs) const; - vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, vector& certs) const; + vector::size_type resolveCertificates(const KeyInfo* keyInfo, ResolvedCertificates& certs) const; + vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs) const; XSECCryptoX509CRL* resolveCRL(const KeyInfo* keyInfo) const; XSECCryptoX509CRL* resolveCRL(DSIGKeyInfoList* keyInfo) const; @@ -337,7 +337,7 @@ XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo) const } vector::size_type InlineKeyResolver::resolveCertificates( - const KeyInfo* keyInfo, vector& certs + const KeyInfo* keyInfo, ResolvedCertificates& certs ) const { // Caching? @@ -348,8 +348,9 @@ vector::size_type InlineKeyResolver::resolveCertificates( if (i != m_cache.end()) { // Found in cache, so just return the results. SharedLock locker(m_lock,false); - certs.assign(i->second.m_certs.begin(), i->second.m_certs.end()); - return certs.size(); + accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); } else { // Elevate lock. @@ -362,11 +363,13 @@ vector::size_type InlineKeyResolver::resolveCertificates( i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; _resolve(i->first, i->second); } - certs.assign(i->second.m_certs.begin(), i->second.m_certs.end()); - return certs.size(); + accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); } } - return _resolveCertificates(keyInfo, certs); + accessOwned(certs) = true; + return _resolveCertificates(keyInfo, accessCertificates(certs)); } XSECCryptoKey* InlineKeyResolver::resolveKey(DSIGKeyInfoList* keyInfo) const @@ -391,21 +394,22 @@ XSECCryptoKey* InlineKeyResolver::resolveKey(DSIGKeyInfoList* keyInfo) const } vector::size_type InlineKeyResolver::resolveCertificates( - DSIGKeyInfoList* keyInfo, vector& certs + DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs ) const { - certs.clear(); + accessCertificates(certs).clear(); + accessOwned(certs) = false; DSIGKeyInfoList::size_type sz = keyInfo->getSize(); - for (DSIGKeyInfoList::size_type i=0; certs.empty() && iitem(i)->getKeyInfoType()==DSIGKeyInfo::KEYINFO_X509) { DSIGKeyInfoX509* x509 = static_cast(keyInfo->item(i)); int count = x509->getCertificateListSize(); for (int j=0; jgetCertificateCryptoItem(j)); + accessCertificates(certs).push_back(x509->getCertificateCryptoItem(j)); } } } - return certs.size(); + return accessCertificates(certs).size(); } XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(DSIGKeyInfoList* keyInfo) const diff --git a/xmltooling/signature/impl/KeyResolver.cpp b/xmltooling/signature/impl/KeyResolver.cpp index 994d900..971c9fd 100644 --- a/xmltooling/signature/impl/KeyResolver.cpp +++ b/xmltooling/signature/impl/KeyResolver.cpp @@ -40,14 +40,14 @@ void XMLTOOL_API xmlsignature::registerKeyResolvers() } vector::size_type KeyResolver::resolveCertificates( - const KeyInfo* keyInfo, vector& certs + const KeyInfo* keyInfo, ResolvedCertificates& certs ) const { return 0; } vector::size_type KeyResolver::resolveCertificates( - DSIGKeyInfoList* keyInfo, vector& certs + DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs ) const { return 0; diff --git a/xmltoolingtest/InlineKeyResolverTest.h b/xmltoolingtest/InlineKeyResolverTest.h index 5010fde..9cfbcde 100644 --- a/xmltoolingtest/InlineKeyResolverTest.h +++ b/xmltoolingtest/InlineKeyResolverTest.h @@ -56,7 +56,7 @@ public: auto_ptr crl(m_resolver->resolveCRL(kiObject.get())); TSM_ASSERT("Unable to resolve CRL.", crl.get()!=NULL); - vector certs; + KeyResolver::ResolvedCertificates certs; TSM_ASSERT_EQUALS("Wrong certificate count.", m_resolver->resolveCertificates(kiObject.get(), certs), 1); } }; -- 2.1.4