X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fsecurity%2Fimpl%2FInlineKeyResolver.cpp;h=a9771fb34b52623675e42b1e0eecc1a4f347c3c9;hb=b3887773bcb867e8fb7cad376279f2a9ee39dda2;hp=30e9dee547f42807102172b9ad70eaf76f3316fe;hpb=cb5804ce4c3915b1e37517438bf10e3019befc75;p=shibboleth%2Fxmltooling.git diff --git a/xmltooling/security/impl/InlineKeyResolver.cpp b/xmltooling/security/impl/InlineKeyResolver.cpp index 30e9dee..a9771fb 100644 --- a/xmltooling/security/impl/InlineKeyResolver.cpp +++ b/xmltooling/security/impl/InlineKeyResolver.cpp @@ -21,15 +21,17 @@ */ #include "internal.h" +#include "logging.h" #include "security/BasicX509Credential.h" +#include "security/KeyInfoCredentialContext.h" #include "security/KeyInfoResolver.h" #include "signature/KeyInfo.h" +#include "signature/Signature.h" #include "util/NDC.h" #include "util/Threads.h" #include "util/XMLConstants.h" #include "validation/ValidatorSuite.h" -#include #include #include #include @@ -40,86 +42,114 @@ #include using namespace xmlsignature; +using namespace xmltooling::logging; using namespace xmltooling; -using namespace log4cpp; using namespace std; namespace xmltooling { class XMLTOOL_DLLLOCAL InlineCredential : public BasicX509Credential { - const KeyInfo* m_inlineKeyInfo; - DSIGKeyInfoList* m_nativeKeyInfo; public: - InlineCredential(const KeyInfo* keyInfo=NULL) - : BasicX509Credential(keyInfo!=NULL), m_inlineKeyInfo(keyInfo), m_nativeKeyInfo(NULL) { + InlineCredential(const KeyInfo* keyInfo=NULL) : BasicX509Credential(keyInfo!=NULL), m_credctx(new KeyInfoCredentialContext(keyInfo)) { } - InlineCredential(DSIGKeyInfoList* keyInfo) - : BasicX509Credential(false), m_inlineKeyInfo(NULL), m_nativeKeyInfo(keyInfo) { + InlineCredential(DSIGKeyInfoList* keyInfo) : BasicX509Credential(false), m_credctx(new KeyInfoCredentialContext(keyInfo)) { + } + InlineCredential(KeyInfoCredentialContext* context) : BasicX509Credential(context->getKeyInfo()!=NULL), m_credctx(NULL) { + } + virtual ~InlineCredential() { + delete m_credctx; } - virtual ~InlineCredential() {} XSECCryptoKey* getPrivateKey() const { return NULL; } - const KeyInfo* getKeyInfo(bool compact=false) const { - return m_inlineKeyInfo; - } - - vector::size_type getKeyNames(vector& results) const { - if (m_inlineKeyInfo) { - const vector& knames=m_inlineKeyInfo->getKeyNames(); - for (vector::const_iterator kn_i=knames.begin(); kn_i!=knames.end(); ++kn_i) { - const XMLCh* n=(*kn_i)->getName(); - if (n && *n) { - char* kn=toUTF8(n); - results.push_back(kn); - delete[] kn; + KeyInfo* getKeyInfo(bool compact=false) const { + KeyInfo* ret = m_credctx->getKeyInfo() ? m_credctx->getKeyInfo()->cloneKeyInfo() : NULL; + if (ret) { + ret->setId(NULL); + ret->getRetrievalMethods().clear(); + if (compact) { + ret->getKeyValues().clear(); + ret->getSPKIDatas().clear(); + ret->getPGPDatas().clear(); + ret->getUnknownXMLObjects().clear(); + VectorOf(X509Data) x509Datas=ret->getX509Datas(); + for (VectorOf(X509Data)::size_type pos = 0; pos < x509Datas.size();) { + x509Datas[pos]->getX509Certificates().clear(); + x509Datas[pos]->getX509CRLs().clear(); + x509Datas[pos]->getUnknownXMLObjects().clear(); + if (x509Datas[pos]->hasChildren()) + ++pos; + else + x509Datas.erase(x509Datas.begin() + pos); } } } - else if (m_nativeKeyInfo) { - for (size_t s=0; sgetSize(); s++) { - const XMLCh* n=m_nativeKeyInfo->item(s)->getKeyName(); - if (n && *n) { - char* kn=toUTF8(n); - results.push_back(kn); - delete[] kn; - } - } + if (!ret->hasChildren()) { + delete ret; + ret = NULL; } - return results.size(); + return ret; } - - void setKey(XSECCryptoKey* key) { - m_key = key; + + const CredentialContext* getCredentialContext() const { + return m_credctx; } - void addCert(XSECCryptoX509* cert) { - m_xseccerts.push_back(cert); + void setCredentialContext(KeyInfoCredentialContext* context) { + m_credctx = context; } - void setCRL(XSECCryptoX509CRL* crl) { - m_crl = crl; - } + void resolve(const KeyInfo* keyInfo, int types=0); + void resolve(DSIGKeyInfoList* keyInfo, int types=0); + + private: + bool resolveCerts(const KeyInfo* keyInfo); + bool resolveKey(const KeyInfo* keyInfo); + bool resolveCRL(const KeyInfo* keyInfo); + + KeyInfoCredentialContext* m_credctx; }; class XMLTOOL_DLLLOCAL InlineKeyResolver : public KeyInfoResolver { public: - InlineKeyResolver() : m_log(Category::getInstance(XMLTOOLING_LOGCAT".KeyInfoResolver")) {} + InlineKeyResolver() {} virtual ~InlineKeyResolver() {} - Credential* resolve(const KeyInfo* keyInfo, int types=0) const; - Credential* resolve(DSIGKeyInfoList* keyInfo, int types=0) const; - - private: - bool resolveCerts(const KeyInfo* keyInfo, InlineCredential* credential) const; - bool resolveKey(const KeyInfo* keyInfo, InlineCredential* credential) const; - bool resolveCRL(const KeyInfo* keyInfo, InlineCredential* credential) const; - - Category& m_log; + Credential* resolve(const KeyInfo* keyInfo, int types=0) const { + if (!keyInfo) + return NULL; + if (types == 0) + types = Credential::RESOLVE_KEYS|X509Credential::RESOLVE_CERTS|X509Credential::RESOLVE_CRLS; + auto_ptr credential(new InlineCredential(keyInfo)); + credential->resolve(keyInfo, types); + return credential.release(); + } + Credential* resolve(DSIGKeyInfoList* keyInfo, int types=0) const { + if (!keyInfo) + return NULL; + if (types == 0) + types = Credential::RESOLVE_KEYS|X509Credential::RESOLVE_CERTS|X509Credential::RESOLVE_CRLS; + auto_ptr credential(new InlineCredential(keyInfo)); + credential->resolve(keyInfo, types); + return credential.release(); + } + Credential* resolve(KeyInfoCredentialContext* context, int types=0) const { + if (!context) + return NULL; + if (types == 0) + types = Credential::RESOLVE_KEYS|X509Credential::RESOLVE_CERTS|X509Credential::RESOLVE_CRLS; + auto_ptr credential(new InlineCredential(context)); + if (context->getKeyInfo()) + credential->resolve(context->getKeyInfo(), types); + else if (context->getNativeKeyInfo()) + credential->resolve(context->getNativeKeyInfo(), types); + credential->setCredentialContext(context); + return credential.release(); + } }; KeyInfoResolver* XMLTOOL_DLLLOCAL InlineKeyInfoResolverFactory(const DOMElement* const & e) @@ -128,39 +158,75 @@ namespace xmltooling { } }; -Credential* InlineKeyResolver::resolve(const KeyInfo* keyInfo, int types) const +void InlineCredential::resolve(const KeyInfo* keyInfo, int types) { #ifdef _DEBUG NDC ndc("resolve"); #endif - if (!keyInfo) - return NULL; - - auto_ptr credential(new InlineCredential(keyInfo)); - if (types == 0) - types = Credential::RESOLVE_KEYS|X509Credential::RESOLVE_CERTS|X509Credential::RESOLVE_CRLS; - if (types & X509Credential::RESOLVE_CERTS) - resolveCerts(keyInfo, credential.get()); + resolveCerts(keyInfo); if (types & Credential::RESOLVE_KEYS) { - // If we have a cert, just use it. - if (types & X509Credential::RESOLVE_CERTS && !credential->getEntityCertificateChain().empty()) - credential->setKey(credential->getEntityCertificateChain().front()->clonePublicKey()); + if (types & X509Credential::RESOLVE_CERTS) { + // If we have a cert, just use it. + if (!m_xseccerts.empty()) + m_key = m_xseccerts.front()->clonePublicKey(); + } // Otherwise try directly for a key and then go for certs if none is found. - else if (!resolveKey(keyInfo, credential.get()) && resolveCerts(keyInfo, credential.get())) - credential->setKey(credential->getEntityCertificateChain().front()->clonePublicKey()); + else if (!resolveKey(keyInfo) && resolveCerts(keyInfo)) { + m_key = m_xseccerts.front()->clonePublicKey(); + } } if (types & X509Credential::RESOLVE_CRLS) - resolveCRL(keyInfo, credential.get()); + resolveCRL(keyInfo); + + const XMLCh* n; + char* kn; + const vector& knames=keyInfo->getKeyNames(); + for (vector::const_iterator kn_i=knames.begin(); kn_i!=knames.end(); ++kn_i) { + n=(*kn_i)->getName(); + if (n && *n) { + kn=toUTF8(n); + m_keyNames.insert(kn); + delete[] kn; + } + } + const vector datas=keyInfo->getX509Datas(); + for (vector::const_iterator x_i=datas.begin(); x_i!=datas.end(); ++x_i) { + const vector snames = const_cast(*x_i)->getX509SubjectNames(); + for (vector::const_iterator sn_i = snames.begin(); sn_i!=snames.end(); ++sn_i) { + n = (*sn_i)->getName(); + if (n && *n) { + kn=toUTF8(n); + m_keyNames.insert(kn); + m_subjectName = kn; + delete[] kn; + } + } - return credential.release(); + const vector inames = const_cast(*x_i)->getX509IssuerSerials(); + if (!inames.empty()) { + const X509IssuerName* iname = inames.front()->getX509IssuerName(); + if (iname) { + kn = toUTF8(iname->getName()); + if (kn) + m_issuerName = kn; + delete[] kn; + } + + const X509SerialNumber* ser = inames.front()->getX509SerialNumber(); + if (ser) + m_serial = XMLString::parseInt(ser->getSerialNumber()); + } + } } -bool InlineKeyResolver::resolveKey(const KeyInfo* keyInfo, InlineCredential* credential) const +bool InlineCredential::resolveKey(const KeyInfo* keyInfo) { + Category& log = Category::getInstance(XMLTOOLING_LOGCAT".KeyInfoResolver."INLINE_KEYINFO_RESOLVER); + // Check for ds:KeyValue const vector& keyValues = keyInfo->getKeyValues(); for (vector::const_iterator i=keyValues.begin(); i!=keyValues.end(); ++i) { @@ -168,18 +234,18 @@ bool InlineKeyResolver::resolveKey(const KeyInfo* keyInfo, InlineCredential* cre SchemaValidators.validate(*i); // see if it's a "valid" key RSAKeyValue* rsakv = (*i)->getRSAKeyValue(); if (rsakv) { - m_log.debug("resolving ds:RSAKeyValue"); + 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())); - credential->setKey(rsa.release()); + m_key = rsa.release(); return true; } DSAKeyValue* dsakv = (*i)->getDSAKeyValue(); if (dsakv) { - m_log.debug("resolving ds:DSAKeyValue"); + 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())); @@ -195,117 +261,64 @@ bool InlineKeyResolver::resolveKey(const KeyInfo* keyInfo, InlineCredential* cre auto_ptr_char g(dsakv->getG()->getValue()); dsa->loadGBase64BigNums(g.get(), strlen(g.get())); } - credential->setKey(dsa.release()); + m_key = dsa.release(); return true; } } catch (ValidationException& ex) { - m_log.warn("skipping invalid ds:KeyValue (%s)", ex.what()); + log.warn("skipping invalid ds:KeyValue (%s)", ex.what()); } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); - m_log.error("caught XML-Security exception loading key: %s", temp.get()); + log.error("caught XML-Security exception loading key: %s", temp.get()); } catch(XSECCryptoException& e) { - m_log.error("caught XML-Security exception loading key: %s", e.getMsg()); + log.error("caught XML-Security exception loading key: %s", e.getMsg()); } } - // Check for RetrievalMethod. - const XMLCh* fragID=NULL; - const XMLObject* treeRoot=NULL; - const vector& methods=keyInfo->getRetrievalMethods(); - for (vector::const_iterator m=methods.begin(); m!=methods.end(); ++m) { - if (!XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_RSAKEYVALUE) && - !XMLString::equals((*m)->getType(),RetrievalMethod::TYPE_DSAKEYVALUE)) - continue; - fragID = (*m)->getURI(); - if (!fragID || *fragID != chPound || !*(fragID+1)) { - m_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) { - m_log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); - continue; - } - if (resolveKey(keyInfo,credential)) - return true; - } return false; } -bool InlineKeyResolver::resolveCerts(const KeyInfo* keyInfo, InlineCredential* credential) const +bool InlineCredential::resolveCerts(const KeyInfo* keyInfo) { + Category& log = Category::getInstance(XMLTOOLING_LOGCAT".KeyInfoResolver."INLINE_KEYINFO_RESOLVER); + // Check for ds:X509Data const vector& x509Datas=keyInfo->getX509Datas(); - for (vector::const_iterator j=x509Datas.begin(); credential->getEntityCertificateChain().empty() && j!=x509Datas.end(); ++j) { + for (vector::const_iterator j=x509Datas.begin(); m_xseccerts.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()) { - m_log.warn("skipping empty ds:X509Certificate"); + log.warn("skipping empty ds:X509Certificate"); } else { - m_log.debug("resolving ds:X509Certificate"); + log.debug("resolving ds:X509Certificate"); auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); x509->loadX509Base64Bin(x.get(), strlen(x.get())); - credential->addCert(x509.release()); + m_xseccerts.push_back(x509.release()); } } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); - m_log.error("caught XML-Security exception loading certificate: %s", temp.get()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); } catch(XSECCryptoException& e) { - m_log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); } } } - - if (credential->getEntityCertificateChain().empty()) { - // Check for RetrievalMethod. - const XMLCh* fragID=NULL; - const XMLObject* treeRoot=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)) { - m_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) { - m_log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); - continue; - } - if (resolveCerts(keyInfo,credential)) - return true; - } - return false; - } - if (m_log.isDebugEnabled()) { - m_log.debug("resolved %d certificate(s)", credential->getEntityCertificateChain().size()); - } - return !credential->getEntityCertificateChain().empty(); + log.debug("resolved %d certificate(s)", m_xseccerts.size()); + return !m_xseccerts.empty(); } -bool InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo, InlineCredential* credential) const +bool InlineCredential::resolveCRL(const KeyInfo* keyInfo) { + Category& log = Category::getInstance(XMLTOOLING_LOGCAT".KeyInfoResolver."INLINE_KEYINFO_RESOLVER); + // Check for ds:X509Data const vector& x509Datas=keyInfo->getX509Datas(); for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { @@ -314,81 +327,47 @@ bool InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo, InlineCredential* cre try { auto_ptr_char x((*k)->getValue()); if (!x.get()) { - m_log.warn("skipping empty ds:X509CRL"); + log.warn("skipping empty ds:X509CRL"); } else { - m_log.debug("resolving ds:X509CRL"); + log.debug("resolving ds:X509CRL"); auto_ptr crl(XMLToolingConfig::getConfig().X509CRL()); crl->loadX509CRLBase64Bin(x.get(), strlen(x.get())); - credential->setCRL(crl.release()); + m_crl = crl.release(); return true; } } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); - m_log.error("caught XML-Security exception loading certificate: %s", temp.get()); + log.error("caught XML-Security exception loading CRL: %s", temp.get()); } catch(XSECCryptoException& e) { - m_log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + log.error("caught XML-Security exception loading CRL: %s", e.getMsg()); } } } - // Check for RetrievalMethod. - const XMLCh* fragID=NULL; - const XMLObject* treeRoot=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)) { - m_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) { - m_log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); - continue; - } - if (resolveCRL(keyInfo,credential)) - return true; - } - return false; } -Credential* InlineKeyResolver::resolve(DSIGKeyInfoList* keyInfo, int types) const +void InlineCredential::resolve(DSIGKeyInfoList* keyInfo, int types) { #ifdef _DEBUG NDC ndc("resolve"); #endif - if (!keyInfo) - return NULL; - - if (types == 0) - types = Credential::RESOLVE_KEYS|X509Credential::RESOLVE_CERTS|X509Credential::RESOLVE_CRLS; - - auto_ptr credential(new InlineCredential(keyInfo)); - if (types & Credential::RESOLVE_KEYS) { // Default resolver handles RSA/DSAKeyValue and X509Certificate elements. try { XSECKeyInfoResolverDefault def; - credential->setKey(def.resolveKey(keyInfo)); + m_key = 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()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver."INLINE_KEYINFO_RESOLVER).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()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver."INLINE_KEYINFO_RESOLVER).error("caught XML-Security exception loading certificate: %s", e.getMsg()); } } @@ -401,7 +380,7 @@ Credential* InlineKeyResolver::resolve(DSIGKeyInfoList* keyInfo, int types) cons int count = x509->getCertificateListSize(); if (count) { for (int j=0; jaddCert(x509->getCertificateCryptoItem(j)); + m_xseccerts.push_back(x509->getCertificateCryptoItem(j)); break; } } @@ -416,20 +395,46 @@ Credential* InlineKeyResolver::resolve(DSIGKeyInfoList* keyInfo, int types) cons try { auto_ptr crlobj(XMLToolingConfig::getConfig().X509CRL()); crlobj->loadX509CRLBase64Bin(buf.get(), strlen(buf.get())); - credential->setCRL(crlobj.release()); + m_crl = crlobj.release(); break; } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", temp.get()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver."INLINE_KEYINFO_RESOLVER).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()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver."INLINE_KEYINFO_RESOLVER).error("caught XML-Security exception loading CRL: %s", e.getMsg()); } } } } } - return credential.release(); + char* kn; + const XMLCh* n; + + for (size_t s=0; sgetSize(); s++) { + DSIGKeyInfo* dki = keyInfo->item(s); + n=dki->getKeyName(); + if (n && *n) { + kn=toUTF8(n); + m_keyNames.insert(kn); + if (dki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) + m_subjectName = kn; + delete[] kn; + } + + if (dki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) { + DSIGKeyInfoX509* kix = static_cast(dki); + n = kix->getX509IssuerName(); + if (n && *n) { + kn=toUTF8(n); + m_issuerName = kn; + delete[] kn; + } + n = kix->getX509IssuerSerialNumber(); + if (n && *n) + m_serial = XMLString::parseInt(n); + } + } }