PKIX trust engine using metadata exts.
authorScott Cantor <cantor.2@osu.edu>
Wed, 27 Dec 2006 23:28:24 +0000 (23:28 +0000)
committerScott Cantor <cantor.2@osu.edu>
Wed, 27 Dec 2006 23:28:24 +0000 (23:28 +0000)
shibsp/Makefile.am
shibsp/MetadataExt.h
shibsp/PKIXTrustEngine.cpp [new file with mode: 0644]
shibsp/PKIXTrustEngine.h [new file with mode: 0644]
shibsp/SPConfig.cpp
shibsp/shibsp.vcproj

index a2f9493..24dc1a9 100644 (file)
@@ -15,6 +15,7 @@ libshibspinclude_HEADERS = \
        ListenerService.h \
        MetadataExt.h \
        paths.h \
+       PKIXTrustEngine.h \
        PropertySet.h \
        version.h \
        SocketListener.h \
@@ -30,11 +31,12 @@ libshibsp_la_SOURCES = \
        ListenerService.cpp \
        MetadataExtImpl.cpp \
        MetadataExtSchemaValidators.cpp \
+       PKIXTrustEngine.cpp \
+       SPConfig.cpp \
+       SPConstants.cpp \ 
        SocketListener.cpp \
        TCPListener.cpp \
-       UnixListener.cpp \
-       SPConfig.cpp \
-       SPConstants.cpp
+       UnixListener.cpp
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
index 7473025..e0a0d6d 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/MetadataExt
+ * @file shibsp/MetadataExt.h
  * 
  * XMLObjects representing Shibboleth metadata extensions
  */
diff --git a/shibsp/PKIXTrustEngine.cpp b/shibsp/PKIXTrustEngine.cpp
new file mode 100644 (file)
index 0000000..c277fb8
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  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.
+ */
+
+/**
+ * PKIXTrustEngine.cpp
+ * 
+ * Shibboleth-specific PKIX-validation TrustEngine
+ */
+
+#include "internal.h"
+#include "MetadataExt.h"
+#include "PKIXTrustEngine.h"
+
+#include <saml/saml2/metadata/Metadata.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/AbstractPKIXTrustEngine.h>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    /**
+     * Adapter between shibmd:KeyAuthority extension and the PKIXValidationInfoIterator interface. 
+     */
+    class SHIBSP_API MetadataPKIXIterator : public AbstractPKIXTrustEngine::PKIXValidationInfoIterator
+    {
+        const XMLObject* m_obj;
+        const Extensions* m_extBlock;
+        const KeyAuthority* m_current;
+        vector<XMLObject*>::const_iterator m_iter;
+        
+        bool m_certsOwned;
+        vector<XSECCryptoX509*> m_certs;
+        vector<XSECCryptoX509CRL*> m_crls;
+        
+    public:
+        MetadataPKIXIterator(const RoleDescriptor& role, const KeyResolver& keyResolver)
+            : PKIXValidationInfoIterator(keyResolver), m_obj(role.getParent()), m_extBlock(NULL), m_current(NULL), m_certsOwned(false) {
+        }
+
+        virtual ~MetadataPKIXIterator() {
+            clear();
+        }
+
+        bool next();
+
+        int getVerificationDepth() const {
+            pair<bool,int> vd = m_current->getVerifyDepth();
+            return vd.first ? vd.second : 1;
+        }
+        
+        const vector<XSECCryptoX509*>& getTrustAnchors() const {
+            return m_certs;
+        }
+
+        const vector<XSECCryptoX509CRL*>& getCRLs() const {
+            return m_crls;
+        }
+    
+    private:
+        void populate();
+
+        void clear() {
+            if (m_certsOwned)
+                for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup<XSECCryptoX509>());
+            m_certs.clear();
+            for_each(m_crls.begin(), m_crls.end(), xmltooling::cleanup<XSECCryptoX509CRL>());
+            m_crls.clear();
+        }
+    };
+
+    class SHIBSP_DLLLOCAL PKIXTrustEngine : public xmltooling::AbstractPKIXTrustEngine
+    {
+    public:
+        PKIXTrustEngine(const DOMElement* e=NULL) : AbstractPKIXTrustEngine(e) {}
+        virtual ~PKIXTrustEngine() {}
+        
+        xmltooling::AbstractPKIXTrustEngine::PKIXValidationInfoIterator* getPKIXValidationInfoIterator(
+            const xmltooling::KeyInfoSource& pkixSource, const xmlsignature::KeyResolver& keyResolver
+            ) const;
+    };
+    
+    SHIBSP_DLLLOCAL PluginManager<TrustEngine,const DOMElement*>::Factory PKIXTrustEngineFactory;
+
+    TrustEngine* SHIBSP_DLLLOCAL PKIXTrustEngineFactory(const DOMElement* const & e)\r
+    {\r
+        return new PKIXTrustEngine(e);\r
+    }\r
+};
+
+void shibsp::registerPKIXTrustEngine()
+{
+    XMLToolingConfig::getConfig().TrustEngineManager.registerFactory(SHIBBOLETH_PKIX_TRUSTENGINE, PKIXTrustEngineFactory);
+}
+
+AbstractPKIXTrustEngine::PKIXValidationInfoIterator* PKIXTrustEngine::getPKIXValidationInfoIterator(
+    const KeyInfoSource& pkixSource, const KeyResolver& keyResolver
+    ) const
+{
+    return new MetadataPKIXIterator(dynamic_cast<const RoleDescriptor&>(pkixSource),keyResolver);
+}
+
+bool MetadataPKIXIterator::next()
+{
+    // If we had a KeyAuthority, look for another in the same block.
+    if (m_current) {
+        // Keep going until we hit the end of the Extensions.
+        vector<XMLObject*>::const_iterator end = m_extBlock->getUnknownXMLObjects().end();
+        while (++m_iter != end) {
+            // If we hit another KeyAuthority, remember it and signal.
+            if (m_current=dynamic_cast<KeyAuthority*>(*m_iter)) {
+                populate();
+                return true;
+            }
+        }
+
+        // If we get here, we hit the end of this Extensions block.
+        // Climb a level, if possible.
+        m_obj = m_extBlock->getParent()->getParent();
+        m_current = NULL;
+        m_extBlock = NULL;
+    }
+
+    // If we get here, we try and find an Extensions block.
+    if (m_obj) {
+        const EntityDescriptor* entity = dynamic_cast<const EntityDescriptor*>(m_obj);
+        if (entity) {
+            m_extBlock = entity->getExtensions();
+        }
+        else {
+            const EntitiesDescriptor* entities = dynamic_cast<const EntitiesDescriptor*>(m_obj);
+            if (entities) {
+                m_extBlock = entities->getExtensions();
+            }
+            else {
+                // Jump a level and try again.
+                m_obj = m_obj->getParent();
+                return next();
+            }
+        }
+    }
+
+    if (m_extBlock) {
+        // We're starting over at a new block.
+        const vector<XMLObject*>& exts = m_extBlock->getUnknownXMLObjects();
+        for (m_iter=exts.begin(); m_iter!=exts.end(); ++m_iter) {
+            // If we hit a KeyAuthority, remember it and signal.
+            if (m_current=dynamic_cast<KeyAuthority*>(*m_iter)) {
+                populate();
+                return true;
+            }
+        }
+
+        // Jump a level and try again.
+        m_obj = m_obj->getParent();
+        return next();
+    }
+    
+    return false;
+}
+
+void MetadataPKIXIterator::populate()
+{
+    // Dump anything old.
+    clear();
+
+    // We have to aggregate the resolution results.
+    KeyResolver::ResolvedCertificates certs;
+    XSECCryptoX509CRL* crl;
+    const vector<KeyInfo*>& keyInfos = m_current->getKeyInfos();
+    for (vector<KeyInfo*>::const_iterator k = keyInfos.begin(); k!=keyInfos.end(); ++k) {
+        vector<XSECCryptoX509*>::size_type count = m_keyResolver.resolveCertificates(*k,certs); 
+        if (count > 0) {
+            // Transfer certificates out of wrapper. 
+            bool own = certs.release(m_certs);
+            if (!m_certs.empty() && own != m_certsOwned) {
+                // Ugh. We have a mashup of "owned" and "unowned".
+                // The ones we just added need to be removed and perhaps freed.
+                do {
+                    if (own)
+                        delete m_certs.back();
+                    m_certs.pop_back();
+                } while (--count > 0);
+            }
+            m_certsOwned = own;
+        }
+
+        crl = m_keyResolver.resolveCRL(*k);
+        if (crl)
+            m_crls.push_back(crl);
+    }
+}
diff --git a/shibsp/PKIXTrustEngine.h b/shibsp/PKIXTrustEngine.h
new file mode 100644 (file)
index 0000000..49cd2c0
--- /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.
+ */
+
+/**
+ * @file shibsp/PKIXTrustEngine.h
+ * 
+ * Shibboleth-specific PKIX-validation TrustEngine 
+ */
+
+#ifndef __shibsp_pkixtrust_h__
+#define __shibsp_pkixtrust_h__
+
+#include <shibsp/base.h>
+
+namespace shibsp {
+    /**
+     * Registers trust engine plugin.
+     */
+    void SHIBSP_API registerPKIXTrustEngine();
+
+    /** TrustEngine based on Shibboleth PKIX metadata extension. */
+    #define SHIBBOLETH_PKIX_TRUSTENGINE  "edu.internet2.middleware.shibboleth.security.provider.PKIXTrustEngine"
+};
+
+#endif /* __shibsp_pkixtrust_h__ */
index 34728fb..9e37be3 100644 (file)
@@ -25,6 +25,7 @@
 #include "exceptions.h"
 #include "ListenerService.h"
 #include "MetadataExt.h"
+#include "PKIXTrustEngine.h"
 #include "SPConfig.h"
 
 #include <log4cpp/Category.hh>
@@ -89,6 +90,7 @@ bool SPInternalConfig::init(const char* catalog_path)
     
     registerListenerServices();
     registerMetadataExtClasses();
+    registerPKIXTrustEngine();
 
     log.info("library initialization complete");
     return true;
index 022e889..ba0d212 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\PKIXTrustEngine.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\SocketListener.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\PKIXTrustEngine.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath=".\PropertySet.h"\r
                                >\r
                        </File>\r