Migration of eduPerson code.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Fri, 4 Apr 2003 05:23:15 +0000 (05:23 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Fri, 4 Apr 2003 05:23:15 +0000 (05:23 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@349 cb58f699-b61c-0410-a6fe-9272a202ed29

13 files changed:
configs/AAP.xml
configs/Makefile.am
configs/shibboleth.ini
schemas/Makefile.am
shib/AAP.cpp [new file with mode: 0644]
shib/Constants.cpp
shib/Makefile.am
shib/ScopedAttribute.cpp [new file with mode: 0644]
shib/ShibConfig.cpp
shib/SimpleAttribute.cpp [new file with mode: 0644]
shib/XML.cpp
shib/internal.h
shib/shib.h

index beac9b9..d91aa00 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="US-ASCII"?>
-<AttributeAcceptancePolicy xmlns="urn:mace:eduPerson:1.0">
+<AttributeAcceptancePolicy xmlns="urn:mace:shibboleth:1.0">
        
        <!--
        An AAP is a set of AttributeRule elements, each one
@@ -13,7 +13,7 @@
                <!--
                Optional site rule that applies to any site
                <AnySite>
-                       <Value>urn:mace:example.edu:exampleEntitlement</Value> ==== a literal test
+                       <Value>urn:mace:example.edu:exampleEntitlement</Value> <==== a literal test
                        <Value Type="regexp">^.+$</Value> ==== any value
                </AnySite>
                -->
index 8bfa395..18cc0f2 100644 (file)
@@ -4,13 +4,13 @@ AUTOMAKE_OPTIONS = foreign
 
 pkgsysconfdir = $(sysconfdir)/@PACKAGE@
 pkgsysconf_DATA = \
-                shibboleth.ini \
-                shibboleth.logger \
-                shire.logger \
-                shar.logger \
-                apache.config \
-                ca-bundle.crt \
-                accessError.html \
-                rmError.html \
-                shireError.html \
-               AAP.xml
+       shibboleth.ini \
+       shibboleth.logger \
+       shire.logger \
+       shar.logger \
+       apache.config \
+       ca-bundle.crt \
+       accessError.html \
+       rmError.html \
+       shireError.html \
+       AAP.xml
index de6bf43..abe30f2 100644 (file)
@@ -8,8 +8,6 @@ sitesFile=http://wayf.internet2.edu/shibboleth/sites.xml
 sitesCertFile=/opt/shibboleth/etc/shibboleth/internet2.pem
 sitesRefresh=3600
 
-aap-uri=/opt/shibboleth/etc/shibboleth/AAP.xml
-
 # SERVER CONFIGURATION
 
 # Optional
@@ -37,6 +35,7 @@ logger=/opt/shibboleth/etc/shibboleth/shar.logger
 #keyfile=/opt/shibboleth/etc/shibboleth/shar.key
 #keypass=
 calist=/opt/shibboleth/etc/shibboleth/ca-bundle.crt
+aap-uri=/opt/shibboleth/etc/shibboleth/AAP.xml
 
 # The following shar items are for caching parameters
 cacheType=memory
@@ -45,8 +44,10 @@ cacheClean=300
 # idle timeout (in minutes)  (240 == 8*60 == 8 hours)
 cacheTimeout=240
 
-[extensions:saml]
-eduPerson=/opt/shibboleth/lib/libeduPerson.so
+[attributes]
+urn:mace:eduPerson:1.0:eduPersonPrincipalName=scoped
+urn:mace:eduPerson:1.0:eduPersonScopedAffiliation=scoped
+urn:mace:eduPerson:1.0:eduPersonEntitlement=simple
 
 [policies]
 InCommon=urn:mace:InCommon:pilot:2003
index db7561f..0c2127e 100644 (file)
@@ -10,5 +10,4 @@ pkgsysconf_DATA = \
                 xmldsig-core-schema.xsd \
                 xmldsig-filter2.xsd \
                 xml.xsd \
-                eduPerson.xsd \
                 shibboleth.xsd
diff --git a/shib/AAP.cpp b/shib/AAP.cpp
new file mode 100644 (file)
index 0000000..f00cbcb
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* AAP.cpp - XML AAP implementation
+
+   Scott Cantor
+   12/21/02
+
+   $History:$
+*/
+
+#include "internal.h"
+
+#include <log4cpp/Category.hh>
+
+using namespace shibboleth;
+using namespace saml;
+using namespace log4cpp;
+using namespace std;
+
+#include <xercesc/framework/URLInputSource.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
+
+AAP::AAP(const char* uri)
+{
+    NDC ndc("AAP");
+    Category& log=Category::getInstance(SHIB_LOGCAT".AAP");
+
+    saml::XML::Parser p;
+    DOMDocument* doc=NULL;
+       try
+    {
+        static XMLCh base[]={chLatin_f, chLatin_i, chLatin_l, chLatin_e, chColon, chForwardSlash, chForwardSlash, chForwardSlash, chNull};
+        URLInputSource src(base,uri);
+        Wrapper4InputSource dsrc(&src,false);
+               doc=p.parse(dsrc);
+
+        log.infoStream() << "Loaded and parsed AAP (" << uri << ")" << CategoryStream::ENDLINE;
+
+               DOMElement* e = doc->getDocumentElement();
+        if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
+            XMLString::compareString(XML::Literals::AttributeAcceptancePolicy,e->getLocalName()))
+        {
+                       log.error("Construction requires a valid AAP file: (shib:AttributeAcceptancePolicy as root element)");
+                       throw MalformedException("Construction requires a valid site file: (shib:AttributeAcceptancePolicy as root element)");
+               }
+
+               // Loop over the AttributeRule elements.
+        DOMNodeList* nlist = e->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::AttributeRule);
+               for (int i=0; nlist && i<nlist->getLength(); i++)
+        {
+            // Insert an empty rule, then get a reference to it.
+            m_attrMap[static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,XML::Literals::Name)]=AttributeRule();
+            AttributeRule& arule=m_attrMap[static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,XML::Literals::Name)];
+
+            // Check for an AnySite rule.
+                       DOMNode* anysite = nlist->item(i)->getFirstChild();
+                       while (anysite && anysite->getNodeType()!=DOMNode::ELEMENT_NODE)
+            {
+                               anysite = anysite->getNextSibling();
+                               continue;
+                       }
+
+            if (anysite && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anysite)->getNamespaceURI()) &&
+                !XMLString::compareString(XML::Literals::AnySite,static_cast<DOMElement*>(anysite)->getLocalName()))
+            {
+                // Process each Value element.
+                DOMNodeList* vlist = static_cast<DOMElement*>(anysite)->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::Value);
+                for (int j=0; vlist && j<vlist->getLength(); j++)
+                {
+                    DOMElement* ve=static_cast<DOMElement*>(vlist->item(j));
+                    DOMNode* valnode=ve->getFirstChild();
+                    if (valnode && valnode->getNodeType()==DOMNode::TEXT_NODE)
+                    {
+                        if (!XMLString::compareString(XML::Literals::literal,ve->getAttributeNS(NULL,XML::Literals::Type)))
+                            arule.m_anySiteRule.push_back(
+                                pair<AttributeRule::value_type,xstring>(AttributeRule::literal,valnode->getNodeValue())
+                                );
+                        else if (!XMLString::compareString(XML::Literals::regexp,ve->getAttributeNS(NULL,XML::Literals::Type)))
+                            arule.m_anySiteRule.push_back(
+                                pair<AttributeRule::value_type,xstring>(AttributeRule::regexp,valnode->getNodeValue())
+                                );
+                        else if (!XMLString::compareString(XML::Literals::xpath,ve->getAttributeNS(NULL,XML::Literals::Type)))
+                            arule.m_anySiteRule.push_back(
+                                pair<AttributeRule::value_type,xstring>(AttributeRule::xpath,valnode->getNodeValue())
+                                );
+                    }
+                }
+            }
+
+            // Loop over the SiteRule elements.
+            DOMNodeList* slist = static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::SiteRule);
+                   for (int k=0; slist && k<slist->getLength(); k++)
+            {
+                arule.m_siteMap[static_cast<DOMElement*>(slist->item(k))->getAttributeNS(NULL,XML::Literals::Name)]=AttributeRule::SiteRule();
+                AttributeRule::SiteRule& srule=arule.m_siteMap[static_cast<DOMElement*>(slist->item(k))->getAttributeNS(NULL,XML::Literals::Name)];
+
+                // Process each Value element.
+                DOMNodeList* vlist = static_cast<DOMElement*>(slist->item(k))->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::Value);
+                for (int j=0; vlist && j<vlist->getLength(); j++)
+                {
+                    DOMElement* ve=static_cast<DOMElement*>(vlist->item(j));
+                    DOMNode* valnode=ve->getFirstChild();
+                    if (valnode && valnode->getNodeType()==DOMNode::TEXT_NODE)
+                    {
+                        if (!XMLString::compareString(XML::Literals::literal,ve->getAttributeNS(NULL,XML::Literals::Type)))
+                            srule.push_back(
+                                pair<AttributeRule::value_type,xstring>(AttributeRule::literal,valnode->getNodeValue())
+                                );
+                        else if (!XMLString::compareString(XML::Literals::regexp,ve->getAttributeNS(NULL,XML::Literals::Type)))
+                            srule.push_back(
+                                pair<AttributeRule::value_type,xstring>(AttributeRule::regexp,valnode->getNodeValue())
+                                );
+                        else if (!XMLString::compareString(XML::Literals::xpath,ve->getAttributeNS(NULL,XML::Literals::Type)))
+                            srule.push_back(
+                                pair<AttributeRule::value_type,xstring>(AttributeRule::xpath,valnode->getNodeValue())
+                                );
+                    }
+                }
+            }
+               }
+    }
+    catch (SAMLException& e)
+    {
+        log.errorStream() << "XML error while parsing AAP: " << e.what() << CategoryStream::ENDLINE;
+        if (doc)
+            doc->release();
+               throw;
+       }
+    catch (...)
+    {
+               log.error("Unexpected error while parsing AAP");
+        if (doc)
+            doc->release();
+               throw;
+    }
+
+}
+
+bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
+{
+    NDC ndc("accept");
+    log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".AAP");
+    
+    if (log.isDebugEnabled())
+    {
+        auto_ptr<char> temp(XMLString::transcode(name));
+        auto_ptr<char> temp2(XMLString::transcode(originSite));
+        log.debug("evaluating value for attribute '%s' from site '%s'",temp.get(),temp2.get());
+    }
+
+    map<xstring,AttributeRule>::const_iterator arule=m_attrMap.find(name);
+    if (arule==m_attrMap.end())
+    {
+        log.warn("attribute not found in AAP, any value is rejected");
+        return false;
+    }
+
+    // Don't currently support non-simple content models...
+    DOMNode* n=e->getFirstChild();
+    if (!n || n->getNodeType()!=DOMNode::TEXT_NODE)
+    {
+        log.warn("implementation does not support complex attribute values");
+        return false;
+    }
+
+    for (AttributeRule::SiteRule::const_iterator i=arule->second.m_anySiteRule.begin(); i!=arule->second.m_anySiteRule.end(); i++)
+    {
+        if (i->first==AttributeRule::literal && i->second==n->getNodeValue())
+        {
+            log.debug("any site, literal match");
+            return true;
+        }
+        else if (i->first==AttributeRule::regexp)
+        {
+            try
+            {
+                RegularExpression re(i->second.c_str());
+                if (re.matches(n->getNodeValue()))
+                {
+                    log.debug("any site, regexp match");
+                    return true;
+                }
+            }
+            catch (XMLException& ex)
+            {
+                auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
+                log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
+                    << log4cpp::CategoryStream::ENDLINE;
+            }
+        }
+        else
+            log.warn("implementation does not support XPath value rules");
+    }
+
+    map<xstring,AttributeRule::SiteRule>::const_iterator srule=arule->second.m_siteMap.find(originSite);
+    if (srule==arule->second.m_siteMap.end())
+    {
+        log.warn("site not found in attribute ruleset, any value is rejected");
+        return false;
+    }
+
+    for (AttributeRule::SiteRule::const_iterator j=srule->second.begin(); j!=srule->second.end(); j++)
+    {
+        if (j->first==AttributeRule::literal && j->second==n->getNodeValue())
+        {
+            log.debug("matching site, literal match");
+            return true;
+        }
+        else if (j->first==AttributeRule::regexp)
+        {
+            try
+            {
+                RegularExpression re(j->second.c_str());
+                if (re.matches(n->getNodeValue()))
+                {
+                    log.debug("matching site, regexp match");
+                    return true;
+                }
+            }
+            catch (XMLException& ex)
+            {
+                auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
+                log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
+                    << log4cpp::CategoryStream::ENDLINE;
+            }
+        }
+        else
+            log.warn("implementation does not support XPath value rules");
+    }
+
+    log.warn("attribute value could not be validated by AAP, rejecting it");
+    return false;
+}
index 5fc5d0b..f243f1c 100644 (file)
 
 #include "internal.h"
 
-const XMLCh shibboleth::Constants::POLICY_INCOMMON[] = // urn:mace:InCommon:2003
+using namespace shibboleth;
+
+const XMLCh Constants::POLICY_INCOMMON[] = // urn:mace:InCommon:2003
 { chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
   chLatin_I, chLatin_n, chLatin_C, chLatin_o, chLatin_m, chLatin_m, chLatin_o, chLatin_n, chColon,
   chDigit_2, chDigit_0, chDigit_0, chDigit_3, chNull
 };
 
-const XMLCh shibboleth::Constants::SHIB_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri
+const XMLCh Constants::SHIB_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri
 {
   chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
   chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
@@ -73,7 +75,7 @@ const XMLCh shibboleth::Constants::SHIB_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:
   chLatin_u, chLatin_r, chLatin_i, chNull
 };
 
-const XMLCh shibboleth::Constants::SHIB_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier
+const XMLCh Constants::SHIB_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier
 {
   chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
   chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
@@ -81,3 +83,4 @@ const XMLCh shibboleth::Constants::SHIB_NAMEID_FORMAT_URI[] = // urn:mace:shibbo
   chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull
 };
 
+saml::QName Constants::SHIB_ATTRIBUTE_VALUE_TYPE(XML::SHIB_NS,XML::Literals::AttributeValueType);
index 8df6584..bdde0ca 100644 (file)
@@ -9,6 +9,7 @@ libshib_HEADERS = shib.h shib-threads.h
 noinst_HEADERS = internal.h
 
 libshib_la_SOURCES = \
+                                       AAP.cpp \
                     ClubShibPOSTProfile.cpp \
                     Constants.cpp \
                     OriginSiteMapper.cpp \
@@ -16,6 +17,8 @@ libshib_la_SOURCES = \
                     ShibConfig.cpp \
                     ShibPOSTProfile.cpp \
                     ShibPOSTProfileFactory.cpp \
+                    ScopedAttribute.cpp \
+                    SimpleAttribute.cpp \
                     XML.cpp \
                     XMLOriginSiteMapper.cpp \
                     shib-threads.cpp
diff --git a/shib/ScopedAttribute.cpp b/shib/ScopedAttribute.cpp
new file mode 100644 (file)
index 0000000..880b8bc
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* ScopedAttribute.cpp - eduPerson scoped attribute base class
+
+   Scott Cantor
+   6/4/02
+
+   $History:$
+*/
+
+#include "internal.h"
+#include <xercesc/util/regx/RegularExpression.hpp>
+#include <log4cpp/Category.hh>
+
+using namespace shibboleth;
+using namespace saml;
+using namespace log4cpp;
+using namespace std;
+
+
+ScopedAttribute::ScopedAttribute(const XMLCh* name, const XMLCh* ns, long lifetime,
+                                 const saml::Iterator<const XMLCh*>& scopes,
+                                 const saml::Iterator<const XMLCh*>& values)
+    : SimpleAttribute(name,ns,lifetime,values)
+{
+    if (scopes.size()!=values.size())
+        throw MalformedException(SAMLException::RESPONDER,"ScopedAttribute() requires the number of scopes to equal the number of values");
+
+    while (scopes.hasNext())
+        m_values.push_back(scopes.next());
+}
+
+ScopedAttribute::ScopedAttribute(DOMElement* e) : SimpleAttribute(e) {}
+
+ScopedAttribute::~ScopedAttribute() {}
+
+bool ScopedAttribute::addValue(DOMElement* e)
+{
+    static XMLCh empty[] = {chNull};
+    if (SAMLAttribute::addValue(e))
+    {
+        DOMAttr* scope=e->getAttributeNodeNS(NULL,Scope);
+        m_scopes.push_back(scope ? scope->getNodeValue() : empty);
+        return true;
+    }
+    return false;
+}
+
+bool ScopedAttribute::accept(DOMElement* e) const
+{
+    OriginSiteMapper mapper;
+    Iterator<pair<xstring,bool> > domains=mapper.getSecurityDomains(m_originSite.c_str());
+    const XMLCh* this_scope=NULL;
+    DOMAttr* scope=e->getAttributeNodeNS(NULL,Scope);
+    if (scope)
+        this_scope=scope->getNodeValue();
+    if (!this_scope || !*this_scope)
+        this_scope=m_originSite.c_str();
+
+    while (domains.hasNext())
+    {
+        const pair<xstring,bool>& p=domains.next();
+        if (p.second)
+        {
+            try
+            {
+                RegularExpression re(p.first.c_str());
+                if (re.matches(this_scope))
+                    return true;
+            }
+            catch (XMLException& ex)
+            {
+                auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
+                NDC ndc("accept");
+                Category& log=Category::getInstance(SHIB_LOGCAT".ScopedAttribute");
+                log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
+                    << CategoryStream::ENDLINE;
+                return false;
+            }
+        }
+        else if (p.first==this_scope)
+            return true;
+    }
+
+    NDC ndc("accept");
+    Category& log=Category::getInstance(SHIB_LOGCAT".ScopedAttribute");
+    if (log.isWarnEnabled())
+    {
+        auto_ptr<char> tmp(XMLString::transcode(this_scope));
+        log.warn("rejecting value with scope of %s",tmp.get());
+    }
+    return false;
+}
+
+Iterator<xstring> ScopedAttribute::getValues() const
+{
+    if (m_scopedValues.empty())
+    {
+        vector<xstring>::const_iterator j=m_scopes.begin();
+        for (vector<xstring>::const_iterator i=m_values.begin(); i!=m_values.end(); i++, j++)
+            m_scopedValues.push_back((*i) + chAt + (!j->empty() ? (*j) : m_originSite));
+    }
+    return Iterator<xstring>(m_scopedValues);
+}
+
+Iterator<string> ScopedAttribute::getSingleByteValues() const
+{
+    getValues();
+    if (m_sbValues.empty())
+    {
+        for (vector<xstring>::const_iterator i=m_scopedValues.begin(); i!=m_scopedValues.end(); i++)
+       {
+           auto_ptr<char> temp(XMLString::transcode(i->c_str()));
+           m_sbValues.push_back(temp.get());
+       }
+    }
+    return Iterator<string>(m_sbValues);
+}
+
+SAMLObject* ScopedAttribute::clone() const
+{
+    ScopedAttribute* dest=new ScopedAttribute(m_name,m_namespace,m_lifetime);
+    dest->m_values.assign(m_values.begin(),m_values.end());
+    dest->m_scopes.assign(m_scopes.begin(),m_scopes.end());
+    return dest;
+}
+
+DOMNode* ScopedAttribute::toDOM(DOMDocument* doc,bool xmlns) const
+{
+    SimpleAttribute::toDOM(doc,xmlns);
+
+    int i=0;
+    DOMNode* n=m_root->getFirstChild();
+    while (n)
+    {
+        if (n->getNodeType()==DOMNode::ELEMENT_NODE)
+        {
+            static_cast<DOMElement*>(n)->setAttributeNS(NULL,Scope,
+                (!m_scopes[i].empty() ? m_scopes[i].c_str() : m_originSite.c_str()));
+            i++;
+        }
+        n=n->getNextSibling();
+    }
+
+    return m_root;
+}
+
+const XMLCh ScopedAttribute::Scope[] = { chLatin_S, chLatin_c, chLatin_o, chLatin_p, chLatin_e, chNull };
index c9c2edc..5f89017 100644 (file)
@@ -70,6 +70,16 @@ using namespace shibboleth;
 SAML_EXCEPTION_FACTORY(UnsupportedProtocolException);
 SAML_EXCEPTION_FACTORY(OriginSiteMapperException);
 
+extern "C" SAMLAttribute* ScopedFactory(DOMElement* e)
+{
+    return new ScopedAttribute(e);
+}
+
+extern "C" SAMLAttribute* SimpleFactory(DOMElement* e)
+{
+    return new SimpleAttribute(e);
+}
+
 namespace {
     ShibInternalConfig g_config;
 }
@@ -86,6 +96,19 @@ bool ShibInternalConfig::init()
     // Register extension schema.
     saml::XML::registerSchema(XML::SHIB_NS,XML::SHIB_SCHEMA_ID);
 
+    if (!aapURL.empty())
+    {
+        try
+        {
+            m_AAP=new AAP(aapURL.c_str());
+        }
+        catch(SAMLException& e)
+        {
+            log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to initialize AAP: %s", e.what());
+            return false;
+        }
+    }
+
     m_lock=RWLock::create();
     m_shutdown_wait = CondWait::create();
     if (!m_lock || !m_shutdown_wait)
@@ -93,6 +116,7 @@ bool ShibInternalConfig::init()
         log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to create mapper locks");
         delete m_lock;
         delete m_shutdown_wait;
+        delete m_AAP;
         return false;
     }
 
@@ -105,6 +129,7 @@ bool ShibInternalConfig::init()
         log4cpp::Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to initialize origin site mapper: %s", e.what());
         delete m_lock;
         delete m_shutdown_wait;
+        delete m_AAP;
         return false;
     }
 
@@ -117,6 +142,7 @@ bool ShibInternalConfig::init()
         delete m_mapper;
         delete m_lock;
         delete m_shutdown_wait;
+        delete m_AAP;
         return false;
     }
     SAMLConfig::getConfig().xmlsig_ptr=m_manager;
@@ -142,6 +168,7 @@ void ShibInternalConfig::term()
     delete mapperCert;
     delete m_lock;
     delete m_shutdown_wait;
+    delete m_AAP;
 }
 
 IOriginSiteMapper* ShibInternalConfig::getMapper()
diff --git a/shib/SimpleAttribute.cpp b/shib/SimpleAttribute.cpp
new file mode 100644 (file)
index 0000000..4869584
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* SimpleAttribute.cpp - simple attribute implementation with AAP-support
+
+   Scott Cantor
+   12/19/02
+
+   $History:$
+*/
+
+#include "internal.h"
+
+using namespace shibboleth;
+
+SimpleAttribute::SimpleAttribute(const XMLCh* name, const XMLCh* ns, long lifetime, const saml::Iterator<const XMLCh*>& values)
+    : SAMLAttribute(name,ns,&Constants::SHIB_ATTRIBUTE_VALUE_TYPE,lifetime,values) {}
+
+SimpleAttribute::SimpleAttribute(DOMElement* e) : SAMLAttribute(e)
+{
+    // Default scope comes from subject.
+    DOMNodeList* nlist=
+        static_cast<DOMElement*>(e->getParentNode())->getElementsByTagNameNS(saml::XML::SAML_NS,L(NameIdentifier));
+    if (!nlist || nlist->getLength() != 1)
+        throw saml::MalformedException(saml::SAMLException::RESPONDER,"SimpleAttribute() can't find saml:NameIdentifier in enclosing statement");
+    m_originSite=static_cast<DOMElement*>(nlist->item(0))->getAttributeNS(NULL,L(NameQualifier));
+}
+
+SimpleAttribute::~SimpleAttribute() {}
+
+saml::SAMLObject* SimpleAttribute::clone() const
+{
+    SimpleAttribute* dest=new SimpleAttribute(m_name,m_namespace,m_lifetime);
+    dest->m_originSite=m_originSite;
+    dest->m_values.assign(m_values.begin(),m_values.end());
+    return dest;
+}
+
+bool SimpleAttribute::accept(DOMElement* e) const
+{
+    ShibInternalConfig& conf=dynamic_cast<ShibInternalConfig&>(ShibConfig::getConfig());
+    return conf.m_AAP ? conf.m_AAP->accept(m_name,m_originSite.c_str(),e) : true;
+}
index ff782f6..074dd6d 100644 (file)
@@ -77,6 +77,11 @@ const XMLCh XML::SHIB_SCHEMA_ID[] = // shibboleth.xsd
 
 // Shibboleth vocabulary literals
 
+const XMLCh XML::Literals::AttributeValueType[] =
+{ chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+  chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull
+};
+
 const XMLCh XML::Literals::Domain[]=
 { chLatin_D, chLatin_o, chLatin_m, chLatin_a, chLatin_i, chLatin_n, chNull };
 
@@ -94,11 +99,40 @@ const XMLCh XML::Literals::Name[]=
 const XMLCh XML::Literals::OriginSite[]=
 { chLatin_O, chLatin_r, chLatin_i, chLatin_g, chLatin_i, chLatin_n, chLatin_S, chLatin_i, chLatin_t, chLatin_e, chNull };
 
-const XMLCh XML::Literals::regexp[]=
-{ chLatin_r, chLatin_e, chLatin_g, chLatin_e, chLatin_x, chLatin_p, chNull };
-
 const XMLCh XML::Literals::Sites[]=
 { chLatin_S, chLatin_i, chLatin_t, chLatin_e, chLatin_s, chNull };
 
+const XMLCh XML::Literals::AnySite[]=
+{ chLatin_A, chLatin_n, chLatin_y, chLatin_S, chLatin_i, chLatin_t, chLatin_e, chNull };
+
+const XMLCh XML::Literals::AttributeAcceptancePolicy[] =
+{ chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+  chLatin_A, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chLatin_a, chLatin_n, chLatin_c, chLatin_e,
+  chLatin_P, chLatin_o, chLatin_l, chLatin_i, chLatin_c, chLatin_y, chNull
+};
+
+const XMLCh XML::Literals::AttributeRule[] =
+{ chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+  chLatin_R, chLatin_u, chLatin_l, chLatin_e, chNull
+};
+
+const XMLCh XML::Literals::SiteRule[] =
+{ chLatin_S, chLatin_i, chLatin_t, chLatin_e, chLatin_R, chLatin_u, chLatin_l, chLatin_e, chNull };
+
+const XMLCh XML::Literals::Type[]=
+{ chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull };
+
+const XMLCh XML::Literals::Value[] =
+{ chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chNull };
+
+const XMLCh XML::Literals::literal[] =
+{ chLatin_l, chLatin_i, chLatin_t, chLatin_e, chLatin_r, chLatin_a, chLatin_l, chNull };
+
+const XMLCh XML::Literals::regexp[] =
+{ chLatin_r, chLatin_e, chLatin_g, chLatin_e, chLatin_x, chLatin_p, chNull };
+
+const XMLCh XML::Literals::xpath[] =
+{ chLatin_x, chLatin_p, chLatin_a, chLatin_t, chLatin_h, chNull };
+
 const XMLCh XML::Literals::xmlns_shib[]=
 { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chColon, chLatin_s, chLatin_h, chLatin_i, chLatin_b, chNull };
index edc0335..a22b898 100644 (file)
 
 namespace shibboleth
 {
-    class ShibInternalConfig : public ShibConfig
-    {
-    public:
-        ShibInternalConfig() : m_mapper(NULL), m_manager(NULL), m_lock(NULL), m_shutdown_wait(NULL), m_refresh_thread(NULL), m_shutdown(false) {}
-
-        // global per-process setup and shutdown of runtime
-        bool init();
-        void term();
-
-        IOriginSiteMapper* getMapper();
-        void releaseMapper(IOriginSiteMapper* mapper);
-        void refresh();
-
-    private:
-        IOriginSiteMapper* m_mapper;
-        xmlSecKeysMngrPtr m_manager;
-        RWLock* m_lock;
-        static void* refresh_fn(void*);
-        bool m_shutdown;
-        CondWait* m_shutdown_wait;
-        Thread*        m_refresh_thread;
-    };
-
     class SHIB_EXPORTS XMLOriginSiteMapper : public IOriginSiteMapper
     {
     public:
@@ -127,6 +104,48 @@ namespace shibboleth
         std::map<saml::xstring,saml::X509Certificate*> m_hsCerts;
     };
 
+    class AAP
+    {
+    public:
+        AAP(const char* uri);
+        bool accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e);
+
+    private:
+        struct AttributeRule
+        {
+            enum value_type { literal, regexp, xpath };
+            typedef std::vector<std::pair<value_type,saml::xstring> > SiteRule;
+            SiteRule m_anySiteRule;
+            std::map<saml::xstring,SiteRule> m_siteMap;
+        };
+
+        std::map<saml::xstring,AttributeRule> m_attrMap;
+    };
+
+    class ShibInternalConfig : public ShibConfig
+    {
+    public:
+        ShibInternalConfig() : m_AAP(NULL), m_mapper(NULL), m_manager(NULL), m_lock(NULL),
+            m_shutdown_wait(NULL), m_refresh_thread(NULL), m_shutdown(false) {}
+
+        // global per-process setup and shutdown of runtime
+        bool init();
+        void term();
+
+        IOriginSiteMapper* getMapper();
+        void releaseMapper(IOriginSiteMapper* mapper);
+        void refresh();
+
+        AAP* m_AAP;
+    private:
+        IOriginSiteMapper* m_mapper;
+        xmlSecKeysMngrPtr m_manager;
+        RWLock* m_lock;
+        static void* refresh_fn(void*);
+        bool m_shutdown;
+        CondWait* m_shutdown_wait;
+        Thread*  m_refresh_thread;
+    };
 }
 
 #endif
index 3317347..4c85407 100644 (file)
@@ -128,6 +128,46 @@ namespace shibboleth
         IOriginSiteMapper* m_mapper;
     };
 
+    class SHIB_EXPORTS SimpleAttribute : public saml::SAMLAttribute
+    {
+    public:
+        SimpleAttribute(const XMLCh* name, const XMLCh* ns, long lifetime=0,
+                        const saml::Iterator<const XMLCh*>& values=saml::Iterator<const XMLCh*>());
+        SimpleAttribute(DOMElement* e);
+        virtual saml::SAMLObject* clone() const;
+        virtual ~SimpleAttribute();
+
+    protected:
+        virtual bool accept(DOMElement* e) const;
+
+        saml::xstring m_originSite;
+    };
+
+    class SHIB_EXPORTS ScopedAttribute : public SimpleAttribute
+    {
+    public:
+        ScopedAttribute(const XMLCh* name, const XMLCh* ns, long lifetime=0,
+                        const saml::Iterator<const XMLCh*>& scopes=saml::Iterator<const XMLCh*>(),
+                        const saml::Iterator<const XMLCh*>& values=saml::Iterator<const XMLCh*>());
+        ScopedAttribute(DOMElement* e);
+        virtual ~ScopedAttribute();
+
+        virtual DOMNode* toDOM(DOMDocument* doc=NULL, bool xmlns=true) const;
+        virtual saml::SAMLObject* clone() const;
+
+        virtual saml::Iterator<saml::xstring> getValues() const;
+        virtual saml::Iterator<std::string> getSingleByteValues() const;
+
+        static const XMLCh Scope[];
+
+    protected:
+        virtual bool accept(DOMElement* e) const;
+        virtual bool addValue(DOMElement* e);
+
+        std::vector<saml::xstring> m_scopes;
+        mutable std::vector<saml::xstring> m_scopedValues;
+    };
+
     class SHIB_EXPORTS ShibPOSTProfile
     {
     public:
@@ -208,6 +248,7 @@ namespace shibboleth
         virtual void releaseMapper(IOriginSiteMapper* mapper)=0;
 
     /* start of external configuration */
+        std::string aapURL;
         std::string mapperURL;
         saml::X509Certificate* mapperCert;
         time_t mapperRefreshInterval;
@@ -219,6 +260,7 @@ namespace shibboleth
         static const XMLCh POLICY_INCOMMON[];
         static const XMLCh SHIB_ATTRIBUTE_NAMESPACE_URI[];
         static const XMLCh SHIB_NAMEID_FORMAT_URI[];
+        static saml::QName SHIB_ATTRIBUTE_VALUE_TYPE; 
     };
 
     class SHIB_EXPORTS XML
@@ -231,14 +273,26 @@ namespace shibboleth
         struct SHIB_EXPORTS Literals
         {
             // Shibboleth vocabulary
+            static const XMLCh AttributeValueType[];
+
             static const XMLCh Domain[];
             static const XMLCh HandleService[];
             static const XMLCh InvalidHandle[];
             static const XMLCh Name[];
             static const XMLCh OriginSite[];
-            static const XMLCh regexp[];
             static const XMLCh Sites[];
 
+            static const XMLCh AnySite[];
+            static const XMLCh AttributeAcceptancePolicy[];
+            static const XMLCh AttributeRule[];
+            static const XMLCh SiteRule[];
+            static const XMLCh Type[];
+            static const XMLCh Value[];
+
+            static const XMLCh literal[];
+            static const XMLCh regexp[];
+            static const XMLCh xpath[];
+
             // XML vocabulary
             static const XMLCh xmlns_shib[];
         };