Address certificate object lifetime with wrapper class.
authorScott Cantor <cantor.2@osu.edu>
Wed, 23 Aug 2006 04:41:08 +0000 (04:41 +0000)
committerScott Cantor <cantor.2@osu.edu>
Wed, 23 Aug 2006 04:41:08 +0000 (04:41 +0000)
xmltooling/security/impl/ExplicitKeyTrustEngine.cpp
xmltooling/signature/KeyResolver.h
xmltooling/signature/impl/FilesystemCredentialResolver.cpp
xmltooling/signature/impl/InlineKeyResolver.cpp
xmltooling/signature/impl/KeyResolver.cpp
xmltoolingtest/InlineKeyResolverTest.h

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