SAML TrustEngine wrappers, ExplicitKeyTrustEngine plugin.
authorcantor <cantor@fb386ef7-a10c-0410-8ebf-fd3f8e989ab0>
Mon, 21 Aug 2006 17:05:22 +0000 (17:05 +0000)
committercantor <cantor@fb386ef7-a10c-0410-8ebf-fd3f8e989ab0>
Mon, 21 Aug 2006 17:05:22 +0000 (17:05 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-opensaml2/trunk@71 fb386ef7-a10c-0410-8ebf-fd3f8e989ab0

17 files changed:
.cdtproject
.project
saml/Makefile.am
saml/SAMLConfig.cpp
saml/SAMLConfig.h
saml/saml.vcproj
saml/security/MetadataKeyInfoIterator.h [new file with mode: 0644]
saml/security/TrustEngine.h [new file with mode: 0644]
saml/security/X509TrustEngine.h [new file with mode: 0644]
saml/security/impl/ExplicitKeyTrustEngine.cpp [new file with mode: 0644]
saml/security/impl/TrustEngine.cpp [new file with mode: 0644]
samltest/Makefile.am
samltest/data/security/FilesystemMetadataProvider.xml [new file with mode: 0644]
samltest/data/security/example-metadata.xml [new file with mode: 0644]
samltest/samltest.vcproj
samltest/security/ExplicitKeyTrustEngineTest.cpp [new file with mode: 0644]
samltest/security/ExplicitKeyTrustEngineTest.h [new file with mode: 0644]

index 00d9ac0..83ab683 100644 (file)
@@ -60,7 +60,7 @@
 <pathentry include="C:/cxxtest" kind="inc" path="" system="true"/>\r
 <pathentry kind="out" path=""/>\r
 <pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>\r
-<pathentry excluding="util/|saml1/|signature/|saml2/|encryption/" kind="src" path="saml"/>\r
+<pathentry excluding="util/|saml1/|signature/|saml2/|encryption/|security/|security/impl/" kind="src" path="saml"/>\r
 <pathentry excluding="impl/" kind="src" path="saml/saml1/core"/>\r
 <pathentry kind="src" path="saml/saml1/core/impl"/>\r
 <pathentry excluding="impl/" kind="src" path="saml/saml1/profile"/>\r
 <pathentry excluding="impl/" kind="src" path="saml/saml2/metadata"/>\r
 <pathentry kind="src" path="saml/saml2/metadata/impl"/>\r
 <pathentry kind="src" path="saml/encryption"/>\r
+<pathentry excluding="impl/" kind="src" path="saml/security"/>\r
+<pathentry kind="src" path="saml/security/impl"/>\r
 <pathentry kind="src" path="saml/signature"/>\r
 <pathentry kind="src" path="saml/util"/>\r
 <pathentry kind="src" path="samltest/signature"/>\r
-<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/" kind="src" path="samltest"/>\r
+<pathentry excluding="saml1/core/impl/|signature/|saml2/core/impl/|saml2/metadata/|security/" kind="src" path="samltest"/>\r
 <pathentry kind="src" path="samltest/saml1/core/impl"/>\r
 <pathentry kind="src" path="samltest/saml2/core/impl"/>\r
 <pathentry kind="src" path="samltest/saml2/metadata"/>\r
+<pathentry kind="src" path="samltest/security"/>\r
 </item>\r
 </data>\r
 </cdtproject>\r
index 6ad4904..22f4aa1 100644 (file)
--- a/.project
+++ b/.project
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <projectDescription>\r
-       <name>OpenSAML2-C</name>\r
+       <name>cpp-opensaml2</name>\r
        <comment></comment>\r
        <projects>\r
                <project>XMLTooling-C</project>\r
index 869eb35..9ef8991 100644 (file)
@@ -6,6 +6,8 @@ libsamlincludedir = $(includedir)/saml
 
 encincludedir = $(includedir)/saml/encryption
 
+secincludedir = $(includedir)/saml/security
+
 sigincludedir = $(includedir)/saml/signature
 
 utilincludedir = $(includedir)/saml/util
@@ -26,6 +28,11 @@ libsamlinclude_HEADERS = \
 encinclude_HEADERS = \
        encryption/EncryptedKeyResolver.h
 
+secinclude_HEADERS = \
+       security/MetadataKeyInfoIterator.h \
+       security/TrustEngine.h \
+       security/X509TrustEngine.h
+
 siginclude_HEADERS = \
        signature/ContentReference.h \
        signature/SignableObject.h \
@@ -58,7 +65,6 @@ noinst_HEADERS = \
 libsaml_la_SOURCES = \
        SAMLArtifact.cpp \
        SAMLConfig.cpp \
-       encryption/EncryptedKeyResolver.cpp \
        saml1/core/impl/AssertionsImpl.cpp \
        saml1/core/impl/AssertionsSchemaValidators.cpp \
        saml1/core/impl/ProtocolsImpl.cpp \
@@ -79,6 +85,9 @@ libsaml_la_SOURCES = \
        saml2/metadata/impl/ObservableMetadataProvider.cpp \
        saml2/metadata/impl/SignatureMetadataFilter.cpp \
        saml2/metadata/impl/WhitelistMetadataFilter.cpp \
+       encryption/EncryptedKeyResolver.cpp \
+       security/impl/TrustEngine.cpp \
+       security/impl/ExplicitKeyTrustEngine.cpp \
        signature/ContentReference.cpp \
        signature/SignatureProfileValidator.cpp \
        util/SAMLConstants.cpp
index 695964a..e154646 100644 (file)
@@ -29,6 +29,7 @@
 #include "saml2/core/Protocols.h"
 #include "saml2/metadata/Metadata.h"
 #include "saml2/metadata/MetadataProvider.h"
+#include "security/TrustEngine.h"
 #include "util/SAMLConstants.h"
 
 #include <xmltooling/XMLToolingConfig.h>
@@ -86,6 +87,7 @@ bool SAMLInternalConfig::init()
     saml2md::registerMetadataClasses();
     saml2md::registerMetadataProviders();
     saml2md::registerMetadataFilters();
+    registerTrustEngines();
 
     log.info("library initialization complete");
     return true;
@@ -105,6 +107,7 @@ void SAMLInternalConfig::term()
     SAMLArtifactManager.deregisterFactories();
     MetadataFilterManager.deregisterFactories();
     MetadataProviderManager.deregisterFactories();
+    TrustEngineManager.deregisterFactories();
 
     XMLToolingConfig::getConfig().term();
     Category::getInstance(SAML_LOGCAT".SAMLConfig").info("library shutdown complete");
index 0c2f7be..b97bda0 100644 (file)
@@ -37,6 +37,7 @@
 namespace opensaml {\r
 \r
     class SAML_API SAMLArtifact;\r
+    class SAML_API TrustEngine;\r
 \r
     namespace saml2md {\r
         class SAML_API MetadataProvider;\r
@@ -131,6 +132,11 @@ namespace opensaml {
          */\r
         xmltooling::PluginManager<SAMLArtifact,const char*> SAMLArtifactManager;\r
 \r
+        /**\r
+         * Manages factories for TrustEngine plugins.\r
+         */\r
+        xmltooling::PluginManager<TrustEngine,const DOMElement*> TrustEngineManager;\r
+\r
     protected:\r
         SAMLConfig() {}\r
     };\r
index 73c7317..0485e28 100644 (file)
                                        >\r
                                </File>\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\MetadataKeyInfoIterator.h"\r
+                                       >\r
+                               </File>\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
diff --git a/saml/security/MetadataKeyInfoIterator.h b/saml/security/MetadataKeyInfoIterator.h
new file mode 100644 (file)
index 0000000..6d408d5
--- /dev/null
@@ -0,0 +1,80 @@
+/*\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
+ * MetadataKeyInfoIterator.h\r
+ * \r
+ * Adapter between SAML metadata and TrustEngine KeyInfoIterator interface.\r
+ */\r
+\r
+#ifndef __saml_keyiter_h__\r
+#define __saml_keyiter_h__\r
+\r
+#include <saml/saml2/metadata/Metadata.h>\r
+\r
+#include <xmltooling/security/TrustEngine.h>\r
+\r
+namespace opensaml {\r
+    \r
+    /**\r
+     * Adapter between SAML metadata and TrustEngine KeyInfoIterator interface. \r
+     */\r
+    class SAML_API MetadataKeyInfoIterator : public xmltooling::TrustEngine::KeyInfoIterator\r
+    {\r
+        const std::vector<saml2md::KeyDescriptor*>& m_keys;\r
+        std::vector<saml2md::KeyDescriptor*>::const_iterator m_iter;\r
+        \r
+        void advance() {\r
+            while (hasNext()) {\r
+                const XMLCh* use=(*m_iter)->getUse();\r
+                if ((!use || !*use || XMLString::equals(use,saml2md::KeyDescriptor::KEYTYPE_SIGNING)) && (*m_iter)->getKeyInfo())\r
+                    return;\r
+                m_iter++;\r
+            }\r
+        }\r
+        \r
+    public:\r
+        MetadataKeyInfoIterator(const saml2md::RoleDescriptor& role) : m_keys(role.getKeyDescriptors()) {\r
+            m_iter=m_keys.begin();\r
+            advance();\r
+        }\r
+\r
+        virtual ~MetadataKeyInfoIterator() {}\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 {\r
+            return m_iter!=m_keys.end();\r
+        }\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() {\r
+            xmlsignature::KeyInfo* ret = (*m_iter)->getKeyInfo();\r
+            m_iter++;\r
+            advance();\r
+            return ret;\r
+        }\r
+    };\r
+};\r
+\r
+#endif /* __saml_keyiter_h__ */\r
diff --git a/saml/security/TrustEngine.h b/saml/security/TrustEngine.h
new file mode 100644 (file)
index 0000000..996286b
--- /dev/null
@@ -0,0 +1,86 @@
+/*\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 saml/security/TrustEngine.h\r
+ * \r
+ * SAML-specific TrustEngine API\r
+ */\r
+\r
+#ifndef __saml_trust_h__\r
+#define __saml_trust_h__\r
+\r
+#include <saml/base.h>\r
+#include <saml/saml2/metadata/Metadata.h>\r
+#include <xmltooling/signature/KeyResolver.h>\r
+\r
+namespace opensaml {\r
+\r
+    /**\r
+     * Adapts SAML metadata as a source of KeyInfo for a TrustEngine\r
+     * and adds SAML-specific signature validation.\r
+     */\r
+    class SAML_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>&lt;KeyResolver&gt; 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
+    public:\r
+        virtual ~TrustEngine() {}\r
+\r
+        /**\r
+         * Determines whether a signed SAML object is correct and valid with respect\r
+         * to the information known about the issuer.\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 role          metadata role supplying key information\r
+         * @param keyResolver   optional externally supplied KeyResolver, or NULL\r
+         */\r
+        virtual bool validate(\r
+            xmlsignature::Signature& sig,\r
+            saml2md::RoleDescriptor& role,\r
+            const xmlsignature::KeyResolver* keyResolver=NULL\r
+            )=0;\r
+    };\r
+    \r
+\r
+    /**\r
+     * Registers TrustEngine classes into the runtime.\r
+     */\r
+    void SAML_API registerTrustEngines();\r
+\r
+    /** TrustEngine based on explicit key information resolved from metadata. */\r
+    #define EXPLICIT_KEY_SAMLTRUSTENGINE  "org.opensaml.security.ExplicitKeyTrustEngine"\r
+};\r
+\r
+#endif /* __saml_trust_h__ */\r
diff --git a/saml/security/X509TrustEngine.h b/saml/security/X509TrustEngine.h
new file mode 100644 (file)
index 0000000..1bc8bb6
--- /dev/null
@@ -0,0 +1,78 @@
+/*\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 saml/security/X509TrustEngine.h\r
+ * \r
+ * Extended TrustEngine interface that adds validation of X.509 credentials.\r
+ */\r
+\r
+#ifndef __saml_x509trust_h__\r
+#define __saml_x509trust_h__\r
+\r
+#include <saml/security/TrustEngine.h>\r
+\r
+namespace opensaml {\r
+\r
+    /**\r
+     * Extended TrustEngine interface that adds validation of X.509 credentials.\r
+     */\r
+    class SAML_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>&lt;KeyResolver&gt; 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\r
+         * to the information known about the peer.\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 role          metadata role supplying key information\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
+            saml2md::RoleDescriptor& role,\r
+            bool checkName=true,\r
+            const xmlsignature::KeyResolver* keyResolver=NULL\r
+            )=0;\r
+    };\r
+    \r
+};\r
+\r
+#endif /* __saml_x509trust_h__ */\r
diff --git a/saml/security/impl/ExplicitKeyTrustEngine.cpp b/saml/security/impl/ExplicitKeyTrustEngine.cpp
new file mode 100644 (file)
index 0000000..4219a90
--- /dev/null
@@ -0,0 +1,118 @@
+/*\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 "exceptions.h"\r
+#include "security/MetadataKeyInfoIterator.h"\r
+#include "security/X509TrustEngine.h"\r
+#include "signature/SignatureProfileValidator.h"\r
+\r
+#include <log4cpp/Category.hh>\r
+#include <xmltooling/security/X509TrustEngine.h>\r
+#include <xmltooling/util/NDC.h>\r
+\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+using namespace xmlsignature;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+namespace opensaml {\r
+    class SAML_DLLLOCAL ExplicitKeyTrustEngine : public X509TrustEngine\r
+    {\r
+    public:\r
+        ExplicitKeyTrustEngine(const DOMElement* e) : X509TrustEngine(e), m_engine(NULL) {\r
+            auto_ptr<xmltooling::TrustEngine> engine(\r
+                xmltooling::XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE, e)\r
+                );\r
+            if (m_engine=dynamic_cast<xmltooling::X509TrustEngine*>(engine.get()))\r
+                engine.release();\r
+            else\r
+                throw xmltooling::UnknownExtensionException("Embedded trust engine does not support required interface.");\r
+        }\r
+        \r
+        virtual ~ExplicitKeyTrustEngine() {\r
+            delete m_engine;\r
+        }\r
+\r
+        virtual bool validate(\r
+            Signature& sig,\r
+            RoleDescriptor& role,\r
+            const KeyResolver* keyResolver=NULL\r
+            );\r
+        virtual bool validate(\r
+            XSECCryptoX509* certEE,\r
+            const vector<XSECCryptoX509*>& certChain,\r
+            RoleDescriptor& role,\r
+            bool checkName=true,\r
+            const KeyResolver* keyResolver=NULL\r
+            );\r
+\r
+    private:\r
+        xmltooling::X509TrustEngine* m_engine;\r
+    };\r
+\r
+    TrustEngine* SAML_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)\r
+    {\r
+        return new ExplicitKeyTrustEngine(e);\r
+    }\r
+};\r
+\r
+bool ExplicitKeyTrustEngine::validate(\r
+    Signature& sig,\r
+    RoleDescriptor& role,\r
+    const KeyResolver* keyResolver\r
+    )\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("validate");\r
+#endif\r
+    Category& log=Category::getInstance(SAML_LOGCAT".TrustEngine");\r
+    \r
+    log.debug("attempting to validate signature profile");\r
+    SignatureProfileValidator sigValidator;\r
+    try {\r
+        sigValidator.validate(&sig);\r
+        log.debug("signature profile validated");\r
+    }\r
+    catch (xmltooling::ValidationException& e) {\r
+        if (log.isDebugEnabled()) {\r
+            log.debug("signature profile failed to validate: %s", e.what());\r
+        }\r
+        return false;\r
+    }\r
+\r
+    MetadataKeyInfoIterator keys(role);\r
+    return static_cast<xmltooling::TrustEngine*>(m_engine)->validate(sig,keys,keyResolver);\r
+}\r
+\r
+bool ExplicitKeyTrustEngine::validate(\r
+    XSECCryptoX509* certEE,\r
+    const vector<XSECCryptoX509*>& certChain,\r
+    RoleDescriptor& role,\r
+    bool checkName,\r
+    const KeyResolver* keyResolver\r
+    )\r
+{\r
+    MetadataKeyInfoIterator keys(role);\r
+    return m_engine->validate(certEE,certChain,keys,checkName,keyResolver);\r
+}\r
diff --git a/saml/security/impl/TrustEngine.cpp b/saml/security/impl/TrustEngine.cpp
new file mode 100644 (file)
index 0000000..f5084c2
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  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"
+
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace opensaml {
+    SAML_DLLLOCAL PluginManager<TrustEngine,const DOMElement*>::Factory ExplicitKeyTrustEngineFactory; 
+};
+
+void SAML_API opensaml::registerTrustEngines()
+{
+    SAMLConfig& conf=SAMLConfig::getConfig();
+    conf.TrustEngineManager.registerFactory(EXPLICIT_KEY_SAMLTRUSTENGINE, ExplicitKeyTrustEngineFactory);
+}
index f76a967..73e4212 100644 (file)
@@ -17,6 +17,7 @@ samltest_h = \
     signature/SAML1RequestTest.h \
     signature/SAML1ResponseTest.h \
     signature/SAML2AssertionTest.h \
+    security/ExplicitKeyTrustEngineTest.h \
     saml1/core/impl/ActionTest.h \
     saml1/core/impl/AdviceTest.h \
     saml1/core/impl/AssertionIDReferenceTest.h \
diff --git a/samltest/data/security/FilesystemMetadataProvider.xml b/samltest/data/security/FilesystemMetadataProvider.xml
new file mode 100644 (file)
index 0000000..9f4af74
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FilesystemMetadataProvider path="../samltest/data/security/example-metadata.xml" validate="0"/>
diff --git a/samltest/data/security/example-metadata.xml b/samltest/data/security/example-metadata.xml
new file mode 100644 (file)
index 0000000..5c88e41
--- /dev/null
@@ -0,0 +1,33 @@
+<EntityDescriptor 
+       xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+       xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+       entityID="https://idp.example.org">
+       
+       <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+               <KeyDescriptor use="signing">
+                   <ds:KeyInfo>
+                       <ds:X509Data>
+                               <ds:X509Certificate>
+                                       MIICjzCCAfigAwIBAgIJAKk8t1hYcMkhMA0GCSqGSIb3DQEBBAUAMDoxCzAJBgNV
+                                       BAYTAlVTMRIwEAYDVQQKEwlJbnRlcm5ldDIxFzAVBgNVBAMTDnNwLmV4YW1wbGUu
+                                       b3JnMB4XDTA1MDYyMDE1NDgzNFoXDTMyMTEwNTE1NDgzNFowOjELMAkGA1UEBhMC
+                                       VVMxEjAQBgNVBAoTCUludGVybmV0MjEXMBUGA1UEAxMOc3AuZXhhbXBsZS5vcmcw
+                                       gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANlZ1L1mKzYbUVKiMQLhZlfGDyYa
+                                       /jjCiaXP0WhLNgvJpOTeajvsrApYNnFX5MLNzuC3NeQIjXUNLN2Yo2MCSthBIOL5
+                                       qE5dka4z9W9zytoflW1LmJ8vXpx8Ay/meG4z//J5iCpYVEquA0xl28HUIlownZUF
+                                       7w7bx0cF/02qrR23AgMBAAGjgZwwgZkwHQYDVR0OBBYEFJZiO1qsyAyc3HwMlL9p
+                                       JpN6fbGwMGoGA1UdIwRjMGGAFJZiO1qsyAyc3HwMlL9pJpN6fbGwoT6kPDA6MQsw
+                                       CQYDVQQGEwJVUzESMBAGA1UEChMJSW50ZXJuZXQyMRcwFQYDVQQDEw5zcC5leGFt
+                                       cGxlLm9yZ4IJAKk8t1hYcMkhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD
+                                       gYEAMFq/UeSQyngE0GpZueyD2UW0M358uhseYOgGEIfm+qXIFQF6MYwNoX7WFzhC
+                                       LJZ2E6mEvZZFHCHUtl7mGDvsRwgZ85YCtRbvleEpqfgNQToto9pLYe+X6vvH9Z6p
+                                       gmYsTmak+kxO93JprrOd9xp8aZPMEprL7VCdrhbZEfyYER0=
+                               </ds:X509Certificate>
+                       </ds:X509Data>
+                   </ds:KeyInfo>
+               </KeyDescriptor>
+
+               <SingleSignOnService Binding="foo" Location="foo"/>
+       </IDPSSODescriptor>
+
+</EntityDescriptor>\r
index e3eb662..ba7d52f 100644 (file)
                                        </File>\r
                                </Filter>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="security"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\security\ExplicitKeyTrustEngineTest.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Unit Tests"\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        >\r
                                        <Tool\r
                                                Name="VCCustomBuildTool"\r
-                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                               CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;&#x0D;&#x0A;"\r
                                                Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
                                        />\r
                                </FileConfiguration>\r
                                        </File>\r
                                </Filter>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="security"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\security\ExplicitKeyTrustEngineTest.h"\r
+                                       >\r
+                                       <FileConfiguration\r
+                                               Name="Debug|Win32"\r
+                                               >\r
+                                               <Tool\r
+                                                       Name="VCCustomBuildTool"\r
+                                                       CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                                       Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                               />\r
+                                       </FileConfiguration>\r
+                                       <FileConfiguration\r
+                                               Name="Release|Win32"\r
+                                               >\r
+                                               <Tool\r
+                                                       Name="VCCustomBuildTool"\r
+                                                       CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o &quot;$(InputDir)$(InputName)&quot;.cpp &quot;$(InputPath)&quot;"\r
+                                                       Outputs="&quot;$(InputDir)$(InputName)&quot;.cpp"\r
+                                               />\r
+                                       </FileConfiguration>\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
diff --git a/samltest/security/ExplicitKeyTrustEngineTest.cpp b/samltest/security/ExplicitKeyTrustEngineTest.cpp
new file mode 100644 (file)
index 0000000..99b6dd0
--- /dev/null
@@ -0,0 +1,27 @@
+/* Generated file, do not edit */\r
+\r
+#ifndef CXXTEST_RUNNING\r
+#define CXXTEST_RUNNING\r
+#endif\r
+\r
+#define _CXXTEST_HAVE_STD\r
+#define _CXXTEST_HAVE_EH\r
+#define _CXXTEST_ABORT_TEST_ON_FAIL\r
+#include <cxxtest/TestListener.h>\r
+#include <cxxtest/TestTracker.h>\r
+#include <cxxtest/TestRunner.h>\r
+#include <cxxtest/RealDescriptions.h>\r
+\r
+#include "c:\cvs\cpp-opensaml2\samltest\security\ExplicitKeyTrustEngineTest.h"\r
+\r
+static ExplicitKeyTrustEngineTest suite_ExplicitKeyTrustEngineTest;\r
+\r
+static CxxTest::List Tests_ExplicitKeyTrustEngineTest = { 0, 0 };\r
+CxxTest::StaticSuiteDescription suiteDescription_ExplicitKeyTrustEngineTest( "c:\\cvs\\cpp-opensaml2\\samltest\\security\\ExplicitKeyTrustEngineTest.h", 25, "ExplicitKeyTrustEngineTest", suite_ExplicitKeyTrustEngineTest, Tests_ExplicitKeyTrustEngineTest );\r
+\r
+static class TestDescription_ExplicitKeyTrustEngineTest_testExplicitKeyTrustEngine : public CxxTest::RealTestDescription {\r
+public:\r
+ TestDescription_ExplicitKeyTrustEngineTest_testExplicitKeyTrustEngine() : CxxTest::RealTestDescription( Tests_ExplicitKeyTrustEngineTest, suiteDescription_ExplicitKeyTrustEngineTest, 35, "testExplicitKeyTrustEngine" ) {}\r
+ void runTest() { suite_ExplicitKeyTrustEngineTest.testExplicitKeyTrustEngine(); }\r
+} testDescription_ExplicitKeyTrustEngineTest_testExplicitKeyTrustEngine;\r
+\r
diff --git a/samltest/security/ExplicitKeyTrustEngineTest.h b/samltest/security/ExplicitKeyTrustEngineTest.h
new file mode 100644 (file)
index 0000000..511de41
--- /dev/null
@@ -0,0 +1,83 @@
+/*\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
+#include "internal.h"\r
+#include <saml/security/TrustEngine.h>\r
+#include <saml/saml2/metadata/MetadataProvider.h>\r
+\r
+using namespace opensaml::saml2;\r
+using namespace opensaml::saml2md;\r
+using namespace xmlsignature;\r
+\r
+class ExplicitKeyTrustEngineTest : public CxxTest::TestSuite, public SAMLObjectBaseTestCase {\r
+public:\r
+    void setUp() {\r
+        SAMLObjectBaseTestCase::setUp();\r
+    }\r
+    \r
+    void tearDown() {\r
+        SAMLObjectBaseTestCase::tearDown();\r
+    }\r
+\r
+    void testExplicitKeyTrustEngine() {\r
+        string config = data_path + "security/FilesystemMetadataProvider.xml";\r
+        ifstream in(config.c_str());\r
+        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);\r
+        XercesJanitor<DOMDocument> janitor(doc);\r
+\r
+        auto_ptr_XMLCh path("path");\r
+        string s = data_path + "security/example-metadata.xml";\r
+        auto_ptr_XMLCh file(s.c_str());\r
+        doc->getDocumentElement()->setAttributeNS(NULL,path.get(),file.get());\r
+\r
+        // Build metadata provider.\r
+        auto_ptr<MetadataProvider> metadataProvider(\r
+            SAMLConfig::getConfig().MetadataProviderManager.newPlugin(FILESYSTEM_METADATA_PROVIDER,doc->getDocumentElement())\r
+            );\r
+        try {\r
+            metadataProvider->init();\r
+        }\r
+        catch (XMLToolingException& ex) {\r
+            TS_TRACE(ex.what());\r
+            throw;\r
+        }\r
+        \r
+        // Build trust engine.\r
+        auto_ptr<opensaml::TrustEngine> trustEngine(\r
+            SAMLConfig::getConfig().TrustEngineManager.newPlugin(EXPLICIT_KEY_SAMLTRUSTENGINE, NULL)\r
+            );\r
+        \r
+        // Get signed assertion.\r
+        config = data_path + "signature/SAML2Assertion.xml";\r
+        ifstream in2(config.c_str());\r
+        DOMDocument* doc2=XMLToolingConfig::getConfig().getParser().parse(in2);\r
+        XercesJanitor<DOMDocument> janitor2(doc2);\r
+        auto_ptr<Assertion> assertion(dynamic_cast<Assertion*>(XMLObjectBuilder::getBuilder(doc2->getDocumentElement())->buildFromDocument(doc2)));\r
+        janitor2.release();\r
+\r
+        Locker locker(metadataProvider.get());\r
+        const EntityDescriptor* descriptor = metadataProvider->getEntityDescriptor("https://idp.example.org");\r
+        TSM_ASSERT("Retrieved entity descriptor was null", descriptor!=NULL);\r
+        \r
+        Signature* sig=assertion->getSignature();\r
+        TSM_ASSERT("Signature not present", sig!=NULL);\r
+\r
+        RoleDescriptor* role=descriptor->getIDPSSODescriptors().front();\r
+        TSM_ASSERT("Role not present", role!=NULL);\r
+        \r
+        TSM_ASSERT("Signature failed to validate.", trustEngine->validate(*sig, *role, metadataProvider->getKeyResolver()));\r
+    }\r
+};\r