From d96a01ce4d9648bb3186f74d43610b6f12d49758 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Thu, 12 Apr 2007 03:56:04 +0000 Subject: [PATCH] Add credential context APIs, refactor criteria matching, auto-extract criteria from KeyInfos. --- xmltooling/Makefile.am | 2 + xmltooling/XMLToolingConfig.cpp | 3 +- xmltooling/encryption/impl/Decrypter.cpp | 19 +- xmltooling/security/BasicX509Credential.h | 13 +- xmltooling/security/Credential.h | 38 +++- xmltooling/security/CredentialContext.h | 47 +++++ xmltooling/security/CredentialCriteria.h | 124 +++++++++--- xmltooling/security/KeyInfoCredentialContext.h | 80 ++++++++ xmltooling/security/KeyInfoResolver.h | 17 ++ xmltooling/security/X509Credential.h | 13 +- .../security/impl/AbstractPKIXTrustEngine.cpp | 13 +- xmltooling/security/impl/BasicX509Credential.cpp | 24 +-- xmltooling/security/impl/Credential.cpp | 58 ++++-- .../security/impl/ExplicitKeyTrustEngine.cpp | 8 +- .../security/impl/FilesystemCredentialResolver.cpp | 28 +-- xmltooling/security/impl/InlineKeyResolver.cpp | 223 ++++++++++----------- xmltooling/signature/KeyInfo.h | 7 + xmltooling/signature/Signature.h | 8 + xmltooling/signature/impl/KeyInfoImpl.cpp | 35 ++++ xmltooling/signature/impl/XMLSecSignatureImpl.cpp | 15 ++ xmltooling/util/XMLHelper.cpp | 3 +- xmltooling/xmltooling.vcproj | 8 + 22 files changed, 562 insertions(+), 224 deletions(-) create mode 100644 xmltooling/security/CredentialContext.h create mode 100644 xmltooling/security/KeyInfoCredentialContext.h diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index 2b26988..1959236 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -61,8 +61,10 @@ secinclude_HEADERS = \ security/BasicX509Credential.h \ security/ChainingTrustEngine.h \ security/Credential.h \ + security/CredentialContext.h \ security/CredentialCriteria.h \ security/CredentialResolver.h \ + security/KeyInfoCredentialContext.h \ security/KeyInfoResolver.h \ security/OpenSSLCredential.h \ security/TrustEngine.h \ diff --git a/xmltooling/XMLToolingConfig.cpp b/xmltooling/XMLToolingConfig.cpp index 86c8396..6066437 100644 --- a/xmltooling/XMLToolingConfig.cpp +++ b/xmltooling/XMLToolingConfig.cpp @@ -253,6 +253,7 @@ bool XMLToolingInternalConfig::init() registerKeyInfoResolvers(); registerCredentialResolvers(); registerTrustEngines(); + registerXMLAlgorithms(); #endif registerSOAPTransports(); initSOAPTransports(); @@ -301,7 +302,7 @@ void XMLToolingInternalConfig::term() TrustEngineManager.deregisterFactories(); CredentialResolverManager.deregisterFactories(); KeyInfoResolverManager.deregisterFactories(); - registerXMLAlgorithms(); + m_algorithmMap.clear(); #endif delete m_keyInfoResolver; diff --git a/xmltooling/encryption/impl/Decrypter.cpp b/xmltooling/encryption/impl/Decrypter.cpp index 58a6dd0..c7b1097 100644 --- a/xmltooling/encryption/impl/Decrypter.cpp +++ b/xmltooling/encryption/impl/Decrypter.cpp @@ -86,9 +86,13 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData, // Resolve a decryption key directly. vector creds; + int types = + CredentialCriteria::KEYINFO_EXTRACTION_KEY | + CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | + CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; if (m_criteria) { m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - m_criteria->setKeyInfo(encryptedData.getKeyInfo()); + m_criteria->setKeyInfo(encryptedData.getKeyInfo(), types); const EncryptionMethod* meth = encryptedData.getEncryptionMethod(); if (meth) m_criteria->setXMLAlgorithm(meth->getAlgorithm()); @@ -97,7 +101,7 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData, else { CredentialCriteria criteria; criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - criteria.setKeyInfo(encryptedData.getKeyInfo()); + criteria.setKeyInfo(encryptedData.getKeyInfo(), types); const EncryptionMethod* meth = encryptedData.getEncryptionMethod(); if (meth) criteria.setXMLAlgorithm(meth->getAlgorithm()); @@ -164,12 +168,15 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML if (!m_cipher) m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedKey.getDOM()->getOwnerDocument()); - // Resolve key decryption key. We can't loop over possible credentials because - // we can't tell a valid decrypt from an invalid one. + // Resolve key decryption keys. + int types = + CredentialCriteria::KEYINFO_EXTRACTION_KEY | + CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | + CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; vector creds; if (m_criteria) { m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - m_criteria->setKeyInfo(encryptedKey.getKeyInfo()); + m_criteria->setKeyInfo(encryptedKey.getKeyInfo(), types); const EncryptionMethod* meth = encryptedKey.getEncryptionMethod(); if (meth) m_criteria->setXMLAlgorithm(meth->getAlgorithm()); @@ -178,7 +185,7 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML else { CredentialCriteria criteria; criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - criteria.setKeyInfo(encryptedKey.getKeyInfo()); + criteria.setKeyInfo(encryptedKey.getKeyInfo(), types); const EncryptionMethod* meth = encryptedKey.getEncryptionMethod(); if (meth) criteria.setXMLAlgorithm(meth->getAlgorithm()); diff --git a/xmltooling/security/BasicX509Credential.h b/xmltooling/security/BasicX509Credential.h index 617f174..6435655 100644 --- a/xmltooling/security/BasicX509Credential.h +++ b/xmltooling/security/BasicX509Credential.h @@ -56,6 +56,9 @@ namespace xmltooling { /** The private/secret key/keypair. */ XSECCryptoKey* m_key; + /** Key names (derived from credential, KeyInfo, or both). */ + std::set m_keyNames; + /** The X.509 certificate chain. */ std::vector m_xseccerts; @@ -159,18 +162,14 @@ namespace xmltooling { return NULL; } - std::vector::size_type getKeyNames(std::vector& results) const; + const std::set& getKeyNames() const { + return m_keyNames; + } const xmlsignature::KeyInfo* getKeyInfo(bool compact=false) const { return compact ? m_compactKeyInfo : (m_keyInfo ? m_keyInfo : m_compactKeyInfo); } - /** - * Gets an immutable collection of certificates in the entity's trust chain. The entity certificate is contained - * within this list. No specific ordering of the certificates is guaranteed. - * - * @return a certificate chain - */ const std::vector& getEntityCertificateChain() const { return m_xseccerts; } diff --git a/xmltooling/security/Credential.h b/xmltooling/security/Credential.h index c333b67..3b3362c 100644 --- a/xmltooling/security/Credential.h +++ b/xmltooling/security/Credential.h @@ -26,12 +26,18 @@ #include #include +#include +#include + namespace xmlsignature { class XMLTOOL_API KeyInfo; }; namespace xmltooling { + class XMLTOOL_API CredentialCriteria; + class XMLTOOL_API CredentialContext; + /** * Wraps keys and related functionality. * @@ -48,7 +54,8 @@ namespace xmltooling { virtual ~Credential() {} enum ResolveTypes { - RESOLVE_KEYS = 1 + RESOLVE_KEYS = 1, + RESOLVE_NAMES = 2 }; /** @@ -80,13 +87,14 @@ namespace xmltooling { virtual XSECCryptoKey* getPublicKey() const=0; /** - * Returns names representing the Credential, generally when the Credential itself merely - * points to a Credential rather than containing one. + * Returns names representing the Credential. + * + *

Names should be unique in the context of the comparisons against CredentialCriteria + * that deployments expect to see. * - * @param results array to populate with names - * @return the number of names returned + * @return a sorted set of names */ - virtual std::vector::size_type getKeyNames(std::vector& results) const=0; + virtual const std::set& getKeyNames() const=0; /** * Returns a ds:KeyInfo object representing the Credential for use in @@ -98,12 +106,22 @@ namespace xmltooling { virtual const xmlsignature::KeyInfo* getKeyInfo(bool compact=false) const=0; /** - * Compares the public key inside the Credential to a second public key. + * Get the credential context information, which provides additional information + * specific to the context in which the credential was resolved. + * + * @return resolution context of the credential + */ + virtual const CredentialContext* getCredentalContext() const { + return NULL; + } + + /** + * Determines whether the supplied CredentialCriteria matches this Credential. * - * @param key the public key to compare - * @return true iff the keys are equal + * @param criteria the CredentialCriteria to evaluate + * @return true iff this Credential is consistent with the criteria */ - virtual bool isEqual(XSECCryptoKey& key) const; + virtual bool matches(const CredentialCriteria& criteria) const; }; }; diff --git a/xmltooling/security/CredentialContext.h b/xmltooling/security/CredentialContext.h new file mode 100644 index 0000000..4add335 --- /dev/null +++ b/xmltooling/security/CredentialContext.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +/** + * @file xmltooling/security/CredentialContext.h + * + * Marker interface for implementations which hold information specific to a + * particular context within which a CredentialResolver resolves a Credential. + */ + +#if !defined(__xmltooling_credctx_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_credctx_h__ + +#include + +namespace xmltooling { + + /** + * Marker interface for implementations which hold information specific to a + * particular context within which a CredentialResolver resolves a Credential. + */ + class XMLTOOL_API CredentialContext + { + MAKE_NONCOPYABLE(CredentialContext); + protected: + CredentialContext() {} + + public: + virtual ~CredentialContext() {} + + }; +}; + +#endif /* __xmltooling_credctx_h__ */ diff --git a/xmltooling/security/CredentialCriteria.h b/xmltooling/security/CredentialCriteria.h index 80509fd..d304597 100644 --- a/xmltooling/security/CredentialCriteria.h +++ b/xmltooling/security/CredentialCriteria.h @@ -24,10 +24,12 @@ #define __xmltooling_credcrit_h__ #include +#include +#include #include #include -#include +#include #include #include @@ -40,8 +42,12 @@ namespace xmltooling { { MAKE_NONCOPYABLE(CredentialCriteria); public: - CredentialCriteria() : m_keyUsage(UNSPECIFIED_CREDENTIAL), m_keySize(0), m_keyInfo(NULL), m_nativeKeyInfo(NULL) {} - virtual ~CredentialCriteria() {} + CredentialCriteria() : m_keyUsage(UNSPECIFIED_CREDENTIAL), m_keySize(0), m_key(NULL), + m_keyInfo(NULL), m_nativeKeyInfo(NULL), m_credential(NULL) { + } + virtual ~CredentialCriteria() { + delete m_credential; + } enum UsageType { UNSPECIFIED_CREDENTIAL, @@ -145,25 +151,50 @@ namespace xmltooling { } /** - * Get the key name criteria. + * Gets key name criteria. * - * @return the key name + * @return an immutable set of key names */ - const char* getKeyName() const { - return m_keyName.c_str(); + const std::set& getKeyNames() const { + return m_keyNames; } - + /** - * Set the key name criteria. + * Gets key name criteria. * - * @param keyName key name to set + * @return a mutable set of key names */ - void setKeyName(const char* keyName) { - m_keyName.erase(); - if (keyName) - m_keyName = keyName; + std::set& getKeyNames() { + return m_keyNames; } - + + /** + * Returns the public key criteria. + * + * @return a public key + */ + virtual XSECCryptoKey* getPublicKey() const { + return m_key; + } + + /** + * Sets the public key criteria. + * + *

The lifetime of the key MUST extend + * for the lifetime of this object. + * + * @param key a public key + */ + void setPublicKey(XSECCryptoKey* key) { + m_key = key; + } + + enum keyinfo_extraction_t { + KEYINFO_EXTRACTION_KEY = 1, + KEYINFO_EXTRACTION_KEYNAMES = 2, + KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES = 4 + }; + /** * Gets the KeyInfo criteria. * @@ -176,10 +207,29 @@ namespace xmltooling { /** * Sets the KeyInfo criteria. * - * @param keyInfo the KeyInfo criteria + * @param keyInfo the KeyInfo criteria + * @param extraction bitmask of criteria to auto-extract from KeyInfo */ - void setKeyInfo(const xmlsignature::KeyInfo* keyInfo) { + virtual void setKeyInfo(const xmlsignature::KeyInfo* keyInfo, int extraction=0) { + delete m_credential; + m_credential = NULL; m_keyInfo = keyInfo; + if (!keyInfo || !extraction) + return; + + int types = (extraction & KEYINFO_EXTRACTION_KEY) ? Credential::RESOLVE_KEYS : 0; + types |= (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0; + m_credential = XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(keyInfo,types); + + if (extraction & KEYINFO_EXTRACTION_KEY) + setPublicKey(m_credential->getPublicKey()); + if (extraction & KEYINFO_EXTRACTION_KEYNAMES) + m_keyNames.insert(m_credential->getKeyNames().begin(), m_credential->getKeyNames().end()); + if (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) { + const X509Credential* xcred = dynamic_cast(m_credential); + if (xcred && !xcred->getEntityCertificateChain().empty()) + X509Credential::extractNames(xcred->getEntityCertificateChain().front(), m_keyNames); + } } /** @@ -194,28 +244,56 @@ namespace xmltooling { /** * Sets the KeyInfo criteria. * - * @param keyInfo the KeyInfo criteria + * @param keyInfo the KeyInfo criteria + * @param extraction bitmask of criteria to auto-extract from KeyInfo */ - void setNativeKeyInfo(DSIGKeyInfoList* keyInfo) { + virtual void setNativeKeyInfo(DSIGKeyInfoList* keyInfo, int extraction=0) { + delete m_credential; + m_credential = NULL; m_nativeKeyInfo = keyInfo; + if (!keyInfo || !extraction) + return; + + int types = (extraction & KEYINFO_EXTRACTION_KEY) ? Credential::RESOLVE_KEYS : 0; + types |= (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0; + m_credential = XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(keyInfo,types); + + if (extraction & KEYINFO_EXTRACTION_KEY) + setPublicKey(m_credential->getPublicKey()); + if (extraction & KEYINFO_EXTRACTION_KEYNAMES) + m_keyNames.insert(m_credential->getKeyNames().begin(), m_credential->getKeyNames().end()); + if (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) { + const X509Credential* xcred = dynamic_cast(m_credential); + if (xcred && !xcred->getEntityCertificateChain().empty()) + X509Credential::extractNames(xcred->getEntityCertificateChain().front(), m_keyNames); + } } - void setSignature(const xmlsignature::Signature& sig) { + /** + * Sets the KeyInfo criteria from an XML Signature. + * + * @param sig the Signature containing KeyInfo criteria + * @param extraction bitmask of criteria to auto-extract from KeyInfo + */ + void setSignature(const xmlsignature::Signature& sig, int extraction=0) { setXMLAlgorithm(sig.getSignatureAlgorithm()); xmlsignature::KeyInfo* k = sig.getKeyInfo(); if (k) - return setKeyInfo(k); + return setKeyInfo(k,extraction); DSIGSignature* dsig = sig.getXMLSignature(); if (dsig) - setNativeKeyInfo(dsig->getKeyInfoList()); + setNativeKeyInfo(dsig->getKeyInfoList(),extraction); } private: UsageType m_keyUsage; unsigned int m_keySize; - std::string m_peerName,m_keyAlgorithm,m_keyName; + std::string m_peerName,m_keyAlgorithm; + std::set m_keyNames; + XSECCryptoKey* m_key; const xmlsignature::KeyInfo* m_keyInfo; DSIGKeyInfoList* m_nativeKeyInfo; + Credential* m_credential; }; }; diff --git a/xmltooling/security/KeyInfoCredentialContext.h b/xmltooling/security/KeyInfoCredentialContext.h new file mode 100644 index 0000000..31bcc0e --- /dev/null +++ b/xmltooling/security/KeyInfoCredentialContext.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +/** + * @file xmltooling/security/KeyInfoCredentialContext.h + * + * Context for credentials resolved out of a KeyInfo. + */ + +#if !defined(__xmltooling_keyinfocredctx_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_keyinfocredctx_h__ + +#include +#include +#include + +namespace xmlsignature { + class XMLTOOL_API KeyInfo; +} + +namespace xmltooling { + + /** + * Context for credentials resolved out of a KeyInfo. + */ + class XMLTOOL_API KeyInfoCredentialContext : public CredentialContext + { + public: + /** + * Constructor + */ + KeyInfoCredentialContext(const xmlsignature::KeyInfo* keyInfo=NULL) : m_keyInfo(keyInfo), m_nativeKeyInfo(NULL) { + } + + /** + * Constructor + */ + KeyInfoCredentialContext(DSIGKeyInfoList* keyInfo) : m_keyInfo(NULL), m_nativeKeyInfo(keyInfo) { + } + + virtual ~KeyInfoCredentialContext() {} + + /** + * Gets the KeyInfo context. + * + * @return the KeyInfo context + */ + const xmlsignature::KeyInfo* getKeyInfo() const { + return m_keyInfo; + } + + /** + * Gets the native KeyInfo context. + * + * @return the native KeyInfo context + */ + DSIGKeyInfoList* getNativeKeyInfo() const { + return m_nativeKeyInfo; + } + + private: + const xmlsignature::KeyInfo* m_keyInfo; + DSIGKeyInfoList* m_nativeKeyInfo; + }; +}; + +#endif /* __xmltooling_keyinfocredctx_h__ */ diff --git a/xmltooling/security/KeyInfoResolver.h b/xmltooling/security/KeyInfoResolver.h index 61c5bf2..e1af10d 100644 --- a/xmltooling/security/KeyInfoResolver.h +++ b/xmltooling/security/KeyInfoResolver.h @@ -34,11 +34,16 @@ namespace xmltooling { class XMLTOOL_API Credential; class XMLTOOL_API CredentialCriteria; + class XMLTOOL_API KeyInfoCredentialContext; /** * Resolves credentials from KeyInfo information. * *

Credential-specific bitmasks can be provided to control what to resolve. + * + *

Implementations should only establish KeyNames on the basis of explicit names + * within the KeyInfo object, never by extracting names out of physical credentials + * found within it. */ class XMLTOOL_API KeyInfoResolver { MAKE_NONCOPYABLE(KeyInfoResolver); @@ -68,6 +73,18 @@ namespace xmltooling { virtual Credential* resolve(DSIGKeyInfoList* keyInfo, int types=0) const=0; /** + * Returns a credential based on the KeyInfo information in the supplied + * context. The caller must release the credential when done with it. + * + *

The context object will be owned by the Credential and freed with it. + * + * @param context context containing the key information + * @param types types of credentials to resolve, or 0 for any/all + * @return the resolved credential, or NULL + */ + virtual Credential* resolve(KeyInfoCredentialContext* context, int types=0) const=0; + + /** * Returns a credential based on the supplied KeyInfo information. * The caller must release the credential when done with it. * diff --git a/xmltooling/security/X509Credential.h b/xmltooling/security/X509Credential.h index 764d82f..b751398 100644 --- a/xmltooling/security/X509Credential.h +++ b/xmltooling/security/X509Credential.h @@ -26,7 +26,6 @@ #include #include -#include #include namespace xmltooling { @@ -43,8 +42,8 @@ namespace xmltooling { virtual ~X509Credential() {} enum ResolveTypes { - RESOLVE_CERTS = 2, - RESOLVE_CRLS = 4 + RESOLVE_CERTS = 4, + RESOLVE_CRLS = 8 }; /** @@ -61,6 +60,14 @@ namespace xmltooling { * @return CRL associated with the credential */ virtual XSECCryptoX509CRL* getCRL() const=0; + + /** + * Extracts Subject CN and DNS/URI subjectAltNames from a certificate. + * + * @param x509 certificate to extract + * @param names a set to insert names into + */ + static void extractNames(XSECCryptoX509* x509, std::set& names); }; }; diff --git a/xmltooling/security/impl/AbstractPKIXTrustEngine.cpp b/xmltooling/security/impl/AbstractPKIXTrustEngine.cpp index de9a0bb..7be35fb 100644 --- a/xmltooling/security/impl/AbstractPKIXTrustEngine.cpp +++ b/xmltooling/security/impl/AbstractPKIXTrustEngine.cpp @@ -142,13 +142,15 @@ bool AbstractPKIXTrustEngine::checkEntityNames( { Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); + // We resolve to a set of trusted credentials. vector creds; credResolver.resolve(creds,&criteria); // Build a list of acceptable names. - vector keynames(1,criteria.getPeerName()); + set trustednames; + trustednames.insert(criteria.getPeerName()); for (vector::const_iterator cred = creds.begin(); cred!=creds.end(); ++cred) - (*cred)->getKeyNames(keynames); + trustednames.insert((*cred)->getKeyNames().begin(), (*cred)->getKeyNames().end()); char buf[256]; X509_NAME* subject=X509_get_subject_name(certEE); @@ -177,7 +179,7 @@ bool AbstractPKIXTrustEngine::checkEntityNames( } // Check each keyname. - for (vector::const_iterator n=keynames.begin(); n!=keynames.end(); n++) { + for (set::const_iterator n=trustednames.begin(); n!=trustednames.end(); n++) { #ifdef HAVE_STRCASECMP if (!strcasecmp(n->c_str(),subjectstr.c_str()) || !strcasecmp(n->c_str(),subjectstr2.c_str())) { #else @@ -201,8 +203,7 @@ bool AbstractPKIXTrustEngine::checkEntityNames( if (check->type==GEN_DNS || check->type==GEN_URI) { const char* altptr = (char*)ASN1_STRING_data(check->d.ia5); const int altlen = ASN1_STRING_length(check->d.ia5); - - for (vector::const_iterator n=keynames.begin(); n!=keynames.end(); n++) { + for (set::const_iterator n=trustednames.begin(); n!=trustednames.end(); n++) { #ifdef HAVE_STRCASECMP if ((check->type==GEN_DNS && !strncasecmp(altptr,n->c_str(),altlen)) #else @@ -222,7 +223,7 @@ bool AbstractPKIXTrustEngine::checkEntityNames( log.debug("unable to match subjectAltName, trying TLS CN match"); memset(buf,0,sizeof(buf)); if (X509_NAME_get_text_by_NID(subject,NID_commonName,buf,255)>0) { - for (vector::const_iterator n=keynames.begin(); n!=keynames.end(); n++) { + for (set::const_iterator n=trustednames.begin(); n!=trustednames.end(); n++) { #ifdef HAVE_STRCASECMP if (!strcasecmp(buf,n->c_str())) { #else diff --git a/xmltooling/security/impl/BasicX509Credential.cpp b/xmltooling/security/impl/BasicX509Credential.cpp index d6f41da..05b7a30 100644 --- a/xmltooling/security/impl/BasicX509Credential.cpp +++ b/xmltooling/security/impl/BasicX509Credential.cpp @@ -49,12 +49,12 @@ void BasicX509Credential::initKeyInfo() delete m_compactKeyInfo; m_compactKeyInfo = NULL; - vector names; - if (getKeyNames(names)>0) { + const set& names = getKeyNames(); + if (!names.empty()) { m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo(); VectorOf(KeyName) knames = m_compactKeyInfo->getKeyNames(); - for (vector::const_iterator n = names.begin(); n!=names.end(); ++n) { - xmltooling::auto_ptr_XMLCh wide(n->c_str()); + for (set::const_iterator n = names.begin(); n!=names.end(); ++n) { + auto_ptr_XMLCh wide(n->c_str()); KeyName* kname = KeyNameBuilder::buildKeyName(); kname->setName(wide.get()); knames.push_back(kname); @@ -74,21 +74,21 @@ void BasicX509Credential::initKeyInfo() } } -vector::size_type BasicX509Credential::getKeyNames(vector& results) const +void X509Credential::extractNames(XSECCryptoX509* x509, set& names) { - if (m_xseccerts.empty() || m_xseccerts.front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) - return 0; + if (!x509 || x509->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) + return; - X509* cert = static_cast(m_xseccerts.front())->getOpenSSLX509(); + X509* cert = static_cast(x509)->getOpenSSLX509(); if (!cert) - return 0; + return; X509_NAME* subject=X509_get_subject_name(cert); if (subject) { char buf[256]; memset(buf,0,sizeof(buf)); if (X509_NAME_get_text_by_NID(subject,NID_commonName,buf,255)>0) - results.push_back(buf); + names.insert(buf); STACK_OF(GENERAL_NAME)* altnames=(STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); if (altnames) { @@ -102,13 +102,11 @@ vector::size_type BasicX509Credential::getKeyNames(vector& resul if (altlen>0) { alt.erase(); alt.append(altptr,altlen); - results.push_back(alt); + names.insert(alt); } } } } GENERAL_NAMES_free(altnames); } - - return results.size(); } diff --git a/xmltooling/security/impl/Credential.cpp b/xmltooling/security/impl/Credential.cpp index 2656f8d..024e8bd 100644 --- a/xmltooling/security/impl/Credential.cpp +++ b/xmltooling/security/impl/Credential.cpp @@ -22,6 +22,8 @@ #include "internal.h" #include "security/Credential.h" +#include "security/CredentialCriteria.h" +#include "security/KeyInfoResolver.h" #include #include @@ -30,33 +32,65 @@ #include using namespace xmltooling; +using namespace std; -bool Credential::isEqual(XSECCryptoKey& key) const +bool Credential::matches(const CredentialCriteria& criteria) const { - XSECCryptoKey* key2 = getPublicKey(); - if (!key2) { - log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Credential").warn("no public key in credential for comparison"); + // Algorithm check, if specified and we have one. + const char* alg = criteria.getKeyAlgorithm(); + if (alg && *alg) { + const char* alg2 = getAlgorithm(); + if (alg2 && *alg2) + if (strcmp(alg,alg2)) + return false; + } + + // KeySize check, if specified and we have one. + if (criteria.getKeySize()>0 && getKeySize()>0 && criteria.getKeySize() != getKeySize()) return false; + + // See if we can test key names. + const set& critnames = criteria.getKeyNames(); + const set& crednames = getKeyNames(); + if (!critnames.empty() && !crednames.empty()) { + bool found = false; + for (set::const_iterator n = critnames.begin(); n!=critnames.end(); ++n) { + if (crednames.count(*n)>0) { + found = true; + break; + } + } + if (!found) + return false; } - if (key.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL || + // See if we have to match a specific key. + XSECCryptoKey* key1 = criteria.getPublicKey(); + if (!key1) + return true; // no key to compare against, so we're done + + XSECCryptoKey* key2 = getPublicKey(); + if (!key2) + return false; // no key here, so we can't possibly match the criteria + + if (key1->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL || key2->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { - log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Credential").warn("non-OpenSSL credentials are not supported."); + log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Credential").warn("comparison of non-OpenSSL credentials are not supported"); return false; } - if (key.getKeyType()==XSECCryptoKey::KEY_RSA_PUBLIC || key.getKeyType()==XSECCryptoKey::KEY_RSA_PAIR) { - if (key2->getKeyType()!=XSECCryptoKey::KEY_RSA_PUBLIC && key2->getKeyType()==XSECCryptoKey::KEY_RSA_PAIR) + if (key1->getKeyType()==XSECCryptoKey::KEY_RSA_PUBLIC || key1->getKeyType()==XSECCryptoKey::KEY_RSA_PAIR) { + if (key2->getKeyType()!=XSECCryptoKey::KEY_RSA_PUBLIC && key2->getKeyType()!=XSECCryptoKey::KEY_RSA_PAIR) return false; - RSA* rsa1 = static_cast(&key)->getOpenSSLRSA(); + RSA* rsa1 = static_cast(key1)->getOpenSSLRSA(); RSA* rsa2 = static_cast(key2)->getOpenSSLRSA(); return (BN_cmp(rsa1->n,rsa2->n) == 0 && BN_cmp(rsa1->e,rsa2->e) == 0); } - if (key.getKeyType()==XSECCryptoKey::KEY_DSA_PUBLIC || key.getKeyType()==XSECCryptoKey::KEY_DSA_PAIR) { - if (key2->getKeyType()!=XSECCryptoKey::KEY_DSA_PUBLIC && key2->getKeyType()==XSECCryptoKey::KEY_DSA_PAIR) + if (key1->getKeyType()==XSECCryptoKey::KEY_DSA_PUBLIC || key1->getKeyType()==XSECCryptoKey::KEY_DSA_PAIR) { + if (key2->getKeyType()!=XSECCryptoKey::KEY_DSA_PUBLIC && key2->getKeyType()!=XSECCryptoKey::KEY_DSA_PAIR) return false; - DSA* dsa1 = static_cast(&key)->getOpenSSLDSA(); + DSA* dsa1 = static_cast(key1)->getOpenSSLDSA(); DSA* dsa2 = static_cast(key2)->getOpenSSLDSA(); return (BN_cmp(dsa1->pub_key,dsa2->pub_key) == 0); } diff --git a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp index e89ccac..61c5290 100644 --- a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp +++ b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp @@ -94,13 +94,13 @@ bool ExplicitKeyTrustEngine::validate( vector credentials; if (criteria) { criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL); - criteria->setSignature(sig); + criteria->setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY); credResolver.resolve(credentials,criteria); } else { CredentialCriteria cc; cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL); - cc.setSignature(sig); + cc.setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY); credResolver.resolve(credentials,&cc); } if (credentials.empty()) { @@ -144,14 +144,14 @@ bool ExplicitKeyTrustEngine::validate( vector credentials; if (criteria) { criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL); - criteria->setKeyInfo(keyInfo); + criteria->setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY); criteria->setXMLAlgorithm(sigAlgorithm); credResolver.resolve(credentials,criteria); } else { CredentialCriteria cc; cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL); - cc.setKeyInfo(keyInfo); + cc.setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY); cc.setXMLAlgorithm(sigAlgorithm); credResolver.resolve(credentials,&cc); } diff --git a/xmltooling/security/impl/FilesystemCredentialResolver.cpp b/xmltooling/security/impl/FilesystemCredentialResolver.cpp index a790bd7..b1247d4 100644 --- a/xmltooling/security/impl/FilesystemCredentialResolver.cpp +++ b/xmltooling/security/impl/FilesystemCredentialResolver.cpp @@ -70,6 +70,8 @@ namespace xmltooling { public: FilesystemCredential(FilesystemCredentialResolver* resolver, XSECCryptoKey* key, const std::vector& xseccerts) : BasicX509Credential(key, xseccerts), m_resolver(resolver) { + if (!m_xseccerts.empty()) + extractNames(m_xseccerts.front(), m_keyNames); initKeyInfo(); } virtual ~FilesystemCredential() { @@ -98,13 +100,13 @@ namespace xmltooling { void unlock() {} const Credential* resolve(const CredentialCriteria* criteria=NULL) const { - return matches(criteria) ? m_credential : NULL; + return (criteria ? (m_credential->matches(*criteria) ? m_credential : NULL) : m_credential); } virtual vector::size_type resolve( vector& results, const CredentialCriteria* criteria=NULL ) const { - if (matches(criteria)) { + if (!criteria || m_credential->matches(*criteria)) { results.push_back(m_credential); return 1; } @@ -115,28 +117,6 @@ namespace xmltooling { private: XSECCryptoKey* loadKey(); - bool matches(const CredentialCriteria* criteria) const { - bool match = true; - if (criteria) { - const char* alg = criteria->getKeyAlgorithm(); - if (alg && *alg) { - const char* alg2 = m_credential->getAlgorithm(); - if (alg2 && *alg2) - match = XMLString::equals(alg,alg2); - } - if (match && criteria->getKeySize()>0 && m_credential->getKeySize()>0) - match = (criteria->getKeySize() == m_credential->getKeySize()); - if (match && m_credential->getPublicKey()) { - // See if we have to match a specific key. - auto_ptr cred( - XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(*criteria,Credential::RESOLVE_KEYS) - ); - if (cred.get()) - match = cred->isEqual(*(m_credential->getPublicKey())); - } - } - return match; - } enum format_t { PEM=SSL_FILETYPE_PEM, DER=SSL_FILETYPE_ASN1, _PKCS12, UNKNOWN }; diff --git a/xmltooling/security/impl/InlineKeyResolver.cpp b/xmltooling/security/impl/InlineKeyResolver.cpp index 30e9dee..122aff3 100644 --- a/xmltooling/security/impl/InlineKeyResolver.cpp +++ b/xmltooling/security/impl/InlineKeyResolver.cpp @@ -22,8 +22,10 @@ #include "internal.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" @@ -48,78 +50,81 @@ 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; + return m_credctx->getKeyInfo(); } - 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; - } - } - } - 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; - } - } - } - return results.size(); + const CredentialContext* getCredentialContext() const { + return m_credctx; } - void setKey(XSECCryptoKey* key) { - m_key = key; + void setCredentialContext(KeyInfoCredentialContext* context) { + m_credctx = context; } - void addCert(XSECCryptoX509* cert) { - m_xseccerts.push_back(cert); - } + void resolve(const KeyInfo* keyInfo, int types=0); + void resolve(DSIGKeyInfoList* keyInfo, int types=0); - void setCRL(XSECCryptoX509CRL* crl) { - m_crl = crl; - } + 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 +133,37 @@ 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); - return credential.release(); + keyInfo->extractNames(m_keyNames); } -bool InlineKeyResolver::resolveKey(const KeyInfo* keyInfo, InlineCredential* credential) const +bool InlineCredential::resolveKey(const KeyInfo* keyInfo) { + Category& log = Category::getInstance(XMLTOOLING_LOGCAT".KeyInfoResolver"); + // Check for ds:KeyValue const vector& keyValues = keyInfo->getKeyValues(); for (vector::const_iterator i=keyValues.begin(); i!=keyValues.end(); ++i) { @@ -168,18 +171,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,19 +198,19 @@ 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()); } } @@ -221,7 +224,7 @@ bool InlineKeyResolver::resolveKey(const KeyInfo* keyInfo, InlineCredential* cre continue; fragID = (*m)->getURI(); if (!fragID || *fragID != chPound || !*(fragID+1)) { - m_log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); + log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); continue; } if (!treeRoot) { @@ -231,45 +234,47 @@ bool InlineKeyResolver::resolveKey(const KeyInfo* keyInfo, InlineCredential* cre } 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"); + log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); continue; } - if (resolveKey(keyInfo,credential)) + if (resolveKey(keyInfo)) 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"); + // 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()) { + if (m_xseccerts.empty()) { // Check for RetrievalMethod. const XMLCh* fragID=NULL; const XMLObject* treeRoot=NULL; @@ -279,7 +284,7 @@ bool InlineKeyResolver::resolveCerts(const KeyInfo* keyInfo, InlineCredential* c continue; fragID = (*m)->getURI(); if (!fragID || *fragID != chPound || !*(fragID+1)) { - m_log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); + log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); continue; } if (!treeRoot) { @@ -289,23 +294,23 @@ bool InlineKeyResolver::resolveCerts(const KeyInfo* keyInfo, InlineCredential* c } 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"); + log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); continue; } - if (resolveCerts(keyInfo,credential)) + if (resolveCerts(keyInfo)) 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"); + // Check for ds:X509Data const vector& x509Datas=keyInfo->getX509Datas(); for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { @@ -314,22 +319,22 @@ 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 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()); } } } @@ -343,7 +348,7 @@ bool InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo, InlineCredential* cre continue; fragID = (*m)->getURI(); if (!fragID || *fragID != chPound || !*(fragID+1)) { - m_log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); + log.warn("skipping ds:RetrievalMethod with an empty or non-local reference"); continue; } if (!treeRoot) { @@ -353,35 +358,27 @@ bool InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo, InlineCredential* cre } 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"); + log.warn("skipping ds:RetrievalMethod, local reference did not resolve to a ds:KeyInfo"); continue; } - if (resolveCRL(keyInfo,credential)) + if (resolveCRL(keyInfo)) 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()); @@ -401,7 +398,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,7 +413,7 @@ 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) { @@ -431,5 +428,5 @@ Credential* InlineKeyResolver::resolve(DSIGKeyInfoList* keyInfo, int types) cons } } - return credential.release(); + Signature::extractNames(keyInfo, m_keyNames); } diff --git a/xmltooling/signature/KeyInfo.h b/xmltooling/signature/KeyInfo.h index d9382a8..a0d16f5 100644 --- a/xmltooling/signature/KeyInfo.h +++ b/xmltooling/signature/KeyInfo.h @@ -160,6 +160,13 @@ namespace xmlsignature { DECL_TYPED_CHILDREN(SPKIData); /** KeyInfoType local name */ static const XMLCh TYPE_NAME[]; + + /** + * Populates a set of key names using the information found in this KeyInfo object. + * + * @param names a set of names to populate + */ + virtual void extractNames(std::set& names) const=0; END_XMLOBJECT; DECL_XMLSIGOBJECTBUILDER(PGPData); diff --git a/xmltooling/signature/Signature.h b/xmltooling/signature/Signature.h index a4d74e5..aa8db50 100644 --- a/xmltooling/signature/Signature.h +++ b/xmltooling/signature/Signature.h @@ -193,6 +193,14 @@ namespace xmlsignature { unsigned int in_len ); + /** + * Populates a set of key names using the information found in a native KeyInfo object. + * + * @param keyInfo a native KeyInfo object + * @param names a set of names to populate + */ + static void extractNames(DSIGKeyInfoList* keyInfo, std::set& names); + protected: Signature() {} }; diff --git a/xmltooling/signature/impl/KeyInfoImpl.cpp b/xmltooling/signature/impl/KeyInfoImpl.cpp index 1f59137..9a2152e 100644 --- a/xmltooling/signature/impl/KeyInfoImpl.cpp +++ b/xmltooling/signature/impl/KeyInfoImpl.cpp @@ -705,6 +705,41 @@ namespace xmlsignature { IMPL_TYPED_CHILDREN(PGPData,m_children.end()); IMPL_XMLOBJECT_CHILDREN(UnknownXMLObject,m_children.end()); + void extractNames(set& names) const { + const XMLCh* n; + char* kn; + const vector& knames=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); + names.insert(kn); + delete[] kn; + } + } + const vector datas=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); + names.insert(kn); + delete[] kn; + } + } + const vector skis = const_cast(*x_i)->getX509SKIs(); + for (vector::const_iterator sk_i = skis.begin(); sk_i!=skis.end(); ++sk_i) { + n = (*sk_i)->getValue(); + if (n && *n) { + kn=toUTF8(n); + names.insert(kn); + delete[] kn; + } + } + } + } + protected: void marshallAttributes(DOMElement* domElement) const { MARSHALL_ID_ATTRIB(Id,ID,NULL); diff --git a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp index 57ab8bc..388ceb0 100644 --- a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp +++ b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp @@ -533,3 +533,18 @@ bool Signature::verifyRawSignature( throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + e.getMsg()); } } + +void Signature::extractNames(DSIGKeyInfoList* keyInfo, set& names) +{ + char* kn; + const XMLCh* n; + + for (size_t s=0; sgetSize(); s++) { + n=keyInfo->item(s)->getKeyName(); + if (n && *n) { + kn=toUTF8(n); + names.insert(kn); + delete[] kn; + } + } +} diff --git a/xmltooling/util/XMLHelper.cpp b/xmltooling/util/XMLHelper.cpp index d0fa6c2..cf4f5ed 100644 --- a/xmltooling/util/XMLHelper.cpp +++ b/xmltooling/util/XMLHelper.cpp @@ -29,8 +29,7 @@ #include using namespace xmltooling; -using std::ostream; -using std::list; +using namespace std; static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull }; diff --git a/xmltooling/xmltooling.vcproj b/xmltooling/xmltooling.vcproj index 9334729..a81e37c 100644 --- a/xmltooling/xmltooling.vcproj +++ b/xmltooling/xmltooling.vcproj @@ -685,6 +685,10 @@ > + + @@ -693,6 +697,10 @@ > + + -- 2.1.4