X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fsignature%2Fimpl%2FInlineKeyResolver.cpp;h=df99b942f6da8fc1aa7fde49de441beca222c6cd;hb=5cb314df178f78c6fa7b9826c2c5a5298ec7a473;hp=c34db20f01b9306060b60a9dbe9153421f6c8cb8;hpb=a21d1f24fc3fb85928b014b69c0e6916dcb66955;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/signature/impl/InlineKeyResolver.cpp b/xmltooling/signature/impl/InlineKeyResolver.cpp index c34db20..df99b94 100644 --- a/xmltooling/signature/impl/InlineKeyResolver.cpp +++ b/xmltooling/signature/impl/InlineKeyResolver.cpp @@ -1,330 +1,550 @@ -/* - * Copyright 2001-2005 Internet2 - * - * Licensed 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. - */ - -/** - * InlineKeyResolver.cpp - * - * Resolves key information directly from recognized KeyInfo structures. - */ - -#include "internal.h" -#include "signature/KeyResolver.h" -#include "util/NDC.h" -#include "util/Threads.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -namespace xmlsignature { - class XMLTOOL_DLLLOCAL InlineKeyResolver : public KeyResolver - { - public: - InlineKeyResolver(const DOMElement* e); - virtual ~InlineKeyResolver(); - - 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; - - private: - struct XMLTOOL_DLLLOCAL CacheEntry { - CacheEntry() : m_key(NULL) {} - ~CacheEntry() { - delete m_key; - for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); - } - XSECCryptoKey* m_key; - vector m_certs; - }; - - void _resolve(const KeyInfo* keyInfo, CacheEntry& entry) const; - XSECCryptoKey* _resolveKey(const KeyInfo* keyInfo) const; - vector::size_type _resolveCertificates(const KeyInfo* keyInfo, vector& certs) const; - - RWLock* m_lock; - mutable map m_cache; - }; - - KeyResolver* XMLTOOL_DLLLOCAL InlineKeyResolverFactory(const DOMElement* const & e) - { - return new InlineKeyResolver(e); - } -}; - -static const XMLCh cache[] = UNICODE_LITERAL_5(c,a,c,h,e); - -InlineKeyResolver::InlineKeyResolver(const DOMElement* e) : m_lock(NULL) -{ - const XMLCh* flag = e ? e->getAttributeNS(NULL,cache) : NULL; - if (flag && XMLString::equals(flag,XMLConstants::XML_TRUE) || XMLString::equals(flag,XMLConstants::XML_ONE)) - m_lock=RWLock::create(); -} - -InlineKeyResolver::~InlineKeyResolver() -{ - m_cache.clear(); - delete m_lock; -} - -void InlineKeyResolver::_resolve(const KeyInfo* keyInfo, CacheEntry& entry) const -{ - if (_resolveCertificates(keyInfo, entry.m_certs)>0) - entry.m_key = entry.m_certs.front()->clonePublicKey(); - else - entry.m_key = _resolveKey(keyInfo); -} - -XSECCryptoKey* InlineKeyResolver::_resolveKey(const KeyInfo* keyInfo) const -{ -#ifdef _DEBUG - NDC ndc("_resolveKey"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); - - // Check for ds:X509Data - const vector& x509Datas=keyInfo->getX509Datas(); - for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { - try { - const vector x509Certs=const_cast(*j)->getX509Certificates(); - if (!x509Certs.empty()) { - auto_ptr_char x(x509Certs.front()->getValue()); - if (!x.get()) { - log.warn("skipping empty ds:X509Certificate"); - } - else { - log.debug("resolving ds:X509Certificate"); - auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); - x509->loadX509Base64Bin(x.get(), strlen(x.get())); - return x509->clonePublicKey(); - } - } - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - } - - // Check for ds:KeyValue - const vector& keyValues = keyInfo->getKeyValues(); - for (vector::const_iterator i=keyValues.begin(); i!=keyValues.end(); ++i) { - try { - KeyInfoSchemaValidators.validate(*i); // see if it's a "valid" key - RSAKeyValue* rsakv = (*i)->getRSAKeyValue(); - if (rsakv) { - log.debug("resolving ds:RSAKeyValue"); - auto_ptr_char mod(rsakv->getModulus()->getValue()); - auto_ptr_char exp(rsakv->getExponent()->getValue()); - auto_ptr rsa(XSECPlatformUtils::g_cryptoProvider->keyRSA()); - rsa->loadPublicModulusBase64BigNums(mod.get(), strlen(mod.get())); - rsa->loadPublicExponentBase64BigNums(exp.get(), strlen(exp.get())); - return rsa.release(); - } - DSAKeyValue* dsakv = (*i)->getDSAKeyValue(); - if (dsakv) { - log.debug("resolving ds:DSAKeyValue"); - auto_ptr dsa(XSECPlatformUtils::g_cryptoProvider->keyDSA()); - auto_ptr_char y(dsakv->getY()->getValue()); - dsa->loadYBase64BigNums(y.get(), strlen(y.get())); - if (dsakv->getP()) { - auto_ptr_char p(dsakv->getP()->getValue()); - dsa->loadPBase64BigNums(p.get(), strlen(p.get())); - } - if (dsakv->getQ()) { - auto_ptr_char q(dsakv->getQ()->getValue()); - dsa->loadQBase64BigNums(q.get(), strlen(q.get())); - } - if (dsakv->getG()) { - auto_ptr_char g(dsakv->getG()->getValue()); - dsa->loadGBase64BigNums(g.get(), strlen(g.get())); - } - return dsa.release(); - } - } - catch (ValidationException& ex) { - log.warn("skipping invalid ds:KeyValue (%s)", ex.what()); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading key: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading key: %s", e.getMsg()); - } - } - - log.warn("unable to resolve key"); - return NULL; -} - -vector::size_type InlineKeyResolver::_resolveCertificates( - const KeyInfo* keyInfo, vector& certs - ) const -{ -#ifdef _DEBUG - NDC ndc("_resolveCertificates"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); - - // Check for ds:X509Data - const vector& x509Datas=keyInfo->getX509Datas(); - for (vector::const_iterator j=x509Datas.begin(); certs.empty() && j!=x509Datas.end(); ++j) { - const vector x509Certs=const_cast(*j)->getX509Certificates(); - for (vector::const_iterator k=x509Certs.begin(); k!=x509Certs.end(); ++k) { - try { - auto_ptr_char x((*k)->getValue()); - if (!x.get()) { - log.warn("skipping empty ds:X509Certificate"); - } - else { - log.debug("resolving ds:X509Certificate"); - auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); - x509->loadX509Base64Bin(x.get(), strlen(x.get())); - certs.push_back(x509.release()); - } - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - } - } - if (log.isDebugEnabled()) { - log.debug("resolved %d certificate%s", certs.size(), certs.size()==1 ? "" : "s"); - } - return certs.size(); -} - -XSECCryptoKey* InlineKeyResolver::resolveKey(const KeyInfo* keyInfo) const -{ - // Caching? - if (m_lock) { - // Get read lock. - m_lock->rdlock(); - map::iterator i=m_cache.find(keyInfo); - if (i != m_cache.end()) { - // Found in cache, so just return the results. - SharedLock locker(m_lock,false); - return i->second.m_key ? i->second.m_key->clone() : NULL; - } - else { - // Elevate lock. - m_lock->unlock(); - m_lock->wrlock(); - SharedLock locker(m_lock,false); - // Recheck cache. - i=m_cache.find(keyInfo); - if (i == m_cache.end()) { - i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; - _resolve(i->first, i->second); - } - return i->second.m_key ? i->second.m_key->clone() : NULL; - } - } - return _resolveKey(keyInfo); -} - -vector::size_type InlineKeyResolver::resolveCertificates( - const KeyInfo* keyInfo, vector& certs - ) const -{ - // Caching? - if (m_lock) { - // Get read lock. - m_lock->rdlock(); - map::iterator i=m_cache.find(keyInfo); - 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(); - } - else { - // Elevate lock. - m_lock->unlock(); - m_lock->wrlock(); - SharedLock locker(m_lock,false); - // Recheck cache. - i=m_cache.find(keyInfo); - if (i == m_cache.end()) { - 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(); - } - } - return _resolveCertificates(keyInfo, certs); -} - -XSECCryptoKey* InlineKeyResolver::resolveKey(DSIGKeyInfoList* keyInfo) const -{ -#ifdef _DEBUG - NDC ndc("_resolveKey"); -#endif - - // Default resolver handles RSA/DSAKeyValue and X509Certificate elements. - try { - XSECKeyInfoResolverDefault def; - return def.resolveKey(keyInfo); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - return NULL; -} - -vector::size_type InlineKeyResolver::resolveCertificates( - DSIGKeyInfoList* keyInfo, vector& certs - ) const -{ - certs.clear(); - 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)); - } - } - } - return certs.size(); -} +/* + * Copyright 2001-2007 Internet2 + * + * Licensed 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. + */ + +/** + * InlineKeyResolver.cpp + * + * Resolves key information directly from recognized KeyInfo structures. + */ + +#include "internal.h" +#include "signature/CachingKeyResolver.h" +#include "signature/KeyInfo.h" +#include "util/NDC.h" +#include "util/Threads.h" +#include "util/XMLConstants.h" +#include "validation/ValidatorSuite.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace xmlsignature; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +namespace xmlsignature { + class XMLTOOL_DLLLOCAL InlineKeyResolver : public CachingKeyResolver + { + public: + InlineKeyResolver(const DOMElement* e); + virtual ~InlineKeyResolver(); + + XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const; + XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) 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; + + void clearCache() { + if (m_lock) + m_lock->wrlock(); + m_cache.clear(); + if (m_lock) + m_lock->unlock(); + } + + private: + struct XMLTOOL_DLLLOCAL CacheEntry { + CacheEntry() : m_key(NULL), m_crl(NULL) {} + ~CacheEntry() { + delete m_key; + for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); + delete m_crl; + } + XSECCryptoKey* m_key; + vector m_certs; + XSECCryptoX509CRL* m_crl; + }; + + void _resolve(const KeyInfo* keyInfo, CacheEntry& entry) const; + XSECCryptoKey* _resolveKey(const KeyInfo* keyInfo) const; + vector::size_type _resolveCertificates(const KeyInfo* keyInfo, vector& certs) const; + XSECCryptoX509CRL* _resolveCRL(const KeyInfo* keyInfo) const; + + RWLock* m_lock; + mutable map m_cache; + }; + + KeyResolver* XMLTOOL_DLLLOCAL InlineKeyResolverFactory(const DOMElement* const & e) + { + return new InlineKeyResolver(e); + } +}; + +static const XMLCh cache[] = UNICODE_LITERAL_5(c,a,c,h,e); + +InlineKeyResolver::InlineKeyResolver(const DOMElement* e) : m_lock(NULL) +{ + const XMLCh* flag = e ? e->getAttributeNS(NULL,cache) : NULL; + if (flag && XMLString::equals(flag,xmlconstants::XML_TRUE) || XMLString::equals(flag,xmlconstants::XML_ONE)) + m_lock=RWLock::create(); +} + +InlineKeyResolver::~InlineKeyResolver() +{ + clearCache(); + delete m_lock; +} + +void InlineKeyResolver::_resolve(const KeyInfo* keyInfo, CacheEntry& entry) const +{ + if (_resolveCertificates(keyInfo, entry.m_certs)>0) + entry.m_key = entry.m_certs.front()->clonePublicKey(); + else + entry.m_key = _resolveKey(keyInfo); + entry.m_crl = _resolveCRL(keyInfo); +} + +XSECCryptoKey* InlineKeyResolver::_resolveKey(const KeyInfo* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("_resolveKey"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); + + if (!keyInfo) + return NULL; + + // Check for ds:X509Data + const vector& x509Datas=keyInfo->getX509Datas(); + for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { + try { + const vector x509Certs=const_cast(*j)->getX509Certificates(); + if (!x509Certs.empty()) { + auto_ptr_char x(x509Certs.front()->getValue()); + if (!x.get()) { + log.warn("skipping empty ds:X509Certificate"); + } + else { + log.debug("resolving ds:X509Certificate"); + auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); + x509->loadX509Base64Bin(x.get(), strlen(x.get())); + return x509->clonePublicKey(); + } + } + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + } + + // Check for ds:KeyValue + const vector& keyValues = keyInfo->getKeyValues(); + for (vector::const_iterator i=keyValues.begin(); i!=keyValues.end(); ++i) { + try { + SchemaValidators.validate(*i); // see if it's a "valid" key + RSAKeyValue* rsakv = (*i)->getRSAKeyValue(); + if (rsakv) { + log.debug("resolving ds:RSAKeyValue"); + auto_ptr_char mod(rsakv->getModulus()->getValue()); + auto_ptr_char exp(rsakv->getExponent()->getValue()); + auto_ptr rsa(XSECPlatformUtils::g_cryptoProvider->keyRSA()); + rsa->loadPublicModulusBase64BigNums(mod.get(), strlen(mod.get())); + rsa->loadPublicExponentBase64BigNums(exp.get(), strlen(exp.get())); + return rsa.release(); + } + DSAKeyValue* dsakv = (*i)->getDSAKeyValue(); + if (dsakv) { + log.debug("resolving ds:DSAKeyValue"); + auto_ptr dsa(XSECPlatformUtils::g_cryptoProvider->keyDSA()); + auto_ptr_char y(dsakv->getY()->getValue()); + dsa->loadYBase64BigNums(y.get(), strlen(y.get())); + if (dsakv->getP()) { + auto_ptr_char p(dsakv->getP()->getValue()); + dsa->loadPBase64BigNums(p.get(), strlen(p.get())); + } + if (dsakv->getQ()) { + auto_ptr_char q(dsakv->getQ()->getValue()); + dsa->loadQBase64BigNums(q.get(), strlen(q.get())); + } + if (dsakv->getG()) { + auto_ptr_char g(dsakv->getG()->getValue()); + dsa->loadGBase64BigNums(g.get(), strlen(g.get())); + } + return dsa.release(); + } + } + catch (ValidationException& ex) { + log.warn("skipping invalid ds:KeyValue (%s)", ex.what()); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading key: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading key: %s", e.getMsg()); + } + } + + // Check for RetrievalMethod. + const XMLCh* fragID=NULL; + const XMLObject* treeRoot=NULL; + XSECCryptoKey* remote=NULL; + const vector methods=keyInfo->getRetrievalMethods(); + for (vector::const_iterator m=methods.begin(); m!=methods.end(); ++m) { + if (!XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_X509DATA) && + !XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_RSAKEYVALUE) && + !XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_DSAKEYVALUE)) + continue; + fragID = (*m)->getURI(); + if (!fragID || *fragID != chPound || !*(fragID+1)) { + log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); + continue; + } + if (!treeRoot) { + treeRoot = keyInfo; + while (treeRoot->getParent()) + treeRoot = treeRoot->getParent(); + } + keyInfo = dynamic_cast(XMLHelper::getXMLObjectById(*treeRoot, fragID+1)); + if (!keyInfo) { + log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); + continue; + } + remote = _resolveKey(keyInfo); + if (remote) + return remote; + } + + log.warn("unable to resolve key"); + return NULL; +} + +vector::size_type InlineKeyResolver::_resolveCertificates( + const KeyInfo* keyInfo, vector& certs + ) const +{ +#ifdef _DEBUG + NDC ndc("_resolveCertificates"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); + + if (!keyInfo) + return 0; + + // Check for ds:X509Data + const vector& x509Datas=keyInfo->getX509Datas(); + for (vector::const_iterator j=x509Datas.begin(); certs.empty() && j!=x509Datas.end(); ++j) { + const vector x509Certs=const_cast(*j)->getX509Certificates(); + for (vector::const_iterator k=x509Certs.begin(); k!=x509Certs.end(); ++k) { + try { + auto_ptr_char x((*k)->getValue()); + if (!x.get()) { + log.warn("skipping empty ds:X509Certificate"); + } + else { + log.debug("resolving ds:X509Certificate"); + auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); + x509->loadX509Base64Bin(x.get(), strlen(x.get())); + certs.push_back(x509.release()); + } + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + } + } + + if (certs.empty()) { + // Check for RetrievalMethod. + const XMLCh* fragID=NULL; + const XMLObject* treeRoot=NULL; + const vector methods=keyInfo->getRetrievalMethods(); + for (vector::const_iterator m=methods.begin(); certs.empty() && m!=methods.end(); ++m) { + if (!XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_X509DATA)) + continue; + fragID = (*m)->getURI(); + if (!fragID || *fragID != chPound || !*(fragID+1)) { + log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); + continue; + } + if (!treeRoot) { + treeRoot = keyInfo; + while (treeRoot->getParent()) + treeRoot = treeRoot->getParent(); + } + keyInfo = dynamic_cast(XMLHelper::getXMLObjectById(*treeRoot, fragID+1)); + if (!keyInfo) { + log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); + continue; + } + _resolveCertificates(keyInfo, certs); + } + } + + if (log.isDebugEnabled()) { + log.debug("resolved %d certificate%s", certs.size(), certs.size()==1 ? "" : "s"); + } + return certs.size(); +} + +XSECCryptoX509CRL* InlineKeyResolver::_resolveCRL(const KeyInfo* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("_resolveCRL"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); + + if (!keyInfo) + return NULL; + + // Check for ds:X509Data + const vector& x509Datas=keyInfo->getX509Datas(); + for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { + const vector x509CRLs=const_cast(*j)->getX509CRLs(); + for (vector::const_iterator k=x509CRLs.begin(); k!=x509CRLs.end(); ++k) { + try { + auto_ptr_char x((*k)->getValue()); + if (!x.get()) { + log.warn("skipping empty ds:X509CRL"); + } + else { + log.debug("resolving ds:X509CRL"); + auto_ptr crl(XMLToolingConfig::getConfig().X509CRL()); + crl->loadX509CRLBase64Bin(x.get(), strlen(x.get())); + return crl.release(); + } + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + } + } + + // Check for RetrievalMethod. + const XMLCh* fragID=NULL; + const XMLObject* treeRoot=NULL; + XSECCryptoX509CRL* remote=NULL; + const vector methods=keyInfo->getRetrievalMethods(); + for (vector::const_iterator m=methods.begin(); m!=methods.end(); ++m) { + if (!XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_X509DATA)) + continue; + fragID = (*m)->getURI(); + if (!fragID || *fragID != chPound || !*(fragID+1)) { + log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); + continue; + } + if (!treeRoot) { + treeRoot = keyInfo; + while (treeRoot->getParent()) + treeRoot = treeRoot->getParent(); + } + keyInfo = dynamic_cast(XMLHelper::getXMLObjectById(*treeRoot, fragID+1)); + if (!keyInfo) { + log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); + continue; + } + remote = _resolveCRL(keyInfo); + if (remote) + return remote; + } + + return NULL; +} + +XSECCryptoKey* InlineKeyResolver::resolveKey(const KeyInfo* keyInfo) const +{ + // Caching? + if (m_lock) { + // Get read lock. + m_lock->rdlock(); + map::iterator i=m_cache.find(keyInfo); + if (i != m_cache.end()) { + // Found in cache, so just return the results. + SharedLock locker(m_lock,false); + return i->second.m_key ? i->second.m_key->clone() : NULL; + } + else { + // Elevate lock. + m_lock->unlock(); + m_lock->wrlock(); + SharedLock locker(m_lock,false); + // Recheck cache. + i=m_cache.find(keyInfo); + if (i == m_cache.end()) { + i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; + _resolve(i->first, i->second); + } + return i->second.m_key ? i->second.m_key->clone() : NULL; + } + } + return _resolveKey(keyInfo); +} + +XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo) const +{ + // Caching? + if (m_lock) { + // Get read lock. + m_lock->rdlock(); + map::iterator i=m_cache.find(keyInfo); + if (i != m_cache.end()) { + // Found in cache, so just return the results. + SharedLock locker(m_lock,false); + return i->second.m_crl ? i->second.m_crl->clone() : NULL; + } + else { + // Elevate lock. + m_lock->unlock(); + m_lock->wrlock(); + SharedLock locker(m_lock,false); + // Recheck cache. + i=m_cache.find(keyInfo); + if (i == m_cache.end()) { + i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; + _resolve(i->first, i->second); + } + return i->second.m_crl ? i->second.m_crl->clone() : NULL; + } + } + return _resolveCRL(keyInfo); +} + +vector::size_type InlineKeyResolver::resolveCertificates( + const KeyInfo* keyInfo, ResolvedCertificates& certs + ) const +{ + // Caching? + if (m_lock) { + // Get read lock. + m_lock->rdlock(); + map::iterator i=m_cache.find(keyInfo); + if (i != m_cache.end()) { + // Found in cache, so just return the results. + SharedLock locker(m_lock,false); + accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); + } + else { + // Elevate lock. + m_lock->unlock(); + m_lock->wrlock(); + SharedLock locker(m_lock,false); + // Recheck cache. + i=m_cache.find(keyInfo); + if (i == m_cache.end()) { + i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; + _resolve(i->first, i->second); + } + accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); + } + } + accessOwned(certs) = true; + return _resolveCertificates(keyInfo, accessCertificates(certs)); +} + +XSECCryptoKey* InlineKeyResolver::resolveKey(DSIGKeyInfoList* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("resolveKey"); +#endif + + if (!keyInfo) + return NULL; + + // Default resolver handles RSA/DSAKeyValue and X509Certificate elements. + try { + XSECKeyInfoResolverDefault def; + return def.resolveKey(keyInfo); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + return NULL; +} + +vector::size_type InlineKeyResolver::resolveCertificates( + DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs + ) const +{ + accessCertificates(certs).clear(); + accessOwned(certs) = false; + + if (!keyInfo) + return 0; + + DSIGKeyInfoList::size_type sz = keyInfo->getSize(); + for (DSIGKeyInfoList::size_type i=0; accessCertificates(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)); + } + } + } + return accessCertificates(certs).size(); +} + +XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(DSIGKeyInfoList* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("resolveCRL"); +#endif + + if (!keyInfo) + return NULL; + + DSIGKeyInfoList::size_type sz = keyInfo->getSize(); + for (DSIGKeyInfoList::size_type i=0; iitem(i)->getKeyInfoType()==DSIGKeyInfo::KEYINFO_X509) { + auto_ptr_char buf(static_cast(keyInfo->item(i))->getX509CRL()); + if (buf.get()) { + try { + auto_ptr crlobj(XMLToolingConfig::getConfig().X509CRL()); + crlobj->loadX509CRLBase64Bin(buf.get(), strlen(buf.get())); + return crlobj.release(); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", temp.get()); + } + catch(XSECCryptoException& e) { + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", e.getMsg()); + } + } + } + } + return NULL; +}