https://issues.shibboleth.net/jira/browse/SSPCPP-312
authorScott Cantor <cantor.2@osu.edu>
Tue, 26 Oct 2010 15:55:12 +0000 (15:55 +0000)
committerScott Cantor <cantor.2@osu.edu>
Tue, 26 Oct 2010 15:55:12 +0000 (15:55 +0000)
shibsp/Makefile.am
shibsp/attribute/Attribute.cpp
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/Base64AttributeDecoder.cpp [new file with mode: 0644]
shibsp/shibsp.vcxproj
shibsp/shibsp.vcxproj.filters

index 7681b5e..1a9c00e 100644 (file)
@@ -165,6 +165,7 @@ libshibsp_lite_la_SOURCES = \
 
 libshibsp_la_SOURCES = \
        ${common_sources} \
+       attribute/Base64AttributeDecoder.cpp \
        attribute/DOMAttributeDecoder.cpp \
        attribute/KeyInfoAttributeDecoder.cpp \
        attribute/NameIDAttributeDecoder.cpp \
index 6a7da4b..89f69bf 100644 (file)
@@ -56,6 +56,7 @@ namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory DOMAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory XMLAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory Base64AttributeDecoderFactory;
 
     static const XMLCh _StringAttributeDecoder[] = UNICODE_LITERAL_22(S,t,r,i,n,g,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _ScopedAttributeDecoder[] = UNICODE_LITERAL_22(S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
@@ -64,6 +65,11 @@ namespace shibsp {
     static const XMLCh _KeyInfoAttributeDecoder[] =UNICODE_LITERAL_23(K,e,y,I,n,f,o,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _DOMAttributeDecoder[] =    UNICODE_LITERAL_19(D,O,M,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _XMLAttributeDecoder[] =    UNICODE_LITERAL_19(X,M,L,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    static const XMLCh _Base64AttributeDecoder[] = {
+        chLatin_B, chLatin_a, chLatin_s, chLatin_e, chDigit_6, chDigit_4,
+        chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+        chLatin_D, chLatin_e, chLatin_c, chLatin_o, chLatin_d, chLatin_e, chLatin_r, chNull
+    };
 
     static const XMLCh caseSensitive[] =           UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
     static const XMLCh hashAlg[] =                 UNICODE_LITERAL_7(h,a,s,h,A,l,g);
@@ -79,6 +85,7 @@ xmltooling::QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::
 xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
 xmltooling::QName shibsp::DOMAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _DOMAttributeDecoder);
 xmltooling::QName shibsp::XMLAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _XMLAttributeDecoder);
+xmltooling::QName shibsp::Base64AttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _Base64AttributeDecoder);
 
 void shibsp::registerAttributeDecoders()
 {
@@ -90,6 +97,7 @@ void shibsp::registerAttributeDecoders()
     conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(DOMAttributeDecoderType, DOMAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(Base64AttributeDecoderType, Base64AttributeDecoderFactory);
 }
 
 AttributeDecoder::AttributeDecoder(const DOMElement *e)
index 24054f2..03b7485 100644 (file)
@@ -110,6 +110,9 @@ namespace shibsp {
     /** Decodes arbitrary XML into an XMLAttribute. */
     extern SHIBSP_API xmltooling::QName XMLAttributeDecoderType;
 
+    /** Decodes base64-encoded data into a SimpleAttribute. */
+    extern SHIBSP_API xmltooling::QName Base64AttributeDecoderType;
+
     /** Registers built-in AttributeDecoders into the runtime. */
     void registerAttributeDecoders();
 };
diff --git a/shibsp/attribute/Base64AttributeDecoder.cpp b/shibsp/attribute/Base64AttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..6f1edd7
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *  Copyright 2010 The Danish CLARIN Consortium
+ *
+ * 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.
+ */
+
+/**
+ * Base64AttributeDecoder.cpp
+ *
+ * Decodes SAML containing base64-encoded values into SimpleAttributes.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+#include <xercesc/util/Base64.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL Base64AttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        Base64AttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+        ~Base64AttributeDecoder() {}
+
+        shibsp::Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=nullptr, const char* relyingParty=nullptr
+            ) const;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL Base64AttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new Base64AttributeDecoder(e);
+    }
+};
+
+shibsp::Attribute* Base64AttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
+    vector<string>& dest = simple->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.Base64");
+
+    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+        if (saml2attr) {
+            const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml2attr->getName());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu base64-encoded value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+            if (saml1attr) {
+                const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+                v = values.begin();
+                stop = values.end();
+                if (log.isDebugEnabled()) {
+                    auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu base64-encoded value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+                }
+            }
+            else {
+                log.warn("XMLObject type not recognized by Base64AttributeDecoder, no values returned");
+                return nullptr;
+            }
+        }
+
+        for (; v!=stop; ++v) {
+            if (!(*v)->hasChildren()) {
+                auto_ptr_char val((*v)->getTextContent());
+                if (val.get() && *val.get()) {
+                    xsecsize_t x;
+                    XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(val.get()),&x);
+                    if (decoded) {
+                        dest.push_back(reinterpret_cast<char*>(decoded));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                        XMLString::release(&decoded);
+#else
+                        XMLString::release((char**)&decoded);
+#endif
+                    }
+                    else {
+                        log.warn("skipping AttributeValue, unable to base64-decode");
+                    }
+                }
+                else
+                    log.warn("skipping empty AttributeValue");
+            }
+            else {
+                log.warn("skipping complex AttributeValue");
+            }
+        }
+
+        return dest.empty() ? nullptr : _decode(simple.release());
+    }
+
+    const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
+    if (saml2name) {
+        if (log.isDebugEnabled()) {
+            auto_ptr_char f(saml2name->getFormat());
+            log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+        }
+        auto_ptr_char val(saml2name->getName());
+        if (val.get() && *val.get()) {
+            xsecsize_t x;
+            XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(val.get()),&x);
+            if (decoded) {
+                dest.push_back(reinterpret_cast<char*>(decoded));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&decoded);
+#else
+                XMLString::release((char**)&decoded);
+#endif
+            }
+            else {
+                log.warn("ignoring NameID, unable to base64-decode");
+            }
+        }
+        else
+            log.warn("ignoring empty NameID");
+    }
+    else {
+        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+        if (saml1name) {
+            if (log.isDebugEnabled()) {
+                auto_ptr_char f(saml1name->getFormat());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"
+                    );
+            }
+            auto_ptr_char val(saml1name->getName());
+            if (val.get() && *val.get()) {
+                xsecsize_t x;
+                XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(val.get()),&x);
+                if (decoded) {
+                    dest.push_back(reinterpret_cast<char*>(decoded));
+    #ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                    XMLString::release(&decoded);
+    #else
+                    XMLString::release((char**)&decoded);
+    #endif
+                }
+                else {
+                    log.warn("ignoring NameIdentifier, unable to base64-decode");
+                }
+            }
+            else
+                log.warn("ignoring empty NameIdentifier");
+        }
+        else {
+            log.warn("XMLObject type not recognized by Base64AttributeDecoder, no values returned");
+            return nullptr;
+        }
+    }
+
+    return dest.empty() ? nullptr : _decode(simple.release());
+}
index 58cb9a6..8839b82 100644 (file)
   <ItemGroup>\r
     <ClCompile Include="AbstractSPRequest.cpp" />\r
     <ClCompile Include="Application.cpp" />\r
+    <ClCompile Include="attribute\Base64AttributeDecoder.cpp" />\r
     <ClCompile Include="binding\impl\XMLProtocolProvider.cpp" />\r
     <ClCompile Include="handler\impl\DiscoveryFeed.cpp" />\r
     <ClCompile Include="handler\impl\LogoutInitiator.cpp" />\r
index a9d09ff..b52f78e 100644 (file)
     <ClCompile Include="handler\impl\DiscoveryFeed.cpp">\r
       <Filter>Source Files\handler\impl</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="attribute\Base64AttributeDecoder.cpp">\r
+      <Filter>Source Files\attribute</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="remoting\impl\SocketListener.h">\r