if (ini->get_tag(app, SHIBTARGET_TAG_AAP, true, &tag))
shibConf.aapFile=tag;
- if (! ini->get_tag (app, SHIBTARGET_TAG_SITES, true, &tag)) {
- log.fatal("No Sites File found in configuration");
- throw runtime_error ("No Sites File found in configuration");
- }
- shibConf.mapperFile=tag;
-
try {
if (!shibConf.init()) {
log.fatal ("Failed to initialize Shib library");
delete iter;
}
+ // Load the specified metadata.
+ bool anyAdded=false;
+ if (ini->get_tag(app, SHIBTARGET_TAG_METADATA, true, &tag) && ini->exists(tag))
+ {
+ ShibINI::Iterator* iter=ini->tag_iterator(tag);
+ for (const string* prov=iter->begin(); prov; prov=iter->next())
+ {
+ const string source=ini->get(tag,*prov);
+ log.info("registering metadata provider: type=%s, source=%s",prov->c_str(),source.c_str());
+ if (shibConf.addMapper(prov->c_str(),source.c_str()))
+ anyAdded=true;
+ }
+ delete iter;
+ }
+ if (!anyAdded)
+ {
+ log.fatal("No metadata providers successfully added");
+ throw runtime_error("No metadata providers successfully added");
+ }
+
// Register attributes based on built-in classes.
if (ini->exists("attributes")) {
log.info("registering attributes");
int RPCError::getCode() { return m_priv->status; }
-const char* RPCError::getOriginErrorURL()
+string RPCError::getOriginErrorURL()
{
- const char* res=NULL;
- static const char* msg="No URL Available";
+ string res="No URL Available";
if (!m_priv->origin.empty())
{
- OriginSiteMapper mapper;
- res=mapper.getErrorURL(m_priv->origin.c_str());
+ OriginSiteMapper mapper(m_priv->origin.c_str());
+ if (!mapper.fail())
+ {
+ const char* temp=mapper->getErrorURL(m_priv->origin.c_str());
+ if (temp)
+ res=temp;
+ }
}
- return res ? res : msg;
+ return res;
}
-const char* RPCError::getOriginContactName()
-{
- const char* res=NULL;
- static const char* msg="No Name Available";
+string RPCError::getOriginContactName()
+{
+ string res="No Name Available";
if (!m_priv->origin.empty())
{
- OriginSiteMapper mapper;
- Iterator<const IContactInfo*> i=mapper.getContacts(m_priv->origin.c_str());
+ OriginSiteMapper mapper(m_priv->origin.c_str());
+ Iterator<const IContactInfo*> i=
+ mapper.fail() ? Iterator<const IContactInfo*>() : mapper->getContacts(m_priv->origin.c_str());
while (i.hasNext())
{
const IContactInfo* c=i.next();
- if (c->getType()==IContactInfo::technical)
+ if (c->getType()==IContactInfo::technical && c->getName())
{
res=c->getName();
break;
}
}
}
- return res ? res : msg;
+ return res;
}
-const char* RPCError::getOriginContactEmail()
+string RPCError::getOriginContactEmail()
{
- const char* res=NULL;
- static const char* msg="No Email Available";
+ string res="No Email Available";
if (!m_priv->origin.empty())
{
- OriginSiteMapper mapper;
- Iterator<const IContactInfo*> i=mapper.getContacts(m_priv->origin.c_str());
+ OriginSiteMapper mapper(m_priv->origin.c_str());
+ Iterator<const IContactInfo*> i=
+ mapper.fail() ? Iterator<const IContactInfo*>() : mapper->getContacts(m_priv->origin.c_str());
while (i.hasNext())
{
const IContactInfo* c=i.next();
- if (c->getType()==IContactInfo::technical)
+ if (c->getType()==IContactInfo::technical && c->getEmail())
{
res=c->getEmail();
break;
}
}
}
- return res ? res : msg;
+ return res;
}
/* shib-target.cpp */
/* application names */
-#define SHIBTARGET_GENERAL "general"
-#define SHIBTARGET_SHAR "shar"
-#define SHIBTARGET_SHIRE "shire"
-#define SHIBTARGET_RM "rm"
+#define SHIBTARGET_GENERAL "general"
+#define SHIBTARGET_SHAR "shar"
+#define SHIBTARGET_SHIRE "shire"
+#define SHIBTARGET_RM "rm"
#define SHIBTARGET_POLICIES "policies"
/* configuration tags */
-#define SHIBTARGET_TAG_LOGGER "logger"
-#define SHIBTARGET_TAG_SCHEMAS "schemadir"
-#define SHIBTARGET_TAG_CERTFILE "certfile"
-#define SHIBTARGET_TAG_KEYFILE "keyfile"
-#define SHIBTARGET_TAG_KEYPASS "keypass"
-#define SHIBTARGET_TAG_CALIST "calist"
+#define SHIBTARGET_TAG_LOGGER "logger"
+#define SHIBTARGET_TAG_SCHEMAS "schemadir"
+#define SHIBTARGET_TAG_CERTFILE "certfile"
+#define SHIBTARGET_TAG_KEYFILE "keyfile"
+#define SHIBTARGET_TAG_KEYPASS "keypass"
+#define SHIBTARGET_TAG_CALIST "calist"
-#define SHIBTARGET_TAG_AATIMEOUT "AATimeout"
-#define SHIBTARGET_TAG_AACONNECTTO "AAConnectTimeout"
-#define SHIBTARGET_TAG_SAMLCOMPAT "SAMLCompat"
+#define SHIBTARGET_TAG_AATIMEOUT "AATimeout"
+#define SHIBTARGET_TAG_AACONNECTTO "AAConnectTimeout"
+#define SHIBTARGET_TAG_SAMLCOMPAT "SAMLCompat"
#define SHIBTARGET_TAG_AAP "aap-uri"
-#define SHIBTARGET_TAG_SITES "sitesFile"
+#define SHIBTARGET_TAG_METADATA "metadata"
-#define SHIBTARGET_TAG_DEFAULTLIFE "defaultLife"
+#define SHIBTARGET_TAG_DEFAULTLIFE "defaultLife"
-#define SHIBTARGET_TAG_CACHETYPE "cacheType"
-#define SHIBTARGET_TAG_CACHECLEAN "cacheClean"
-#define SHIBTARGET_TAG_CACHETIMEOUT "cacheTimeout"
+#define SHIBTARGET_TAG_CACHETYPE "cacheType"
+#define SHIBTARGET_TAG_CACHECLEAN "cacheClean"
+#define SHIBTARGET_TAG_CACHETIMEOUT "cacheTimeout"
-#define SHIBTARGET_TAG_REQATTRS "requestAttributes"
+#define SHIBTARGET_TAG_REQATTRS "requestAttributes"
/* initialize and finalize the target library (return 0 on success, 1 on failure) */
int shib_target_initialize (const char* application, const char* ini_file);
const char* getType();
const char* getText();
const char* getDesc();
- const char* getOriginErrorURL();
- const char* getOriginContactName();
- const char* getOriginContactEmail();
+ std::string getOriginErrorURL();
+ std::string getOriginContactName();
+ std::string getOriginContactEmail();
int getCode();
private:
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* OriginSiteMapper.h - a mapper implementation that uses an XML-based registry
+/* OriginSiteMapper.h - a wrapper class that insures proper release of mappers
Scott Cantor
9/27/02
using namespace saml;
using namespace std;
-OriginSiteMapper::OriginSiteMapper() : m_mapper(ShibConfig::getConfig().getMapper()) {}
-
-OriginSiteMapper::~OriginSiteMapper()
-{
- ShibConfig::getConfig().releaseMapper(m_mapper);
-}
-
-Iterator<const IContactInfo*> OriginSiteMapper::getContacts(const XMLCh* originSite) const
+OriginSiteMapper::OriginSiteMapper(const XMLCh* originSite) : m_mapper(NULL)
{
- return m_mapper->getContacts(originSite);
+ ShibInternalConfig& config=dynamic_cast<ShibInternalConfig&>(ShibConfig::getConfig());
+ config.m_lock->lock();
+ for (ShibInternalConfig::OriginMapperMap::iterator i=config.m_originMap.begin(); i!=config.m_originMap.end(); i++)
+ {
+ i->second->lock();
+ if (i->second->has(originSite))
+ {
+ m_mapper=i->second;
+ break;
+ }
+ i->second->unlock();
+ }
+ config.m_lock->unlock();
}
-const char* OriginSiteMapper::getErrorURL(const XMLCh* originSite) const
-{
- return m_mapper->getErrorURL(originSite);
-}
-
-Iterator<xstring> OriginSiteMapper::getHandleServiceNames(const XMLCh* originSite) const
-{
- return m_mapper->getHandleServiceNames(originSite);
-}
-
-XSECCryptoX509* OriginSiteMapper::getHandleServiceCert(const XMLCh* handleService) const
-{
- return m_mapper->getHandleServiceCert(handleService);
-}
-
-Iterator<pair<xstring,bool> > OriginSiteMapper::getSecurityDomains(const XMLCh* originSite) const
-{
- return m_mapper->getSecurityDomains(originSite);
-}
-
-time_t OriginSiteMapper::getTimestamp() const
+OriginSiteMapper::~OriginSiteMapper()
{
- return m_mapper->getTimestamp();
+ if (m_mapper)
+ m_mapper->unlock();
}
-
if (!SimpleAttribute::accept(e))
return false;
- OriginSiteMapper mapper;
- Iterator<pair<xstring,bool> > domains=mapper.getSecurityDomains(m_originSite.c_str());
+ OriginSiteMapper mapper(m_originSite.c_str());
+ Iterator<pair<xstring,bool> > domains=
+ (mapper.fail()) ? Iterator<pair<xstring,bool> >() : mapper->getSecurityDomains(m_originSite.c_str());
const XMLCh* this_scope=NULL;
DOMAttr* scope=e->getAttributeNodeNS(NULL,Scope);
if (scope)
using namespace saml;
using namespace shibboleth;
using namespace log4cpp;
+using namespace std;
SAML_EXCEPTION_FACTORY(UnsupportedProtocolException);
SAML_EXCEPTION_FACTORY(OriginSiteMapperException);
ShibConfig::~ShibConfig() {}
+extern "C" IOriginSiteMapper* XMLMapperFactory(const char* source)
+{
+ return new XMLOriginSiteMapper(source,false);
+}
+
+extern "C" IOriginSiteMapper* XMLTrustMapperFactory(const char* source)
+{
+ return new XMLOriginSiteMapper(source,true);
+}
+
bool ShibInternalConfig::init()
{
saml::NDC ndc("init");
}
}
- m_lock=RWLock::create();
+ m_lock=Mutex::create();
if (!m_lock)
{
- Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to create mapper locks");
- delete m_lock;
- delete m_AAP;
- return false;
- }
-
- try
- {
- m_mapper=new XMLOriginSiteMapper(mapperFile.c_str());
- }
- catch(SAMLException& e)
- {
- Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to initialize origin site mapper: %s", e.what());
- delete m_lock;
+ Category::getInstance(SHIB_LOGCAT".ShibConfig").fatal("init: failed to create mapper lock");
delete m_AAP;
return false;
}
+
+ regFactory("edu.internet2.middleware.shibboleth.metadata.origin.XML",&XMLMapperFactory);
+ regFactory("edu.internet2.middleware.shibboleth.metadata.origin.XMLTrust",&XMLTrustMapperFactory);
return true;
}
void ShibInternalConfig::term()
{
- delete m_mapper;
+ for (OriginMapperMap::iterator i=m_originMap.begin(); i!=m_originMap.end(); i++)
+ delete i->second;
delete m_lock;
delete m_AAP;
}
-IOriginSiteMapper* ShibInternalConfig::getMapper()
+void ShibInternalConfig::regFactory(const char* type, OriginSiteMapperFactory* factory)
{
- m_lock->rdlock();
-
- // Check if we need to refresh.
-#ifdef WIN32
- struct _stat stat_buf;
- if (_stat(mapperFile.c_str(), &stat_buf) == 0)
-#else
- struct stat stat_buf;
- if (stat(mapperFile.c_str(), &stat_buf) == 0)
-#endif
+ if (type && factory)
+ m_originFactoryMap[type]=factory;
+}
+
+void ShibInternalConfig::unregFactory(const char* type)
+{
+ if (type)
+ m_originFactoryMap.erase(type);
+}
+
+bool ShibInternalConfig::addMapper(const char* type, const char* source)
+{
+ saml::NDC ndc("addMapper");
+
+ bool ret=false;
+ m_lock->lock();
+ try
{
- if (m_mapper->getTimestamp()>0 && m_mapper->getTimestamp()<stat_buf.st_mtime)
+ OriginMapperFactoryMap::const_iterator i=m_originFactoryMap.find(type);
+ if (i!=m_originFactoryMap.end())
{
- // Elevate lock and recheck.
- m_lock->unlock();
- m_lock->wrlock();
- if (m_mapper->getTimestamp()>0 && m_mapper->getTimestamp()<stat_buf.st_mtime)
+ if (m_originMap.find(pair<string,string>(type,source))==m_originMap.end())
{
- try
- {
- IOriginSiteMapper* new_mapper=new XMLOriginSiteMapper(mapperFile.c_str());
- delete m_mapper;
- m_mapper=new_mapper;
- m_lock->unlock();
- }
- catch(SAMLException& e)
- {
- m_lock->unlock();
- saml::NDC ndc("getMapper");
- Category::getInstance(SHIB_LOGCAT".ShibConfig").error("failed to reload origin site mapper, sticking with what we have: %s", e.what());
- }
- catch(...)
- {
- m_lock->unlock();
- saml::NDC ndc("getMapper");
- Category::getInstance(SHIB_LOGCAT".ShibConfig").error("caught an unknown exception, sticking with what we have");
- }
+ m_originMap[pair<string,string>(type,source)]=(i->second)(source);
+ ret=true;
}
else
- {
- m_lock->unlock();
- }
- m_lock->rdlock();
+ throw OriginSiteMapperException("ShibConfig::addMapper() cannot add a duplicate mapper");
}
+ else
+ throw OriginSiteMapperException("ShibConfig::addMapper() unable to locate a mapper factory of the requested type");
+
+ }
+ catch (SAMLException& e)
+ {
+ Category::getInstance(SHIB_LOGCAT".ShibConfig").error(
+ "failed to add %s mapper to system using source '%s': %s", type, source, e.what()
+ );
+ }
+ catch (...)
+ {
+ Category::getInstance(SHIB_LOGCAT".ShibConfig").error(
+ "failed to add %s mapper to system using source '%s': unknown exception", type, source
+ );
}
-
- return m_mapper;
-}
-
-void ShibInternalConfig::releaseMapper(IOriginSiteMapper* mapper)
-{
m_lock->unlock();
+ return ret;
}
ShibConfig& ShibConfig::getConfig()
const XMLCh* handleService = assertion->getIssuer();
// Is this a trusted HS?
- OriginSiteMapper mapper;
- Iterator<xstring> hsNames=mapper.getHandleServiceNames(originSite);
+ OriginSiteMapper mapper(originSite);
+ Iterator<xstring> hsNames=mapper.fail() ? Iterator<xstring>() : mapper->getHandleServiceNames(originSite);
bool bFound = false;
while (!bFound && hsNames.hasNext())
if (!XMLString::compareString(hsNames.next().c_str(),handleService))
if (!bFound)
throw TrustException(SAMLException::RESPONDER, "ShibPOSTProfile::accept() detected an untrusted HS for the origin site");
- XSECCryptoX509* hsCert=mapper.getHandleServiceCert(handleService);
+ XSECCryptoX509* hsCert=mapper->getHandleServiceCert(handleService);
// Signature verification now takes place. We check the assertion and the response.
// Assertion signing is optional, response signing is mandatory.
#include <sys/stat.h>
#include <log4cpp/Category.hh>
+#include <xercesc/framework/URLInputSource.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
using namespace shibboleth;
using namespace log4cpp;
using namespace std;
-#include <xercesc/framework/URLInputSource.hpp>
+class shibboleth::XMLOriginSiteMapperImpl
+{
+public:
+ XMLOriginSiteMapperImpl(const char* pathname, bool loadTrust);
+ ~XMLOriginSiteMapperImpl();
+
+ struct OriginSite
+ {
+ OriginSite(const XMLCh* errorURL) : m_errorURL(XMLString::transcode(errorURL)) {}
+ ~OriginSite();
+ class ContactInfo : public IContactInfo
+ {
+ public:
+ ContactInfo(ContactType type, const XMLCh* name, const XMLCh* email);
+
+ ContactType getType() const { return m_type; }
+ const char* getName() const { return m_name.get(); }
+ const char* getEmail() const { return m_email.get(); }
+
+ private:
+ ContactType m_type;
+ std::auto_ptr<char> m_name, m_email;
+ };
+
+ std::vector<const IContactInfo*> m_contacts;
+ std::auto_ptr<char> m_errorURL;
+ std::vector<saml::xstring> m_handleServices;
+ std::vector<std::pair<saml::xstring,bool> > m_domains;
+ };
-XMLOriginSiteMapper::XMLOriginSiteMapper(const char* pathname) : m_filestamp(0)
-{
- NDC ndc("XMLOriginSiteMapper");
- Category& log=Category::getInstance(SHIB_LOGCAT".XMLOriginSiteMapper");
+ std::map<saml::xstring,OriginSite*> m_sites;
+ std::map<saml::xstring,XSECCryptoX509*> m_hsCerts;
+};
-#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;
+XMLOriginSiteMapperImpl::XMLOriginSiteMapperImpl(const char* pathname, bool loadTrust)
+{
+ NDC ndc("XMLOriginSiteMapperImpl");
+ Category& log=Category::getInstance(SHIB_LOGCAT".XMLOriginSiteMapperImpl");
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,pathname);
Wrapper4InputSource dsrc(&src,false);
- doc=p.parse(dsrc);
+ doc=p.parse(dsrc);
log.infoStream() << "Loaded and parsed site file (" << pathname << ")" << CategoryStream::ENDLINE;
- DOMElement* e = doc->getDocumentElement();
+ DOMElement* e = doc->getDocumentElement();
if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
XMLString::compareString(XML::Literals::Sites,e->getLocalName()))
{
- log.error("Construction requires a valid site file: (shib:Sites as root element)");
- throw OriginSiteMapperException("Construction requires a valid site file: (shib:Sites as root element)");
- }
+ log.error("Construction requires a valid site file: (shib:Sites as root element)");
+ throw OriginSiteMapperException("Construction requires a valid site file: (shib:Sites as root element)");
+ }
- // Loop over the OriginSite elements.
+ // Loop over the OriginSite elements.
DOMNodeList* nlist = e->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::OriginSite);
- for (int i=0; nlist && i<nlist->getLength(); i++)
+ for (int i=0; nlist && i<nlist->getLength(); i++)
{
DOMElement* os_e=static_cast<DOMElement*>(nlist->item(i));
auto_ptr<XMLCh> os_name(XMLString::replicate(os_e->getAttributeNS(NULL,XML::Literals::Name)));
XMLString::trim(os_name.get());
- if (!os_name.get() || !*os_name)
- continue;
+ if (!os_name.get() || !*os_name)
+ continue;
- OriginSite* os_obj = new OriginSite(os_e->getAttributeNS(NULL,XML::Literals::ErrorURL));
- m_sites[os_name.get()]=os_obj;
+ OriginSite* os_obj = new OriginSite(os_e->getAttributeNS(NULL,XML::Literals::ErrorURL));
+ m_sites[os_name.get()]=os_obj;
- DOMNode* os_child = nlist->item(i)->getFirstChild();
- while (os_child)
+ DOMNode* os_child = nlist->item(i)->getFirstChild();
+ while (os_child)
{
if (os_child->getNodeType()!=DOMNode::ELEMENT_NODE)
{
- os_child = os_child->getNextSibling();
- continue;
- }
+ os_child = os_child->getNextSibling();
+ continue;
+ }
- // Process the various kinds of OriginSite children that we care about...
+ // Process the various kinds of OriginSite children that we care about...
if (!XMLString::compareString(XML::SHIB_NS,os_child->getNamespaceURI()) &&
!XMLString::compareString(XML::Literals::Contact,os_child->getLocalName()))
{
os_obj->m_contacts.push_back(cinfo);
}
else if (!XMLString::compareString(XML::SHIB_NS,os_child->getNamespaceURI()) &&
- !XMLString::compareString(XML::Literals::HandleService,os_child->getLocalName()))
+ !XMLString::compareString(XML::Literals::HandleService,os_child->getLocalName()))
{
auto_ptr<XMLCh> hs_name(XMLString::replicate(static_cast<DOMElement*>(os_child)->getAttributeNS(NULL,XML::Literals::Name)));
XMLString::trim(hs_name.get());
- if (hs_name.get() && *hs_name)
+ if (hs_name.get() && *hs_name)
{
- os_obj->m_handleServices.push_back(hs_name.get());
+ os_obj->m_handleServices.push_back(hs_name.get());
// Look for ds:KeyInfo.
- DOMNode* ki=os_child->getFirstChild();
+ DOMNode* ki=os_child->getFirstChild();
while (ki && ki->getNodeType()!=DOMNode::ELEMENT_NODE)
- ki=ki->getNextSibling();
+ 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();
+ 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();
+ x509=x509->getNextSibling();
if (x509 && !XMLString::compareString(saml::XML::XMLSIG_NS,x509->getNamespaceURI()) &&
!XMLString::compareString(saml::XML::Literals::X509Certificate,x509->getNamespaceURI()))
{
m_hsCerts[hs_name.get()]=cert;
}
}
- }
- }
- }
+ }
+ }
+ }
else if (!XMLString::compareString(XML::SHIB_NS,os_child->getNamespaceURI()) &&
- !XMLString::compareString(XML::Literals::Domain,os_child->getLocalName()))
+ !XMLString::compareString(XML::Literals::Domain,os_child->getLocalName()))
{
auto_ptr<XMLCh> dom(XMLString::replicate(os_child->getFirstChild()->getNodeValue()));
XMLString::trim(dom.get());
- if (dom.get() && *dom)
+ if (dom.get() && *dom)
{
static const XMLCh one[]={ chDigit_1, chNull };
static const XMLCh tru[]={ chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull };
const XMLCh* regexp=static_cast<DOMElement*>(os_child)->getAttributeNS(NULL,XML::Literals::regexp);
bool flag=(!XMLString::compareString(regexp,one) || !XMLString::compareString(regexp,tru));
- os_obj->m_domains.push_back(pair<xstring,bool>(dom.get(),flag));
+ os_obj->m_domains.push_back(pair<xstring,bool>(dom.get(),flag));
}
- }
- os_child = os_child->getNextSibling();
- }
- }
+ }
+ os_child = os_child->getNextSibling();
+ }
+ }
}
catch (SAMLException& e)
{
- log.errorStream() << "XML error while parsing site configuration: " << e.what() << CategoryStream::ENDLINE;
+ log.errorStream() << "XML error while parsing site configuration: " << e.what() << CategoryStream::ENDLINE;
if (doc)
doc->release();
- throw;
- }
+ throw;
+ }
catch (...)
{
- log.error("Unexpected error while parsing site configuration");
+ log.error("Unexpected error while parsing site configuration");
if (doc)
doc->release();
- throw;
+ throw;
}
+ if (doc)
+ doc->release();
}
-XMLOriginSiteMapper::~XMLOriginSiteMapper()
+XMLOriginSiteMapperImpl::~XMLOriginSiteMapperImpl()
{
for (map<xstring,OriginSite*>::iterator i=m_sites.begin(); i!=m_sites.end(); i++)
delete i->second;
delete j->second;
}
-XMLOriginSiteMapper::OriginSite::ContactInfo::ContactInfo(ContactType type, const XMLCh* name, const XMLCh* email)
+XMLOriginSiteMapper::XMLOriginSiteMapper(const char* pathname, bool loadTrust)
+ : m_filestamp(0), m_source(pathname), m_trust(loadTrust), 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 XMLOriginSiteMapperImpl(pathname,loadTrust);
+ m_lock=RWLock::create();
+}
+
+XMLOriginSiteMapperImpl::OriginSite::ContactInfo::ContactInfo(ContactType type, const XMLCh* name, const XMLCh* email)
: m_type(type), m_name(XMLString::transcode(name)), m_email(XMLString::transcode(email)) {}
-XMLOriginSiteMapper::OriginSite::~OriginSite()
+XMLOriginSiteMapperImpl::OriginSite::~OriginSite()
{
for (vector<const IContactInfo*>::iterator i=m_contacts.begin(); i!=m_contacts.end(); i++)
delete const_cast<IContactInfo*>(*i);
}
+XMLOriginSiteMapper::~XMLOriginSiteMapper()
+{
+ delete m_lock;
+ delete m_impl;
+}
+
+void XMLOriginSiteMapper::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
+ {
+ XMLOriginSiteMapperImpl* new_mapper=new XMLOriginSiteMapperImpl(m_source.c_str(),m_trust);
+ delete m_impl;
+ m_impl=new_mapper;
+ m_lock->unlock();
+ }
+ catch(SAMLException& e)
+ {
+ m_lock->unlock();
+ saml::NDC ndc("lock");
+ Category::getInstance(SHIB_LOGCAT".XMLOriginSiteMapper").error("failed to reload metadata, sticking with what we have: %s", e.what());
+ }
+ catch(...)
+ {
+ m_lock->unlock();
+ saml::NDC ndc("lock");
+ Category::getInstance(SHIB_LOGCAT".XMLOriginSiteMapper").error("caught an unknown exception, sticking with what we have");
+ }
+ }
+ else
+ {
+ m_lock->unlock();
+ }
+ m_lock->rdlock();
+ }
+ }
+}
+
+void XMLOriginSiteMapper::unlock()
+{
+ m_lock->unlock();
+}
+
+bool XMLOriginSiteMapper::has(const XMLCh* originSite) const
+{
+ return m_impl->m_sites.find(originSite)!=m_impl->m_sites.end();
+}
+
Iterator<const IContactInfo*> XMLOriginSiteMapper::getContacts(const XMLCh* originSite) const
{
- map<xstring,OriginSite*>::const_iterator i=m_sites.find(originSite);
- if (i==m_sites.end())
+ map<xstring,XMLOriginSiteMapperImpl::OriginSite*>::const_iterator i=m_impl->m_sites.find(originSite);
+ if (i==m_impl->m_sites.end())
return Iterator<const IContactInfo*>();
return Iterator<const IContactInfo*>(i->second->m_contacts);
}
const char* XMLOriginSiteMapper::getErrorURL(const XMLCh* originSite) const
{
- map<xstring,OriginSite*>::const_iterator i=m_sites.find(originSite);
- if (i==m_sites.end())
+ map<xstring,XMLOriginSiteMapperImpl::OriginSite*>::const_iterator i=m_impl->m_sites.find(originSite);
+ if (i==m_impl->m_sites.end())
return NULL;
return i->second->m_errorURL.get();
}
Iterator<xstring> XMLOriginSiteMapper::getHandleServiceNames(const XMLCh* originSite) const
{
- map<xstring,OriginSite*>::const_iterator i=m_sites.find(originSite);
- if (i==m_sites.end())
+ map<xstring,XMLOriginSiteMapperImpl::OriginSite*>::const_iterator i=m_impl->m_sites.find(originSite);
+ if (i==m_impl->m_sites.end())
return Iterator<xstring>();
return Iterator<xstring>(i->second->m_handleServices);
}
XSECCryptoX509* XMLOriginSiteMapper::getHandleServiceCert(const XMLCh* handleService) const
{
- map<xstring,XSECCryptoX509*>::const_iterator i=m_hsCerts.find(handleService);
- return (i!=m_hsCerts.end()) ? i->second : NULL;
+ map<xstring,XSECCryptoX509*>::const_iterator i=m_impl->m_hsCerts.find(handleService);
+ return (i!=m_impl->m_hsCerts.end()) ? i->second : NULL;
}
Iterator<pair<xstring,bool> > XMLOriginSiteMapper::getSecurityDomains(const XMLCh* originSite) const
{
- map<xstring,OriginSite*>::const_iterator i=m_sites.find(originSite);
- if (i==m_sites.end())
+ map<xstring,XMLOriginSiteMapperImpl::OriginSite*>::const_iterator i=m_impl->m_sites.find(originSite);
+ if (i==m_impl->m_sites.end())
return Iterator<pair<xstring,bool> >();
return Iterator<pair<xstring,bool> >(i->second->m_domains);
}
namespace shibboleth
{
+ class XMLOriginSiteMapperImpl;
class SHIB_EXPORTS XMLOriginSiteMapper : public IOriginSiteMapper
{
public:
- XMLOriginSiteMapper(const char* pathname);
+ XMLOriginSiteMapper(const char* pathname, bool loadTrust);
~XMLOriginSiteMapper();
- virtual saml::Iterator<const IContactInfo*> getContacts(const XMLCh* originSite) const;
- virtual const char* getErrorURL(const XMLCh* originSite) const;
- virtual saml::Iterator<saml::xstring> getHandleServiceNames(const XMLCh* originSite) const;
- virtual XSECCryptoX509* getHandleServiceCert(const XMLCh* handleService) const;
- virtual saml::Iterator<std::pair<saml::xstring,bool> > getSecurityDomains(const XMLCh* originSite) const;
- virtual time_t getTimestamp() const { return m_filestamp; }
+ void lock();
+ void unlock();
- private:
- struct OriginSite
- {
- OriginSite(const XMLCh* errorURL) : m_errorURL(XMLString::transcode(errorURL)) {}
- ~OriginSite();
+ bool has(const XMLCh* originSite) const;
+ saml::Iterator<const IContactInfo*> getContacts(const XMLCh* originSite) const;
+ const char* getErrorURL(const XMLCh* originSite) const;
+ saml::Iterator<saml::xstring> getHandleServiceNames(const XMLCh* originSite) const;
+ XSECCryptoX509* getHandleServiceCert(const XMLCh* handleService) const;
+ saml::Iterator<std::pair<saml::xstring,bool> > getSecurityDomains(const XMLCh* originSite) const;
+ time_t getTimestamp() const { return m_filestamp; }
- class ContactInfo : public IContactInfo
- {
- public:
- ContactInfo(ContactType type, const XMLCh* name, const XMLCh* email);
-
- ContactType getType() const { return m_type; }
- const char* getName() const { return m_name.get(); }
- const char* getEmail() const { return m_email.get(); }
-
- private:
- ContactType m_type;
- std::auto_ptr<char> m_name, m_email;
- };
-
- std::vector<const IContactInfo*> m_contacts;
- std::auto_ptr<char> m_errorURL;
- std::vector<saml::xstring> m_handleServices;
- std::vector<std::pair<saml::xstring,bool> > m_domains;
- };
-
- std::map<saml::xstring,OriginSite*> m_sites;
- std::map<saml::xstring,XSECCryptoX509*> m_hsCerts;
+ private:
+ std::string m_source;
+ bool m_trust;
time_t m_filestamp;
+ RWLock* m_lock;
+ XMLOriginSiteMapperImpl* m_impl;
};
class AAP
class ShibInternalConfig : public ShibConfig
{
public:
- ShibInternalConfig() : m_AAP(NULL), m_mapper(NULL), m_lock(NULL) {}
+ ShibInternalConfig() : m_AAP(NULL), m_lock(NULL) {}
- // global per-process setup and shutdown of runtime
bool init();
void term();
- IOriginSiteMapper* getMapper();
- void releaseMapper(IOriginSiteMapper* mapper);
+ void regFactory(const char* type, OriginSiteMapperFactory* factory);
+ void unregFactory(const char* type);
+
+ bool addMapper(const char* type, const char* source);
AAP* m_AAP;
+
private:
- IOriginSiteMapper* m_mapper;
- RWLock* m_lock;
+ friend class OriginSiteMapper;
+
+ typedef std::map<std::string, OriginSiteMapperFactory*> OriginMapperFactoryMap;
+ OriginMapperFactoryMap m_originFactoryMap;
+
+ typedef std::map<std::pair<std::string, std::string>, IOriginSiteMapper*> OriginMapperMap;
+ OriginMapperMap m_originMap;
+ Mutex* m_lock;
};
}
template class SHIB_EXPORTS saml::ArrayIterator<const IContactInfo*>;
#endif
- struct SHIB_EXPORTS IOriginSiteMapper
- {
- virtual saml::Iterator<const IContactInfo*> getContacts(const XMLCh* originSite) const=0;
- virtual const char* getErrorURL(const XMLCh* originSite) const=0;
- virtual saml::Iterator<saml::xstring> getHandleServiceNames(const XMLCh* originSite) const=0;
- virtual XSECCryptoX509* getHandleServiceCert(const XMLCh* handleService) const=0;
- virtual saml::Iterator<std::pair<saml::xstring,bool> > getSecurityDomains(const XMLCh* originSite) const=0;
- virtual time_t getTimestamp() const=0;
- virtual ~IOriginSiteMapper() {};
- };
-
- class SHIB_EXPORTS OriginSiteMapper : public IOriginSiteMapper
- {
- public:
- OriginSiteMapper();
- ~OriginSiteMapper();
- virtual saml::Iterator<const IContactInfo*> getContacts(const XMLCh* originSite) const;
- virtual const char* getErrorURL(const XMLCh* originSite) const;
- virtual saml::Iterator<saml::xstring> getHandleServiceNames(const XMLCh* originSite) const;
- virtual XSECCryptoX509* getHandleServiceCert(const XMLCh* handleService) const;
- virtual saml::Iterator<std::pair<saml::xstring,bool> > getSecurityDomains(const XMLCh* originSite) const;
- virtual time_t getTimestamp() const;
-
- private:
- OriginSiteMapper(const OriginSiteMapper&);
- void operator=(const OriginSiteMapper&);
- IOriginSiteMapper* m_mapper;
- };
-
class SHIB_EXPORTS SimpleAttribute : public saml::SAMLAttribute
{
public:
static ShibPOSTProfile* getInstance(const saml::Iterator<const XMLCh*>& policies, const XMLCh* issuer);
};
+ // Metadata abstract interface
+ struct SHIB_EXPORTS IOriginSiteMapper
+ {
+ virtual void lock()=0;
+ virtual void unlock()=0;
+
+ virtual bool has(const XMLCh* originSite) const=0;
+ virtual saml::Iterator<const IContactInfo*> getContacts(const XMLCh* originSite) const=0;
+ virtual const char* getErrorURL(const XMLCh* originSite) const=0;
+ virtual saml::Iterator<saml::xstring> getHandleServiceNames(const XMLCh* originSite) const=0;
+ virtual XSECCryptoX509* getHandleServiceCert(const XMLCh* handleService) const=0;
+ virtual saml::Iterator<std::pair<saml::xstring,bool> > getSecurityDomains(const XMLCh* originSite) const=0;
+ virtual time_t getTimestamp() const=0;
+ virtual ~IOriginSiteMapper() {};
+ };
+
+ // Helper class to hide synchronization details
+ class SHIB_EXPORTS OriginSiteMapper
+ {
+ public:
+ OriginSiteMapper(const XMLCh* originSite);
+ ~OriginSiteMapper();
+ bool fail() const {return m_mapper==NULL;}
+ const IOriginSiteMapper* operator->() const {return m_mapper;}
+
+ private:
+ OriginSiteMapper(const OriginSiteMapper&);
+ void operator=(const OriginSiteMapper&);
+ IOriginSiteMapper* m_mapper;
+ };
+
+ extern "C" { typedef IOriginSiteMapper* OriginSiteMapperFactory(const char* source); }
+
class SHIB_EXPORTS ShibConfig
{
public:
// enables runtime and clients to access configuration
static ShibConfig& getConfig();
- virtual IOriginSiteMapper* getMapper()=0;
- virtual void releaseMapper(IOriginSiteMapper* mapper)=0;
-
+ // allows pluggable implementations of metadata mappers
+ virtual void regFactory(const char* type, OriginSiteMapperFactory* factory)=0;
+ virtual void unregFactory(const char* type)=0;
+
+ // builds a specific metadata lookup object
+ virtual bool addMapper(const char* type, const char* source)=0;
+
/* start of external configuration */
std::string aapFile;
- std::string mapperFile;
/* end of external configuration */
};