io/AbstractXMLObjectMarshaller.h \
io/AbstractXMLObjectUnmarshaller.h
+secinclude_HEADERS = \
+ security/TrustEngine.h \
+ security/X509TrustEngine.h
+
siginclude_HEADERS = \
signature/CachingKeyResolver.h \
signature/ContentReference.h \
xmlsec_sources = \
encryption/impl/Decrypter.cpp \
encryption/impl/Encrypter.cpp \
+ security/impl/TrustEngine.cpp \
+ security/impl/ExplicitKeyTrustEngine.cpp \
signature/impl/CredentialResolver.cpp \
signature/impl/FilesystemCredentialResolver.cpp \
signature/impl/InlineKeyResolver.cpp \
#include "XMLToolingConfig.h"
#include "encryption/Encryption.h"
#include "impl/UnknownElement.h"
+#include "security/TrustEngine.h"
#include "signature/CredentialResolver.h"
-#include "signature/KeyResolver.h"
-#include "signature/Signature.h"
#include "util/NDC.h"
#include "util/XMLConstants.h"
#include "validation/Validator.h"
REGISTER_EXCEPTION_FACTORY(SignatureException,xmlsignature);
registerKeyResolvers();
registerCredentialResolvers();
+ registerTrustEngines();
#endif
}
catch (const xercesc::XMLException&) {
XMLToolingException::deregisterFactories();
#ifndef XMLTOOLING_NO_XMLSEC
+ TrustEngineManager.deregisterFactories();
CredentialResolverManager.deregisterFactories();
KeyResolverManager.deregisterFactories();
#endif
#endif\r
\r
namespace xmltooling {\r
+ \r
+ class XMLTOOL_API TrustEngine;\r
\r
/**\r
* Singleton object that manages library startup/shutdown.configuration.\r
* Manages factories for CredentialResolver plugins.\r
*/\r
xmltooling::PluginManager<xmlsignature::CredentialResolver,const DOMElement*> CredentialResolverManager;\r
+\r
+ /**\r
+ * Manages factories for TrustEngine plugins.\r
+ */\r
+ xmltooling::PluginManager<TrustEngine,const DOMElement*> TrustEngineManager;\r
#endif\r
\r
protected:\r
--- /dev/null
+/*\r
+ * Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file security/TrustEngine.h\r
+ * \r
+ * Evaluates the trustworthiness and validity of XML Signatures against\r
+ * implementation-specific requirements.\r
+ */\r
+\r
+#if !defined(__xmltooling_trust_h__) && !defined(XMLTOOLING_NO_XMLSEC)\r
+#define __xmltooling_trust_h__\r
+\r
+#include <xmltooling/signature/KeyResolver.h>\r
+#include <xmltooling/signature/Signature.h>\r
+\r
+namespace xmltooling {\r
+\r
+ /**\r
+ * Evaluates the trustworthiness and validity of XML Signatures against\r
+ * implementation-specific requirements.\r
+ */\r
+ class XMLTOOL_API TrustEngine {\r
+ MAKE_NONCOPYABLE(TrustEngine);\r
+ protected:\r
+ /**\r
+ * Constructor.\r
+ * \r
+ * If a DOM is supplied, the following XML content is supported:\r
+ * \r
+ * <ul>\r
+ * <li><KeyResolver> elements with a type attribute\r
+ * </ul>\r
+ * \r
+ * XML namespaces are ignored in the processing of this content.\r
+ * \r
+ * @param e DOM to supply configuration for provider\r
+ */\r
+ TrustEngine(const DOMElement* e=NULL);\r
+ \r
+ /** Default KeyResolver instance. */\r
+ xmlsignature::KeyResolver* m_keyResolver;\r
+ \r
+ public:\r
+ virtual ~TrustEngine();\r
+ \r
+ /**\r
+ * Callback interface to supply KeyInfo objects to a TrustEngine.\r
+ * Applications can adapt TrustEngines to their environment by supplying\r
+ * implementations of this interface, or create specialized TrustEngine APIs\r
+ * by combining a KeyInfoIterator with a delegated TrustEngine. \r
+ */\r
+ class XMLTOOL_API KeyInfoIterator {\r
+ MAKE_NONCOPYABLE(KeyInfoIterator);\r
+ protected:\r
+ KeyInfoIterator() {}\r
+ public:\r
+ virtual ~KeyInfoIterator() {}\r
+ \r
+ /**\r
+ * Indicates whether additional KeyInfo objects are available.\r
+ * \r
+ * @return true iff another KeyInfo object can be fetched\r
+ */\r
+ virtual bool hasNext() const=0;\r
+ \r
+ /**\r
+ * Returns the next KeyInfo object available.\r
+ * \r
+ * @return the next KeyInfo object, or NULL if none are left\r
+ */\r
+ virtual const xmlsignature::KeyInfo* next()=0;\r
+ };\r
+ \r
+ /**\r
+ * Determines whether a signature is correct and valid with respect to the\r
+ * KeyInfo data supplied. It is the responsibility of the application to\r
+ * ensure that the KeyInfo information supplied is in fact associated with\r
+ * the peer who created the signature. \r
+ * \r
+ * A custom KeyResolver can be supplied from outside the TrustEngine.\r
+ * Alternatively, one may be specified to the plugin constructor.\r
+ * A non-caching, inline resolver will be used as a fallback.\r
+ * \r
+ * @param sig reference to a signature object to validate\r
+ * @param keyInfoSource supplies KeyInfo objects to the TrustEngine\r
+ * @param keyResolver optional externally supplied KeyResolver, or NULL\r
+ */\r
+ virtual bool validate(\r
+ xmlsignature::Signature& sig,\r
+ KeyInfoIterator& keyInfoSource,\r
+ const xmlsignature::KeyResolver* keyResolver=NULL\r
+ )=0;\r
+ };\r
+\r
+ /**\r
+ * Registers TrustEngine classes into the runtime.\r
+ */\r
+ void XMLTOOL_API registerTrustEngines();\r
+\r
+ /** TrustEngine based on explicit knowledge of peer key information. */\r
+ #define EXPLICIT_KEY_TRUSTENGINE "org.opensaml.xmlooling.security.ExplicitKeyTrustEngine"\r
+};\r
+\r
+#endif /* __xmltooling_trust_h__ */\r
--- /dev/null
+/*\r
+ * Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file security/X509TrustEngine.h\r
+ * \r
+ * Extended TrustEngine interface that adds validation of X.509 credentials.\r
+ */\r
+\r
+#if !defined(__xmltooling_x509trust_h__) && !defined(XMLTOOLING_NO_XMLSEC)\r
+#define __xmltooling_x509trust_h__\r
+\r
+#include <xmltooling/security/TrustEngine.h>\r
+\r
+namespace xmltooling {\r
+\r
+ /**\r
+ * Extended TrustEngine interface that adds validation of X.509 credentials.\r
+ */\r
+ class XMLTOOL_API X509TrustEngine : public TrustEngine {\r
+ protected:\r
+ /**\r
+ * Constructor.\r
+ * \r
+ * If a DOM is supplied, the following XML content is supported:\r
+ * \r
+ * <ul>\r
+ * <li><KeyResolver> elements with a type attribute\r
+ * </ul>\r
+ * \r
+ * XML namespaces are ignored in the processing of this content.\r
+ * \r
+ * @param e DOM to supply configuration for provider\r
+ */\r
+ X509TrustEngine(const DOMElement* e=NULL) : TrustEngine(e) {}\r
+ \r
+ public:\r
+ virtual ~X509TrustEngine() {}\r
+ \r
+ /**\r
+ * Determines whether an X.509 credential is valid with respect to the\r
+ * KeyInfo data supplied. It is the responsibility of the application to\r
+ * ensure that the KeyInfo information supplied is in fact associated with\r
+ * the peer who presented the signature. \r
+ * \r
+ * A custom KeyResolver can be supplied from outside the TrustEngine.\r
+ * Alternatively, one may be specified to the plugin constructor.\r
+ * A non-caching, inline resolver will be used as a fallback.\r
+ * \r
+ * @param certEE end-entity certificate to validate\r
+ * @param certChain the complete set of certificates presented for validation (includes certEE)\r
+ * @param keyInfoSource supplies KeyInfo objects to the TrustEngine\r
+ * @param checkName true iff certificate subject/name checking has <b>NOT</b> already occurred\r
+ * @param keyResolver optional externally supplied KeyResolver, or NULL\r
+ */\r
+ virtual bool validate(\r
+ XSECCryptoX509* certEE,\r
+ const std::vector<XSECCryptoX509*>& certChain,\r
+ TrustEngine::KeyInfoIterator& keyInfoSource,\r
+ bool checkName=true,\r
+ const xmlsignature::KeyResolver* keyResolver=NULL\r
+ )=0;\r
+ };\r
+ \r
+};\r
+\r
+#endif /* __xmltooling_x509trust_h__ */\r
--- /dev/null
+/*\r
+ * Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * ExplicitKeyTrustEngine.cpp\r
+ * \r
+ * TrustEngine based on explicit knowledge of peer key information.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "security/X509TrustEngine.h"\r
+#include "signature/SignatureValidator.h"\r
+#include "util/NDC.h"\r
+\r
+#include <log4cpp/Category.hh>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xsec/enc/openssl/OpenSSLCryptoX509.hpp>\r
+\r
+using namespace xmlsignature;\r
+using namespace xmltooling;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+namespace xmltooling {\r
+ class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public X509TrustEngine\r
+ {\r
+ public:\r
+ ExplicitKeyTrustEngine(const DOMElement* e) : X509TrustEngine(e) {}\r
+ virtual ~ExplicitKeyTrustEngine() {}\r
+\r
+ virtual bool validate(\r
+ Signature& sig,\r
+ TrustEngine::KeyInfoIterator& keyInfoSource,\r
+ const KeyResolver* keyResolver=NULL\r
+ );\r
+ virtual bool validate(\r
+ XSECCryptoX509* certEE,\r
+ const vector<XSECCryptoX509*>& certChain,\r
+ TrustEngine::KeyInfoIterator& keyInfoSource,\r
+ bool checkName=true,\r
+ const KeyResolver* keyResolver=NULL\r
+ );\r
+\r
+ private:\r
+ };\r
+\r
+ TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)\r
+ {\r
+ return new ExplicitKeyTrustEngine(e);\r
+ }\r
+};\r
+\r
+bool ExplicitKeyTrustEngine::validate(\r
+ Signature& sig,\r
+ TrustEngine::KeyInfoIterator& keyInfoSource,\r
+ const KeyResolver* keyResolver\r
+ )\r
+{\r
+#ifdef _DEBUG\r
+ NDC ndc("validate");\r
+#endif\r
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");\r
+ \r
+ if (!keyInfoSource.hasNext()) {\r
+ log.warn("unable to validate signature, no key information available for peer");\r
+ return false;\r
+ }\r
+ \r
+ log.debug("attempting to validate signature with the key information for peer");\r
+ SignatureValidator sigValidator;\r
+ while (keyInfoSource.hasNext()) {\r
+ XSECCryptoKey* key = (keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoSource.next());\r
+ if (key) {\r
+ log.debug("attempting to validate signature with public key...");\r
+ try {\r
+ sigValidator.setKey(key); // key now owned by validator\r
+ sigValidator.validate(&sig);\r
+ log.info("signature validated with public key");\r
+ return true;\r
+ }\r
+ catch (ValidationException& e) {\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("public key did not validate signature: %s", e.what());\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ log.debug("key information does not resolve to a public key, skipping it");\r
+ }\r
+ }\r
+\r
+ log.error("no peer key information validated the signature");\r
+ return false;\r
+}\r
+\r
+bool ExplicitKeyTrustEngine::validate(\r
+ XSECCryptoX509* certEE,\r
+ const vector<XSECCryptoX509*>& certChain,\r
+ TrustEngine::KeyInfoIterator& keyInfoSource,\r
+ bool checkName,\r
+ const KeyResolver* keyResolver\r
+ )\r
+{\r
+#ifdef _DEBUG\r
+ NDC ndc("validate");\r
+#endif\r
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");\r
+ \r
+ if (!certEE) {\r
+ log.error("unable to validate, end-entity certificate was null");\r
+ return false;\r
+ }\r
+ else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {\r
+ log.error("only the OpenSSL XSEC provider is supported");\r
+ return false;\r
+ }\r
+ else if (!keyInfoSource.hasNext()) {\r
+ log.warn("unable to validate, no key information available for peer");\r
+ return false;\r
+ }\r
+\r
+ // The new "basic" trust implementation relies solely on certificates living within the\r
+ // role interface to verify the EE certificate.\r
+\r
+ log.debug("attempting to match key information from peer with end-entity certificate");\r
+ vector<XSECCryptoX509*> resolvedCerts;\r
+ while (keyInfoSource.hasNext()) {\r
+ resolvedCerts.clear();\r
+ if (0 == (keyResolver ? keyResolver : m_keyResolver)->resolveCertificates(keyInfoSource.next(),resolvedCerts)) {\r
+ log.debug("key information does not resolve to a certificate, skipping it");\r
+ continue;\r
+ }\r
+\r
+ log.debug("checking if certificates contained within key information match end-entity certificate");\r
+ if (resolvedCerts.front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {\r
+ log.error("only the OpenSSL XSEC provider is supported");\r
+ continue;\r
+ }\r
+ else if (!X509_cmp(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(),static_cast<OpenSSLCryptoX509*>(resolvedCerts.front())->getOpenSSLX509())) {\r
+ log.info("end-entity certificate matches certificate from peer key information");\r
+ return true;\r
+ }\r
+ }\r
+\r
+ log.debug("no certificates within this peer's key information matched the given end-entity certificate");\r
+ return false;\r
+}\r
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * TrustEngine.cpp
+ *
+ * Registration of factories for built-in engines
+ */
+
+#include "internal.h"
+#include "security/TrustEngine.h"
+
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace xmltooling;
+using namespace std;
+
+namespace xmltooling {
+ XMLTOOL_DLLLOCAL PluginManager<TrustEngine,const DOMElement*>::Factory ExplicitKeyTrustEngineFactory;
+};
+
+void XMLTOOL_API xmltooling::registerTrustEngines()
+{
+ XMLToolingConfig& conf=XMLToolingConfig::getConfig();
+ conf.TrustEngineManager.registerFactory(EXPLICIT_KEY_TRUSTENGINE, ExplicitKeyTrustEngineFactory);
+}
+
+static const XMLCh GenericKeyResolver[] = UNICODE_LITERAL_11(K,e,y,R,e,s,o,l,v,e,r);
+static const XMLCh type[] = UNICODE_LITERAL_4(t,y,p,e);
+
+TrustEngine::TrustEngine(const DOMElement* e) : m_keyResolver(NULL)
+{
+ DOMElement* child = e ? XMLHelper::getFirstChildElement(e,GenericKeyResolver) : NULL;
+ if (child) {
+ auto_ptr_char t(child->getAttributeNS(NULL,type));
+ if (t.get())
+ m_keyResolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(t.get(),child);
+ else
+ throw UnknownExtensionException("<KeyResolver> element found with no type attribute");
+ }
+ else if (!m_keyResolver) {
+ m_keyResolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER, child);
+ }
+}
+
+TrustEngine::~TrustEngine()
+{
+ delete m_keyResolver;
+}
namespace xmlsignature {\r
\r
/**\r
- * Validator for signatures based on a KeyResolver\r
+ * Validator for signatures based on a Key or a KeyResolver\r
*/\r
- class XMLTOOL_API SignatureValidator : public virtual xmltooling::Validator\r
+ class XMLTOOL_API SignatureValidator : public xmltooling::Validator\r
{\r
public:\r
/**\r
- * Constructor\r
+ * Constructor using a KeyResolver\r
* \r
- * @param resolver the key resolver to use, will be freed by Validator\r
+ * @param resolver the key resolver to use, will be freed by Validator\r
*/\r
- SignatureValidator(KeyResolver* resolver) : m_resolver(resolver) {\r
+ SignatureValidator(KeyResolver* resolver) : m_key(NULL), m_resolver(resolver) {\r
+ }\r
+\r
+ /**\r
+ * Constructor using a Key\r
+ * \r
+ * @param key the verification key to use, will be freed by Validator\r
+ */\r
+ SignatureValidator(XSECCryptoKey* key=NULL) : m_key(key), m_resolver(NULL) {\r
}\r
\r
virtual ~SignatureValidator() {\r
+ delete m_key;\r
delete m_resolver;\r
}\r
\r
- void validate(const xmltooling::XMLObject* xmlObject) const;\r
+ virtual void validate(const xmltooling::XMLObject* xmlObject) const;\r
\r
virtual void validate(const Signature* signature) const;\r
\r
/**\r
+ * Replace the current Key, if any, with a new one.\r
+ * \r
+ * @param key the Key to attach \r
+ */\r
+ void setKey(XSECCryptoKey* key) {\r
+ delete m_key;\r
+ delete m_resolver;\r
+ m_resolver=NULL;\r
+ m_key=key;\r
+ }\r
+\r
+ /**\r
* Replace the current KeyResolver, if any, with a new one.\r
* \r
* @param resolver the KeyResolver to attach \r
*/\r
void setKeyResolver(KeyResolver* resolver) {\r
+ delete m_key;\r
delete m_resolver;\r
+ m_key=NULL;\r
m_resolver=resolver;\r
}\r
\r
protected:\r
+ XSECCryptoKey* m_key;\r
KeyResolver* m_resolver;\r
};\r
\r
</File>\r
</Filter>\r
</Filter>\r
+ <Filter\r
+ Name="security"\r
+ >\r
+ <Filter\r
+ Name="impl"\r
+ >\r
+ <File\r
+ RelativePath=".\security\impl\ExplicitKeyTrustEngine.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\security\impl\TrustEngine.cpp"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ </Filter>\r
</Filter>\r
<Filter\r
Name="Header Files"\r
>\r
</File>\r
</Filter>\r
+ <Filter\r
+ Name="security"\r
+ >\r
+ <File\r
+ RelativePath=".\security\TrustEngine.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\security\X509TrustEngine.h"\r
+ >\r
+ </File>\r
+ </Filter>\r
</Filter>\r
<Filter\r
Name="Resource Files"\r