[cpp-opensaml] branch main updated: CPPOST-118 - Metadata filter for adding UIInfo extensions

Scott Cantor cantor.2 at osu.edu
Mon Dec 7 15:22:29 UTC 2020


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository cpp-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-opensaml.git;a=commit;h=b627a28d0b270c7c9fd7a47a0b2089b5353f8b81

The following commit(s) were added to refs/heads/main by this push:
       new  b627a28   CPPOST-118 - Metadata filter for adding UIInfo extensions
b627a28 is described below

commit b627a28d0b270c7c9fd7a47a0b2089b5353f8b81
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Dec 7 10:21:43 2020 -0500

    CPPOST-118 - Metadata filter for adding UIInfo extensions
    
    https://issues.shibboleth.net/jira/browse/CPPOST-118
---
 Projects/vc15/saml/saml.vcxproj                    |   1 +
 Projects/vc15/saml/saml.vcxproj.filters            |   3 +
 saml/Makefile.am                                   |   1 +
 saml/saml2/metadata/MetadataFilter.h               |   3 +
 .../impl/EntityAttributesMetadataFilter.cpp        |   2 +-
 saml/saml2/metadata/impl/MetadataProvider.cpp      |   7 +-
 saml/saml2/metadata/impl/UIInfoMetadataFilter.cpp  | 183 +++++++++++++++++++++
 7 files changed, 197 insertions(+), 3 deletions(-)

diff --git a/Projects/vc15/saml/saml.vcxproj b/Projects/vc15/saml/saml.vcxproj
index aa96717..7fe001f 100644
--- a/Projects/vc15/saml/saml.vcxproj
+++ b/Projects/vc15/saml/saml.vcxproj
@@ -202,6 +202,7 @@
     <ClCompile Include="..\..\..\saml\saml2\metadata\impl\InlineLogoMetadataFilter.cpp" />
     <ClCompile Include="..\..\..\saml\saml2\metadata\impl\NameEntityMatcher.cpp" />
     <ClCompile Include="..\..\..\saml\saml2\metadata\impl\RegistrationAuthorityEntityMatcher.cpp" />
+    <ClCompile Include="..\..\..\saml\saml2\metadata\impl\UIInfoMetadataFilter.cpp" />
     <ClCompile Include="..\..\..\saml\SAMLConfig.cpp" />
     <ClCompile Include="..\..\..\saml\util\CommonDomainCookie.cpp" />
     <ClCompile Include="..\..\..\saml\util\SAMLConstants.cpp" />
diff --git a/Projects/vc15/saml/saml.vcxproj.filters b/Projects/vc15/saml/saml.vcxproj.filters
index 4d922ae..a916981 100644
--- a/Projects/vc15/saml/saml.vcxproj.filters
+++ b/Projects/vc15/saml/saml.vcxproj.filters
@@ -369,6 +369,9 @@
     <ClCompile Include="..\..\..\saml\saml2\metadata\impl\InlineLogoMetadataFilter.cpp">
       <Filter>Source Files\saml2\metadata\impl</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\saml\saml2\metadata\impl\UIInfoMetadataFilter.cpp">
+      <Filter>Source Files\saml2\metadata\impl</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\saml\Assertion.h">
diff --git a/saml/Makefile.am b/saml/Makefile.am
index 048ebdd..d60c0d3 100644
--- a/saml/Makefile.am
+++ b/saml/Makefile.am
@@ -154,6 +154,7 @@ libsaml_la_SOURCES = \
 	saml2/metadata/impl/InlineLogoMetadataFilter.cpp \
 	saml2/metadata/impl/RequireValidUntilMetadataFilter.cpp \
 	saml2/metadata/impl/SignatureMetadataFilter.cpp \
+	saml2/metadata/impl/UIInfoMetadataFilter.cpp \
 	saml2/metadata/impl/RegistrationAuthorityEntityMatcher.cpp \
 	saml2/metadata/impl/XMLMetadataProvider.cpp \
 	saml2/binding/impl/SAML2Artifact.cpp \
diff --git a/saml/saml2/metadata/MetadataFilter.h b/saml/saml2/metadata/MetadataFilter.h
index e1632d8..5f83c70 100644
--- a/saml/saml2/metadata/MetadataFilter.h
+++ b/saml/saml2/metadata/MetadataFilter.h
@@ -138,6 +138,9 @@ namespace opensaml {
         /** MetadataFilter that adds EntityAttributes extension. */
         #define ENTITYATTR_METADATA_FILTER          "EntityAttributes"
 
+        /** MetadataFilter that adds UIInfo extension. */
+        #define UIINFO_METADATA_FILTER              "UIInfo"
+
         /** MetadataFilter that removes inline logos from metadata. */
         #define INLINELOGO_METADATA_FILTER          "InlineLogo"
 
diff --git a/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp b/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp
index 390d1c7..df19038 100644
--- a/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp
+++ b/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp
@@ -151,7 +151,7 @@ void EntityAttributesMetadataFilter::filterEntity(EntityDescriptor* entity) cons
 {
     if (!entity->getEntityID())
         return;
-
+    
     pair<applymap_t::const_iterator,applymap_t::const_iterator> tags = m_applyMap.equal_range(entity->getEntityID());
     if (tags.first != tags.second) {
         EntityAttributes* wrapper = getEntityAttributes(entity);
diff --git a/saml/saml2/metadata/impl/MetadataProvider.cpp b/saml/saml2/metadata/impl/MetadataProvider.cpp
index 0b0e922..b2aa2a6 100644
--- a/saml/saml2/metadata/impl/MetadataProvider.cpp
+++ b/saml/saml2/metadata/impl/MetadataProvider.cpp
@@ -59,6 +59,7 @@ namespace opensaml {
         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory RequireValidUntilMetadataFilterFactory;
         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory EntityRoleMetadataFilterFactory;
         SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory EntityAttributesMetadataFilterFactory;
+        SAML_DLLLOCAL PluginManager<MetadataFilter,string,const DOMElement*>::Factory UIInfoMetadataFilterFactory;
     };
 };
 
@@ -78,11 +79,13 @@ void SAML_API opensaml::saml2md::registerMetadataFilters()
     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(INCLUDE_METADATA_FILTER, IncludeMetadataFilterFactory);
     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(INLINELOGO_METADATA_FILTER, InlineLogoMetadataFilterFactory);
     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(SIGNATURE_METADATA_FILTER, SignatureMetadataFilterFactory);
+    SAMLConfig::getConfig().MetadataFilterManager.registerFactory(ENTITYROLE_METADATA_FILTER, EntityRoleMetadataFilterFactory);
+    SAMLConfig::getConfig().MetadataFilterManager.registerFactory(ENTITYATTR_METADATA_FILTER, EntityAttributesMetadataFilterFactory);
+    SAMLConfig::getConfig().MetadataFilterManager.registerFactory(UIINFO_METADATA_FILTER, UIInfoMetadataFilterFactory);
+
     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(REQUIREVALIDUNTIL_METADATA_FILTER, RequireValidUntilMetadataFilterFactory);
     // additional name matching Java code
     SAMLConfig::getConfig().MetadataFilterManager.registerFactory("RequiredValidUntil", RequireValidUntilMetadataFilterFactory);
-    SAMLConfig::getConfig().MetadataFilterManager.registerFactory(ENTITYROLE_METADATA_FILTER, EntityRoleMetadataFilterFactory);
-    SAMLConfig::getConfig().MetadataFilterManager.registerFactory(ENTITYATTR_METADATA_FILTER, EntityAttributesMetadataFilterFactory);
     
     // Deprecated names.
     SAMLConfig::getConfig().MetadataFilterManager.registerFactory(BLACKLIST_METADATA_FILTER, ExcludeMetadataFilterFactory);
diff --git a/saml/saml2/metadata/impl/UIInfoMetadataFilter.cpp b/saml/saml2/metadata/impl/UIInfoMetadataFilter.cpp
new file mode 100644
index 0000000..fd0d609
--- /dev/null
+++ b/saml/saml2/metadata/impl/UIInfoMetadataFilter.cpp
@@ -0,0 +1,183 @@
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you 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.
+ */
+
+/**
+ * UIInfoMetadataFilter.cpp
+ *
+ * Adds UIInfo extension to entities.
+ */
+
+#include "internal.h"
+#include "saml2/metadata/Metadata.h"
+#include "saml2/metadata/MetadataFilter.h"
+
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/casts.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <xmltooling/logging.h>
+
+using namespace opensaml::saml2;
+using namespace opensaml::saml2md;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
+using namespace std;
+
+namespace opensaml {
+    namespace saml2md {
+
+        class SAML_DLLLOCAL UIInfoMetadataFilter : public MetadataFilter
+        {
+        public:
+            UIInfoMetadataFilter(const DOMElement* e);
+            ~UIInfoMetadataFilter() {}
+
+            const char* getId() const { return UIINFO_METADATA_FILTER; }
+            void doFilter(const MetadataFilterContext* ctx, XMLObject& xmlObject) const;
+
+        private:
+            void filterEntity(EntityDescriptor* entity) const;
+            void filterGroup(EntitiesDescriptor* entities) const;
+            Extensions* getContainer(IDPSSODescriptor* entity) const;
+
+            Category& m_log;
+            bool m_replace;
+            vector< boost::shared_ptr<UIInfo> > m_infos;
+            typedef map<xstring,const UIInfo*> applymap_t;
+            applymap_t m_applyMap;
+        };
+
+        MetadataFilter* SAML_DLLLOCAL UIInfoMetadataFilterFactory(const DOMElement* const & e, bool)
+        {
+            return new UIInfoMetadataFilter(e);
+        }
+
+        static const XMLCh Entity[] =       UNICODE_LITERAL_6(E,n,t,i,t,y);
+        static const XMLCh replace[] =      UNICODE_LITERAL_7(r,e,p,l,a,c,e);
+    };
+};
+
+
+UIInfoMetadataFilter::UIInfoMetadataFilter(const DOMElement* e)
+    : m_log(Category::getInstance(SAML_LOGCAT".MetadataFilter.UIInfo")),
+        m_replace(XMLHelper::getAttrBool(e, false, replace))
+{
+    // Contains ordered set of UIInfo and Entity elements.
+    // We track each one we find, and then consume an Entity by adding.
+    // a mapping from the Entity to the last-seen UIInfo.
+
+    const UIInfo* lastSeen = nullptr;
+
+    DOMElement* child = XMLHelper::getFirstChildElement(e);
+    while (child) {
+        if (XMLHelper::isNodeNamed(child, samlconstants::SAML20MD_UI_NS, UIInfo::LOCAL_NAME)) {
+            boost::shared_ptr<XMLObject> obj(UIInfoBuilder::buildOneFromElement(child));
+            m_infos.push_back(boost::dynamic_pointer_cast<UIInfo>(obj));
+            lastSeen = m_infos.back().get();
+        }
+        else if (XMLString::equals(child->getLocalName(), Entity)) {
+            const XMLCh* eid = XMLHelper::getTextContent(child);
+            if (eid && *eid && lastSeen) {
+                m_applyMap.insert(applymap_t::value_type(eid, lastSeen));
+            }
+        }
+        else {
+            m_log.warn("ignoring unrecognized element, one of mdui:UIInfo or Entity required");
+        }
+        child = XMLHelper::getNextSiblingElement(child);
+    }
+
+    if (m_applyMap.empty()) {
+        m_log.warn("UIInfo filter has no rules to apply");
+    }
+}
+
+void UIInfoMetadataFilter::doFilter(const MetadataFilterContext*, XMLObject& xmlObject) const
+{
+    if (m_applyMap.empty())
+        return;
+
+    EntitiesDescriptor* group = dynamic_cast<EntitiesDescriptor*>(&xmlObject);
+    if (group) {
+        filterGroup(group);
+    }
+    else {
+        EntityDescriptor* entity = dynamic_cast<EntityDescriptor*>(&xmlObject);
+        if (entity) {
+            filterEntity(entity);
+        }
+        else {
+            throw MetadataFilterException(UIINFO_METADATA_FILTER " MetadataFilter was given an improper metadata instance to filter.");
+        }
+    }
+}
+
+void UIInfoMetadataFilter::filterGroup(EntitiesDescriptor* entities) const
+{
+    const vector<EntityDescriptor*>& v = const_cast<const EntitiesDescriptor*>(entities)->getEntityDescriptors();
+    for_each(v.begin(), v.end(), lambda::bind(&UIInfoMetadataFilter::filterEntity, this, _1));
+
+    const vector<EntitiesDescriptor*>& v2 = const_cast<const EntitiesDescriptor*>(entities)->getEntitiesDescriptors();
+    for_each(v2.begin(), v2.end(), lambda::bind(&UIInfoMetadataFilter::filterGroup, this, _1));
+}
+
+void UIInfoMetadataFilter::filterEntity(EntityDescriptor* entity) const
+{
+    if (!entity->getEntityID())
+        return;
+
+    applymap_t::const_iterator uiinfo = m_applyMap.find(entity->getEntityID());
+    if (uiinfo == m_applyMap.end())
+        return;
+
+    VectorOf(IDPSSODescriptor) roles = entity->getIDPSSODescriptors();
+    for (VectorOf(IDPSSODescriptor)::iterator i = roles.begin(); i != roles.end(); ++i) {
+        Extensions* ext = getContainer(*i);
+        if (ext) {
+            auto_ptr<UIInfo> dup(uiinfo->second->cloneUIInfo());
+            ext->getUnknownXMLObjects().push_back(dup.get());
+            dup.release();
+        }
+    }
+}
+
+Extensions* UIInfoMetadataFilter::getContainer(IDPSSODescriptor* role) const
+{
+    Extensions* exts = role->getExtensions();
+    if (!exts) {
+        role->setExtensions(ExtensionsBuilder::buildExtensions());
+        return role->getExtensions();
+    }
+
+    VectorOf(XMLObject) children = exts->getUnknownXMLObjects();
+    for (VectorOf(XMLObject)::iterator i = children.begin(); i != children.end(); ++i) {
+        if (dynamic_cast<UIInfo*>(*i)) {
+            if (!m_replace)
+                return nullptr;
+            children.erase(i);
+            break;
+        }
+    }
+
+    return exts;
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list