New metadata API, fixes to SAML wrappers, simpler plugin API
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 18 Mar 2004 18:58:26 +0000 (18:58 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Thu, 18 Mar 2004 18:58:26 +0000 (18:58 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@842 cb58f699-b61c-0410-a6fe-9272a202ed29

shib/Metadata.cpp
shib/ReloadableXMLFile.cpp
shib/ShibBinding.cpp
shib/ShibConfig.cpp
shib/ShibPOSTProfile.cpp
shib/internal.h
shib/shib.h

index 04889fa..5e23853 100644 (file)
@@ -118,28 +118,22 @@ bool Trust::validate(
     const IProviderRole* role, const SAMLSignedObject& token,
     const Iterator<IMetadata*>& metadatas) const
 {
-    bool ret=false;
     m_trusts.reset();
-    while (!ret && m_trusts.hasNext()) {
-        ITrust* i=m_trusts.next();
-        i->lock();
-        ret=i->validate(revocations,role,token,metadatas);
-        i->unlock();
+    while (m_trusts.hasNext()) {
+        if (m_trusts.next()->validate(revocations,role,token,metadatas))
+            return true;
     }
-    return ret;
+    return false;
 }
 
 bool Trust::attach(const Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx) const
 {
-    bool ret=false;
     m_trusts.reset();
-    while (!ret && m_trusts.hasNext()) {
-        ITrust* i=m_trusts.next();
-        i->lock();
-        ret=i->attach(revocations,role,ctx);
-        i->unlock();
+    while (m_trusts.hasNext()) {
+        if (m_trusts.next()->attach(revocations,role,ctx))
+            return true;
     }
-    return ret;
+    return false;
 }
 
 const ICredResolver* Credentials::lookup(const char* id)
index da2d5f2..87a0466 100644 (file)
@@ -67,7 +67,7 @@ using namespace saml;
 using namespace log4cpp;
 using namespace std;
 
-ReloadableXMLFileImpl::ReloadableXMLFileImpl(const DOMElement* e) : m_doc(NULL), m_root(saml::XML::getFirstChildElement(e)) {}
+ReloadableXMLFileImpl::ReloadableXMLFileImpl(const DOMElement* e) : m_doc(NULL), m_root(e) {}
 
 ReloadableXMLFileImpl::ReloadableXMLFileImpl(const char* pathname) : m_doc(NULL), m_root(NULL)
 {
@@ -115,7 +115,7 @@ ReloadableXMLFileImpl::~ReloadableXMLFileImpl()
 
 ReloadableXMLFile::ReloadableXMLFile(const DOMElement* e) : m_root(e), m_impl(NULL), m_filestamp(0), m_lock(NULL)
 {
-    static const XMLCh url[] = { chLatin_u, chLatin_r, chLatin_l, chNull };
+    static const XMLCh url[] = { chLatin_u, chLatin_r, chLatin_i, chNull };
     const XMLCh* pathname=e->getAttributeNS(NULL,url);
     if (pathname && *pathname)
     {
@@ -159,7 +159,7 @@ void ReloadableXMLFile::lock()
             {
                 try
                 {
-                    ReloadableXMLFileImpl* new_config=newImplementation(m_source.c_str());
+                    ReloadableXMLFileImpl* new_config=newImplementation(m_source.c_str(),false);
                     delete m_impl;
                     m_impl=new_config;
                     m_filestamp=stat_buf.st_mtime;
@@ -191,7 +191,7 @@ ReloadableXMLFileImpl* ReloadableXMLFile::getImplementation() const
 {
     if (!m_impl) {
         if (m_source.empty())
-            m_impl=newImplementation(m_root);
+            m_impl=newImplementation(saml::XML::getFirstChildElement(m_root));
         else
             m_impl=newImplementation(m_source.c_str());
     }
index 028bc31..c84807b 100644 (file)
@@ -101,37 +101,24 @@ bool shibboleth::ssl_ctx_callback(void* ssl_ctx, void* userptr)
 
 SAMLResponse* ShibBinding::send(
     SAMLRequest& req,
-    const IProvider* provider,
+    const IAttributeAuthorityRole* AA,
     const char* credResolverId,
+    const Iterator<const XMLCh*>& audiences,
     const Iterator<SAMLAuthorityBinding*>& bindings,
     SAMLConfig::SAMLBindingConfig& conf
     )
 {
     NDC ndc("send");
+    Category& log=Category::getInstance(SHIB_LOGCAT".ShibBinding");
+    
     static const XMLCh VER[] = {chDigit_1, chNull};
     static const saml::QName qname(saml::XML::SAMLP_NS,L(AttributeQuery));
     
     conf.ssl_ctx_callback=reinterpret_cast<SAMLConfig::SAMLBindingConfig::ssl_ctx_callback_fn>(ssl_ctx_callback);
     conf.ssl_ctx_data=this;
-    m_AA=NULL;
+    m_AA=AA;
     m_credResolverId=credResolverId;
     
-    // Try to locate an AA role.
-    Iterator<const IProviderRole*> roles=provider->getRoles();
-    while (!m_AA && roles.hasNext()) {
-        const IProviderRole* role=roles.next();
-        if (dynamic_cast<const IAttributeAuthorityRole*>(role)) {
-            // Check for SAML 1.x protocol support.
-            Iterator<const XMLCh*> protocols=role->getProtocolSupportEnumeration();
-            while (!m_AA && protocols.hasNext()) {
-                if (!XMLString::compareString(protocols.next(),saml::XML::SAMLP_NS))
-                    m_AA=dynamic_cast<const IAttributeAuthorityRole*>(role);
-            }
-        }
-    }
-    if (!m_AA)
-        throw MetadataException("ShibBinding::send() unable to locate metadata for provider's Attribute Authority");
-
     // First try any bindings provided by caller.
     const XMLCh* prevBinding=NULL;
     Trust t(m_trusts);
@@ -146,16 +133,36 @@ SAMLResponse* ShibBinding::send(
             auto_ptr<SAMLResponse> r(m_binding->send(*ab, req, conf));
             if (r->isSigned() && !t.validate(m_revocations,m_AA,*r))
                 throw TrustException("ShibBinding::send() unable to verify signed response");
-            Iterator<SAMLAssertion*> iter_a=r->getAssertions();
-            while (iter_a.hasNext()) {
-                SAMLAssertion* _a=iter_a.next();
-                if (_a->isSigned() && !t.validate(m_revocations,m_AA,*_a))
-                    throw TrustException("ShibBinding::send() unable to verify signed assertion");
+            Iterator<SAMLAssertion*> _a=r->getAssertions();
+            for (unsigned long i=0; i < _a.size(); i++) {
+                // Check any conditions.
+                Iterator<SAMLCondition*> conds=_a[i]->getConditions();
+                while (conds.hasNext()) {
+                    SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
+                    if (!cond || !cond->eval(audiences)) {
+                        log.warn("assertion condition is false, removing it");
+                        r->removeAssertion(i);
+                        i--;
+                        break;
+                    }
+                }
+                
+                // Check signature.
+                if (_a[i]->isSigned() && !t.validate(m_revocations,m_AA,*(_a[i]))) {
+                    log.warn("signed assertion failed to validate, removing it");
+                    r->removeAssertion(i);
+                    i--;
+                }
             }
-            return r.release();
+            
+            // Any left?
+            if (r->getAssertions().size())
+                return r.release();
+            else
+                log.warn("all assertions removed from response, dumping it");
         }
         catch (SAMLException& e) {
-            Category::getInstance(SHIB_LOGCAT".ShibBinding").error("caught SAML exception during SAML attribute query: %s", e.what());
+            log.error("caught SAML exception during SAML attribute query: %s", e.what());
         }
     }
     
@@ -177,16 +184,34 @@ SAMLResponse* ShibBinding::send(
             auto_ptr<SAMLResponse> r(m_binding->send(ab, req, conf));
             if (r->isSigned() && !t.validate(m_revocations,m_AA,*r))
                 throw TrustException("ShibBinding::send() unable to verify signed response");
-            Iterator<SAMLAssertion*> iter_a=r->getAssertions();
-            while (iter_a.hasNext()) {
-                SAMLAssertion* _a=iter_a.next();
-                if (_a->isSigned() && !t.validate(m_revocations,m_AA,*_a))
-                    throw TrustException("ShibBinding::send() unable to verify signed assertion");
+
+            Iterator<SAMLAssertion*> _a=r->getAssertions();
+            for (unsigned long i=0; i < _a.size();) {
+                // Check any conditions.
+                Iterator<SAMLCondition*> conds=_a[i]->getConditions();
+                while (conds.hasNext()) {
+                    SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
+                    if (!cond || !cond->eval(audiences)) {
+                        log.warn("assertion condition is false, removing it");
+                        r->removeAssertion(i);
+                    }
+                }
+                
+                // Check signature.
+                if (_a[i]->isSigned() && !t.validate(m_revocations,m_AA,*(_a[i]))) {
+                    log.warn("signed assertion failed to validate, removing it");
+                    r->removeAssertion(i);
+                }
             }
-            return r.release();
+
+            // Any left?
+            if (r->getAssertions().size())
+                return r.release();
+            else
+                log.warn("all assertions removed from response, dumping it");
         }
         catch (SAMLException& e) {
-            Category::getInstance(SHIB_LOGCAT".ShibBinding").error("caught SAML exception during SAML attribute query: %s", e.what());
+            log.error("caught SAML exception during SAML attribute query: %s", e.what());
         }
     }
     
index 412205c..63bb303 100644 (file)
@@ -70,149 +70,40 @@ using namespace shibboleth;
 using namespace log4cpp;
 using namespace std;
 
-SAML_EXCEPTION_FACTORY(UnsupportedProtocolException);
 SAML_EXCEPTION_FACTORY(MetadataException);
 SAML_EXCEPTION_FACTORY(CredentialException);
 
 namespace {
-    ShibInternalConfig g_config;
+    ShibConfig g_config;
 }
 
-ShibConfig::~ShibConfig() {}
-
-bool ShibInternalConfig::init()
+bool ShibConfig::init()
 {
-    saml::NDC ndc("init");
-
-    REGISTER_EXCEPTION_FACTORY(edu.internet2.middleware.shibboleth.common,UnsupportedProtocolException);
     REGISTER_EXCEPTION_FACTORY(edu.internet2.middleware.shibboleth.common,MetadataException);
     REGISTER_EXCEPTION_FACTORY(edu.internet2.middleware.shibboleth.common,CredentialException);
-
     return true;
 }
 
-void ShibInternalConfig::regFactory(const char* type, MetadataFactory* factory)
-{
-    if (type && factory)
-        m_metadataFactoryMap[type]=factory;
-}
+void ShibConfig::term() {}
 
-void ShibInternalConfig::regFactory(const char* type, RevocationFactory* factory)
+void PlugManager::regFactory(const char* type, Factory* factory)
 {
     if (type && factory)
-        m_revocationFactoryMap[type]=factory;
+        m_map[type]=factory;
 }
 
-void ShibInternalConfig::regFactory(const char* type, TrustFactory* factory)
+IPlugIn* PlugManager::newPlugin(const char* type, const DOMElement* source)
 {
-    if (type && factory)
-        m_trustFactoryMap[type]=factory;
-}
-
-void ShibInternalConfig::regFactory(const char* type, CredentialsFactory* factory)
-{
-    if (type && factory)
-    {
-        m_credFactoryMap[type]=factory;
-        SAMLConfig::getConfig().binding_defaults.ssl_ctx_callback=
-            reinterpret_cast<SAMLConfig::SAMLBindingConfig::ssl_ctx_callback_fn>(ssl_ctx_callback);
-    }
-}
-
-void ShibInternalConfig::regFactory(const char* type, CredResolverFactory* factory)
-{
-    if (type && factory)
-        m_credResolverFactoryMap[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_revocationFactoryMap.erase(type);
-        m_trustFactoryMap.erase(type);
-        m_credFactoryMap.erase(type);
-        m_aapFactoryMap.erase(type);
-        m_credResolverFactoryMap.erase(type);
-    }
-}
-
-IMetadata* ShibInternalConfig::newMetadata(const char* type, const DOMElement* source) const
-{
-    MetadataFactoryMap::const_iterator i=m_metadataFactoryMap.find(type);
-    if (i==m_metadataFactoryMap.end())
-    {
-        NDC ndc("newMetadata");
-        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown metadata type: %s",type);
-        return NULL;
-    }
-    return i->second(source);
-}
-
-IRevocation* ShibInternalConfig::newRevocation(const char* type, const DOMElement* source) const
-{
-    RevocationFactoryMap::const_iterator i=m_revocationFactoryMap.find(type);
-    if (i==m_revocationFactoryMap.end())
-    {
-        NDC ndc("newRevocation");
-        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown revocation type: %s",type);
-        return NULL;
-    }
-    return i->second(source);
-}
-
-ITrust* ShibInternalConfig::newTrust(const char* type, const DOMElement* source) const
-{
-    TrustFactoryMap::const_iterator i=m_trustFactoryMap.find(type);
-    if (i==m_trustFactoryMap.end())
-    {
-        NDC ndc("newTrust");
-        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown trust type: %s",type);
-        return NULL;
-    }
-    return i->second(source);
-}
-
-ICredentials* ShibInternalConfig::newCredentials(const char* type, const DOMElement* source) const
-{
-    CredentialsFactoryMap::const_iterator i=m_credFactoryMap.find(type);
-    if (i==m_credFactoryMap.end())
-    {
-        NDC ndc("newCredentials");
-        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown credentials type: %s",type);
-        return NULL;
-    }
-    return i->second(source);
-}
-
-IAAP* ShibInternalConfig::newAAP(const char* type, const DOMElement* source) const
-{
-    AAPFactoryMap::const_iterator i=m_aapFactoryMap.find(type);
-    if (i==m_aapFactoryMap.end())
-    {
-        NDC ndc("newAAP");
-        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown AAP type: %s",type);
-        return NULL;
-    }
+    FactoryMap::const_iterator i=m_map.find(type);
+    if (i==m_map.end())
+        throw saml::UnsupportedExtensionException(std::string("unable to build plugin of type '") + type + "'");
     return i->second(source);
 }
 
-ICredResolver* ShibInternalConfig::newCredResolver(const char* type, const DOMElement* source) const
+void PlugManager::unregFactory(const char* type)
 {
-    CredResolverFactoryMap::const_iterator i=m_credResolverFactoryMap.find(type);
-    if (i==m_credResolverFactoryMap.end())
-    {
-        NDC ndc("newCredResolver");
-        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown cred resolver type: %s",type);
-        return NULL;
-    }
-    return i->second(source);
+    if (type)
+        m_map.erase(type);
 }
 
 ShibConfig& ShibConfig::getConfig()
index 5e087a6..3459b61 100644 (file)
@@ -85,17 +85,20 @@ const SAMLAuthenticationStatement* ShibPOSTProfile::getSSOStatement(const SAMLAs
 
 const XMLCh* ShibPOSTProfile::getProviderId(const saml::SAMLResponse& r)
 {
+    // Favor an AuthnStatement Subject NameQualifier, but use Issuer if need be.
+    const XMLCh* ret=NULL;
     Iterator<SAMLAssertion*> ia=r.getAssertions();
     while (ia.hasNext()) {
-        Iterator<SAMLStatement*> is=ia.next()->getStatements();
+        SAMLAssertion* a=ia.next();
+        ret=a->getIssuer();
+        Iterator<SAMLStatement*> is=a->getStatements();
         while (is.hasNext()) {
-            SAMLStatement* s=is.next();
-            SAMLAuthenticationStatement* as=dynamic_cast<SAMLAuthenticationStatement*>(s);
-            if (as)
+            SAMLAuthenticationStatement* as=dynamic_cast<SAMLAuthenticationStatement*>(is.next());
+            if (as && as->getSubject()->getNameQualifier())
                 return as->getSubject()->getNameQualifier();
         }
     }
-    return NULL;
+    return ret;
 }
 
 SAMLResponse* ShibPOSTProfile::accept(
@@ -165,30 +168,26 @@ SAMLResponse* ShibPOSTProfile::accept(
     while (roles.hasNext()) {
         const IProviderRole* role=roles.next();
         if (dynamic_cast<const IIDPProviderRole*>(role)) {
-            const IProviderRole* IDP=dynamic_cast<const IProviderRole*>(role);
-            // Check for SAML 1.x protocol support.
-            Iterator<const XMLCh*> protocols=IDP->getProtocolSupportEnumeration();
-            while (protocols.hasNext()) {
-                if (!XMLString::compareString(protocols.next(),Constants::SHIB_NS)) {
-                    log.debug("passing response to trust layer");
-                    
-                    // Use this role to evaluate the signature.
-                    Trust t(m_trusts);
-                    if (!t.validate(m_revocations,role,*r))
-                        throw TrustException("ShibPOSTProfile::accept() unable to verify signed response");
-                    
-                    // Assertion(s) signed?
-                    Iterator<SAMLAssertion*> itera=r->getAssertions();
-                    while (itera.hasNext()) {
-                        SAMLAssertion* _a=itera.next();
-                        if (_a->isSigned()) {
-                            log.debug("passing signed assertion to trust layer"); 
-                            if (!t.validate(m_revocations,role,*_a))
-                                throw TrustException("ShibPOSTProfile::accept() unable to verify signed assertion");
-                        }
+            // Check for Shibboleth 1.x protocol support.
+            if (role->hasSupport(Constants::SHIB_NS)) {
+                log.debug("passing response to trust layer");
+                
+                // Use this role to evaluate the signature.
+                Trust t(m_trusts);
+                if (!t.validate(m_revocations,role,*r))
+                    throw TrustException("ShibPOSTProfile::accept() unable to verify signed response");
+                
+                // Assertion(s) signed?
+                Iterator<SAMLAssertion*> itera=r->getAssertions();
+                while (itera.hasNext()) {
+                    SAMLAssertion* _a=itera.next();
+                    if (_a->isSigned()) {
+                        log.debug("passing signed assertion to trust layer"); 
+                        if (!t.validate(m_revocations,role,*_a))
+                            throw TrustException("ShibPOSTProfile::accept() unable to verify signed assertion");
                     }
-                    return r.release();
                 }
+                return r.release();
             }
         }
     }
index dd603a3..e141e91 100644 (file)
@@ -78,6 +78,7 @@
 
 namespace shibboleth
 {
+        /*
     class ShibInternalConfig : public ShibConfig
     {
     public:
@@ -115,6 +116,7 @@ namespace shibboleth
         AAPFactoryMap m_aapFactoryMap;
         CredResolverFactoryMap m_credResolverFactoryMap;
     };
+        */
 
     // OpenSSL Utilities
     
index 3454830..ca543d9 100644 (file)
@@ -87,10 +87,33 @@ namespace shibboleth
             virtual ~name() throw () {} \
         }
 
-    DECLARE_SHIB_EXCEPTION(UnsupportedProtocolException,SAMLException);
     DECLARE_SHIB_EXCEPTION(MetadataException,SAMLException);
     DECLARE_SHIB_EXCEPTION(CredentialException,SAMLException);
 
+    // Manages pluggable implementations of interfaces
+    // Would prefer this to be a template, but the Windows STL isn't DLL-safe.
+
+    struct SHIB_EXPORTS IPlugIn
+    {
+        virtual ~IPlugIn() {}
+    };
+
+    class SHIB_EXPORTS PlugManager
+    {
+    public:
+        PlugManager() {}
+        ~PlugManager() {}
+
+        typedef IPlugIn* Factory(const DOMElement* source);
+        void regFactory(const char* type, Factory* factory);
+        void unregFactory(const char* type);
+        IPlugIn* newPlugin(const char* type, const DOMElement* source);
+
+    private:
+        typedef std::map<std::string, Factory*> FactoryMap;
+        FactoryMap m_map;
+    };
+
     // Metadata abstract interfaces, inching toward SAML 2.0...
     
     struct SHIB_EXPORTS ILockable
@@ -147,6 +170,7 @@ namespace shibboleth
     {
         virtual const IProvider* getProvider() const=0;
         virtual saml::Iterator<const XMLCh*> getProtocolSupportEnumeration() const=0;
+        virtual bool hasSupport(const XMLCh* version) const=0;
         virtual saml::Iterator<const IKeyDescriptor*> getKeyDescriptors() const=0;
         virtual const IOrganization* getOrganization() const=0;
         virtual saml::Iterator<const IContactPerson*> getContacts() const=0;
@@ -219,13 +243,13 @@ namespace shibboleth
         virtual ~IProvider() {}
     };
     
-    struct SHIB_EXPORTS IMetadata : public virtual ILockable
+    struct SHIB_EXPORTS IMetadata : public virtual ILockable, public virtual IPlugIn
     {
         virtual const IProvider* lookup(const XMLCh* providerId) const=0;
         virtual ~IMetadata() {}
     };
 
-    struct SHIB_EXPORTS IRevocation : public virtual ILockable
+    struct SHIB_EXPORTS IRevocation : public virtual ILockable, public virtual IPlugIn
     {
         virtual saml::Iterator<void*> getRevocationLists(const IProvider* provider, const IProviderRole* role=NULL) const=0;
         virtual ~IRevocation() {}
@@ -234,18 +258,18 @@ namespace shibboleth
     // Trust interface hides *all* details of signature and SSL validation.
     // Pluggable providers can fully override the Shibboleth trust model here.
     
-    struct SHIB_EXPORTS ITrust : public virtual ILockable
+    struct SHIB_EXPORTS ITrust : public virtual IPlugIn
     {
         virtual bool validate(
             const saml::Iterator<IRevocation*>& revocations,
             const IProviderRole* role, const saml::SAMLSignedObject& token,
             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*)
-            ) const=0;
-        virtual bool attach(const saml::Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx) const=0;
+            )=0;
+        virtual bool attach(const saml::Iterator<IRevocation*>& revocations, const IProviderRole* role, void* ctx)=0;
         virtual ~ITrust() {}
     };
     
-    struct SHIB_EXPORTS ICredResolver
+    struct SHIB_EXPORTS ICredResolver : public virtual IPlugIn
     {
         virtual void attach(void* ctx) const=0;
         virtual XSECCryptoKey* getKey() const=0;
@@ -255,7 +279,7 @@ namespace shibboleth
         virtual ~ICredResolver() {}
     };
 
-    struct SHIB_EXPORTS ICredentials : public virtual ILockable
+    struct SHIB_EXPORTS ICredentials : public virtual ILockable, public virtual IPlugIn
     {
         virtual const ICredResolver* lookup(const char* id) const=0;
         virtual ~ICredentials() {}
@@ -272,7 +296,7 @@ namespace shibboleth
         virtual ~IAttributeRule() {}
     };
     
-    struct SHIB_EXPORTS IAAP : public virtual ILockable
+    struct SHIB_EXPORTS IAAP : public virtual ILockable, public virtual IPlugIn
     {
         virtual const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const=0;
         virtual const IAttributeRule* lookup(const char* alias) const=0;
@@ -307,6 +331,18 @@ namespace shibboleth
 
     // Glue classes between abstract metadata and concrete providers
     
+    class SHIB_EXPORTS Locker
+    {
+    public:
+        Locker(ILockable* lockee) : m_lockee(lockee) {m_lockee->lock();}
+        ~Locker() {if (m_lockee) m_lockee->unlock();}
+        
+    private:
+        Locker(const Locker&);
+        void operator=(const Locker&);
+        ILockable* m_lockee;
+    };
+    
     class SHIB_EXPORTS Metadata
     {
     public:
@@ -450,8 +486,9 @@ namespace shibboleth
 
         saml::SAMLResponse* send(
             saml::SAMLRequest& req,
-            const IProvider* provider,
+            const IAttributeAuthorityRole* AA,
             const char* credResolverId=NULL,
+            const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
             const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*),
             saml::SAMLConfig::SAMLBindingConfig& conf=saml::SAMLConfig::getConfig().binding_defaults
             );
@@ -466,44 +503,21 @@ namespace shibboleth
         saml::SAMLBinding* m_binding;
     };
 
-    extern "C" {
-        typedef IMetadata* MetadataFactory(const DOMElement* source);
-        typedef IRevocation* RevocationFactory(const DOMElement* source);
-        typedef ITrust* TrustFactory(const DOMElement* source);
-        typedef ICredentials* CredentialsFactory(const DOMElement* source);
-        typedef IAAP* AAPFactory(const DOMElement* source);
-        typedef ICredResolver* CredResolverFactory(const DOMElement* source);
-    }
-    
     class SHIB_EXPORTS ShibConfig
     {
     public:
         ShibConfig() {}
-        virtual ~ShibConfig();
+        virtual ~ShibConfig() {}
 
         // global per-process setup and shutdown of Shibboleth runtime
-        virtual bool init()=0;
-        virtual void term()=0;
+        virtual bool init();
+        virtual void term();
 
         // enables runtime and clients to access configuration
         static ShibConfig& getConfig();
 
         // allows pluggable implementations of metadata and configuration data
-        virtual void regFactory(const char* type, MetadataFactory* factory)=0;
-        virtual void regFactory(const char* type, RevocationFactory* factory)=0;
-        virtual void regFactory(const char* type, TrustFactory* factory)=0;
-        virtual void regFactory(const char* type, CredentialsFactory* factory)=0;
-        virtual void regFactory(const char* type, AAPFactory* factory)=0;
-        virtual void regFactory(const char* type, CredResolverFactory* factory)=0;
-        virtual void unregFactory(const char* type)=0;
-        
-        // build a specific metadata lookup object
-        virtual IMetadata* newMetadata(const char* type, const DOMElement* source) const=0;
-        virtual IRevocation* newRevocation(const char* type, const DOMElement* source) const=0;
-        virtual ITrust* newTrust(const char* type, const DOMElement* source) const=0;
-        virtual ICredentials* newCredentials(const char* type, const DOMElement* source) const=0;
-        virtual IAAP* newAAP(const char* type, const DOMElement* source) const=0;
-        virtual ICredResolver* newCredResolver(const char* type, const DOMElement* source) const=0;
+        PlugManager m_plugMgr;
     };
 
     /* Helper classes for implementing reloadable XML-based config files
@@ -536,15 +550,15 @@ namespace shibboleth
         ReloadableXMLFileImpl* getImplementation() const;
 
     protected:
-        virtual ReloadableXMLFileImpl* newImplementation(const char* pathname) const=0;
-        virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e) const=0;
+        virtual ReloadableXMLFileImpl* newImplementation(const char* pathname, bool first=true) const=0;
+        virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e, bool first=true) const=0;
+        mutable ReloadableXMLFileImpl* m_impl;
         
     private:
         const DOMElement* m_root;
         std::string m_source;
         time_t m_filestamp;
         RWLock* m_lock;
-        mutable ReloadableXMLFileImpl* m_impl;
     };
 }