- }\r
-\r
- // Provides filter to exclude special config elements.\r
- short acceptNode(const DOMNode* node) const;\r
- \r
- private:\r
- void cleanup();\r
- const ServiceProvider* m_sp; // this is ok because its locking scope includes us\r
- const XMLApplication* m_base;\r
- string m_hash;\r
-#ifndef SHIBSP_LITE\r
- MetadataProvider* m_metadata;\r
- TrustEngine* m_trust;\r
- AttributeExtractor* m_attrExtractor;\r
- AttributeFilter* m_attrFilter;\r
- AttributeResolver* m_attrResolver;\r
- CredentialResolver* m_credResolver;\r
- vector<const XMLCh*> m_audiences;\r
-#endif\r
- set<string> m_remoteUsers;\r
- mutable vector<string> m_unsetHeaders;\r
- RWLock* m_unsetLock;\r
-\r
- // manage handler objects\r
- vector<Handler*> m_handlers;\r
-\r
- // maps location (path info) to applicable handlers\r
- map<string,const Handler*> m_handlerMap;\r
-\r
- // maps unique indexes to consumer services\r
- map<unsigned int,const Handler*> m_acsIndexMap;\r
- \r
- // pointer to default consumer service\r
- const Handler* m_acsDefault;\r
-\r
- // maps binding strings to supporting consumer service(s)\r
-#ifdef HAVE_GOOD_STL\r
- typedef map<xstring,vector<const Handler*> > ACSBindingMap;\r
-#else\r
- typedef map<string,vector<const Handler*> > ACSBindingMap;\r
-#endif\r
- ACSBindingMap m_acsBindingMap;\r
-\r
- // pointer to default session initiator\r
- const SessionInitiator* m_sessionInitDefault;\r
-\r
- // maps unique ID strings to session initiators\r
- map<string,const SessionInitiator*> m_sessionInitMap;\r
-\r
-#ifndef SHIBSP_LITE\r
- // RelyingParty properties\r
- DOMPropertySet* m_partyDefault;\r
-#ifdef HAVE_GOOD_STL\r
- map<xstring,PropertySet*> m_partyMap;\r
-#else\r
- map<const XMLCh*,PropertySet*> m_partyMap;\r
-#endif\r
-#endif\r
- };\r
-\r
- // Top-level configuration implementation\r
- class SHIBSP_DLLLOCAL XMLConfig;\r
- class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter\r
- {\r
- public:\r
- XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);\r
- ~XMLConfigImpl();\r
- \r
- RequestMapper* m_requestMapper;\r
- map<string,Application*> m_appmap;\r
-#ifndef SHIBSP_LITE\r
- map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;\r
-#endif\r
- \r
- // Provides filter to exclude special config elements.\r
- short acceptNode(const DOMNode* node) const;\r
-\r
- void setDocument(DOMDocument* doc) {\r
- m_document = doc;\r
- }\r
-\r
- private:\r
- void doExtensions(const DOMElement* e, const char* label, Category& log);\r
-\r
- const XMLConfig* m_outer;\r
- DOMDocument* m_document;\r
- };\r
-\r
- class SHIBSP_DLLLOCAL XMLConfig : public ServiceProvider, public ReloadableXMLFile, public Remoted\r
- {\r
- public:\r
- XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),\r
- m_impl(NULL), m_listener(NULL), m_sessionCache(NULL)\r
-#ifndef SHIBSP_LITE\r
- , m_tranLog(NULL)\r
-#endif\r
- {\r
- }\r
- \r
- void init() {\r
- load();\r
- }\r
-\r
- ~XMLConfig() {\r
- delete m_impl;\r
- delete m_sessionCache;\r
- delete m_listener;\r
-#ifndef SHIBSP_LITE\r
- delete m_tranLog;\r
- SAMLConfig::getConfig().setArtifactMap(NULL);\r
- XMLToolingConfig::getConfig().setReplayCache(NULL);\r
- for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());\r
-#endif\r
- }\r
-\r
- // PropertySet\r
- void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}\r
- pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);}\r
- pair<bool,const char*> getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);}\r
- pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);}\r
- pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);}\r
- pair<bool,int> getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);}\r
- const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}\r
- const DOMElement* getElement() const {return m_impl->getElement();}\r
-\r
- // Remoted\r
- void receive(DDF& in, ostream& out);\r
-\r
- // ServiceProvider\r
-#ifndef SHIBSP_LITE\r
- TransactionLog* getTransactionLog() const {\r
- if (m_tranLog)\r
- return m_tranLog;\r
- throw ConfigurationException("No TransactionLog available.");\r
- }\r
-\r
- StorageService* getStorageService(const char* id) const {\r
- if (id) {\r
- map<string,StorageService*>::const_iterator i=m_storage.find(id);\r
- if (i!=m_storage.end())\r
- return i->second;\r
- }\r
- return NULL;\r
- }\r
-#endif\r
-\r
- ListenerService* getListenerService(bool required=true) const {\r
- if (required && !m_listener)\r
- throw ConfigurationException("No ListenerService available.");\r
- return m_listener;\r
- }\r
-\r
- SessionCache* getSessionCache(bool required=true) const {\r
- if (required && !m_sessionCache)\r
- throw ConfigurationException("No SessionCache available.");\r
- return m_sessionCache;\r
- }\r
-\r
- RequestMapper* getRequestMapper(bool required=true) const {\r
- if (required && !m_impl->m_requestMapper)\r
- throw ConfigurationException("No RequestMapper available.");\r
- return m_impl->m_requestMapper;\r
- }\r
-\r
- const Application* getApplication(const char* applicationId) const {\r
- map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);\r
- return (i!=m_impl->m_appmap.end()) ? i->second : NULL;\r
- }\r
-\r
-#ifndef SHIBSP_LITE\r
- const PropertySet* getPolicySettings(const char* id) const {\r
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
- if (i!=m_impl->m_policyMap.end())\r
- return i->second.first;\r
- throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
- }\r
-\r
- const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {\r
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
- if (i!=m_impl->m_policyMap.end())\r
- return i->second.second;\r
- throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
- }\r
-#endif\r
-\r
- protected:\r
- pair<bool,DOMElement*> load();\r
-\r
- private:\r
- friend class XMLConfigImpl;\r
- XMLConfigImpl* m_impl;\r
- mutable ListenerService* m_listener;\r
- mutable SessionCache* m_sessionCache;\r
-#ifndef SHIBSP_LITE\r
- mutable TransactionLog* m_tranLog;\r
- mutable map<string,StorageService*> m_storage;\r
-#endif\r
- };\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( pop )\r
-#endif\r
-\r
- static const XMLCh _Application[] = UNICODE_LITERAL_11(A,p,p,l,i,c,a,t,i,o,n);\r
- static const XMLCh Applications[] = UNICODE_LITERAL_12(A,p,p,l,i,c,a,t,i,o,n,s);\r
- static const XMLCh _ArtifactMap[] = UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);\r
- static const XMLCh _AttributeExtractor[] = UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);\r
- static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);\r
- static const XMLCh _AttributeResolver[] = UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);\r
- static const XMLCh _AssertionConsumerService[] = UNICODE_LITERAL_24(A,s,s,e,r,t,i,o,n,C,o,n,s,u,m,e,r,S,e,r,v,i,c,e);\r
- static const XMLCh _Audience[] = UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);\r
- static const XMLCh Binding[] = UNICODE_LITERAL_7(B,i,n,d,i,n,g);\r
- static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);\r
- static const XMLCh DefaultRelyingParty[] = UNICODE_LITERAL_19(D,e,f,a,u,l,t,R,e,l,y,i,n,g,P,a,r,t,y);\r
- static const XMLCh _Extensions[] = UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);\r
- static const XMLCh fatal[] = UNICODE_LITERAL_5(f,a,t,a,l);\r
- static const XMLCh _Handler[] = UNICODE_LITERAL_7(H,a,n,d,l,e,r);\r
- static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);\r
- static const XMLCh Implementation[] = UNICODE_LITERAL_14(I,m,p,l,e,m,e,n,t,a,t,i,o,n);\r
- static const XMLCh InProcess[] = UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s);\r
- static const XMLCh Library[] = UNICODE_LITERAL_7(L,i,b,r,a,r,y);\r
- static const XMLCh Listener[] = UNICODE_LITERAL_8(L,i,s,t,e,n,e,r);\r
- static const XMLCh logger[] = UNICODE_LITERAL_6(l,o,g,g,e,r);\r
- static const XMLCh _ManageNameIDService[] = UNICODE_LITERAL_19(M,a,n,a,g,e,N,a,m,e,I,D,S,e,r,v,i,c,e);\r
- static const XMLCh MemoryListener[] = UNICODE_LITERAL_14(M,e,m,o,r,y,L,i,s,t,e,n,e,r);\r
- static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);\r
- static const XMLCh OutOfProcess[] = UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);\r
- static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h);\r
- static const XMLCh Policy[] = UNICODE_LITERAL_6(P,o,l,i,c,y);\r
- static const XMLCh RelyingParty[] = UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);\r
- static const XMLCh _ReplayCache[] = UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);\r
- static const XMLCh _RequestMapper[] = UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);\r
- static const XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e);\r
- static const XMLCh SecurityPolicies[] = UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);\r
- static const XMLCh _SessionCache[] = UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);\r
- static const XMLCh _SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);\r
- static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);\r
- static const XMLCh _StorageService[] = UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);\r
- static const XMLCh TCPListener[] = UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);\r
- static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);\r
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);\r
- static const XMLCh UnixListener[] = UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);\r
-\r
- class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter\r
- {\r
- public:\r
- short acceptNode(const DOMNode* node) const {\r
- if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,Rule))\r
- return FILTER_REJECT;\r
- return FILTER_ACCEPT;\r
- }\r
- };\r
-};\r
-\r
-namespace shibsp {\r
- ServiceProvider* XMLServiceProviderFactory(const DOMElement* const & e)\r
- {\r
- return new XMLConfig(e);\r
- }\r
-};\r
-\r
-XMLApplication::XMLApplication(\r
- const ServiceProvider* sp,\r
- const DOMElement* e,\r
- const XMLApplication* base\r
- ) : m_sp(sp), m_base(base),\r
-#ifndef SHIBSP_LITE\r
- m_metadata(NULL), m_trust(NULL), m_attrExtractor(NULL), m_attrFilter(NULL), m_attrResolver(NULL), m_credResolver(NULL), m_partyDefault(NULL),\r
-#endif\r
- m_sessionInitDefault(NULL), m_unsetLock(NULL), m_acsDefault(NULL)\r
-{\r
-#ifdef _DEBUG\r
- xmltooling::NDC ndc("XMLApplication");\r
-#endif\r
- Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");\r
-\r
- try {\r
- // First load any property sets.\r
- load(e,log,this);\r
- if (base)\r
- setParent(base);\r
-\r
- SPConfig& conf=SPConfig::getConfig();\r
-#ifndef SHIBSP_LITE\r
- SAMLConfig& samlConf=SAMLConfig::getConfig();\r
-#endif\r
- XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();\r
-\r
- // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec.\r
- static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\r
- string tohash=getId();\r
- tohash+=getString("entityID").second;\r
- for (const char* ch = tohash.c_str(); *ch; ++ch) {\r
- m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);\r
- m_hash += (DIGITS[0x0F & *ch]);\r
- }\r
-\r
- // Load attribute ID lists for REMOTE_USER and header clearing.\r
- if (conf.isEnabled(SPConfig::InProcess)) {\r
- pair<bool,const char*> attributes = getString("REMOTE_USER");\r
- if (attributes.first) {\r
- char* dup = strdup(attributes.second);\r
- char* pos;\r
- char* start = dup;\r
- while (start && *start) {\r
- while (*start && isspace(*start))\r
- start++;\r
- if (!*start)\r
- break;\r
- pos = strchr(start,' ');\r
- if (pos)\r
- *pos=0;\r
- m_remoteUsers.insert(start);\r
- start = pos ? pos+1 : NULL;\r
- }\r
- free(dup);\r
- }\r
-\r
- attributes = getString("unsetHeaders");\r
- if (attributes.first) {\r
- char* dup = strdup(attributes.second);\r
- char* pos;\r
- char* start = dup;\r
- while (start && *start) {\r
- while (*start && isspace(*start))\r
- start++;\r
- if (!*start)\r
- break;\r
- pos = strchr(start,' ');\r
- if (pos)\r
- *pos=0;\r
- m_unsetHeaders.push_back(start);\r
- start = pos ? pos+1 : NULL;\r
- }\r
- free(dup);\r
- m_unsetHeaders.push_back("Shib-Application-ID");\r
- }\r
- }\r
-\r
- const PropertySet* sessions = getPropertySet("Sessions");\r
-\r
- // Process handlers.\r
- Handler* handler=NULL;\r
- bool hardACS=false, hardSessionInit=false;\r
- const DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : NULL;\r
- while (child) {\r
- try {\r
- // A handler is based on the Binding property in conjunction with the element name.\r
- // If it's an ACS or SI, also handle index/id mappings and defaulting.\r
- if (XMLString::equals(child->getLocalName(),_AssertionConsumerService)) {\r
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
- if (!bindprop.get() || !*(bindprop.get())) {\r
- log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it...");\r
- child = XMLHelper::getNextSiblingElement(child);\r
- continue;\r
- }\r
- handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
- // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)\r
-#ifdef HAVE_GOOD_STL\r
- m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);\r
-#else\r
- m_acsBindingMap[handler->getString("Binding").second].push_back(handler);\r
-#endif\r
- m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;\r
- \r
- if (!hardACS) {\r
- pair<bool,bool> defprop=handler->getBool("isDefault");\r
- if (defprop.first) {\r
- if (defprop.second) {\r
- hardACS=true;\r
- m_acsDefault=handler;\r
- }\r
- }\r
- else if (!m_acsDefault)\r
- m_acsDefault=handler;\r
- }\r
- }\r
- else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- if (!type.get() || !*(type.get())) {\r
- log.warn("SessionInitiator element has no type attribute, skipping it...");\r
- child = XMLHelper::getNextSiblingElement(child);\r
- continue;\r
- }\r
- SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
- handler=sihandler;\r
- pair<bool,const char*> si_id=handler->getString("id");\r
- if (si_id.first && si_id.second)\r
- m_sessionInitMap[si_id.second]=sihandler;\r
- if (!hardSessionInit) {\r
- pair<bool,bool> defprop=handler->getBool("isDefault");\r
- if (defprop.first) {\r
- if (defprop.second) {\r
- hardSessionInit=true;\r
- m_sessionInitDefault=sihandler;\r
- }\r
- }\r
- else if (!m_sessionInitDefault)\r
- m_sessionInitDefault=sihandler;\r
- }\r
- }\r
- else if (XMLString::equals(child->getLocalName(),_SingleLogoutService)) {\r
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
- if (!bindprop.get() || !*(bindprop.get())) {\r
- log.warn("md:SingleLogoutService element has no Binding attribute, skipping it...");\r
- child = XMLHelper::getNextSiblingElement(child);\r
- continue;\r
- }\r
- handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
- }\r
- else if (XMLString::equals(child->getLocalName(),_ManageNameIDService)) {\r
- auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
- if (!bindprop.get() || !*(bindprop.get())) {\r
- log.warn("md:ManageNameIDService element has no Binding attribute, skipping it...");\r
- child = XMLHelper::getNextSiblingElement(child);\r
- continue;\r
- }\r
- handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
- }\r
- else {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- if (!type.get() || !*(type.get())) {\r
- log.warn("Handler element has no type attribute, skipping it...");\r
- child = XMLHelper::getNextSiblingElement(child);\r
- continue;\r
- }\r
- handler=conf.HandlerManager.newPlugin(type.get(),make_pair(child, getId()));\r
- }\r
-\r
- // Save off the objects after giving the property set to the handler for its use.\r
- m_handlers.push_back(handler);\r
-\r
- // Insert into location map.\r
- pair<bool,const char*> location=handler->getString("Location");\r
- if (location.first && *location.second == '/')\r
- m_handlerMap[location.second]=handler;\r
- else if (location.first)\r
- m_handlerMap[string("/") + location.second]=handler;\r
-\r
- }\r
- catch (exception& ex) {\r
- log.error("caught exception processing handler element: %s", ex.what());\r
- }\r
- \r
- child = XMLHelper::getNextSiblingElement(child);\r
- }\r
-\r
-#ifndef SHIBSP_LITE\r
- DOMNodeList* nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);\r
- for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++)\r
- if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())\r
- m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());\r
-\r
- // Always include our own entityID as an audience.\r
- m_audiences.push_back(getXMLString("entityID").second);\r
-\r
- if (conf.isEnabled(SPConfig::Metadata)) {\r
- child = XMLHelper::getFirstChildElement(e,_MetadataProvider);\r
- if (child) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- log.info("building MetadataProvider of type %s...",type.get());\r
- try {\r
- auto_ptr<MetadataProvider> mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child));\r
- mp->init();\r
- m_metadata = mp.release();\r
- }\r
- catch (exception& ex) {\r
- log.crit("error building/initializing MetadataProvider: %s", ex.what());\r
- }\r
- }\r
- }\r
-\r
- if (conf.isEnabled(SPConfig::Trust)) {\r
- child = XMLHelper::getFirstChildElement(e,_TrustEngine);\r
- if (child) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- log.info("building TrustEngine of type %s...",type.get());\r
- try {\r
- m_trust = xmlConf.TrustEngineManager.newPlugin(type.get(),child);\r
- }\r
- catch (exception& ex) {\r
- log.crit("error building TrustEngine: %s", ex.what());\r
- }\r
- }\r
- }\r
-\r
- if (conf.isEnabled(SPConfig::AttributeResolution)) {\r
- child = XMLHelper::getFirstChildElement(e,_AttributeExtractor);\r
- if (child) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- log.info("building AttributeExtractor of type %s...",type.get());\r
- try {\r
- m_attrExtractor = conf.AttributeExtractorManager.newPlugin(type.get(),child);\r
- }\r
- catch (exception& ex) {\r
- log.crit("error building AttributeExtractor: %s", ex.what());\r
- }\r
- }\r
-\r
- child = XMLHelper::getFirstChildElement(e,_AttributeFilter);\r
- if (child) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- log.info("building AttributeFilter of type %s...",type.get());\r
- try {\r
- m_attrFilter = conf.AttributeFilterManager.newPlugin(type.get(),child);\r
- }\r
- catch (exception& ex) {\r
- log.crit("error building AttributeFilter: %s", ex.what());\r
- }\r
- }\r
-\r
- child = XMLHelper::getFirstChildElement(e,_AttributeResolver);\r
- if (child) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- log.info("building AttributeResolver of type %s...",type.get());\r
- try {\r
- m_attrResolver = conf.AttributeResolverManager.newPlugin(type.get(),child);\r
- }\r
- catch (exception& ex) {\r
- log.crit("error building AttributeResolver: %s", ex.what());\r
- }\r
- }\r
-\r
- if (m_unsetHeaders.empty()) {\r
- if (m_attrExtractor) {\r
- Locker extlock(m_attrExtractor);\r
- m_attrExtractor->getAttributeIds(m_unsetHeaders);\r
- }\r
- if (m_attrResolver) {\r
- Locker reslock(m_attrResolver);\r
- m_attrResolver->getAttributeIds(m_unsetHeaders);\r
- }\r
- if (m_base && m_unsetHeaders.empty())\r
- m_unsetHeaders.insert(m_unsetHeaders.end(), m_base->m_unsetHeaders.begin(), m_base->m_unsetHeaders.end());\r
- else\r
- m_unsetHeaders.push_back("Shib-Application-ID");\r
- }\r
- }\r
-\r
- if (conf.isEnabled(SPConfig::Credentials)) {\r
- child = XMLHelper::getFirstChildElement(e,_CredentialResolver);\r
- if (child) {\r
- auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
- log.info("building CredentialResolver of type %s...",type.get());\r
- try {\r
- m_credResolver = xmlConf.CredentialResolverManager.newPlugin(type.get(),child);\r
- }\r
- catch (exception& ex) {\r
- log.crit("error building CredentialResolver: %s", ex.what());\r
- }\r
- }\r
- }\r
-\r
- // Finally, load relying parties.\r
- child = XMLHelper::getFirstChildElement(e,DefaultRelyingParty);\r
- if (child) {\r
- m_partyDefault=new DOMPropertySet();\r
- m_partyDefault->load(child,log,this);\r
- child = XMLHelper::getFirstChildElement(child,RelyingParty);\r
- while (child) {\r
- auto_ptr<DOMPropertySet> rp(new DOMPropertySet());\r
- rp->load(child,log,this);\r
- rp->setParent(m_partyDefault);\r
- m_partyMap[child->getAttributeNS(NULL,saml2::Attribute::NAME_ATTRIB_NAME)]=rp.release();\r
- child = XMLHelper::getNextSiblingElement(child,RelyingParty);\r
- }\r
- }\r
-#endif\r
-\r
- // In process only, we need a shared lock around accessing the header clearing list.\r
- if (!conf.isEnabled(SPConfig::OutOfProcess)) {\r
- m_unsetLock = RWLock::create();\r
- }\r
+ }
+
+ // Provides filter to exclude special config elements.
+ short acceptNode(const DOMNode* node) const;
+
+ private:
+ void cleanup();
+ const ServiceProvider* m_sp; // this is ok because its locking scope includes us
+ const XMLApplication* m_base;
+ string m_hash;
+#ifndef SHIBSP_LITE
+ MetadataProvider* m_metadata;
+ TrustEngine* m_trust;
+ AttributeExtractor* m_attrExtractor;
+ AttributeFilter* m_attrFilter;
+ AttributeResolver* m_attrResolver;
+ CredentialResolver* m_credResolver;
+ vector<const XMLCh*> m_audiences;
+
+ // RelyingParty properties
+ DOMPropertySet* m_partyDefault;
+#ifdef HAVE_GOOD_STL
+ map<xstring,PropertySet*> m_partyMap;
+#else
+ map<const XMLCh*,PropertySet*> m_partyMap;
+#endif
+#endif
+ set<string> m_remoteUsers;
+ mutable vector<string> m_unsetHeaders;
+ RWLock* m_unsetLock;
+
+ // manage handler objects
+ vector<Handler*> m_handlers;
+
+ // maps location (path info) to applicable handlers
+ map<string,const Handler*> m_handlerMap;
+
+ // maps unique indexes to consumer services
+ map<unsigned int,const Handler*> m_acsIndexMap;
+
+ // pointer to default consumer service
+ const Handler* m_acsDefault;
+
+ // maps binding strings to supporting consumer service(s)
+#ifdef HAVE_GOOD_STL
+ typedef map<xstring,vector<const Handler*> > ACSBindingMap;
+#else
+ typedef map<string,vector<const Handler*> > ACSBindingMap;
+#endif
+ ACSBindingMap m_acsBindingMap;
+
+ // pointer to default session initiator
+ const SessionInitiator* m_sessionInitDefault;
+
+ // maps unique ID strings to session initiators
+ map<string,const SessionInitiator*> m_sessionInitMap;
+
+ // pointer to default artifact resolution service
+ const Handler* m_artifactResolutionDefault;
+
+ pair<bool,int> getArtifactEndpointIndex() const {
+ if (m_artifactResolutionDefault) return m_artifactResolutionDefault->getInt("index");
+ return m_base ? m_base->getArtifactEndpointIndex() : make_pair(false,0);
+ }
+ };
+
+ // Top-level configuration implementation
+ class SHIBSP_DLLLOCAL XMLConfig;
+ class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter
+ {
+ public:
+ XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);
+ ~XMLConfigImpl();
+
+ RequestMapper* m_requestMapper;
+ map<string,Application*> m_appmap;
+#ifndef SHIBSP_LITE
+ map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
+#endif
+
+ // Provides filter to exclude special config elements.
+ short acceptNode(const DOMNode* node) const;
+
+ void setDocument(DOMDocument* doc) {
+ m_document = doc;
+ }
+
+ private:
+ void doExtensions(const DOMElement* e, const char* label, Category& log);
+
+ const XMLConfig* m_outer;
+ DOMDocument* m_document;
+ };
+
+ class SHIBSP_DLLLOCAL XMLConfig : public ServiceProvider, public ReloadableXMLFile, public Remoted
+ {
+ public:
+ XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),
+ m_impl(NULL), m_listener(NULL), m_sessionCache(NULL)
+#ifndef SHIBSP_LITE
+ , m_tranLog(NULL)
+#endif
+ {
+ }
+
+ void init() {
+ load();
+ }
+
+ ~XMLConfig() {
+ delete m_impl;
+ delete m_sessionCache;
+ delete m_listener;
+#ifndef SHIBSP_LITE
+ delete m_tranLog;
+ SAMLConfig::getConfig().setArtifactMap(NULL);
+ XMLToolingConfig::getConfig().setReplayCache(NULL);
+ for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());
+#endif
+ }
+
+ // PropertySet
+ void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}
+ pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);}
+ pair<bool,const char*> getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);}
+ pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);}
+ pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);}
+ pair<bool,int> getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);}
+ const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}
+ const DOMElement* getElement() const {return m_impl->getElement();}
+
+ // Remoted
+ void receive(DDF& in, ostream& out);
+
+ // ServiceProvider
+#ifndef SHIBSP_LITE
+ TransactionLog* getTransactionLog() const {
+ if (m_tranLog)
+ return m_tranLog;
+ throw ConfigurationException("No TransactionLog available.");
+ }
+
+ StorageService* getStorageService(const char* id) const {
+ if (id) {
+ map<string,StorageService*>::const_iterator i=m_storage.find(id);
+ if (i!=m_storage.end())
+ return i->second;
+ }
+ return NULL;
+ }
+#endif
+
+ ListenerService* getListenerService(bool required=true) const {
+ if (required && !m_listener)
+ throw ConfigurationException("No ListenerService available.");
+ return m_listener;
+ }
+
+ SessionCache* getSessionCache(bool required=true) const {
+ if (required && !m_sessionCache)
+ throw ConfigurationException("No SessionCache available.");
+ return m_sessionCache;
+ }
+
+ RequestMapper* getRequestMapper(bool required=true) const {
+ if (required && !m_impl->m_requestMapper)
+ throw ConfigurationException("No RequestMapper available.");
+ return m_impl->m_requestMapper;
+ }
+
+ const Application* getApplication(const char* applicationId) const {
+ map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);
+ return (i!=m_impl->m_appmap.end()) ? i->second : NULL;
+ }
+
+#ifndef SHIBSP_LITE
+ const PropertySet* getPolicySettings(const char* id) const {
+ map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
+ if (i!=m_impl->m_policyMap.end())
+ return i->second.first;
+ throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
+ }
+
+ const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {
+ map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
+ if (i!=m_impl->m_policyMap.end())
+ return i->second.second;
+ throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
+ }
+#endif
+
+ protected:
+ pair<bool,DOMElement*> load();
+
+ private:
+ friend class XMLConfigImpl;
+ XMLConfigImpl* m_impl;
+ mutable ListenerService* m_listener;
+ mutable SessionCache* m_sessionCache;
+#ifndef SHIBSP_LITE
+ mutable TransactionLog* m_tranLog;
+ mutable map<string,StorageService*> m_storage;
+#endif
+ };
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
+
+ static const XMLCh _Application[] = UNICODE_LITERAL_11(A,p,p,l,i,c,a,t,i,o,n);
+ static const XMLCh Applications[] = UNICODE_LITERAL_12(A,p,p,l,i,c,a,t,i,o,n,s);
+ static const XMLCh _ArtifactMap[] = UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);
+ static const XMLCh _AttributeExtractor[] = UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
+ static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
+ static const XMLCh _AttributeResolver[] = UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);
+ static const XMLCh _AssertionConsumerService[] = UNICODE_LITERAL_24(A,s,s,e,r,t,i,o,n,C,o,n,s,u,m,e,r,S,e,r,v,i,c,e);
+ static const XMLCh _ArtifactResolutionService[] =UNICODE_LITERAL_25(A,r,t,i,f,a,c,t,R,e,s,o,l,u,t,i,o,n,S,e,r,v,i,c,e);
+ static const XMLCh _Audience[] = UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);
+ static const XMLCh Binding[] = UNICODE_LITERAL_7(B,i,n,d,i,n,g);
+ static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
+ static const XMLCh DefaultRelyingParty[] = UNICODE_LITERAL_19(D,e,f,a,u,l,t,R,e,l,y,i,n,g,P,a,r,t,y);
+ static const XMLCh _Extensions[] = UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);
+ static const XMLCh fatal[] = UNICODE_LITERAL_5(f,a,t,a,l);
+ static const XMLCh _Handler[] = UNICODE_LITERAL_7(H,a,n,d,l,e,r);
+ static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
+ static const XMLCh Implementation[] = UNICODE_LITERAL_14(I,m,p,l,e,m,e,n,t,a,t,i,o,n);
+ static const XMLCh InProcess[] = UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s);
+ static const XMLCh Library[] = UNICODE_LITERAL_7(L,i,b,r,a,r,y);
+ static const XMLCh Listener[] = UNICODE_LITERAL_8(L,i,s,t,e,n,e,r);
+ static const XMLCh logger[] = UNICODE_LITERAL_6(l,o,g,g,e,r);
+ static const XMLCh _ManageNameIDService[] = UNICODE_LITERAL_19(M,a,n,a,g,e,N,a,m,e,I,D,S,e,r,v,i,c,e);
+ static const XMLCh MemoryListener[] = UNICODE_LITERAL_14(M,e,m,o,r,y,L,i,s,t,e,n,e,r);
+ static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);
+ static const XMLCh OutOfProcess[] = UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);
+ static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h);
+ static const XMLCh Policy[] = UNICODE_LITERAL_6(P,o,l,i,c,y);
+ static const XMLCh RelyingParty[] = UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);
+ static const XMLCh _ReplayCache[] = UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);
+ static const XMLCh _RequestMapper[] = UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);
+ static const XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e);
+ static const XMLCh SecurityPolicies[] = UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);
+ static const XMLCh _SessionCache[] = UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);
+ static const XMLCh _SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
+ static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);
+ static const XMLCh _StorageService[] = UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);
+ static const XMLCh TCPListener[] = UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);
+ static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
+ static const XMLCh UnixListener[] = UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);
+
+ class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter
+ {
+ public:
+ short acceptNode(const DOMNode* node) const {
+ if (XMLHelper::isNodeNamed(node,shibspconstants::SHIB2SPCONFIG_NS,Rule))
+ return FILTER_REJECT;
+ return FILTER_ACCEPT;
+ }
+ };
+};
+
+namespace shibsp {
+ ServiceProvider* XMLServiceProviderFactory(const DOMElement* const & e)
+ {
+ return new XMLConfig(e);
+ }
+};
+
+XMLApplication::XMLApplication(
+ const ServiceProvider* sp,
+ const DOMElement* e,
+ const XMLApplication* base
+ ) : m_sp(sp), m_base(base),
+#ifndef SHIBSP_LITE
+ m_metadata(NULL), m_trust(NULL),
+ m_attrExtractor(NULL), m_attrFilter(NULL), m_attrResolver(NULL),
+ m_credResolver(NULL), m_partyDefault(NULL),
+#endif
+ m_unsetLock(NULL), m_acsDefault(NULL), m_sessionInitDefault(NULL), m_artifactResolutionDefault(NULL)
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("XMLApplication");
+#endif
+ Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");
+
+ try {
+ // First load any property sets.
+ load(e,log,this);
+ if (base)
+ setParent(base);
+
+ SPConfig& conf=SPConfig::getConfig();
+#ifndef SHIBSP_LITE
+ SAMLConfig& samlConf=SAMLConfig::getConfig();
+#endif
+ XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
+
+ // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec.
+ static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ string tohash=getId();
+ tohash+=getString("entityID").second;
+ for (const char* ch = tohash.c_str(); *ch; ++ch) {
+ m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);
+ m_hash += (DIGITS[0x0F & *ch]);
+ }
+
+ // Load attribute ID lists for REMOTE_USER and header clearing.
+ if (conf.isEnabled(SPConfig::InProcess)) {
+ pair<bool,const char*> attributes = getString("REMOTE_USER");
+ if (attributes.first) {
+ char* dup = strdup(attributes.second);
+ char* pos;
+ char* start = dup;
+ while (start && *start) {
+ while (*start && isspace(*start))
+ start++;
+ if (!*start)
+ break;
+ pos = strchr(start,' ');
+ if (pos)
+ *pos=0;
+ m_remoteUsers.insert(start);
+ start = pos ? pos+1 : NULL;
+ }
+ free(dup);
+ }
+
+ attributes = getString("unsetHeaders");
+ if (attributes.first) {
+ char* dup = strdup(attributes.second);
+ char* pos;
+ char* start = dup;
+ while (start && *start) {
+ while (*start && isspace(*start))
+ start++;
+ if (!*start)
+ break;
+ pos = strchr(start,' ');
+ if (pos)
+ *pos=0;
+ m_unsetHeaders.push_back(start);
+ start = pos ? pos+1 : NULL;
+ }
+ free(dup);
+ m_unsetHeaders.push_back("Shib-Application-ID");
+ }
+ }
+
+ const PropertySet* sessions = getPropertySet("Sessions");
+
+ // Process handlers.
+ Handler* handler=NULL;
+ bool hardACS=false, hardSessionInit=false, hardArt=false;
+ const DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : NULL;
+ while (child) {
+ try {
+ // A handler is based on the Binding property in conjunction with the element name.
+ // If it's an ACS or SI, also handle index/id mappings and defaulting.
+ if (XMLString::equals(child->getLocalName(),_AssertionConsumerService)) {
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
+ if (!bindprop.get() || !*(bindprop.get())) {
+ log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it...");
+ child = XMLHelper::getNextSiblingElement(child);
+ continue;
+ }
+ handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
+ // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)
+#ifdef HAVE_GOOD_STL
+ m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
+#else
+ m_acsBindingMap[handler->getString("Binding").second].push_back(handler);
+#endif
+ m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;
+
+ if (!hardACS) {
+ pair<bool,bool> defprop=handler->getBool("isDefault");
+ if (defprop.first) {
+ if (defprop.second) {
+ hardACS=true;
+ m_acsDefault=handler;
+ }
+ }
+ else if (!m_acsDefault)
+ m_acsDefault=handler;
+ }
+ }
+ else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ if (!type.get() || !*(type.get())) {
+ log.warn("SessionInitiator element has no type attribute, skipping it...");
+ child = XMLHelper::getNextSiblingElement(child);
+ continue;
+ }
+ SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));
+ handler=sihandler;
+ pair<bool,const char*> si_id=handler->getString("id");
+ if (si_id.first && si_id.second)
+ m_sessionInitMap[si_id.second]=sihandler;
+ if (!hardSessionInit) {
+ pair<bool,bool> defprop=handler->getBool("isDefault");
+ if (defprop.first) {
+ if (defprop.second) {
+ hardSessionInit=true;
+ m_sessionInitDefault=sihandler;
+ }
+ }
+ else if (!m_sessionInitDefault)
+ m_sessionInitDefault=sihandler;
+ }
+ }
+ else if (XMLString::equals(child->getLocalName(),_ArtifactResolutionService)) {
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
+ if (!bindprop.get() || !*(bindprop.get())) {
+ log.warn("md:ArtifactResolutionService element has no Binding attribute, skipping it...");
+ child = XMLHelper::getNextSiblingElement(child);
+ continue;
+ }
+ handler=conf.ArtifactResolutionServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
+
+ if (!hardArt) {
+ pair<bool,bool> defprop=handler->getBool("isDefault");
+ if (defprop.first) {
+ if (defprop.second) {
+ hardArt=true;
+ m_artifactResolutionDefault=handler;
+ }
+ }
+ else if (!m_artifactResolutionDefault)
+ m_artifactResolutionDefault=handler;
+ }
+ }
+ else if (XMLString::equals(child->getLocalName(),_SingleLogoutService)) {
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
+ if (!bindprop.get() || !*(bindprop.get())) {
+ log.warn("md:SingleLogoutService element has no Binding attribute, skipping it...");
+ child = XMLHelper::getNextSiblingElement(child);
+ continue;
+ }
+ handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
+ }
+ else if (XMLString::equals(child->getLocalName(),_ManageNameIDService)) {
+ auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
+ if (!bindprop.get() || !*(bindprop.get())) {
+ log.warn("md:ManageNameIDService element has no Binding attribute, skipping it...");
+ child = XMLHelper::getNextSiblingElement(child);
+ continue;
+ }
+ handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
+ }
+ else {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ if (!type.get() || !*(type.get())) {
+ log.warn("Handler element has no type attribute, skipping it...");
+ child = XMLHelper::getNextSiblingElement(child);
+ continue;
+ }
+ handler=conf.HandlerManager.newPlugin(type.get(),make_pair(child, getId()));
+ }
+
+ m_handlers.push_back(handler);
+
+ // Insert into location map.
+ pair<bool,const char*> location=handler->getString("Location");
+ if (location.first && *location.second == '/')
+ m_handlerMap[location.second]=handler;
+ else if (location.first)
+ m_handlerMap[string("/") + location.second]=handler;
+
+ }
+ catch (exception& ex) {
+ log.error("caught exception processing handler element: %s", ex.what());
+ }
+
+ child = XMLHelper::getNextSiblingElement(child);
+ }
+
+#ifndef SHIBSP_LITE
+ DOMNodeList* nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);
+ for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++)
+ if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
+ m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
+
+ // Always include our own entityID as an audience.
+ m_audiences.push_back(getXMLString("entityID").second);
+
+ if (conf.isEnabled(SPConfig::Metadata)) {
+ child = XMLHelper::getFirstChildElement(e,_MetadataProvider);
+ if (child) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ log.info("building MetadataProvider of type %s...",type.get());
+ try {
+ auto_ptr<MetadataProvider> mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child));
+ mp->init();
+ m_metadata = mp.release();
+ }
+ catch (exception& ex) {
+ log.crit("error building/initializing MetadataProvider: %s", ex.what());
+ }
+ }
+ }
+
+ if (conf.isEnabled(SPConfig::Trust)) {
+ child = XMLHelper::getFirstChildElement(e,_TrustEngine);
+ if (child) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ log.info("building TrustEngine of type %s...",type.get());
+ try {
+ m_trust = xmlConf.TrustEngineManager.newPlugin(type.get(),child);
+ }
+ catch (exception& ex) {
+ log.crit("error building TrustEngine: %s", ex.what());
+ }
+ }
+ }
+
+ if (conf.isEnabled(SPConfig::AttributeResolution)) {
+ child = XMLHelper::getFirstChildElement(e,_AttributeExtractor);
+ if (child) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ log.info("building AttributeExtractor of type %s...",type.get());
+ try {
+ m_attrExtractor = conf.AttributeExtractorManager.newPlugin(type.get(),child);
+ }
+ catch (exception& ex) {
+ log.crit("error building AttributeExtractor: %s", ex.what());
+ }
+ }
+
+ child = XMLHelper::getFirstChildElement(e,_AttributeFilter);
+ if (child) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ log.info("building AttributeFilter of type %s...",type.get());
+ try {
+ m_attrFilter = conf.AttributeFilterManager.newPlugin(type.get(),child);
+ }
+ catch (exception& ex) {
+ log.crit("error building AttributeFilter: %s", ex.what());
+ }
+ }
+
+ child = XMLHelper::getFirstChildElement(e,_AttributeResolver);
+ if (child) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ log.info("building AttributeResolver of type %s...",type.get());
+ try {
+ m_attrResolver = conf.AttributeResolverManager.newPlugin(type.get(),child);
+ }
+ catch (exception& ex) {
+ log.crit("error building AttributeResolver: %s", ex.what());
+ }
+ }
+
+ if (m_unsetHeaders.empty()) {
+ if (m_attrExtractor) {
+ Locker extlock(m_attrExtractor);
+ m_attrExtractor->getAttributeIds(m_unsetHeaders);
+ }
+ if (m_attrResolver) {
+ Locker reslock(m_attrResolver);
+ m_attrResolver->getAttributeIds(m_unsetHeaders);
+ }
+ if (m_base && m_unsetHeaders.empty())
+ m_unsetHeaders.insert(m_unsetHeaders.end(), m_base->m_unsetHeaders.begin(), m_base->m_unsetHeaders.end());
+ else
+ m_unsetHeaders.push_back("Shib-Application-ID");
+ }
+ }
+
+ if (conf.isEnabled(SPConfig::Credentials)) {
+ child = XMLHelper::getFirstChildElement(e,_CredentialResolver);
+ if (child) {
+ auto_ptr_char type(child->getAttributeNS(NULL,_type));
+ log.info("building CredentialResolver of type %s...",type.get());
+ try {
+ m_credResolver = xmlConf.CredentialResolverManager.newPlugin(type.get(),child);
+ }
+ catch (exception& ex) {
+ log.crit("error building CredentialResolver: %s", ex.what());
+ }
+ }
+ }
+
+ // Finally, load relying parties.
+ child = XMLHelper::getFirstChildElement(e,DefaultRelyingParty);
+ if (child) {
+ m_partyDefault=new DOMPropertySet();
+ m_partyDefault->load(child,log,this);
+ child = XMLHelper::getFirstChildElement(child,RelyingParty);
+ while (child) {
+ auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
+ rp->load(child,log,this);
+ rp->setParent(m_partyDefault);
+ m_partyMap[child->getAttributeNS(NULL,saml2::Attribute::NAME_ATTRIB_NAME)]=rp.release();
+ child = XMLHelper::getNextSiblingElement(child,RelyingParty);
+ }
+ }
+#endif
+
+ // In process only, we need a shared lock around accessing the header clearing list.
+ if (!conf.isEnabled(SPConfig::OutOfProcess)) {
+ m_unsetLock = RWLock::create();
+ }