Rework decoder handling in simple resolver, add IdP/SP names to decoder API, hook...
[shibboleth/sp.git] / shibsp / attribute / resolver / impl / SimpleAttributeResolver.cpp
index 294bc63..19f2e84 100644 (file)
@@ -226,9 +226,12 @@ namespace shibsp {
         chLatin_r, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chColon,\r
         chLatin_s, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chNull\r
     };\r
+    static const XMLCh _AttributeDecoder[] =    UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);\r
     static const XMLCh _AttributeResolver[] =   UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);\r
     static const XMLCh allowQuery[] =           UNICODE_LITERAL_10(a,l,l,o,w,Q,u,e,r,y);\r
-    static const XMLCh decoderType[] =          UNICODE_LITERAL_11(d,e,c,o,d,e,r,T,y,p,e);\r
+    static const XMLCh decoderId[] =            UNICODE_LITERAL_9(d,e,c,o,d,e,r,I,d);\r
+    static const XMLCh _id[] =                  UNICODE_LITERAL_2(i,d);\r
+    static const XMLCh _type[] =                UNICODE_LITERAL_4(t,y,p,e);\r
 };\r
 \r
 SimpleResolverImpl::SimpleResolverImpl(const DOMElement* e) : m_document(NULL), m_allowQuery(true)\r
@@ -246,42 +249,42 @@ SimpleResolverImpl::SimpleResolverImpl(const DOMElement* e) : m_document(NULL),
         log.info("SAML attribute queries disabled");\r
         m_allowQuery = false;\r
     }\r
+\r
+    DOMElement* child = XMLHelper::getFirstChildElement(e, SIMPLE_NS, _AttributeDecoder);\r
+    while (child) {\r
+        auto_ptr_char id(child->getAttributeNS(NULL, _id));\r
+        auto_ptr_char type(child->getAttributeNS(NULL, _type));\r
+        try {\r
+            log.info("building AttributeDecoder (%s) of type %s", id.get(), type.get());\r
+            m_decoderMap[id.get()] = SPConfig::getConfig().AttributeDecoderManager.newPlugin(type.get(), child);\r
+        }\r
+        catch (exception& ex) {\r
+            log.error("error building AttributeDecoder (%s): %s", id.get(), ex.what());\r
+        }\r
+        child = XMLHelper::getNextSiblingElement(child, SIMPLE_NS, _AttributeDecoder);\r
+    }\r
     \r
-    e = XMLHelper::getFirstChildElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
-    while (e) {\r
+    child = XMLHelper::getFirstChildElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
+    while (child) {\r
         // Check for missing Name.\r
-        const XMLCh* name = e->getAttributeNS(NULL, opensaml::saml2::Attribute::NAME_ATTRIB_NAME);\r
+        const XMLCh* name = child->getAttributeNS(NULL, opensaml::saml2::Attribute::NAME_ATTRIB_NAME);\r
         if (!name || !*name) {\r
             log.warn("skipping saml:Attribute declared with no Name");\r
-            e = XMLHelper::getNextSiblingElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
+            child = XMLHelper::getNextSiblingElement(child, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
             continue;\r
         }\r
 \r
-        auto_ptr_char id(e->getAttributeNS(NULL, opensaml::saml2::Attribute::FRIENDLYNAME_ATTRIB_NAME));\r
-        if (!id.get() || !*id.get()) {\r
-            log.warn("skipping saml:Attribute declared with no FriendlyName");\r
-            e = XMLHelper::getNextSiblingElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
+        const AttributeDecoder* decoder=NULL;\r
+        auto_ptr_char id(child->getAttributeNS(NULL, opensaml::saml2::Attribute::FRIENDLYNAME_ATTRIB_NAME));\r
+        auto_ptr_char d(child->getAttributeNS(SIMPLE_NS, decoderId));\r
+        if (!id.get() || !*id.get() || !d.get() || !*d.get() || !(decoder=m_decoderMap[d.get()])) {\r
+            log.warn("skipping saml:Attribute declared with no FriendlyName or resolvable AttributeDecoder");\r
+            child = XMLHelper::getNextSiblingElement(child, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
             continue;\r
         }\r
         \r
-        auto_ptr_char d(e->getAttributeNS(SIMPLE_NS, decoderType));\r
-        const char* dtype = d.get();\r
-        if (!dtype || !*dtype)\r
-            dtype = SIMPLE_ATTRIBUTE_DECODER;\r
-        AttributeDecoder*& decoder = m_decoderMap[dtype];\r
-        if (!decoder) {\r
-            try {\r
-                decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(dtype, NULL);\r
-            }\r
-            catch (exception& ex) {\r
-                log.error("error building AttributeDecoder: %s", ex.what());\r
-                e = XMLHelper::getNextSiblingElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
-                continue;\r
-            }\r
-        }\r
-                \r
         // Empty NameFormat implies the usual Shib URI naming defaults.\r
-        const XMLCh* format = e->getAttributeNS(NULL, opensaml::saml2::Attribute::NAMEFORMAT_ATTRIB_NAME);\r
+        const XMLCh* format = child->getAttributeNS(NULL, opensaml::saml2::Attribute::NAMEFORMAT_ATTRIB_NAME);\r
         if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI) ||\r
                 XMLString::equals(format, opensaml::saml2::Attribute::URI_REFERENCE))\r
             format = &chNull;  // ignore default Format/Namespace values\r
@@ -296,7 +299,7 @@ SimpleResolverImpl::SimpleResolverImpl(const DOMElement* e) : m_document(NULL),
 #endif\r
         if (decl.first) {\r
             log.warn("skipping duplicate saml:Attribute declaration (same Name and NameFormat)");\r
-            e = XMLHelper::getNextSiblingElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
+            child = XMLHelper::getNextSiblingElement(child, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
             continue;\r
         }\r
 \r
@@ -305,13 +308,13 @@ SimpleResolverImpl::SimpleResolverImpl(const DOMElement* e) : m_document(NULL),
             auto_ptr_char n(name);\r
             auto_ptr_char f(format);\r
 #endif\r
-            log.debug("creating declaration for (Name=%s) %s%s)", n.get(), *f.get() ? "(Format/Namespace=" : "", f.get());\r
+            log.debug("creating declaration for Attribute %s%s%s", n.get(), *f.get() ? ", Format/Namespace:" : "", f.get());\r
         }\r
         \r
         decl.first = decoder;\r
         decl.second = id.get();\r
         \r
-        e = XMLHelper::getNextSiblingElement(e, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
+        child = XMLHelper::getNextSiblingElement(child, samlconstants::SAML20_NS, opensaml::saml2::Attribute::LOCAL_NAME);\r
     }\r
 }\r
 \r
@@ -326,6 +329,9 @@ void SimpleResolverImpl::resolve(
 \r
     vector<shibsp::Attribute*>& resolved = ctx.getResolvedAttributes();\r
 \r
+    auto_ptr_char assertingParty(ctx.getEntityDescriptor() ? ctx.getEntityDescriptor()->getEntityID() : NULL);\r
+    const char* relyingParty = ctx.getApplication().getString("providerId").second;\r
+\r
 #ifdef HAVE_GOOD_STL\r
     map< pair<xstring,xstring>,pair<const AttributeDecoder*,string> >::const_iterator rule;\r
 #else\r
@@ -343,8 +349,13 @@ void SimpleResolverImpl::resolve(
         auto_ptr_char temp(format);\r
         if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {\r
 #endif\r
-            if (aset.empty() || aset.count(rule->second.second))\r
-                resolved.push_back(rule->second.first->decode(rule->second.second.c_str(), &ctx.getNameID()));\r
+            if (aset.empty() || aset.count(rule->second.second)) {\r
+                resolved.push_back(\r
+                    rule->second.first->decode(\r
+                        rule->second.second.c_str(), &ctx.getNameID(), assertingParty.get(), relyingParty\r
+                        )\r
+                    );\r
+            }\r
         }\r
     }\r
 \r
@@ -365,8 +376,11 @@ void SimpleResolverImpl::resolve(
             auto_ptr_char temp2(format);\r
             if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {\r
 #endif\r
-            if (aset.empty() || aset.count(rule->second.second))\r
-                resolved.push_back(rule->second.first->decode(rule->second.second.c_str(), *a));\r
+                if (aset.empty() || aset.count(rule->second.second)) {\r
+                    resolved.push_back(\r
+                        rule->second.first->decode(rule->second.second.c_str(), *a, assertingParty.get(), relyingParty)\r
+                        );\r
+                }\r
             }\r
         }\r
     }\r
@@ -383,6 +397,9 @@ void SimpleResolverImpl::resolve(
 \r
     vector<shibsp::Attribute*>& resolved = ctx.getResolvedAttributes();\r
 \r
+    auto_ptr_char assertingParty(ctx.getEntityDescriptor() ? ctx.getEntityDescriptor()->getEntityID() : NULL);\r
+    const char* relyingParty = ctx.getApplication().getString("providerId").second;\r
+\r
 #ifdef HAVE_GOOD_STL\r
     map< pair<xstring,xstring>,pair<const AttributeDecoder*,string> >::const_iterator rule;\r
 #else\r
@@ -400,8 +417,13 @@ void SimpleResolverImpl::resolve(
         auto_ptr_char temp(format);\r
         if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {\r
 #endif\r
-            if (aset.empty() || aset.count(rule->second.second))\r
-                resolved.push_back(rule->second.first->decode(rule->second.second.c_str(), &ctx.getNameID()));\r
+            if (aset.empty() || aset.count(rule->second.second)) {\r
+                resolved.push_back(\r
+                    rule->second.first->decode(\r
+                        rule->second.second.c_str(), &ctx.getNameID(), assertingParty.get(), relyingParty\r
+                        )\r
+                    );\r
+            }\r
         }\r
     }\r
 \r
@@ -422,8 +444,11 @@ void SimpleResolverImpl::resolve(
             auto_ptr_char temp2(format);\r
             if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {\r
 #endif\r
-            if (aset.empty() || aset.count(rule->second.second))\r
-                resolved.push_back(rule->second.first->decode(rule->second.second.c_str(), *a));\r
+                if (aset.empty() || aset.count(rule->second.second)) {\r
+                    resolved.push_back(\r
+                        rule->second.first->decode(rule->second.second.c_str(), *a, assertingParty.get(), relyingParty)\r
+                        );\r
+                }\r
             }\r
         }\r
     }\r