https://issues.shibboleth.net/jira/browse/SSPCPP-95
authorScott Cantor <cantor.2@osu.edu>
Thu, 17 Jul 2008 21:38:39 +0000 (21:38 +0000)
committerScott Cantor <cantor.2@osu.edu>
Thu, 17 Jul 2008 21:38:39 +0000 (21:38 +0000)
schemas/shibboleth-2.0-attribute-map.xsd
shibsp/Makefile.am
shibsp/attribute/Attribute.cpp
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp [new file with mode: 0644]
shibsp/shibsp.vcproj

index 634e895..3a72cda 100644 (file)
         </restriction>
     </simpleType>
 
+    <simpleType name="anyURI">
+        <restriction base="anyURI">
+            <minLength value="1"/>
+        </restriction>
+    </simpleType>
+
     <simpleType name="listOfStrings">
         <list itemType="am:string"/>
     </simpleType>
         </complexContent>
     </complexType>
 
+    <complexType name="NameIDFromScopedAttributeDecoder">
+        <annotation>
+            <documentation>
+                Decoder for attributes with scoped values that produces a NameID attribute with
+                the scope dropped and the NameQualifiers defaulted.
+            </documentation>
+        </annotation>
+        <complexContent>
+            <extension base="am:ScopedAttributeDecoder">
+                <attribute name="format" type="am:anyURI">
+                    <annotation>
+                        <documentation>
+                            Value to use as the NameID Format.
+                        </documentation>
+                    </annotation>
+                </attribute>
+                <attribute name="formatter" type="am:string">
+                    <annotation>
+                        <documentation>
+                            The pattern used to generate string versions of the attribute's values.
+                        </documentation>
+                    </annotation>
+                </attribute>
+            </extension>
+        </complexContent>
+    </complexType>
+
 </schema>
\ No newline at end of file
index 7145bdb..703da9d 100644 (file)
@@ -154,6 +154,7 @@ libshibsp_lite_la_SOURCES = \
 libshibsp_la_SOURCES = \
        ${common_sources} \
        attribute/NameIDAttributeDecoder.cpp \
+       attribute/NameIDFromScopedAttributeDecoder.cpp \
        attribute/ScopedAttributeDecoder.cpp \
        attribute/StringAttributeDecoder.cpp \
        attribute/filtering/impl/AttributeFilter.cpp \
index a943272..d4301e4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2007 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
@@ -16,7 +16,7 @@
 
 /**
  * shibsp/attribute/Attribute.cpp
- * 
+ *
  * A resolved attribute.
  */
 
@@ -41,23 +41,25 @@ namespace shibsp {
     SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in) {
         return new SimpleAttribute(in);
     }
-    
+
     SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in) {
         return new ScopedAttribute(in);
     }
-    
+
     SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in) {
         return new NameIDAttribute(in);
     }
-    
+
 #ifndef SHIBSP_LITE
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory NameIDAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
 
     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);
     static const XMLCh _NameIDAttributeDecoder[] = UNICODE_LITERAL_22(N,a,m,e,I,D,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    static const XMLCh _NameIDFromScopedAttributeDecoder[] = UNICODE_LITERAL_32(N,a,m,e,I,D,F,r,o,m,S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
 
     static const XMLCh caseSensitive[] =           UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
 #endif
@@ -67,6 +69,7 @@ namespace shibsp {
 QName shibsp::StringAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _StringAttributeDecoder);
 QName shibsp::ScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _ScopedAttributeDecoder);
 QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDAttributeDecoder);
+QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
 
 void shibsp::registerAttributeDecoders()
 {
@@ -74,6 +77,7 @@ void shibsp::registerAttributeDecoders()
     conf.AttributeDecoderManager.registerFactory(StringAttributeDecoderType, StringAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(ScopedAttributeDecoderType, ScopedAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(NameIDAttributeDecoderType, NameIDAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(NameIDFromScopedAttributeDecoderType, NameIDFromScopedAttributeDecoderFactory);
 }
 
 AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true)
index 4d0fe94..7063ceb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright 2001-2007 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
@@ -16,7 +16,7 @@
 
 /**
  * @file shibsp/attribute/AttributeDecoder.h
- * 
+ *
  * Decodes SAML NameID/Attribute objects into resolved Attributes.
  */
 
@@ -47,10 +47,10 @@ namespace shibsp {
 
     public:
         virtual ~AttributeDecoder() {}
-        
+
         /**
          * Decodes an XMLObject into a resolved Attribute.
-         * 
+         *
          * @param ids               array containing primary identifier in first position, followed by any aliases
          * @param xmlObject         XMLObject to decode
          * @param assertingParty    name of the party asserting the attribute
@@ -68,13 +68,16 @@ namespace shibsp {
 
     /** Decodes into a SimpleAttribute. */
     extern SHIBSP_API xmltooling::QName StringAttributeDecoderType;
-    
-    /** Decodes into a ScopedAttribute. */
+
+    /** Decodes scoped and NameID attributes into a ScopedAttribute. */
     extern SHIBSP_API xmltooling::QName ScopedAttributeDecoderType;
 
-    /** Decodes into a NameIDAttribute. */
+    /** Decodes NameID information into a NameIDAttribute. */
     extern SHIBSP_API xmltooling::QName NameIDAttributeDecoderType;
 
+    /** Decodes scoped attributes into a NameIDAttribute. */
+    extern SHIBSP_API xmltooling::QName NameIDFromScopedAttributeDecoderType;
+
     /** Registers built-in AttributeDecoders into the runtime. */
     void registerAttributeDecoders();
 };
diff --git a/shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp b/shibsp/attribute/NameIDFromScopedAttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..7e807b9
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *  Copyright 2001-2007 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.
+ */
+
+/**
+ * NameIDFromNameIDFromScopedAttributeDecoder.cpp
+ *
+ * Decodes SAML "scoped" attributes into NameIDAttributes.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/NameIDAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    static XMLCh format[] =                 UNICODE_LITERAL_6(f,o,r,m,a,t);
+    static XMLCh formatter[] =              UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+    static const XMLCh Scope[] =            UNICODE_LITERAL_5(S,c,o,p,e);
+    static const XMLCh scopeDelimeter[] =   UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,e,t,e,r);
+
+    class SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        NameIDFromScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimeter('@'),
+                m_format(e ? e->getAttributeNS(NULL,format) : NULL), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) {
+            if (e && e->hasAttributeNS(NULL,scopeDelimeter)) {
+                auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimeter));
+                m_delimeter = *(d.get());
+            }
+        }
+        ~NameIDFromScopedAttributeDecoder() {}
+
+        shibsp::Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        char m_delimeter;
+        auto_ptr_char m_format;
+        auto_ptr_char m_formatter;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new NameIDFromScopedAttributeDecoder(e);
+    }
+};
+
+shibsp::Attribute* NameIDFromScopedAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+
+    char* val;
+    char* scope;
+    const XMLCh* xmlscope;
+    QName scopeqname(NULL,Scope);
+    auto_ptr<NameIDAttribute> nameid(
+        new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)
+        );
+    nameid->setCaseSensitive(m_caseSensitive);
+    vector<NameIDAttribute::Value>& dest = nameid->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameIDFromScoped");
+
+    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 NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu 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 NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                        ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                        );
+                }
+            }
+            else {
+                log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");
+                return NULL;
+            }
+        }
+
+        for (; v!=stop; ++v) {
+            if (!(*v)->hasChildren()) {
+                val = toUTF8((*v)->getTextContent());
+                if (val && *val) {
+                    dest.push_back(NameIDAttribute::Value());
+                    NameIDAttribute::Value& destval = dest.back();
+                    const AttributeExtensibleXMLObject* aexo=dynamic_cast<const AttributeExtensibleXMLObject*>(*v);
+                    xmlscope = aexo ? aexo->getAttribute(scopeqname) : NULL;
+                    if (!xmlscope || !*xmlscope) {
+                        // Terminate the value at the scope delimiter.
+                        if (scope = strchr(val, m_delimeter))
+                            *scope++ = 0;
+                    }
+                    destval.m_Name = val;
+                    if (m_format.get() && *m_format.get())
+                        destval.m_Format = m_format.get();
+                    if (assertingParty)
+                        destval.m_NameQualifier = assertingParty;
+                    if (relyingParty)
+                        destval.m_SPNameQualifier = relyingParty;
+                }
+                else {
+                    log.warn("skipping empty AttributeValue");
+                }
+                delete[] val;
+            }
+            else {
+                log.warn("skipping complex AttributeValue");
+            }
+        }
+
+        return dest.empty() ? NULL : nameid.release();
+    }
+
+    log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");
+    return NULL;
+}
index 85acc66..bb58f7e 100644 (file)
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\NameIDFromScopedAttributeDecoder.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\ScopedAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r