Reimplemented AAP consistent with Metadata/Trust APIs
authorScott Cantor <cantor.2@osu.edu>
Fri, 27 Jun 2003 21:02:26 +0000 (21:02 +0000)
committerScott Cantor <cantor.2@osu.edu>
Fri, 27 Jun 2003 21:02:26 +0000 (21:02 +0000)
Moved all attribute configuration data into this layer.

shib/AAP.cpp
shib/Metadata.cpp
shib/ScopedAttribute.cpp
shib/ShibConfig.cpp
shib/SimpleAttribute.cpp
shib/XML.cpp
shib/XMLMetadata.cpp
shib/internal.h
shib/shib.h

index e8b169b..245dcdf 100644 (file)
@@ -68,177 +68,352 @@ using namespace std;
 #include <xercesc/framework/URLInputSource.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
-AAP::AAP(const char* uri)
+extern "C" SAMLAttribute* AttributeFactory(DOMElement* e)
 {
-    NDC ndc("AAP");
-    Category& log=Category::getInstance(SHIB_LOGCAT".AAP");
+    DOMNode* n=e->getFirstChild();
+    while (n && n->getNodeType()!=DOMNode::ELEMENT_NODE)
+        n=n->getNextSibling();
+    if (n && static_cast<DOMElement*>(n)->hasAttributeNS(NULL,SHIB_L(Scope)))
+        return new ScopedAttribute(e);
+    return new SimpleAttribute(e);
+}
+
+class shibboleth::XMLAAPImpl
+{
+public:
+    XMLAAPImpl(const char* pathname);
+    ~XMLAAPImpl();
+    
+    void regAttributes() const;
+
+    class AttributeRule : public IAttributeRule
+    {
+    public:
+        AttributeRule(const DOMElement* e);
+        ~AttributeRule() {}
+        
+        const XMLCh* getName() const { return m_name; }
+        const XMLCh* getNamespace() const { return m_namespace; }
+        const char* getFactory() const { return m_factory.get(); }
+        const char* getAlias() const { return m_alias.get(); }
+        const char* getHeader() const { return m_header.get(); }
+        bool accept(const XMLCh* originSite, const DOMElement* e) const;
+
+    private:    
+        const XMLCh* m_name;
+        const XMLCh* m_namespace;
+        auto_ptr<char> m_factory;
+        auto_ptr<char> m_alias;
+        auto_ptr<char> m_header;
+        
+        enum value_type { literal, regexp, xpath };
+        struct SiteRule
+        {
+            SiteRule() : anyValue(false) {}
+            bool anyValue;
+            vector<pair<value_type,const XMLCh*> > valueRules;
+        };
+
+        SiteRule m_anySiteRule;
+        map<xstring,SiteRule> m_siteMap;
+    };
+
+    vector<const IAttributeRule*> m_attrs;
+    map<string,const IAttributeRule*> m_aliasMap;
+    map<xstring,AttributeRule*> m_attrMap;
+    DOMDocument* m_doc;
+};
+
+XMLAAPImpl::XMLAAPImpl(const char* pathname) : m_doc(NULL)
+{
+    NDC ndc("XMLAAPImpl");
+    Category& log=Category::getInstance(SHIB_LOGCAT".XMLAAPImpl");
 
     saml::XML::Parser p;
-    DOMDocument* doc=NULL;
-       try
+    try
     {
         static XMLCh base[]={chLatin_f, chLatin_i, chLatin_l, chLatin_e, chColon, chForwardSlash, chForwardSlash, chForwardSlash, chNull};
-        URLInputSource src(base,uri);
+        URLInputSource src(base,pathname);
         Wrapper4InputSource dsrc(&src,false);
-               doc=p.parse(dsrc);
+        m_doc=p.parse(dsrc);
 
-        log.infoStream() << "Loaded and parsed AAP (" << uri << ")" << CategoryStream::ENDLINE;
+        log.infoStream() << "Loaded and parsed AAP file (" << pathname << ")" << CategoryStream::ENDLINE;
 
-               DOMElement* e = doc->getDocumentElement();
+        DOMElement* e = m_doc->getDocumentElement();
         if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
-            XMLString::compareString(XML::Literals::AttributeAcceptancePolicy,e->getLocalName()))
+            XMLString::compareString(SHIB_L(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)");
-               }
+            log.error("Construction requires a valid AAP file: (shib:AttributeAcceptancePolicy as root element)");
+            throw MalformedException("Construction requires a valid AAP 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++)
+        // Loop over the AttributeRule elements.
+        DOMNodeList* nlist = e->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(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)];
+            AttributeRule* rule=new AttributeRule(static_cast<DOMElement*>(nlist->item(i)));
+            m_attrMap[xstring(rule->getName()) + chBang + chBang + (rule->getNamespace() ? rule->getNamespace() : Constants::SHIB_ATTRIBUTE_NAMESPACE_URI)]=rule;
+            m_attrs.push_back(rule);
+            if (rule->getAlias())
+                m_aliasMap[rule->getAlias()]=rule;
+        }
+    }
+    catch (SAMLException& e)
+    {
+        log.errorStream() << "XML error while parsing AAP: " << e.what() << CategoryStream::ENDLINE;
+        for (map<xstring,AttributeRule*>::iterator i=m_attrMap.begin(); i!=m_attrMap.end(); i++)
+            delete i->second;
+        if (m_doc)
+            m_doc->release();
+        throw;
+    }
+    catch (...)
+    {
+        log.error("Unexpected error while parsing AAP");
+        for (map<xstring,AttributeRule*>::iterator i=m_attrMap.begin(); i!=m_attrMap.end(); i++)
+            delete i->second;
+        if (m_doc)
+            m_doc->release();
+        throw;
+    }
 
-            // 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()))
-            {
-                // Check for an AnyValue rule.
-                DOMNode* anyval = anysite->getFirstChild();
-                       while (anyval && anyval->getNodeType()!=DOMNode::ELEMENT_NODE)
-                {
-                               anyval = anyval->getNextSibling();
-                               continue;
-                           }
+XMLAAPImpl::~XMLAAPImpl()
+{
+    for (map<xstring,AttributeRule*>::iterator i=m_attrMap.begin(); i!=m_attrMap.end(); i++)
+    {
+        SAMLAttribute::unregFactory(i->second->getName(),i->second->getNamespace());
+        delete i->second;
+    }
+    if (m_doc)
+        m_doc->release();
+}
+
+void XMLAAPImpl::regAttributes() const
+{
+    for (map<xstring,AttributeRule*>::const_iterator i=m_attrMap.begin(); i!=m_attrMap.end(); i++)
+    {
+        if (i->second->getFactory()==NULL)
+            SAMLAttribute::regFactory(i->second->getName(),i->second->getNamespace(),AttributeFactory);
+        else
+        {
+            saml::NDC ndc("regAttributes");
+            Category::getInstance(SHIB_LOGCAT".XMLAAPImpl").error("do not support custom attribute factories yet");
+        }
+    }
+}
+
+XMLAAPImpl::AttributeRule::AttributeRule(const DOMElement* e) :
+    m_factory(XMLString::transcode(e->getAttributeNS(NULL,SHIB_L(Factory)))),
+    m_alias(XMLString::transcode(e->getAttributeNS(NULL,SHIB_L(Alias)))),
+    m_header(XMLString::transcode(e->getAttributeNS(NULL,SHIB_L(Header))))
+    
+{
+    m_name=e->getAttributeNS(NULL,SHIB_L(Name));
+    m_namespace=e->getAttributeNS(NULL,SHIB_L(Namespace));
+    if (!m_namespace || !*m_namespace)
+        m_namespace=Constants::SHIB_ATTRIBUTE_NAMESPACE_URI;
+    
+    // Check for an AnySite rule.
+    DOMNode* anysite = e->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(SHIB_L(AnySite),static_cast<DOMElement*>(anysite)->getLocalName()))
+    {
+        // Check for an AnyValue rule.
+        DOMNode* anyval = anysite->getFirstChild();
+        while (anyval && anyval->getNodeType()!=DOMNode::ELEMENT_NODE)
+        {
+            anyval = anyval->getNextSibling();
+            continue;
+        }
 
-                if (anyval && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anyval)->getNamespaceURI()) &&
-                    !XMLString::compareString(XML::Literals::AnyValue,static_cast<DOMElement*>(anyval)->getLocalName()))
+        if (anyval && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anyval)->getNamespaceURI()) &&
+            !XMLString::compareString(SHIB_L(AnyValue),static_cast<DOMElement*>(anyval)->getLocalName()))
+        {
+            m_anySiteRule.anyValue=true;
+        }
+        else
+        {
+            // 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)
                 {
-                    arule.m_anySiteRule.anyValue=true;
+                    if (!XMLString::compareString(SHIB_L(literal),ve->getAttributeNS(NULL,SHIB_L(Type))))
+                        m_anySiteRule.valueRules.push_back(pair<value_type,const XMLCh*>(literal,valnode->getNodeValue()));
+                    else if (!XMLString::compareString(SHIB_L(regexp),ve->getAttributeNS(NULL,SHIB_L(Type))))
+                        m_anySiteRule.valueRules.push_back(pair<value_type,const XMLCh*>(regexp,valnode->getNodeValue()));
+                    else if (!XMLString::compareString(SHIB_L(xpath),ve->getAttributeNS(NULL,SHIB_L(Type))))
+                        m_anySiteRule.valueRules.push_back(pair<value_type,const XMLCh*>(xpath,valnode->getNodeValue()));
                 }
-                else
+            }
+        }
+    }
+
+    // Loop over the SiteRule elements.
+    DOMNodeList* slist = e->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(SiteRule));
+    for (int k=0; slist && k<slist->getLength(); k++)
+    {
+        m_siteMap[static_cast<DOMElement*>(slist->item(k))->getAttributeNS(NULL,SHIB_L(Name))]=SiteRule();
+        SiteRule& srule=m_siteMap[static_cast<DOMElement*>(slist->item(k))->getAttributeNS(NULL,SHIB_L(Name))];
+
+        // Check for an AnyValue rule.
+        DOMNode* anyval = slist->item(k)->getFirstChild();
+        while (anyval && anyval->getNodeType()!=DOMNode::ELEMENT_NODE)
+        {
+            anyval = anyval->getNextSibling();
+            continue;
+        }
+
+        if (anyval && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anyval)->getNamespaceURI()) &&
+            !XMLString::compareString(SHIB_L(AnyValue),static_cast<DOMElement*>(anyval)->getLocalName()))
+        {
+            srule.anyValue=true;
+        }
+        else
+        {
+            // Process each Value element.
+            DOMNodeList* vlist = static_cast<DOMElement*>(slist->item(k))->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(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)
                 {
-                    // 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.valueRules.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.valueRules.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.valueRules.push_back(
-                                    pair<AttributeRule::value_type,xstring>(AttributeRule::xpath,valnode->getNodeValue())
-                                    );
-                        }
-                    }
+                    if (!XMLString::compareString(SHIB_L(literal),ve->getAttributeNS(NULL,SHIB_L(Type))))
+                        srule.valueRules.push_back(pair<value_type,const XMLCh*>(literal,valnode->getNodeValue()));
+                    else if (!XMLString::compareString(SHIB_L(regexp),ve->getAttributeNS(NULL,SHIB_L(Type))))
+                        srule.valueRules.push_back(pair<value_type,const XMLCh*>(regexp,valnode->getNodeValue()));
+                    else if (!XMLString::compareString(SHIB_L(xpath),ve->getAttributeNS(NULL,SHIB_L(Type))))
+                        srule.valueRules.push_back(pair<value_type,const XMLCh*>(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)];
+XMLAAP::XMLAAP(const char* pathname) : m_filestamp(0), m_source(pathname), m_impl(NULL)
+{
+#ifdef WIN32
+    struct _stat stat_buf;
+    if (_stat(pathname, &stat_buf) == 0)
+#else
+    struct stat stat_buf;
+    if (stat(pathname, &stat_buf) == 0)
+#endif
+        m_filestamp=stat_buf.st_mtime;
+    m_impl=new XMLAAPImpl(pathname);
+    SAMLConfig::getConfig().saml_lock();
+    m_impl->regAttributes();
+    SAMLConfig::getConfig().saml_unlock();
+    m_lock=RWLock::create();
+}
 
-                // Check for an AnyValue rule.
-                DOMNode* anyval = slist->item(k)->getFirstChild();
-                       while (anyval && anyval->getNodeType()!=DOMNode::ELEMENT_NODE)
-                {
-                               anyval = anyval->getNextSibling();
-                               continue;
-                           }
+XMLAAP::~XMLAAP()
+{
+    delete m_lock;
+    delete m_impl;
+}
 
-                if (anyval && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anyval)->getNamespaceURI()) &&
-                    !XMLString::compareString(XML::Literals::AnyValue,static_cast<DOMElement*>(anyval)->getLocalName()))
+void XMLAAP::lock()
+{
+    m_lock->rdlock();
+
+    // Check if we need to refresh.
+#ifdef WIN32
+    struct _stat stat_buf;
+    if (_stat(m_source.c_str(), &stat_buf) == 0)
+#else
+    struct stat stat_buf;
+    if (stat(m_source.c_str(), &stat_buf) == 0)
+#endif
+    {
+        if (m_filestamp>0 && m_filestamp<stat_buf.st_mtime)
+        {
+            // Elevate lock and recheck.
+            m_lock->unlock();
+            m_lock->wrlock();
+            if (m_filestamp>0 && m_filestamp<stat_buf.st_mtime)
+            {
+                try
+                {
+                    XMLAAPImpl* new_mapper=new XMLAAPImpl(m_source.c_str());
+                    SAMLConfig::getConfig().saml_lock();
+                    delete m_impl;
+                    m_impl=new_mapper;
+                    m_impl->regAttributes();
+                    SAMLConfig::getConfig().saml_unlock();
+                    m_filestamp=stat_buf.st_mtime;
+                    m_lock->unlock();
+                }
+                catch(SAMLException& e)
                 {
-                    srule.anyValue=true;
+                    m_lock->unlock();
+                    saml::NDC ndc("lock");
+                    Category::getInstance(SHIB_LOGCAT".XMLAAP").error("failed to reload AAP, sticking with what we have: %s", e.what());
                 }
-                else
+                catch(...)
                 {
-                    // 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.valueRules.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.valueRules.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.valueRules.push_back(
-                                    pair<AttributeRule::value_type,xstring>(AttributeRule::xpath,valnode->getNodeValue())
-                                    );
-                        }
-                    }
+                    m_lock->unlock();
+                    saml::NDC ndc("lock");
+                    Category::getInstance(SHIB_LOGCAT".XMLAAP").error("caught an unknown exception, sticking with what we have");
                 }
             }
-               }
-    }
-    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;
+            else
+            {
+                m_lock->unlock();
+            }
+            m_lock->rdlock();
+        }
     }
+}
 
+void XMLAAP::unlock()
+{
+    m_lock->unlock();
+}
+
+const IAttributeRule* XMLAAP::lookup(const XMLCh* attrName, const XMLCh* attrNamespace) const
+{
+    map<xstring,XMLAAPImpl::AttributeRule*>::const_iterator i=m_impl->m_attrMap.find(
+        xstring(attrName) + chBang + chBang + (attrNamespace ? attrNamespace : Constants::SHIB_ATTRIBUTE_NAMESPACE_URI)
+        );
+    return (i==m_impl->m_attrMap.end()) ? NULL : i->second;
 }
 
-bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
+const IAttributeRule* XMLAAP::lookup(const char* alias) const
+{
+    map<string,const IAttributeRule*>::const_iterator i=m_impl->m_aliasMap.find(alias);
+    return (i==m_impl->m_aliasMap.end()) ? NULL : i->second;
+}
+
+Iterator<const IAttributeRule*> XMLAAP::getAttributeRules() const
+{
+    return m_impl->m_attrs;
+}
+
+bool XMLAAPImpl::AttributeRule::accept(const XMLCh* originSite, const DOMElement* e) const
 {
     NDC ndc("accept");
-    log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".AAP");
+    log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".XMLAAPImpl");
     
     if (log.isDebugEnabled())
     {
-        auto_ptr<char> temp(XMLString::transcode(name));
+        auto_ptr<char> temp(XMLString::transcode(m_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())
-    {
-        if (log.isWarnEnabled())
-        {
-            auto_ptr<char> temp(XMLString::transcode(name));
-            log.warn("attribute %s not found in AAP, any value is rejected",temp.get());
-        }
-        return false;
-    }
-
     // Don't currently support non-simple content models...
     DOMNode* n=e->getFirstChild();
     if (!n || n->getNodeType()!=DOMNode::TEXT_NODE)
@@ -247,28 +422,27 @@ bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
         return false;
     }
 
-    if (arule->second.m_anySiteRule.anyValue)
+    if (m_anySiteRule.anyValue)
     {
         log.debug("any site, any value, match");
         return true;
     }
 
-    for (vector<pair<AttributeRule::value_type,xstring> >::const_iterator i=arule->second.m_anySiteRule.valueRules.begin();
-            i!=arule->second.m_anySiteRule.valueRules.end(); i++)
+    for (vector<pair<value_type,const XMLCh*> >::const_iterator i=m_anySiteRule.valueRules.begin(); i!=m_anySiteRule.valueRules.end(); i++)
     {
-        if (i->first==AttributeRule::literal)
+        if (i->first==literal)
         {
-            if (i->second==n->getNodeValue())
+            if (!XMLString::compareString(i->second,n->getNodeValue()))
             {
                 log.debug("any site, literal match");
                 return true;
             }
         }
-        else if (i->first==AttributeRule::regexp)
+        else if (i->first==regexp)
         {
             try
             {
-                RegularExpression re(i->second.c_str());
+                RegularExpression re(i->second);
                 if (re.matches(n->getNodeValue()))
                 {
                     log.debug("any site, regexp match");
@@ -286,12 +460,12 @@ bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
             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())
+    map<xstring,SiteRule>::const_iterator srule=m_siteMap.find(originSite);
+    if (srule==m_siteMap.end())
     {
         if (log.isWarnEnabled())
         {
-            auto_ptr<char> temp(XMLString::transcode(name));
+            auto_ptr<char> temp(XMLString::transcode(m_name));
             auto_ptr<char> temp2(XMLString::transcode(originSite));
             log.warn("site %s not found in attribute %s ruleset, any value is rejected",temp2.get(),temp.get());
         }
@@ -304,22 +478,21 @@ bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
         return true;
     }
 
-    for (vector<pair<AttributeRule::value_type,xstring> >::const_iterator j=srule->second.valueRules.begin();
-            j!=srule->second.valueRules.end(); j++)
+    for (vector<pair<value_type,const XMLCh*> >::const_iterator j=srule->second.valueRules.begin(); j!=srule->second.valueRules.end(); j++)
     {
-        if (j->first==AttributeRule::literal)
+        if (j->first==literal)
         {
-            if (j->second==n->getNodeValue())
+            if (!XMLString::compareString(j->second,n->getNodeValue()))
             {
                 log.debug("matching site, literal match");
                 return true;
             }
         }
-        else if (j->first==AttributeRule::regexp)
+        else if (j->first==regexp)
         {
             try
             {
-                RegularExpression re(j->second.c_str());
+                RegularExpression re(j->second);
                 if (re.matches(n->getNodeValue()))
                 {
                     log.debug("matching site, regexp match");
@@ -339,7 +512,7 @@ bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
 
     if (log.isWarnEnabled())
     {
-        auto_ptr<char> temp(XMLString::transcode(name));
+        auto_ptr<char> temp(XMLString::transcode(m_name));
         auto_ptr<char> temp2(XMLString::transcode(n->getNodeValue()));
         log.warn("attribute %s value {%s} could not be validated by AAP, rejecting it",temp.get(),temp2.get());
     }
index 06340bf..5b35eed 100644 (file)
@@ -63,16 +63,17 @@ using namespace std;
 
 OriginMetadata::OriginMetadata(const XMLCh* site) : m_mapper(NULL), m_site(NULL)
 {
-    ShibInternalConfig& config=dynamic_cast<ShibInternalConfig&>(ShibConfig::getConfig());
-    for (vector<IMetadata*>::iterator i=config.m_providers.begin(); i!=config.m_providers.end(); i++)
+    Iterator<IMetadata*> it=ShibConfig::getConfig().getMetadataProviders();
+    while (it.hasNext())
     {
-        (*i)->lock();
-        if (m_site=dynamic_cast<const IOriginSite*>((*i)->lookup(site)))
+        IMetadata* i=it.next();
+        i->lock();
+        if (m_site=dynamic_cast<const IOriginSite*>(i->lookup(site)))
         {
-            m_mapper=*i;
+            m_mapper=i;
             break;
         }
-        (*i)->unlock();
+        i->unlock();
     }
 }
 
@@ -90,17 +91,18 @@ Iterator<XSECCryptoX509*> Trust::getCertificates(const XMLCh* subject)
         m_mapper=NULL;
     }
     
-    ShibInternalConfig& config=dynamic_cast<ShibInternalConfig&>(ShibConfig::getConfig());
-    for (vector<ITrust*>::iterator i=config.m_trust_providers.begin(); i!=config.m_trust_providers.end(); i++)
+    Iterator<ITrust*> it=ShibConfig::getConfig().getTrustProviders();
+    while (it.hasNext())
     {
-        (*i)->lock();
-        Iterator<XSECCryptoX509*> iter=(*i)->getCertificates(subject);
+        ITrust* i=it.next();
+        i->lock();
+        Iterator<XSECCryptoX509*> iter=i->getCertificates(subject);
         if (iter.size())
         {
-            m_mapper=*i;
+            m_mapper=i;
             return iter;
         }
-        (*i)->unlock();
+        i->unlock();
     }
     return EMPTY(XSECCryptoX509*);
 }
@@ -108,12 +110,13 @@ Iterator<XSECCryptoX509*> Trust::getCertificates(const XMLCh* subject)
 bool Trust::validate(const ISite* site, Iterator<XSECCryptoX509*> certs) const
 {
     bool ret=false;
-    ShibInternalConfig& config=dynamic_cast<ShibInternalConfig&>(ShibConfig::getConfig());
-    for (vector<ITrust*>::iterator i=config.m_trust_providers.begin(); !ret && i!=config.m_trust_providers.end(); i++)
+    Iterator<ITrust*> it=ShibConfig::getConfig().getTrustProviders();
+    while (!ret && it.hasNext())
     {
-        (*i)->lock();
-        ret=(*i)->validate(site,certs);
-        (*i)->unlock();
+        ITrust* i=it.next();
+        i->lock();
+        ret=i->validate(site,certs);
+        i->unlock();
     }
     return ret;
 }
@@ -121,12 +124,13 @@ bool Trust::validate(const ISite* site, Iterator<XSECCryptoX509*> certs) const
 bool Trust::validate(const ISite* site, Iterator<const XMLCh*> certs) const
 {
     bool ret=false;
-    ShibInternalConfig& config=dynamic_cast<ShibInternalConfig&>(ShibConfig::getConfig());
-    for (vector<ITrust*>::iterator i=config.m_trust_providers.begin(); !ret && i!=config.m_trust_providers.end(); i++)
+    Iterator<ITrust*> it=ShibConfig::getConfig().getTrustProviders();
+    while (!ret && it.hasNext())
     {
-        (*i)->lock();
-        ret=(*i)->validate(site,certs);
-        (*i)->unlock();
+        ITrust* i=it.next();
+        i->lock();
+        ret=i->validate(site,certs);
+        i->unlock();
     }
     return ret;
 }
@@ -136,3 +140,41 @@ Trust::~Trust()
     if (m_mapper)
         m_mapper->unlock();
 }
+
+AAP::AAP(const XMLCh* attrName, const XMLCh* attrNamespace) : m_mapper(NULL), m_rule(NULL)
+{
+    Iterator<IAAP*> it=ShibConfig::getConfig().getAAPProviders();
+    while (it.hasNext())
+    {
+        IAAP* i=it.next();
+        i->lock();
+        if (m_rule=i->lookup(attrName,attrNamespace))
+        {
+            m_mapper=i;
+            break;
+        }
+        i->unlock();
+    }
+}
+
+AAP::AAP(const char* alias) : m_mapper(NULL), m_rule(NULL)
+{
+    Iterator<IAAP*> it=ShibConfig::getConfig().getAAPProviders();
+    while (it.hasNext())
+    {
+        IAAP* i=it.next();
+        i->lock();
+        if (m_rule=i->lookup(alias))
+        {
+            m_mapper=i;
+            break;
+        }
+        i->unlock();
+    }
+}
+
+AAP::~AAP()
+{
+    if (m_mapper)
+        m_mapper->unlock();
+}
index f969c52..a051449 100644 (file)
@@ -87,7 +87,7 @@ bool ScopedAttribute::addValue(DOMElement* e)
     static XMLCh empty[] = {chNull};
     if (SAMLAttribute::addValue(e))
     {
-        DOMAttr* scope=e->getAttributeNodeNS(NULL,Scope);
+        DOMAttr* scope=e->getAttributeNodeNS(NULL,SHIB_L(Scope));
         m_scopes.push_back(scope ? scope->getNodeValue() : empty);
         return true;
     }
@@ -103,7 +103,7 @@ bool ScopedAttribute::accept(DOMElement* e) const
     Iterator<pair<const XMLCh*,bool> > domains=
         (mapper.fail()) ? Iterator<pair<const XMLCh*,bool> >() : mapper->getSecurityDomains();
     const XMLCh* this_scope=NULL;
-    DOMAttr* scope=e->getAttributeNodeNS(NULL,Scope);
+    DOMAttr* scope=e->getAttributeNodeNS(NULL,SHIB_L(Scope));
     if (scope)
         this_scope=scope->getNodeValue();
     if (!this_scope || !*this_scope)
@@ -189,7 +189,7 @@ DOMNode* ScopedAttribute::toDOM(DOMDocument* doc,bool xmlns) const
     {
         if (n->getNodeType()==DOMNode::ELEMENT_NODE)
         {
-            static_cast<DOMElement*>(n)->setAttributeNS(NULL,Scope,
+            static_cast<DOMElement*>(n)->setAttributeNS(NULL,SHIB_L(Scope),
                 (!m_scopes[i].empty() ? m_scopes[i].c_str() : m_originSite.c_str()));
             i++;
         }
@@ -199,4 +199,3 @@ DOMNode* ScopedAttribute::toDOM(DOMDocument* doc,bool xmlns) const
     return m_root;
 }
 
-const XMLCh ScopedAttribute::Scope[] = { chLatin_S, chLatin_c, chLatin_o, chLatin_p, chLatin_e, chNull };
index d0ae7a8..5e6ca7b 100644 (file)
@@ -90,6 +90,11 @@ extern "C" ITrust* XMLTrustFactory(const char* source)
     return new XMLTrust(source);
 }
 
+extern "C" IAAP* XMLAAPFactory(const char* source)
+{
+    return new XMLAAP(source);
+}
+
 bool ShibInternalConfig::init()
 {
     saml::NDC ndc("init");
@@ -100,21 +105,9 @@ bool ShibInternalConfig::init()
     // Register extension schema.
     saml::XML::registerSchema(XML::SHIB_NS,XML::SHIB_SCHEMA_ID);
 
-    if (!aapFile.empty())
-    {
-        try
-        {
-            m_AAP=new AAP(aapFile.c_str());
-        }
-        catch(SAMLException& e)
-        {
-            Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to initialize AAP: %s", e.what());
-            return false;
-        }
-    }
-
     regFactory("edu.internet2.middleware.shibboleth.metadata.XML",&XMLMetadataFactory);
     regFactory("edu.internet2.middleware.shibboleth.trust.XML",&XMLTrustFactory);
+    regFactory("edu.internet2.middleware.shibboleth.target.AAP.XML",&XMLAAPFactory);
 
     return true;
 }
@@ -123,7 +116,10 @@ void ShibInternalConfig::term()
 {
     for (vector<IMetadata*>::iterator i=m_providers.begin(); i!=m_providers.end(); i++)
         delete *i;
-    delete m_AAP;
+    for (vector<ITrust*>::iterator j=m_trust_providers.begin(); j!=m_trust_providers.end(); j++)
+        delete *j;
+    for (vector<IAAP*>::iterator k=m_aap_providers.begin(); k!=m_aap_providers.end(); k++)
+        delete *k;
 }
 
 void ShibInternalConfig::regFactory(const char* type, MetadataFactory* factory)
@@ -138,12 +134,19 @@ void ShibInternalConfig::regFactory(const char* type, TrustFactory* factory)
         m_trustFactoryMap[type]=factory;
 }
 
+void ShibInternalConfig::regFactory(const char* type, AAPFactory* factory)
+{
+    if (type && factory)
+        m_aapFactoryMap[type]=factory;
+}
+
 void ShibInternalConfig::unregFactory(const char* type)
 {
     if (type)
     {
         m_metadataFactoryMap.erase(type);
         m_trustFactoryMap.erase(type);
+        m_aapFactoryMap.erase(type);
     }
 }
 
@@ -169,7 +172,16 @@ bool ShibInternalConfig::addMetadata(const char* type, const char* source)
                 ret=true;
             }
             else
-                throw MetadataException("ShibConfig::addMetadata() unable to locate a metadata factory of the requested type");
+            {
+                AAPFactoryMap::const_iterator k=m_aapFactoryMap.find(type);
+                if (k!=m_aapFactoryMap.end())
+                {
+                    m_aap_providers.push_back((k->second)(source));
+                    ret=true;
+                }
+                else
+                    throw MetadataException("ShibConfig::addMetadata() unable to locate a metadata factory of the requested type");
+            }
         }
     }
     catch (SAMLException& e)
index 4869584..8abf727 100644 (file)
@@ -85,6 +85,6 @@ saml::SAMLObject* SimpleAttribute::clone() const
 
 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;
+    AAP aap(m_name,m_namespace);
+    return aap.fail() ? false : aap->accept(m_originSite.c_str(),e);
 }
index e118fe5..2cd5d09 100644 (file)
@@ -82,6 +82,8 @@ const XMLCh XML::Literals::AttributeValueType[] =
   chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull
 };
 
+const XMLCh XML::Literals::Scope[] = { chLatin_S, chLatin_c, chLatin_o, chLatin_p, chLatin_e, chNull };
+
 const XMLCh XML::Literals::AttributeAuthority[] =
 { chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
   chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_o, chLatin_r, chLatin_i, chLatin_t, chLatin_y, chNull
@@ -126,6 +128,9 @@ const XMLCh XML::Literals::KeyAuthority[] =
 const XMLCh XML::Literals::Trust[] =
 { chLatin_T, chLatin_r, chLatin_u, chLatin_s, chLatin_t, chNull };
 
+const XMLCh XML::Literals::Alias[]=
+{ chLatin_A, chLatin_l, chLatin_i, chLatin_a, chLatin_s, chNull };
+
 const XMLCh XML::Literals::AnySite[]=
 { chLatin_A, chLatin_n, chLatin_y, chLatin_S, chLatin_i, chLatin_t, chLatin_e, chNull };
 
@@ -143,6 +148,15 @@ const XMLCh XML::Literals::AttributeRule[] =
   chLatin_R, chLatin_u, chLatin_l, chLatin_e, chNull
 };
 
+const XMLCh XML::Literals::Factory[]=
+{ chLatin_F, chLatin_a, chLatin_c, chLatin_t, chLatin_o, chLatin_r, chLatin_y, chNull };
+
+const XMLCh XML::Literals::Header[]=
+{ chLatin_H, chLatin_e, chLatin_a, chLatin_d, chLatin_e, chLatin_r, chNull };
+
+const XMLCh XML::Literals::Namespace[]=
+{ chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, 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 };
 
index f3f8013..20bddbe 100644 (file)
@@ -359,34 +359,3 @@ const ISite* XMLMetadata::lookup(const XMLCh* site) const
     map<xstring,XMLMetadataImpl::OriginSite*>::const_iterator i=m_impl->m_sites.find(site);
     return (i==m_impl->m_sites.end()) ? NULL : i->second;
 }
-
-                        /*
-                        // Look for ds:KeyInfo.
-                        DOMNode* ki=os_child->getFirstChild();
-                        while (ki && ki->getNodeType()!=DOMNode::ELEMENT_NODE)
-                            ki=ki->getNextSibling();
-                        if (ki && !XMLString::compareString(saml::XML::XMLSIG_NS,ki->getNamespaceURI()) &&
-                            !XMLString::compareString(saml::XML::Literals::KeyInfo,ki->getNamespaceURI()))
-                        {
-                            // Look for ds:X509Data.
-                            DOMNode* xdata=ki->getFirstChild();
-                            while (xdata && xdata->getNodeType()!=DOMNode::ELEMENT_NODE)
-                                xdata=xdata->getNextSibling();
-                            if (xdata && !XMLString::compareString(saml::XML::XMLSIG_NS,xdata->getNamespaceURI()) &&
-                                !XMLString::compareString(saml::XML::Literals::X509Data,xdata->getNamespaceURI()))
-                            {
-                                // Look for ds:X509Certificate.
-                                DOMNode* x509=xdata->getFirstChild();
-                                while (x509 && x509->getNodeType()!=DOMNode::ELEMENT_NODE)
-                                    x509=x509->getNextSibling();
-                                if (x509 && !XMLString::compareString(saml::XML::XMLSIG_NS,x509->getNamespaceURI()) &&
-                                    !XMLString::compareString(saml::XML::Literals::X509Certificate,x509->getNamespaceURI()))
-                                {
-                                    auto_ptr<char> blob(XMLString::transcode(x509->getFirstChild()->getNodeValue()));
-                                    XSECCryptoX509* cert=new OpenSSLCryptoX509();
-                                    cert->loadX509Base64Bin(blob.get(),strlen(blob.get()));
-                                    m_hsCerts[hs_name.get()]=cert;
-                                }
-                            }
-                        }
-                        */
index 204ed32..faaf566 100644 (file)
@@ -115,56 +115,59 @@ namespace shibboleth
         XMLTrustImpl* m_impl;
     };
 
-    class AAP
+    class XMLAAPImpl;
+    class SHIB_EXPORTS XMLAAP : public IAAP
     {
     public:
-        AAP(const char* uri);
-        bool accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e);
+        XMLAAP(const char* pathname);
+        ~XMLAAP();
+        
+        void lock();
+        void unlock();
+        const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const;
+        const IAttributeRule* lookup(const char* alias) const;
+        saml::Iterator<const IAttributeRule*> getAttributeRules() const;
 
     private:
-        struct AttributeRule
-        {
-            enum value_type { literal, regexp, xpath };
-            struct SiteRule
-            {
-                SiteRule() : anyValue(false) {}
-                bool anyValue;
-                std::vector<std::pair<value_type,saml::xstring> > valueRules;
-            };
-
-            SiteRule m_anySiteRule;
-            std::map<saml::xstring,SiteRule> m_siteMap;
-        };
-
-        std::map<saml::xstring,AttributeRule> m_attrMap;
+        std::string m_source;
+        time_t m_filestamp;
+        RWLock* m_lock;
+        XMLAAPImpl* m_impl;
     };
-
+    
     class ShibInternalConfig : public ShibConfig
     {
     public:
-        ShibInternalConfig() : m_AAP(NULL) {}
+        ShibInternalConfig() {}
 
         bool init();
         void term();
 
         void regFactory(const char* type, MetadataFactory* factory);
         void regFactory(const char* type, TrustFactory* factory);
+        void regFactory(const char* type, AAPFactory* factory);
         void unregFactory(const char* type);
         
         bool addMetadata(const char* type, const char* source);
 
-        AAP* m_AAP;
-        
+        saml::Iterator<IMetadata*> getMetadataProviders() const {return m_providers;}
+        saml::Iterator<ITrust*> getTrustProviders() const {return m_trust_providers;}
+        saml::Iterator<IAAP*> getAAPProviders() const {return m_aap_providers;}
+
     private:
         friend class OriginMetadata;
         friend class Trust;
+        friend class AAP;
         
         typedef std::map<std::string, MetadataFactory*> MetadataFactoryMap;
         typedef std::map<std::string, TrustFactory*> TrustFactoryMap;
-        MetadataFactoryMap m_metadataFactoryMap;        
-        TrustFactoryMap m_trustFactoryMap;        
+        typedef std::map<std::string, AAPFactory*> AAPFactoryMap;
+        MetadataFactoryMap m_metadataFactoryMap;
+        TrustFactoryMap m_trustFactoryMap;
+        AAPFactoryMap m_aapFactoryMap;
         std::vector<IMetadata*> m_providers;
         std::vector<ITrust*> m_trust_providers;
+        std::vector<IAAP*> m_aap_providers;
     };
 }
 
index 4523fcc..a446d10 100644 (file)
@@ -70,6 +70,9 @@
 # define SHIB_EXPORTS
 #endif
 
+#define SHIB_L(s) shibboleth::XML::Literals::s
+#define SHIB_L_QNAME(p,s) shibboleth::XML::Literals::p##_##s
+
 namespace shibboleth
 {
 #ifdef NO_RTTI
@@ -149,6 +152,27 @@ namespace shibboleth
         virtual bool validate(const ISite* site, saml::Iterator<const XMLCh*> certs) const=0;
         virtual ~ITrust() {}
     };
+    
+    struct SHIB_EXPORTS IAttributeRule
+    {
+        virtual const XMLCh* getName() const=0;
+        virtual const XMLCh* getNamespace() const=0;
+        virtual const char* getFactory() const=0;
+        virtual const char* getAlias() const=0;
+        virtual const char* getHeader() const=0;
+        virtual bool accept(const XMLCh* originSite, const DOMElement* e) const=0;
+        virtual ~IAttributeRule() {}
+    };
+    
+    struct SHIB_EXPORTS IAAP
+    {
+        virtual void lock()=0;
+        virtual void unlock()=0;
+        virtual const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const=0;
+        virtual const IAttributeRule* lookup(const char* alias) const=0;
+        virtual saml::Iterator<const IAttributeRule*> getAttributeRules() const=0;
+        virtual ~IAAP() {}
+    };
 
 #ifdef SHIB_INSTANTIATE
 # ifdef NO_RTTI
@@ -161,13 +185,21 @@ namespace shibboleth
     template class SHIB_EXPORTS saml::ArrayIterator<const IContactInfo*>;
     template class SHIB_EXPORTS saml::Iterator<const IAuthority*>;
     template class SHIB_EXPORTS saml::ArrayIterator<const IAuthority*>;
+    template class SHIB_EXPORTS saml::Iterator<const IAttributeRule*>;
+    template class SHIB_EXPORTS saml::ArrayIterator<const IAttributeRule*>;
+    template class SHIB_EXPORTS saml::Iterator<IMetadata*>;
+    template class SHIB_EXPORTS saml::ArrayIterator<IMetadata*>;
+    template class SHIB_EXPORTS saml::Iterator<ITrust*>;
+    template class SHIB_EXPORTS saml::ArrayIterator<ITrust*>;
+    template class SHIB_EXPORTS saml::Iterator<IAAP*>;
+    template class SHIB_EXPORTS saml::ArrayIterator<IAAP*>;
 #endif
 
     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*>());
+                        const saml::Iterator<const XMLCh*>& values=EMPTY(const XMLCh*));
         SimpleAttribute(DOMElement* e);
         virtual saml::SAMLObject* clone() const;
         virtual ~SimpleAttribute();
@@ -182,8 +214,8 @@ namespace shibboleth
     {
     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*>());
+                        const saml::Iterator<const XMLCh*>& scopes=EMPTY(const XMLCh*),
+                        const saml::Iterator<const XMLCh*>& values=EMPTY(const XMLCh*));
         ScopedAttribute(DOMElement* e);
         virtual ~ScopedAttribute();
 
@@ -222,9 +254,9 @@ namespace shibboleth
             time_t authInstant,
             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings,
             XSECCryptoKey* responseKey,
-            const saml::Iterator<XSECCryptoX509*>& responseCerts=saml::Iterator<XSECCryptoX509*>(),
+            const saml::Iterator<XSECCryptoX509*>& responseCerts=EMPTY(XSECCryptoX509*),
             XSECCryptoKey* assertionKey=NULL,
-            const saml::Iterator<XSECCryptoX509*>& assertionCerts=saml::Iterator<XSECCryptoX509*>()
+            const saml::Iterator<XSECCryptoX509*>& assertionCerts=EMPTY(XSECCryptoX509*)
             );
         virtual bool checkReplayCache(const saml::SAMLAssertion& a);
 
@@ -264,9 +296,9 @@ namespace shibboleth
             time_t authInstant,
             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings,
             XSECCryptoKey* responseKey,
-            const saml::Iterator<XSECCryptoX509*>& responseCerts=saml::Iterator<XSECCryptoX509*>(),
+            const saml::Iterator<XSECCryptoX509*>& responseCerts=EMPTY(XSECCryptoX509*),
             XSECCryptoKey* assertionKey=NULL,
-            const saml::Iterator<XSECCryptoX509*>& assertionCerts=saml::Iterator<XSECCryptoX509*>()
+            const saml::Iterator<XSECCryptoX509*>& assertionCerts=EMPTY(XSECCryptoX509*)
             );
 
     protected:
@@ -317,8 +349,26 @@ namespace shibboleth
         ITrust* m_mapper;
     };
 
+    class SHIB_EXPORTS AAP
+    {
+    public:
+        AAP(const XMLCh* attrName, const XMLCh* attrNamespace=NULL);
+        AAP(const char* alias);
+        ~AAP();
+        bool fail() const {return m_mapper==NULL;}
+        const IAttributeRule* operator->() const {return m_rule;}
+        operator const IAttributeRule*() const {return m_rule;}
+        
+    private:
+        AAP(const AAP&);
+        void operator=(const AAP&);
+        IAAP* m_mapper;
+        const IAttributeRule* m_rule;
+    };
+
     extern "C" { typedef IMetadata* MetadataFactory(const char* source); }
     extern "C" { typedef ITrust* TrustFactory(const char* source); }
+    extern "C" { typedef IAAP* AAPFactory(const char* source); }
     
     class SHIB_EXPORTS ShibConfig
     {
@@ -336,14 +386,15 @@ namespace shibboleth
         // allows pluggable implementations of metadata
         virtual void regFactory(const char* type, MetadataFactory* factory)=0;
         virtual void regFactory(const char* type, TrustFactory* factory)=0;
+        virtual void regFactory(const char* type, AAPFactory* factory)=0;
         virtual void unregFactory(const char* type)=0;
         
         // builds a specific metadata lookup object
         virtual bool addMetadata(const char* type, const char* source)=0;
         
-    /* start of external configuration */
-        std::string aapFile;
-    /* end of external configuration */
+        virtual saml::Iterator<IMetadata*> getMetadataProviders() const=0;
+        virtual saml::Iterator<ITrust*> getTrustProviders() const=0;
+        virtual saml::Iterator<IAAP*> getAAPProviders() const=0;
     };
 
     struct SHIB_EXPORTS Constants
@@ -365,6 +416,8 @@ namespace shibboleth
             // Shibboleth vocabulary
             static const XMLCh AttributeValueType[];
 
+            static const XMLCh Scope[];
+
             static const XMLCh AttributeAuthority[];
             static const XMLCh Contact[];
             static const XMLCh Domain[];
@@ -380,10 +433,14 @@ namespace shibboleth
             static const XMLCh KeyAuthority[];
             static const XMLCh Trust[];
 
+            static const XMLCh Alias[];
             static const XMLCh AnySite[];
             static const XMLCh AnyValue[];
             static const XMLCh AttributeAcceptancePolicy[];
             static const XMLCh AttributeRule[];
+            static const XMLCh Factory[];
+            static const XMLCh Header[];
+            static const XMLCh Namespace[];
             static const XMLCh SiteRule[];
             static const XMLCh Type[];
             static const XMLCh Value[];