From a21d1f24fc3fb85928b014b69c0e6916dcb66955 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Fri, 11 Aug 2006 02:53:18 +0000 Subject: [PATCH] Extend KeyResolver to include certificate resolution, add inline resolver. --- xmltooling/Makefile.am | 2 + xmltooling/XMLToolingConfig.cpp | 3 +- xmltooling/signature/KeyResolver.h | 49 ++- .../impl/FilesystemCredentialResolver.cpp | 31 +- xmltooling/signature/impl/InlineKeyResolver.cpp | 330 +++++++++++++++++++++ xmltooling/signature/impl/KeyResolver.cpp | 54 ++++ xmltooling/xmltooling.vcproj | 8 + xmltoolingtest/InlineKeyResolverTest.h | 59 ++++ xmltoolingtest/Makefile.am | 1 + xmltoolingtest/data/InlineKeyResolver.xml | 2 + xmltoolingtest/xmltoolingtest.vcproj | 26 ++ 11 files changed, 552 insertions(+), 13 deletions(-) create mode 100644 xmltooling/signature/impl/InlineKeyResolver.cpp create mode 100644 xmltooling/signature/impl/KeyResolver.cpp create mode 100644 xmltoolingtest/InlineKeyResolverTest.h create mode 100644 xmltoolingtest/data/InlineKeyResolver.xml diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index cdcd8b6..bd5c2d4 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -85,6 +85,8 @@ xmlsec_sources = \ encryption/impl/Encrypter.cpp \ signature/impl/CredentialResolver.cpp \ signature/impl/FilesystemCredentialResolver.cpp \ + signature/impl/InlineKeyResolver.cpp \ + signature/impl/KeyResolver.cpp \ signature/impl/SignatureValidator.cpp \ signature/impl/XMLSecSignatureImpl.cpp else diff --git a/xmltooling/XMLToolingConfig.cpp b/xmltooling/XMLToolingConfig.cpp index a5a4e3b..ae102b9 100644 --- a/xmltooling/XMLToolingConfig.cpp +++ b/xmltooling/XMLToolingConfig.cpp @@ -26,7 +26,7 @@ #include "encryption/Encryption.h" #include "impl/UnknownElement.h" #include "signature/CredentialResolver.h" -#include "signature/KeyInfo.h" +#include "signature/KeyResolver.h" #include "signature/Signature.h" #include "util/NDC.h" #include "util/XMLConstants.h" @@ -177,6 +177,7 @@ bool XMLToolingInternalConfig::init() #ifndef XMLTOOLING_NO_XMLSEC XMLObjectBuilder::registerBuilder(QName(XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME),new SignatureBuilder()); REGISTER_EXCEPTION_FACTORY(SignatureException,xmlsignature); + registerKeyResolvers(); registerCredentialResolvers(); #endif } diff --git a/xmltooling/signature/KeyResolver.h b/xmltooling/signature/KeyResolver.h index 2c88250..8a4774b 100644 --- a/xmltooling/signature/KeyResolver.h +++ b/xmltooling/signature/KeyResolver.h @@ -17,7 +17,8 @@ /** * @file KeyResolver.h * - * Resolves keys based on KeyInfo information or other external factors. + * Resolves public keys and certificates based on KeyInfo information or + * external factors. */ #if !defined(__xmltooling_keyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) @@ -27,11 +28,17 @@ #include #include +#include + +#include namespace xmlsignature { /** - * An API for resolving keys. + * An API for resolving keys. The default/simple implementation + * allows a hard-wired key to be supplied. This is mostly + * useful for testing, or to adapt another mechanism for supplying + * keys to this interface. */ class XMLTOOL_API KeyResolver { MAKE_NONCOPYABLE(KeyResolver); @@ -55,7 +62,7 @@ namespace xmlsignature { * @param keyInfo the key information * @return the resolved key */ - virtual XSECCryptoKey* resolveKey(KeyInfo* keyInfo) { + virtual XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const { return m_key ? m_key->clone() : NULL; } @@ -66,14 +73,48 @@ namespace xmlsignature { * @param keyInfo the key information * @return the resolved key */ - virtual XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo=NULL) { + virtual XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const { return m_key ? m_key->clone() : NULL; } + + /** + * 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 + * @return number of certificates returned + */ + virtual std::vector::size_type resolveCertificates( + const KeyInfo* keyInfo, std::vector& certs + ) const; + /** + * 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 + * @return number of certificates returned + */ + virtual std::vector::size_type resolveCertificates( + DSIGKeyInfoList* keyInfo, std::vector& certs + ) const; + protected: XSECCryptoKey* m_key; }; + /** + * Registers KeyResolver classes into the runtime. + */ + void XMLTOOL_API registerKeyResolvers(); + + /** KeyResolver based on hard-wired key */ + #define FILESYSTEM_KEY_RESOLVER "org.opensaml.xmlooling.FilesystemKeyResolver" + + /** KeyResolver based on extracting information directly out of a KeyInfo */ + #define INLINE_KEY_RESOLVER "org.opensaml.xmlooling.InlineKeyResolver" }; #endif /* __xmltooling_keyres_h__ */ diff --git a/xmltooling/signature/impl/FilesystemCredentialResolver.cpp b/xmltooling/signature/impl/FilesystemCredentialResolver.cpp index 86e70b1..c4362d5 100644 --- a/xmltooling/signature/impl/FilesystemCredentialResolver.cpp +++ b/xmltooling/signature/impl/FilesystemCredentialResolver.cpp @@ -21,13 +21,11 @@ */ #include "internal.h" +#include "signature/KeyResolver.h" #include "signature/OpenSSLCredentialResolver.h" #include "util/NDC.h" #include "util/XMLHelper.h" -using namespace xmlsignature; -using namespace xmltooling; - #include #include #include @@ -58,20 +56,31 @@ static int passwd_callback(char* buf, int len, int verify, void* passwd) } namespace xmlsignature { - class FilesystemCredentialResolver : public CredentialResolver + class FilesystemCredentialResolver : public OpenSSLCredentialResolver, public KeyResolver { public: FilesystemCredentialResolver(const DOMElement* e); - ~FilesystemCredentialResolver(); + virtual ~FilesystemCredentialResolver(); Lockable* lock() { return this; } void unlock() {} XSECCryptoKey* loadKey(); - void attach(SSL_CTX* ctx) const; - XSECCryptoKey* getKey() const { return m_key->clone(); } + XSECCryptoKey* getKey() const { return m_key ? m_key->clone() : NULL; } const vector& getCertificates() const { return m_xseccerts; } + void attach(SSL_CTX* ctx) const; + + 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(DSIGKeyInfoList* keyInfo, vector& certs) const { + certs.assign(m_xseccerts.begin(), m_xseccerts.end()); + return certs.size(); + } private: enum format_t { PEM=SSL_FILETYPE_PEM, DER=SSL_FILETYPE_ASN1, _PKCS12, UNKNOWN }; @@ -91,6 +100,11 @@ namespace xmlsignature { { return new FilesystemCredentialResolver(e); } + + KeyResolver* XMLTOOL_DLLLOCAL FilesystemKeyResolverFactory(const DOMElement* const & e) + { + return new FilesystemCredentialResolver(e); + } }; static const XMLCh CAPath[] = UNICODE_LITERAL_6(C,A,P,a,t,h); @@ -100,7 +114,7 @@ static const XMLCh Key[] = UNICODE_LITERAL_3(K,e,y); static const XMLCh password[] = UNICODE_LITERAL_8(p,a,s,s,w,o,r,d); static const XMLCh Path[] = UNICODE_LITERAL_4(P,a,t,h); -FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) +FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) : m_key(NULL) { #ifdef _DEBUG NDC ndc("FilesystemCredentialResolver"); @@ -399,6 +413,7 @@ XSECCryptoKey* FilesystemCredentialResolver::loadKey() FilesystemCredentialResolver::~FilesystemCredentialResolver() { + delete m_key; for_each(m_certs.begin(),m_certs.end(),X509_free); for_each(m_xseccerts.begin(),m_xseccerts.end(),xmltooling::cleanup()); } diff --git a/xmltooling/signature/impl/InlineKeyResolver.cpp b/xmltooling/signature/impl/InlineKeyResolver.cpp new file mode 100644 index 0000000..c34db20 --- /dev/null +++ b/xmltooling/signature/impl/InlineKeyResolver.cpp @@ -0,0 +1,330 @@ +/* + * 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(); +} diff --git a/xmltooling/signature/impl/KeyResolver.cpp b/xmltooling/signature/impl/KeyResolver.cpp new file mode 100644 index 0000000..65925e0 --- /dev/null +++ b/xmltooling/signature/impl/KeyResolver.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * KeyResolver.cpp + * + * Registration of factories for built-in resolvers + */ + +#include "internal.h" +#include "signature/KeyResolver.h" + +using namespace xmlsignature; +using namespace xmltooling; +using namespace std; + +namespace xmlsignature { + XMLTOOL_DLLLOCAL PluginManager::Factory FilesystemKeyResolverFactory; + XMLTOOL_DLLLOCAL PluginManager::Factory InlineKeyResolverFactory; +}; + +void XMLTOOL_API xmlsignature::registerKeyResolvers() +{ + XMLToolingConfig& conf=XMLToolingConfig::getConfig(); + conf.KeyResolverManager.registerFactory(FILESYSTEM_KEY_RESOLVER, FilesystemKeyResolverFactory); + conf.KeyResolverManager.registerFactory(INLINE_KEY_RESOLVER, InlineKeyResolverFactory); +} + +vector::size_type KeyResolver::resolveCertificates( + const KeyInfo* keyInfo, vector& certs + ) const +{ + return 0; +} + +vector::size_type KeyResolver::resolveCertificates( + DSIGKeyInfoList* keyInfo, vector& certs + ) const +{ + return 0; +} diff --git a/xmltooling/xmltooling.vcproj b/xmltooling/xmltooling.vcproj index 51492df..9f6a1ff 100644 --- a/xmltooling/xmltooling.vcproj +++ b/xmltooling/xmltooling.vcproj @@ -300,6 +300,10 @@ > + + @@ -308,6 +312,10 @@ > + + diff --git a/xmltoolingtest/InlineKeyResolverTest.h b/xmltoolingtest/InlineKeyResolverTest.h new file mode 100644 index 0000000..1c9e39e --- /dev/null +++ b/xmltoolingtest/InlineKeyResolverTest.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include + +using namespace xmlsignature; + +class InlineKeyResolverTest : public CxxTest::TestSuite { + KeyResolver* m_resolver; +public: + InlineKeyResolverTest() : m_resolver(NULL) {} + + void setUp() { + string config = data_path + "InlineKeyResolver.xml"; + ifstream in(config.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + XercesJanitor janitor(doc); + m_resolver=XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER,doc->getDocumentElement()); + } + + void tearDown() { + delete m_resolver; + m_resolver=NULL; + } + + void testResolver() { + string path=data_path + "KeyInfo1.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); + TS_ASSERT(doc!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); + TS_ASSERT(kiObject.get()!=NULL); + + auto_ptr key(m_resolver->resolveKey(kiObject.get())); + TSM_ASSERT("Unable to resolve public key.", key.get()!=NULL); + TSM_ASSERT_EQUALS("Unexpected key type.", key->getKeyType(), XSECCryptoKey::KEY_RSA_PUBLIC); + + vector certs; + TSM_ASSERT_EQUALS("Wrong certificate count.", m_resolver->resolveCertificates(kiObject.get(), certs), 1); + } +}; diff --git a/xmltoolingtest/Makefile.am b/xmltoolingtest/Makefile.am index 4525b08..9430f41 100644 --- a/xmltoolingtest/Makefile.am +++ b/xmltoolingtest/Makefile.am @@ -11,6 +11,7 @@ if BUILD_XMLSEC xmlsec_sources = \ EncryptionTest.h \ FilesystemCredentialResolverTest.h \ + InlineKeyResolverTest.h \ SignatureTest.h else xmlsec_sources = diff --git a/xmltoolingtest/data/InlineKeyResolver.xml b/xmltoolingtest/data/InlineKeyResolver.xml new file mode 100644 index 0000000..a7dbb84 --- /dev/null +++ b/xmltoolingtest/data/InlineKeyResolver.xml @@ -0,0 +1,2 @@ + + diff --git a/xmltoolingtest/xmltoolingtest.vcproj b/xmltoolingtest/xmltoolingtest.vcproj index 3bf88f1..8d365db 100644 --- a/xmltoolingtest/xmltoolingtest.vcproj +++ b/xmltoolingtest/xmltoolingtest.vcproj @@ -196,6 +196,10 @@ > + + @@ -310,6 +314,28 @@ + + + + + + + +