New "extensible" DDF-backed attribute type, and a delegation extractor using it.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 9 Apr 2009 17:07:23 +0000 (17:07 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 9 Apr 2009 17:07:23 +0000 (17:07 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/branches/REL_2@2968 cb58f699-b61c-0410-a6fe-9272a202ed29

shibsp/Makefile.am
shibsp/attribute/Attribute.cpp
shibsp/attribute/ExtensibleAttribute.cpp [new file with mode: 0644]
shibsp/attribute/ExtensibleAttribute.h [new file with mode: 0644]
shibsp/attribute/NameIDAttribute.h
shibsp/attribute/resolver/AttributeExtractor.h
shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp [new file with mode: 0644]
shibsp/shibsp-lite.vcproj
shibsp/shibsp.vcproj

index cab0e40..2415bd4 100644 (file)
@@ -46,6 +46,7 @@ libshibspinclude_HEADERS = \
 attrinclude_HEADERS = \
        attribute/Attribute.h \
        attribute/AttributeDecoder.h \
+       attribute/ExtensibleAttribute.h \
        attribute/NameIDAttribute.h \
        attribute/ScopedAttribute.h \
        attribute/SimpleAttribute.h
@@ -107,6 +108,7 @@ common_sources = \
        ServiceProvider.cpp \
        SPConfig.cpp \
        attribute/Attribute.cpp \
+       attribute/ExtensibleAttribute.cpp \
        handler/impl/AbstractHandler.cpp \
        handler/impl/AssertionConsumerService.cpp \
        handler/impl/AssertionLookup.cpp \
index 7792677..feffbd3 100644 (file)
@@ -28,6 +28,7 @@
 #include "attribute/SimpleAttribute.h"
 #include "attribute/ScopedAttribute.h"
 #include "attribute/NameIDAttribute.h"
+#include "attribute/ExtensibleAttribute.h"
 #include "util/SPConstants.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
@@ -50,6 +51,10 @@ namespace shibsp {
         return new NameIDAttribute(in);
     }
 
+    SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
+        return new ExtensibleAttribute(in);
+    }
+
 #ifndef SHIBSP_LITE
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
@@ -96,14 +101,15 @@ void shibsp::registerAttributeFactories()
     Attribute::registerFactory("Simple", SimpleAttributeFactory);
     Attribute::registerFactory("Scoped", ScopedAttributeFactory);
     Attribute::registerFactory("NameID", NameIDAttributeFactory);
+    Attribute::registerFactory("Extensible", ExtensibleAttributeFactory);
 }
 
-std::map<std::string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
+map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
 
 Attribute* Attribute::unmarshall(DDF& in)
 {
     map<string,AttributeFactory*>::const_iterator i = m_factoryMap.find(in.name() ? in.name() : "");
     if (i == m_factoryMap.end())
-        throw AttributeException("No registered factory for Attribute of type ($1).", xmltooling::params(1,in.name()));
+        throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
     return (i->second)(in);
 }
diff --git a/shibsp/attribute/ExtensibleAttribute.cpp b/shibsp/attribute/ExtensibleAttribute.cpp
new file mode 100644 (file)
index 0000000..85298b6
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  Copyright 2009 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.
+ */
+
+/**
+ * shibsp/attribute/ExtensibleAttribute.cpp
+ *
+ * An Attribute whose values are arbitrary structures.
+ */
+
+#include "internal.h"
+#include "SPConfig.h"
+#include "attribute/ExtensibleAttribute.h"
+#include "util/SPConstants.h"
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+
+const vector<string>& ExtensibleAttribute::getSerializedValues() const
+{
+    if (m_serialized.empty()) {
+        const char* formatter = m_obj["_formatter"].string();
+        if (formatter) {
+            string msg = formatter;
+            DDF val = m_obj.first().first();
+            while (!val.isnull()) {
+
+                static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_";
+
+                m_serialized.push_back(string());
+                string& processed = m_serialized.back();
+
+                string::size_type i=0,start=0;
+                while (start!=string::npos && start<msg.length() && (i=msg.find("$",start))!=string::npos) {
+                    if (i>start)
+                        processed += msg.substr(start,i-start); // append everything in between
+                    start=i+1;                                  // move start to the beginning of the token name
+                    i=msg.find_first_not_of(legal,start);       // find token delimiter
+                    if (i==start) {                             // append a non legal character
+                       processed+=msg[start++];
+                       continue;
+                    }
+                    
+                    string tag = msg.substr(start,(i==string::npos) ? i : i-start);
+                    if (tag == "_string" && val.string()) {
+                        processed += val.string();
+                        start=i;
+                    }
+                    else {
+                        DDF child = val.getmember(tag.c_str());
+                        if (child.string())
+                            processed += child.string();
+                        start=i;
+                    }
+                }
+                if (start!=string::npos && start<msg.length())
+                    processed += msg.substr(start,i);    // append rest of string
+
+                val = m_obj.first().next();
+            }
+        }
+    }
+    return Attribute::getSerializedValues();
+}
diff --git a/shibsp/attribute/ExtensibleAttribute.h b/shibsp/attribute/ExtensibleAttribute.h
new file mode 100644 (file)
index 0000000..e10f907
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  Copyright 2009 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/attribute/ExtensibleAttribute.h
+ * 
+ * An Attribute whose values are arbitrary structures.
+ */
+
+#ifndef __shibsp_extattr_h__
+#define __shibsp_extattr_h__
+
+#include <shibsp/attribute/Attribute.h>
+#include <xmltooling/exceptions.h>
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4251 )
+#endif
+
+    /**
+     * An Attribute whose values are arbitrary structures.
+     */
+    class SHIBSP_API ExtensibleAttribute : public Attribute
+    {
+    public:
+        /**
+         * Constructor.
+         * 
+         * @param ids       array with primary identifier in first position, followed by any aliases
+         * @param formatter template for serialization of values
+         */
+        ExtensibleAttribute(const std::vector<std::string>& ids, const char* formatter) : Attribute(ids) {
+            m_obj = Attribute::marshall();
+            m_obj.name("Extensible");
+            m_obj.addmember("_formatter").string(formatter);
+        }
+
+        /**
+         * Constructs based on a remoted ExtensibleAttribute.
+         * 
+         * @param in    input object containing marshalled ExtensibleAttribute
+         */
+        ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy()) {
+        }
+        
+        virtual ~ExtensibleAttribute() {}
+        
+        /**
+         * Returns the set of values in a DDF list.
+         * 
+         * @return  a mutable list object containing the values
+         */
+        DDF getValues() {
+            return m_obj.first();
+        }
+        
+        size_t valueCount() const {
+            return m_obj.first().integer();
+        }
+        
+        void clearSerializedValues() {
+            m_serialized.clear();
+        }
+
+        const char* getString(size_t index) const {
+            return m_obj.first()[static_cast<unsigned long>(index)].string();
+        }
+
+        const char* getScope(size_t index) const {
+            return NULL;
+        }
+
+        void removeValue(size_t index) {
+            Attribute::removeValue(index);
+            DDF vals = m_obj.first();
+            if (index < static_cast<size_t>(vals.integer()))
+                vals[static_cast<unsigned long>(index)].remove().destroy();
+        }
+
+        const std::vector<std::string>& getSerializedValues() const;
+    
+        DDF marshall() const {
+            return m_obj.copy();
+        }
+    
+    private:
+        mutable DDF m_obj;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+};
+
+#endif /* __shibsp_nameidattr_h__ */
index bd292ce..c6b54bf 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * @file shibsp/attribute/NameIDAttribute.h
  * 
- * An Attribute whose values are relations of a value and a scope.
+ * An Attribute whose values are derived from or mappable to a SAML NameID.
  */
 
 #ifndef __shibsp_nameidattr_h__
index a0b0a14..0438296 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -76,6 +76,9 @@ namespace shibsp {
     /** AttributeExtractor based on an XML mapping schema. */
     #define XML_ATTRIBUTE_EXTRACTOR "XML"
 
+    /** AttributeExtractor for DelegationRestriction information. */
+    #define DELEGATION_ATTRIBUTE_EXTRACTOR "Delegation"
+
     /** AttributeExtractor based on chaining together other extractors. */
     #define CHAINING_ATTRIBUTE_EXTRACTOR "Chaining"
 };
index de77496..95bda8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -72,6 +72,7 @@ namespace shibsp {
     static const XMLCh _type[] =                UNICODE_LITERAL_4(t,y,p,e);
 
     SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory XMLAttributeExtractorFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory DelegationAttributeExtractorFactory;
     AttributeExtractor* SHIBSP_DLLLOCAL ChainingExtractorFactory(const DOMElement* const & e)
     {
         return new ChainingAttributeExtractor(e);
@@ -80,6 +81,7 @@ namespace shibsp {
 
 void SHIBSP_API shibsp::registerAttributeExtractors()
 {
+    SPConfig::getConfig().AttributeExtractorManager.registerFactory(DELEGATION_ATTRIBUTE_EXTRACTOR, DelegationAttributeExtractorFactory);
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(XML_ATTRIBUTE_EXTRACTOR, XMLAttributeExtractorFactory);
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory);
 }
diff --git a/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
new file mode 100644 (file)
index 0000000..460ac43
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  Copyright 2009 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.
+ */
+
+/**
+ * DelegationAttributeExtractor.cpp
+ *
+ * AttributeExtractor for DelegationRestriction information.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "ServiceProvider.h"
+#include "attribute/ExtensibleAttribute.h"
+#include "attribute/resolver/AttributeExtractor.h"
+#include "util/SPConstants.h"
+
+#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 )
+#endif
+
+    class DelegationExtractor : public AttributeExtractor
+    {
+    public:
+        DelegationExtractor(const DOMElement* e);
+        ~DelegationExtractor() {}
+
+        Lockable* lock() {
+            return this;
+        }
+
+        void unlock() {
+        }
+
+        void extractAttributes(
+            const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+            ) const;
+
+        void getAttributeIds(std::vector<std::string>& attributes) const {
+            attributes.push_back(m_attributeId);
+        }
+
+    private:
+        string m_attributeId,m_formatter;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+    AttributeExtractor* SHIBSP_DLLLOCAL DelegationAttributeExtractorFactory(const DOMElement* const & e)
+    {
+        return new DelegationExtractor(e);
+    }
+
+    static const XMLCh attributeId[] =  UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
+    static const XMLCh formatter[] =    UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+};
+
+DelegationExtractor::DelegationExtractor(const DOMElement* e) : m_attributeId("delegate"), m_formatter("$Name")
+{
+    if (e) {
+        const XMLCh* a = e->getAttributeNS(NULL, attributeId);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_attributeId = temp.get();
+        }
+        a = e->getAttributeNS(NULL, formatter);
+        if (a && *a) {
+            auto_ptr_char temp(a);
+            m_formatter = temp.get();
+        }
+    }
+}
+
+void DelegationExtractor::extractAttributes(
+    const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
+    ) const
+{
+    const saml2::Assertion* assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
+    if (!assertion || !assertion->getConditions())
+        return;
+
+    const vector<saml2::Condition*>& conditions = const_cast<const saml2::Conditions*>(assertion->getConditions())->getConditions();
+    for (vector<saml2::Condition*>::const_iterator c = conditions.begin(); c != conditions.end(); ++c) {
+        const saml2::DelegationRestrictionType* drt = dynamic_cast<const saml2::DelegationRestrictionType*>(*c);
+        if (drt) {
+            auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(vector<string>(1,m_attributeId), m_formatter.c_str()));
+
+            const vector<saml2::Delegate*>& dels = drt->getDelegates();
+            for (vector<saml2::Delegate*>::const_iterator d = dels.begin(); d != dels.end(); ++d) {
+                if ((*d)->getBaseID()) {
+                    Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.Delegation").error(
+                        "delegate identified by saml:BaseID cannot be processed into an attribute value"
+                        );
+                    continue;
+                }
+
+                saml2::NameID* n = NULL;
+                if ((*d)->getEncryptedID()) {
+                    // TODO: add decryption
+                }
+                else {
+                    n = (*d)->getNameID();
+                }
+                if (n) {
+                    DDF val = DDF(NULL).structure();
+                    if ((*d)->getConfirmationMethod()) {
+                        auto_ptr_char temp((*d)->getConfirmationMethod());
+                        val.addmember("ConfirmationMethod").string(temp.get());
+                    }
+                    if ((*d)->getDelegationInstant()) {
+                        auto_ptr_char temp((*d)->getDelegationInstant()->getRawData());
+                        val.addmember("DelegationInstant").string(temp.get());
+                    }
+
+                    auto_arrayptr<char> name(toUTF8(n->getName()));\r
+                    if (name.get() && *name.get()) {\r
+                        val.addmember("Name").string(name.get());\r
+                        char* str = toUTF8(n->getFormat());\r
+                        if (str && *str)\r
+                            val.addmember("Format").string(str);\r
+                        delete[] str;\r
+\r
+                        str = toUTF8(n->getNameQualifier());\r
+                        if (str && *str)\r
+                            val.addmember("NameQualifier").string(str);\r
+                        delete[] str;\r
+\r
+                        str = toUTF8(n->getSPNameQualifier());\r
+                        if (str && *str)\r
+                            val.addmember("SPNameQualifier").string(str);\r
+                        delete[] str;\r
+\r
+                        str = toUTF8(n->getSPProvidedID());\r
+                        if (str && *str)\r
+                            val.addmember("SPProvidedID").string(str);\r
+                        delete[] str;\r
+                    }\r
+
+                    if (n != (*d)->getNameID())
+                        delete n;
+
+                    if (val.integer())
+                        attr->getValues().add(val);
+                    else
+                        val.destroy();
+                }
+            }
+
+            attributes.push_back(attr.release());
+        }
+    }
+}
index f24771d..32a8f7e 100644 (file)
                                        RelativePath=".\attribute\Attribute.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.cpp"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                        <Filter\r
                                Name="handler"\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttribute.h"\r
                                        >\r
                                </File>\r
index abd0600..87279c0 100644 (file)
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\attribute\resolver\impl\DelegationAttributeExtractor.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\attribute\resolver\impl\QueryAttributeResolver.cpp"\r
                                                        >\r
                                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\ExtensibleAttribute.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttribute.h"\r
                                        >\r
                                </File>\r