BOOST_BIND
BOOST_LAMBDA
BOOST_PTR_CONTAINER
+BOOST_SMART_PTR
BOOST_STRING_ALGO
+BOOST_TUPLE
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
# Thank you Solaris, really.
#include "SessionCache.h"
#include "util/CGIParser.h"
+#include <boost/lexical_cast.hpp>
+
using namespace shibsp;
using namespace opensaml;
using namespace xmltooling;
#endif
AbstractSPRequest::AbstractSPRequest(const char* category)
- : m_sp(nullptr), m_mapper(nullptr), m_app(nullptr), m_sessionTried(false), m_session(nullptr),
- m_log(&Category::getInstance(category)), m_parser(nullptr)
+ : m_sp(SPConfig::getConfig().getServiceProvider()),
+ m_mapper(nullptr), m_app(nullptr), m_sessionTried(false), m_session(nullptr),
+ m_log(&Category::getInstance(category))
{
- m_sp=SPConfig::getConfig().getServiceProvider();
m_sp->lock();
}
m_mapper->unlock();
if (m_sp)
m_sp->unlock();
- delete m_parser;
}
const ServiceProvider& AbstractSPRequest::getServiceProvider() const
{
if (!m_mapper) {
// Map request to application and content settings.
- m_mapper=m_sp->getRequestMapper();
+ m_mapper = m_sp->getRequestMapper();
m_mapper->lock();
m_settings = m_mapper->getSettings(*this);
{
if (!m_app) {
// Now find the application from the URL settings
- m_app=m_sp->getApplication(getRequestSettings().first->getString("applicationId").second);
+ m_app = m_sp->getApplication(getRequestSettings().first->getString("applicationId").second);
if (!m_app)
throw ConfigurationException("Unable to map non-default applicationId to an ApplicationOverride, check configuration.");
}
m_sessionTried = true;
// Need address checking and timeout settings.
- time_t timeout=3600;
+ time_t timeout = 3600;
if (checkTimeout || !ignoreAddress) {
- const PropertySet* props=getApplication().getPropertySet("Sessions");
+ const PropertySet* props = getApplication().getPropertySet("Sessions");
if (props) {
if (checkTimeout) {
- pair<bool,unsigned int> p=props->getUnsignedInt("timeout");
+ pair<bool,unsigned int> p = props->getUnsignedInt("timeout");
if (p.first)
timeout = p.second;
}
- pair<bool,bool> pcheck=props->getBool("consistentAddress");
+ pair<bool,bool> pcheck = props->getBool("consistentAddress");
if (pcheck.first)
ignoreAddress = !pcheck.second;
}
// The cache will either silently pass a session or nullptr back, or throw an exception out.
Session* session = getServiceProvider().getSessionCache()->find(
- getApplication(), *this, ignoreAddress ? nullptr : getRemoteAddr().c_str(), checkTimeout ? &timeout : nullptr
+ getApplication(), *this, (ignoreAddress ? nullptr : getRemoteAddr().c_str()), (checkTimeout ? &timeout : nullptr)
);
if (cache)
m_session = session;
int port = getPort();
const char* scheme = getScheme();
m_url = string(scheme) + "://" + getHostname();
- if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
- ostringstream portstr;
- portstr << port;
- m_url += ":" + portstr.str();
+ if ((!strcmp(scheme,"http") && port != 80) || (!strcmp(scheme,"https") && port != 443)) {
+ m_url += ":" + boost::lexical_cast<string>(port);
}
m_url += m_uri;
}
const char* AbstractSPRequest::getParameter(const char* name) const
{
- if (!m_parser)
- m_parser=new CGIParser(*this);
+ if (!m_parser.get())
+ m_parser.reset(new CGIParser(*this));
- pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
+ pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
return (bounds.first==bounds.second) ? nullptr : bounds.first->second;
}
vector<const char*>::size_type AbstractSPRequest::getParameters(const char* name, vector<const char*>& values) const
{
- if (!m_parser)
- m_parser=new CGIParser(*this);
+ if (!m_parser.get())
+ m_parser.reset(new CGIParser(*this));
- pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
- while (bounds.first!=bounds.second) {
+ pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
+ while (bounds.first != bounds.second) {
values.push_back(bounds.first->second);
++bounds.first;
}
if (!resource)
resource = getRequestURL();
- if (!m_handlerURL.empty() && resource && !strcmp(getRequestURL(),resource))
+ if (!m_handlerURL.empty() && resource && !strcmp(getRequestURL(), resource))
return m_handlerURL.c_str();
+ // Check for relative URL.
string stackresource;
if (resource && *resource == '/') {
// Compute a URL to the root of the site and point resource at constructed string.
int port = getPort();
const char* scheme = getScheme();
stackresource = string(scheme) + "://" + getHostname();
- if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
- ostringstream portstr;
- portstr << port;
- stackresource += ":" + portstr.str();
+ if ((!strcmp(scheme,"http") && port != 80) || (!strcmp(scheme,"https") && port != 443)) {
+ stackresource += ":" + boost::lexical_cast<string>(port);
}
stackresource += resource;
resource = stackresource.c_str();
#endif
throw ConfigurationException("Target resource was not an absolute URL.");
- bool ssl_only=true;
- const char* handler=nullptr;
- const PropertySet* props=getApplication().getPropertySet("Sessions");
+ bool ssl_only = true;
+ const char* handler = nullptr;
+ const PropertySet* props = getApplication().getPropertySet("Sessions");
if (props) {
- pair<bool,bool> p=props->getBool("handlerSSL");
+ pair<bool,bool> p = props->getBool("handlerSSL");
if (p.first)
- ssl_only=p.second;
- pair<bool,const char*> p2=props->getString("handlerURL");
+ ssl_only = p.second;
+ pair<bool,const char*> p2 = props->getString("handlerURL");
if (p2.first)
- handler=p2.second;
+ handler = p2.second;
}
if (!handler) {
}
// break apart the "protocol" string into protocol, host, and "the rest"
- const char* colon=strchr(prot,':');
+ const char* colon = strchr(prot, ':');
colon += 3;
- const char* slash=strchr(colon,'/');
+ const char* slash = strchr(colon, '/');
if (!path)
path = slash;
#define __shibsp_abstreq_h__
#include <shibsp/SPRequest.h>
+#include <boost/scoped_ptr.hpp>
namespace shibsp {
mutable std::string m_url;
void* m_log; // declared void* to avoid log4cpp header conflicts in Apache
mutable std::string m_handlerURL;
- mutable CGIParser* m_parser;
+ mutable boost::scoped_ptr<CGIParser> m_parser;
};
#if defined (_MSC_VER)
#include "remoting/ListenerService.h"
#include <algorithm>
+#include <boost/bind.hpp>
#include <xmltooling/util/Threads.h>
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
Application::Application(const ServiceProvider* sp) : m_sp(sp), m_lock(RWLock::create())
void Application::clearAttributeHeaders(SPRequest& request) const
{
if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
- request.clearHeader(i->first.c_str(), i->second.c_str());
+ for_each(
+ m_unsetHeaders.begin(), m_unsetHeaders.end(),
+ boost::bind(
+ &SPRequest::clearHeader,
+ boost::ref(request),
+ boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1)),
+ boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1))
+ )
+ );
return;
}
// Now holding read lock.
SharedLock unsetLock(m_lock, false);
- for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
- request.clearHeader(i->first.c_str(), i->second.c_str());
+ for_each(
+ m_unsetHeaders.begin(), m_unsetHeaders.end(),
+ boost::bind(
+ &SPRequest::clearHeader,
+ boost::ref(request),
+ boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1)),
+ boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1))
+ )
+ );
}
const Handler* Application::getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding) const
#endif
#include <ctime>
+#include <boost/scoped_ptr.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/version.h>
#include <xmltooling/XMLToolingConfig.h>
using namespace shibsp;
using namespace opensaml;
using namespace xmltooling;
+using namespace boost;
using namespace std;
DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeException,shibsp);
class SHIBSP_DLLLOCAL SPInternalConfig : public SPConfig
{
public:
- SPInternalConfig();
- ~SPInternalConfig();
+ SPInternalConfig() : m_initCount(0), m_lock(Mutex::create()) {}
+ ~SPInternalConfig() {}
bool init(const char* catalog_path=nullptr, const char* inst_prefix=nullptr);
void term();
private:
int m_initCount;
- Mutex* m_lock;
+ scoped_ptr<Mutex> m_lock;
};
SPInternalConfig g_config;
return false;
}
-SPInternalConfig::SPInternalConfig() : m_initCount(0), m_lock(Mutex::create())
-{
-}
-
-SPInternalConfig::~SPInternalConfig()
-{
- delete m_lock;
-}
-
bool SPInternalConfig::init(const char* catalog_path, const char* inst_prefix)
{
#ifdef _DEBUG
#include <fstream>
#include <sstream>
+#include <boost/algorithm/string.hpp>
#ifndef SHIBSP_LITE
# include <saml/exceptions.h>
# include <saml/saml2/metadata/MetadataProvider.h>
Remoted* ServiceProvider::regListener(const char* address, Remoted* listener)
{
- Remoted* ret=nullptr;
- map<string,Remoted*>::const_iterator i=m_listenerMap.find(address);
- if (i!=m_listenerMap.end())
- ret=i->second;
- m_listenerMap[address]=listener;
+ Remoted* ret = nullptr;
+ map<string,Remoted*>::const_iterator i = m_listenerMap.find(address);
+ if (i != m_listenerMap.end())
+ ret = i->second;
+ m_listenerMap[address] = listener;
Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").info("registered remoted message endpoint (%s)",address);
return ret;
}
bool ServiceProvider::unregListener(const char* address, Remoted* current, Remoted* restore)
{
- map<string,Remoted*>::const_iterator i=m_listenerMap.find(address);
- if (i!=m_listenerMap.end() && i->second==current) {
+ map<string,Remoted*>::const_iterator i = m_listenerMap.find(address);
+ if (i != m_listenerMap.end() && i->second == current) {
if (restore)
- m_listenerMap[address]=restore;
+ m_listenerMap[address] = restore;
else
m_listenerMap.erase(address);
Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").info("unregistered remoted message endpoint (%s)",address);
Remoted* ServiceProvider::lookupListener(const char *address) const
{
- map<string,Remoted*>::const_iterator i=m_listenerMap.find(address);
- return (i==m_listenerMap.end()) ? nullptr : i->second;
+ map<string,Remoted*>::const_iterator i = m_listenerMap.find(address);
+ return (i == m_listenerMap.end()) ? nullptr : i->second;
}
pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handler) const
#endif
Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
- const Application* app=nullptr;
+ const Application* app = nullptr;
string targetURL = request.getRequestURL();
try {
else {
TemplateParameters tp;
tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,sendError(log, request, app, "ssl", tp, false));
+ return make_pair(true, sendError(log, request, app, "ssl", tp, false));
}
}
}
// If the request URL contains the handler base URL for this application, either dispatch
// directly (mainly Apache 2.0) or just pass back control.
- if (strstr(targetURL.c_str(),handlerURL)) {
+ if (boost::contains(targetURL, handlerURL)) {
if (handler)
return doHandler(request);
else
pair<bool,bool> requireSession = settings.first->getBool("requireSession");
pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
- string lcAuthType;
- if (authType.first) {
- while (*authType.second)
- lcAuthType += tolower(*authType.second++);
- }
-
// If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
// then we ignore this request and consider it unprotected. Apache might lie to us if
// ShibBasicHijack is on, but that's up to it.
if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
- (!authType.first || m_authTypes.find(lcAuthType) == m_authTypes.end()))
+ (!authType.first || m_authTypes.find(boost::to_lower_copy(string(authType.second))) == m_authTypes.end()))
return make_pair(true, request.returnDecline());
// Fix for secadv 20050901
catch (exception& e) {
log.warn("error during session lookup: %s", e.what());
// If it's not a retryable session failure, we throw to the outer handler for reporting.
- if (dynamic_cast<opensaml::RetryableProfileException*>(&e)==nullptr)
+ if (dynamic_cast<opensaml::RetryableProfileException*>(&e) == nullptr)
throw;
}
if (!session) {
// No session. Maybe that's acceptable?
if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
- return make_pair(true,request.returnOK());
+ return make_pair(true, request.returnOK());
// No session, but we require one. Initiate a new session using the indicated method.
const SessionInitiator* initiator=nullptr;
throw ConfigurationException("No default session initiator found, check configuration.");
}
- return initiator->run(request,false);
+ return initiator->run(request, false);
}
- request.setAuthType(lcAuthType.c_str());
+ request.setAuthType(authType.second);
// We're done. Everything is okay. Nothing to report. Nothing to do..
// Let the caller decide how to proceed.
#endif
Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
- const Application* app=nullptr;
+ const Application* app = nullptr;
const Session* session = nullptr;
string targetURL = request.getRequestURL();
pair<bool,bool> requireSession = settings.first->getBool("requireSession");
pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
- string lcAuthType;
- if (authType.first) {
- while (*authType.second)
- lcAuthType += tolower(*authType.second++);
- }
-
// If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
// then we ignore this request and consider it unprotected. Apache might lie to us if
// ShibBasicHijack is on, but that's up to it.
if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
- (!authType.first || m_authTypes.find(lcAuthType) == m_authTypes.end()))
+ (!authType.first || m_authTypes.find(boost::to_lower_copy(string(authType.second))) == m_authTypes.end()))
return make_pair(true, request.returnDecline());
// Do we have an access control plugin?
}
Locker acllock(settings.second);
- switch (settings.second->authorized(request,session)) {
+ switch (settings.second->authorized(request, session)) {
case AccessControl::shib_acl_true:
log.debug("access control provider granted access");
- return make_pair(true,request.returnOK());
+ return make_pair(true, request.returnOK());
case AccessControl::shib_acl_false:
{
log.warn("access control provider denied access");
TemplateParameters tp(nullptr, nullptr, session);
tp.m_map["requestURL"] = targetURL;
- return make_pair(true,sendError(log, request, app, "access", tp, false));
+ return make_pair(true, sendError(log, request, app, "access", tp, false));
}
default:
// Use the "DECLINE" interface to signal we don't know what to do.
- return make_pair(true,request.returnDecline());
+ return make_pair(true, request.returnDecline());
}
}
else {
- return make_pair(true,request.returnDecline());
+ return make_pair(true, request.returnDecline());
}
}
catch (exception& e) {
#endif
Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
- const Application* app=nullptr;
+ const Application* app = nullptr;
const Session* session = nullptr;
string targetURL = request.getRequestURL();
if (requireSession)
throw opensaml::RetryableProfileException("Unable to obtain session to export to request.");
else
- return make_pair(false,0L); // just bail silently
+ return make_pair(false, 0L); // just bail silently
}
pair<bool,const char*> enc = settings.first->getString("encoding");
}
// Maybe export the assertion keys.
- pair<bool,bool> exp=settings.first->getBool("exportAssertion");
+ pair<bool,bool> exp = settings.first->getBool("exportAssertion");
if (exp.first && exp.second) {
- const PropertySet* sessions=app->getPropertySet("Sessions");
+ const PropertySet* sessions = app->getPropertySet("Sessions");
pair<bool,const char*> exportLocation = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,nullptr);
if (!exportLocation.first)
log.warn("can't export assertions without an exportLocation Sessions property");
// Export the attributes.
const multimap<string,const Attribute*>& attributes = session->getIndexedAttributes();
- for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a!=attributes.end(); ++a) {
+ for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a) {
if (a->second->isInternal())
continue;
string header(app->getSecureHeader(request, a->first.c_str()));
const vector<string>& vals = a->second->getSerializedValues();
- for (vector<string>::const_iterator v = vals.begin(); v!=vals.end(); ++v) {
+ for (vector<string>::const_iterator v = vals.begin(); v != vals.end(); ++v) {
if (!header.empty())
header += ";";
if (enc.first) {
header += encoder->encode(v->c_str());
}
else {
- string::size_type pos = v->find_first_of(';',string::size_type(0));
- if (pos!=string::npos) {
+ string::size_type pos = v->find_first_of(';', string::size_type(0));
+ if (pos != string::npos) {
string value(*v);
- for (; pos != string::npos; pos = value.find_first_of(';',pos)) {
+ for (; pos != string::npos; pos = value.find_first_of(';', pos)) {
value.insert(pos, "\\");
pos += 2;
}
#endif
Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
- const Application* app=nullptr;
+ const Application* app = nullptr;
string targetURL = request.getRequestURL();
try {
}
}
- const char* handlerURL=request.getHandlerURL(targetURL.c_str());
+ const char* handlerURL = request.getHandlerURL(targetURL.c_str());
if (!handlerURL)
throw ConfigurationException("Cannot determine handler from resource URL, check configuration.");
// Make sure we only process handler requests.
- if (!strstr(targetURL.c_str(),handlerURL))
+ if (!boost::contains(targetURL, handlerURL))
return make_pair(true, request.returnDecline());
- const PropertySet* sessionProps=app->getPropertySet("Sessions");
+ const PropertySet* sessionProps = app->getPropertySet("Sessions");
if (!sessionProps)
throw ConfigurationException("Unable to map request to application session settings, check configuration.");
// Process incoming request.
- pair<bool,bool> handlerSSL=sessionProps->getBool("handlerSSL");
+ pair<bool,bool> handlerSSL = sessionProps->getBool("handlerSSL");
// Make sure this is SSL, if it should be
if ((!handlerSSL.first || handlerSSL.second) && !request.isSecure())
// We dispatch based on our path info. We know the request URL begins with or equals the handler URL,
// so the path info is the next character (or null).
- const Handler* handler=app->getHandler(targetURL.c_str() + strlen(handlerURL));
+ const Handler* handler = app->getHandler(targetURL.c_str() + strlen(handlerURL));
if (!handler)
throw ConfigurationException("Shibboleth handler invoked at an unconfigured location.");
- pair<bool,long> hret=handler->run(request);
+ pair<bool,long> hret = handler->run(request);
// Did the handler run successfully?
if (hret.first)
try {
session = request.getSession(false, true);
}
- catch (exception& e2) {
+ catch (exception&) {
}
TemplateParameters tp(&e, nullptr, session);
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ tp.m_map["requestURL"] = targetURL.substr(0, targetURL.find('?'));
tp.m_request = &request;
- return make_pair(true,sendError(log, request, app, "session", tp));
+ return make_pair(true, sendError(log, request, app, "session", tp));
}
}
#include "attribute/AttributeDecoder.h"
#include "attribute/SimpleAttribute.h"
+#include <boost/scoped_ptr.hpp>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml2/core/Assertions.h>
#include <xmltooling/XMLToolingConfig.h>
using namespace opensaml;
using namespace xmlsignature;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
{
public:
KeyInfoAttributeDecoder(const DOMElement* e);
- ~KeyInfoAttributeDecoder() {
- delete m_keyInfoResolver;
- }
+ ~KeyInfoAttributeDecoder() {}
Attribute* decode(
const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=nullptr, const char* relyingParty=nullptr
private:
void extract(const KeyInfo* k, vector<string>& dest) const {
- auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
- if (cred.get()) {
+ scoped_ptr<Credential> cred(getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
+ if (cred) {
dest.push_back(string());
- dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash ? m_keyInfoHashAlg.c_str() : nullptr);
+ dest.back() = SecurityHelper::getDEREncoding(*cred, m_hash ? m_keyInfoHashAlg.c_str() : nullptr);
if (dest.back().empty())
dest.pop_back();
}
}
const KeyInfoResolver* getKeyInfoResolver() const {
- return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
+ return m_keyInfoResolver ? m_keyInfoResolver.get() : XMLToolingConfig::getConfig().getKeyInfoResolver();
}
bool m_hash;
string m_keyInfoHashAlg;
- KeyInfoResolver* m_keyInfoResolver;
+ scoped_ptr<KeyInfoResolver> m_keyInfoResolver;
};
AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)
KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e)
: AttributeDecoder(e),
m_hash(XMLHelper::getAttrBool(e, false, _hash)),
- m_keyInfoHashAlg(XMLHelper::getAttrString(e, "SHA1", keyInfoHashAlg)),
- m_keyInfoResolver(nullptr) {
- e = XMLHelper::getFirstChildElement(e,_KeyInfoResolver);
+ m_keyInfoHashAlg(XMLHelper::getAttrString(e, "SHA1", keyInfoHashAlg)) {
+ e = XMLHelper::getFirstChildElement(e, _KeyInfoResolver);
if (e) {
string t(XMLHelper::getAttrString(e, nullptr, _type));
if (t.empty())
throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
- m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.c_str(), e);
+ m_keyInfoResolver.reset(XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.c_str(), e));
}
}
extract(k, dest);
else if ((*v)->hasChildren()) {
const list<XMLObject*>& children = (*v)->getOrderedChildren();
- for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {
+ for (list<XMLObject*>::const_iterator vv = children.begin(); vv != children.end(); ++vv) {
if (k=dynamic_cast<const KeyInfo*>(*vv))
extract(k, dest);
else
dest.push_back(NameIDAttribute::Value());
NameIDAttribute::Value& val = dest.back();
val.m_Name = name.get();
- char* str = toUTF8(n->getFormat());
- if (str) {
- val.m_Format = str;
- delete[] str;
- }
- str = toUTF8(n->getNameQualifier());
- if (str && *str)
- val.m_NameQualifier = str;
+ auto_arrayptr<char> format(toUTF8(n->getFormat()));
+ if (format.get())
+ val.m_Format = format.get();
+
+ auto_arrayptr<char> nameQualifier(toUTF8(n->getNameQualifier()));
+ if (nameQualifier.get() && *nameQualifier.get())
+ val.m_NameQualifier = nameQualifier.get();
else if (m_defaultQualifiers && assertingParty)
val.m_NameQualifier = assertingParty;
- delete[] str;
- str = toUTF8(n->getSPNameQualifier());
- if (str && *str)
- val.m_SPNameQualifier = str;
+ auto_arrayptr<char> spNameQualifier(toUTF8(n->getSPNameQualifier()));
+ if (spNameQualifier.get() && *spNameQualifier.get())
+ val.m_SPNameQualifier = spNameQualifier.get();
else if (m_defaultQualifiers && relyingParty)
val.m_SPNameQualifier = relyingParty;
- delete[] str;
- str = toUTF8(n->getSPProvidedID());
- if (str) {
- val.m_SPProvidedID = str;
- delete[] str;
- }
+ auto_arrayptr<char> spProvidedID(toUTF8(n->getSPProvidedID()));
+ if (spProvidedID.get())
+ val.m_SPProvidedID = spProvidedID.get();
}
}
dest.push_back(NameIDAttribute::Value());
NameIDAttribute::Value& val = dest.back();
val.m_Name = name.get();
- char* str = toUTF8(n->getFormat());
- if (str) {
- val.m_Format = str;
- delete[] str;
- }
- str = toUTF8(n->getNameQualifier());
- if (str && *str)
- val.m_NameQualifier = str;
+ auto_arrayptr<char> format(toUTF8(n->getFormat()));
+ if (format.get())
+ val.m_Format = format.get();
+
+ auto_arrayptr<char> nameQualifier(toUTF8(n->getNameQualifier()));
+ if (nameQualifier.get() && *nameQualifier.get())
+ val.m_NameQualifier = nameQualifier.get();
else if (m_defaultQualifiers && assertingParty)
val.m_NameQualifier = assertingParty;
- delete[] str;
if (m_defaultQualifiers && relyingParty)
val.m_SPNameQualifier = relyingParty;
const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
) const
{
- char* val;
auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
vector<string>& dest = simple->getValues();
vector<XMLObject*>::const_iterator v,stop;
for (; v!=stop; ++v) {
if (!(*v)->hasChildren()) {
- val = toUTF8((*v)->getTextContent());
- if (val && *val)
- dest.push_back(val);
+ auto_arrayptr<char> val(toUTF8((*v)->getTextContent()));
+ if (val.get() && *val.get())
+ dest.push_back(val.get());
else
log.warn("skipping empty AttributeValue");
- delete[] val;
}
else {
log.warn("skipping complex AttributeValue");
auto_ptr_char f(saml2name->getFormat());
log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
}
- val = toUTF8(saml2name->getName());
+ auto_arrayptr<char> val(toUTF8(saml2name->getName()));
+ if (val.get() && *val.get())
+ dest.push_back(val.get());
+ else
+ log.warn("ignoring empty NameID");
}
else {
const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
ids.front().c_str(), f.get() ? f.get() : "unspecified"
);
}
- val = toUTF8(saml1name->getName());
+ auto_arrayptr<char> val(toUTF8(saml1name->getName()));
+ if (val.get() && *val.get())
+ dest.push_back(val.get());
+ else
+ log.warn("ignoring empty NameIdentifier");
}
else {
log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
}
}
- if (val && *val)
- dest.push_back(val);
- else
- log.warn("ignoring empty NameID");
- delete[] val;
return dest.empty() ? nullptr : _decode(simple.release());
}
#include "security/SecurityPolicy.h"
#include "util/SPConstants.h"
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/tuple/tuple.hpp>
#include <saml/SAMLConfig.h>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml2/core/Assertions.h>
using namespace opensaml::saml2md;
using namespace opensaml;
using namespace xmltooling;
+using namespace boost;
using namespace std;
using saml1::NameIdentifier;
using saml2::NameID;
for (decoded_t::iterator attrs = i->second.begin(); attrs!=i->second.end(); ++attrs)
for_each(attrs->second.begin(), attrs->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
}
- delete m_attrLock;
- delete m_trust;
- delete m_metadata;
- delete m_filter;
- for (attrmap_t::iterator j = m_attrMap.begin(); j!=m_attrMap.end(); ++j)
- delete j->second.first;
if (m_document)
m_document->release();
}
void onEvent(const ObservableMetadataProvider& metadata) const {
// Destroy attributes we cached from this provider.
m_attrLock->wrlock();
+ SharedLock wrapper(m_attrLock, false);
decoded_t& d = m_decodedMap[&metadata];
for (decoded_t::iterator a = d.begin(); a!=d.end(); ++a)
for_each(a->second.begin(), a->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
d.clear();
- m_attrLock->unlock();
}
void extractAttributes(
const char* assertingParty,
const char* relyingParty,
const NameIdentifier& nameid,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void extractAttributes(
const Application& application,
const char* assertingParty,
const char* relyingParty,
const NameID& nameid,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void extractAttributes(
const Application& application,
const char* assertingParty,
const char* relyingParty,
const saml1::Attribute& attr,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void extractAttributes(
const Application& application,
const char* assertingParty,
const char* relyingParty,
const saml2::Attribute& attr,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void extractAttributes(
const Application& application,
const char* assertingParty,
const char* relyingParty,
const saml1::AttributeStatement& statement,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void extractAttributes(
const Application& application,
const char* assertingParty,
const char* relyingParty,
const saml2::AttributeStatement& statement,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void extractAttributes(
const Application& application,
const XMLCh* entityID,
const char* relyingParty,
const Extensions& ext,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const;
void getAttributeIds(vector<string>& attributes) const {
private:
Category& m_log;
DOMDocument* m_document;
- typedef map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > > attrmap_t;
+ typedef map< pair<xstring,xstring>,pair< boost::shared_ptr<AttributeDecoder>,vector<string> > > attrmap_t;
attrmap_t m_attrMap;
vector<string> m_attributeIds;
- vector< pair< pair<xstring,xstring>,bool > > m_requestedAttrs;
+ vector< tuple<xstring,xstring,bool> > m_requestedAttrs;
// settings for embedded assertions in metadata
string m_policyId;
- MetadataProvider* m_metadata;
- TrustEngine* m_trust;
- AttributeFilter* m_filter;
+ scoped_ptr<AttributeFilter> m_filter;
+ scoped_ptr<MetadataProvider> m_metadata;
+ scoped_ptr<TrustEngine> m_trust;
bool m_entityAssertions;
// manages caching of decoded Attributes
- mutable RWLock* m_attrLock;
+ scoped_ptr<RWLock> m_attrLock;
typedef map< const EntityAttributes*,vector<DDF> > decoded_t;
mutable map<const ObservableMetadataProvider*,decoded_t> m_decodedMap;
};
class XMLExtractor : public AttributeExtractor, public ReloadableXMLFile
{
public:
- XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.XML")), m_impl(nullptr) {
+ XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.XML")) {
background_load();
}
~XMLExtractor() {
shutdown();
- delete m_impl;
}
void extractAttributes(
pair<bool,DOMElement*> background_load();
private:
- XMLExtractorImpl* m_impl;
+ scoped_ptr<XMLExtractorImpl> m_impl;
+
+ void extractAttributes(
+ const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, ptr_vector<Attribute>& attributes
+ ) const;
};
#if defined (_MSC_VER)
: m_log(log),
m_document(nullptr),
m_policyId(XMLHelper::getAttrString(e, nullptr, metadataPolicyId)),
- m_metadata(nullptr),
- m_trust(nullptr),
- m_filter(nullptr),
- m_entityAssertions(true),
- m_attrLock(nullptr)
+ m_entityAssertions(true)
{
#ifdef _DEBUG
xmltooling::NDC ndc("XMLExtractorImpl");
if (t.empty())
throw ConfigurationException("MetadataProvider element missing type attribute.");
m_log.info("building MetadataProvider of type %s...", t.c_str());
- auto_ptr<MetadataProvider> mp(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child));
- mp->init();
- m_metadata = mp.release();
+ m_metadata.reset(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child));
+ m_metadata->init();
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
+ m_metadata.reset();
m_entityAssertions = false;
m_log.crit("error building/initializing dedicated MetadataProvider: %s", ex.what());
m_log.crit("disabling support for Assertions in EntityAttributes extension");
if (t.empty())
throw ConfigurationException("TrustEngine element missing type attribute.");
m_log.info("building TrustEngine of type %s...", t.c_str());
- m_trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child);
+ m_trust.reset(XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child));
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_entityAssertions = false;
m_log.crit("error building/initializing dedicated TrustEngine: %s", ex.what());
m_log.crit("disabling support for Assertions in EntityAttributes extension");
if (t.empty())
throw ConfigurationException("AttributeFilter element missing type attribute.");
m_log.info("building AttributeFilter of type %s...", t.c_str());
- m_filter = SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), child);
+ m_filter.reset(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), child));
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_entityAssertions = false;
m_log.crit("error building/initializing dedicated AttributeFilter: %s", ex.what());
m_log.crit("disabling support for Assertions in EntityAttributes extension");
continue;
}
- AttributeDecoder* decoder=nullptr;
+ boost::shared_ptr<AttributeDecoder> decoder;
try {
DOMElement* dchild = XMLHelper::getFirstChildElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeDecoder);
if (dchild) {
auto_ptr<xmltooling::QName> q(XMLHelper::getXSIType(dchild));
if (q.get())
- decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild);
+ decoder.reset(SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild));
}
if (!decoder)
- decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, nullptr);
+ decoder.reset(SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, nullptr));
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("skipping Attribute (%s), error building AttributeDecoder: %s", id.get(), ex.what());
}
format = &chNull; // ignore default Format/Namespace values
// Fetch/create the map entry and see if it's a duplicate rule.
- pair< AttributeDecoder*,vector<string> >& decl = m_attrMap[pair<xstring,xstring>(name,format)];
+ pair< boost::shared_ptr<AttributeDecoder>,vector<string> >& decl = m_attrMap[pair<xstring,xstring>(name,format)];
if (decl.first) {
m_log.warn("skipping duplicate Attribute mapping (same name and nameFormat)");
- delete decoder;
child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
continue;
}
bool requested = XMLHelper::getAttrBool(child, false, isRequested);
bool required = XMLHelper::getAttrBool(child, false, RequestedAttribute::ISREQUIRED_ATTRIB_NAME);
if (required || requested)
- m_requestedAttrs.push_back(make_pair(pair<xstring,xstring>(name,format), required));
+ m_requestedAttrs.push_back(tuple<xstring,xstring,bool>(name,format,required));
name = child->getAttributeNS(nullptr, _aliases);
if (name && *name) {
auto_ptr_char aliases(name);
- char* pos;
- char* start = const_cast<char*>(aliases.get());
- while (start && *start) {
- while (*start && isspace(*start))
- start++;
- if (!*start)
- break;
- pos = strchr(start,' ');
- if (pos)
- *pos=0;
- if (strcmp(start, "REMOTE_USER")) {
- decl.second.push_back(start);
- m_attributeIds.push_back(start);
- }
- else {
- m_log.warn("skipping alias, REMOTE_USER is a reserved name");
- }
- start = pos ? pos+1 : nullptr;
+ string dup(aliases.get());
+ set<string> new_aliases;
+ split(new_aliases, dup, is_space(), algorithm::token_compress_on);
+ set<string>::iterator ru = new_aliases.find("REMOTE_USER");
+ if (ru != new_aliases.end()) {
+ m_log.warn("skipping alias, REMOTE_USER is a reserved name");
+ new_aliases.erase(ru);
}
+ m_attributeIds.insert(m_attributeIds.end(), new_aliases.begin(), new_aliases.end());
}
child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
}
- m_attrLock = RWLock::create();
+ m_attrLock.reset(RWLock::create());
}
void XMLExtractorImpl::generateMetadata(SPSSODescriptor& role) const
static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
sn->setLang(english);
- for (vector< pair< pair<xstring,xstring>,bool > >::const_iterator i = m_requestedAttrs.begin(); i != m_requestedAttrs.end(); ++i) {
+ for (vector< tuple<xstring,xstring,bool> >::const_iterator i = m_requestedAttrs.begin(); i != m_requestedAttrs.end(); ++i) {
RequestedAttribute* req = RequestedAttributeBuilder::buildRequestedAttribute();
svc->getRequestedAttributes().push_back(req);
- req->setName(i->first.first.c_str());
- if (i->first.second.empty())
+ req->setName(i->get<0>().c_str());
+ if (i->get<1>().empty())
req->setNameFormat(saml2::Attribute::URI_REFERENCE);
else
- req->setNameFormat(i->first.second.c_str());
- if (i->second)
+ req->setNameFormat(i->get<1>().c_str());
+ if (i->get<2>())
req->isRequired(true);
}
}
const char* assertingParty,
const char* relyingParty,
const NameIdentifier& nameid,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
- map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
const XMLCh* format = nameid.getFormat();
if (!format || !*format)
format = NameIdentifier::UNSPECIFIED;
- if ((rule=m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
- Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
- if (a)
+ attrmap_t::const_iterator rule;
+ if ((rule = m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
+ auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty));
+ if (a.get()) {
attributes.push_back(a);
+ }
}
else if (m_log.isDebugEnabled()) {
auto_ptr_char temp(format);
const char* assertingParty,
const char* relyingParty,
const NameID& nameid,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
- map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
const XMLCh* format = nameid.getFormat();
if (!format || !*format)
format = NameID::UNSPECIFIED;
- if ((rule=m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
- Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
- if (a)
+ attrmap_t::const_iterator rule;
+ if ((rule = m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
+ auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty));
+ if (a.get()) {
attributes.push_back(a);
+ }
}
else if (m_log.isDebugEnabled()) {
auto_ptr_char temp(format);
const char* assertingParty,
const char* relyingParty,
const saml1::Attribute& attr,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
- map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
const XMLCh* name = attr.getAttributeName();
const XMLCh* format = attr.getAttributeNamespace();
if (!name || !*name)
return;
if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI))
format = &chNull;
- if ((rule=m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
- Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
- if (a)
+ attrmap_t::const_iterator rule;
+ if ((rule = m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
+ auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty));
+ if (a.get()) {
attributes.push_back(a);
+ }
}
else if (m_log.isInfoEnabled()) {
auto_ptr_char temp1(name);
const char* assertingParty,
const char* relyingParty,
const saml2::Attribute& attr,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
- map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
const XMLCh* name = attr.getName();
const XMLCh* format = attr.getNameFormat();
if (!name || !*name)
format = saml2::Attribute::UNSPECIFIED;
else if (XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
format = &chNull;
-
- if ((rule=m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
- Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
- if (a) {
+ attrmap_t::const_iterator rule;
+ if ((rule = m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
+ auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty));
+ if (a.get()) {
attributes.push_back(a);
return;
}
}
else if (XMLString::equals(format, saml2::Attribute::UNSPECIFIED)) {
// As a fallback, if the format is "unspecified", null out the value and re-map.
- if ((rule=m_attrMap.find(pair<xstring,xstring>(name,xstring()))) != m_attrMap.end()) {
- Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
- if (a) {
- attributes.push_back(a);
+ if ((rule = m_attrMap.find(pair<xstring,xstring>(name,xstring()))) != m_attrMap.end()) {
+ auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty));
+ if (a.get()) {
+ attributes.push_back(a.get());
+ a.release();
return;
}
}
const char* assertingParty,
const char* relyingParty,
const saml1::AttributeStatement& statement,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
- const vector<saml1::Attribute*>& attrs = statement.getAttributes();
- for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
- extractAttributes(application, assertingParty, relyingParty, *(*a), attributes);
+ static void (XMLExtractorImpl::* extract)(
+ const Application&, const char*, const char*, const saml1::Attribute&, ptr_vector<Attribute>&
+ ) const = &XMLExtractorImpl::extractAttributes;
+ for_each(
+ make_indirect_iterator(statement.getAttributes().begin()), make_indirect_iterator(statement.getAttributes().end()),
+ boost::bind(extract, this, boost::ref(application), assertingParty, relyingParty, _1, boost::ref(attributes))
+ );
}
void XMLExtractorImpl::extractAttributes(
const char* assertingParty,
const char* relyingParty,
const saml2::AttributeStatement& statement,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
- const vector<saml2::Attribute*>& attrs = statement.getAttributes();
- for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
- extractAttributes(application, assertingParty, relyingParty, *(*a), attributes);
+ static void (XMLExtractorImpl::* extract)(
+ const Application&, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&
+ ) const = &XMLExtractorImpl::extractAttributes;
+ for_each(
+ make_indirect_iterator(statement.getAttributes().begin()), make_indirect_iterator(statement.getAttributes().end()),
+ boost::bind(extract, this, boost::ref(application), assertingParty, relyingParty, _1, boost::ref(attributes))
+ );
}
void XMLExtractorImpl::extractAttributes(
const XMLCh* entityID,
const char* relyingParty,
const Extensions& ext,
- vector<Attribute*>& attributes
+ ptr_vector<Attribute>& attributes
) const
{
const vector<XMLObject*>& exts = ext.getUnknownXMLObjects();
- for (vector<XMLObject*>::const_iterator i = exts.begin(); i!=exts.end(); ++i) {
+ for (vector<XMLObject*>::const_iterator i = exts.begin(); i != exts.end(); ++i) {
const EntityAttributes* container = dynamic_cast<const EntityAttributes*>(*i);
if (!container)
continue;
m_attrLock->unlock();
m_attrLock->wrlock();
cacheEntry = m_decodedMap.find(observable);
- if (cacheEntry==m_decodedMap.end()) {
+ if (cacheEntry == m_decodedMap.end()) {
+ SharedLock locker(m_attrLock, false); // guard in case these throw
// It's still brand new, so hook it for cache activation.
observable->addObserver(this);
// Downgrade the lock.
// We don't have to recheck because we never erase the master map entry entirely, even on changes.
+ locker.release(); // unguard for lock downgrade
m_attrLock->unlock();
m_attrLock->rdlock();
}
}
if (useCache) {
- // We're holding a read lock, so check the cache.
+ // We're holding the lock, so check the cache.
decoded_t::iterator d = cacheEntry->second.find(container);
if (d != cacheEntry->second.end()) {
SharedLock locker(m_attrLock, false); // pop the lock when we're done
for (vector<DDF>::iterator obj = d->second.begin(); obj != d->second.end(); ++obj) {
auto_ptr<Attribute> wrapper(Attribute::unmarshall(*obj));
m_log.debug("recovered cached metadata attribute (%s)", wrapper->getId());
- attributes.push_back(wrapper.release());
+ attributes.push_back(wrapper);
}
break;
}
}
+ // Add a guard for the lock if we're caching.
+ SharedLock locker(useCache ? m_attrLock.get() : nullptr, false);
+
// Use a holding area to support caching.
- vector<Attribute*> holding;
+ ptr_vector<Attribute> holding;
- const vector<saml2::Attribute*>& attrs = container->getAttributes();
- for (vector<saml2::Attribute*>::const_iterator attr = attrs.begin(); attr != attrs.end(); ++attr) {
- try {
- extractAttributes(application, nullptr, relyingParty, *(*attr), holding);
- }
- catch (...) {
- if (useCache)
- m_attrLock->unlock();
- for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
- throw;
- }
- }
+ // Extract attributes into holding area with no asserting party set.
+ static void (XMLExtractorImpl::* extractV2Attr)(
+ const Application&, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&
+ ) const = &XMLExtractorImpl::extractAttributes;
+ for_each(
+ make_indirect_iterator(container->getAttributes().begin()), make_indirect_iterator(container->getAttributes().end()),
+ boost::bind(extractV2Attr, this, boost::ref(application), nullptr, relyingParty, _1, boost::ref(holding))
+ );
if (entityID && m_entityAssertions) {
const vector<saml2::Assertion*>& asserts = container->getAssertions();
- for (vector<saml2::Assertion*>::const_iterator assert = asserts.begin(); assert != asserts.end(); ++assert) {
- if (!(*assert)->getSignature()) {
+ for (indirect_iterator<vector<saml2::Assertion*>::const_iterator> assert = make_indirect_iterator(asserts.begin());
+ assert != make_indirect_iterator(asserts.end()); ++assert) {
+ if (!(assert->getSignature())) {
if (m_log.isDebugEnabled()) {
auto_ptr_char eid(entityID);
m_log.debug("skipping unsigned assertion in metadata extension for entity (%s)", eid.get());
}
continue;
}
- else if ((*assert)->getAttributeStatements().empty()) {
+ else if (assert->getAttributeStatements().empty()) {
if (m_log.isDebugEnabled()) {
auto_ptr_char eid(entityID);
m_log.debug("skipping assertion with no AttributeStatement in metadata extension for entity (%s)", eid.get());
}
else {
// Check subject.
- const NameID* subject = (*assert)->getSubject() ? (*assert)->getSubject()->getNameID() : nullptr;
+ const NameID* subject = assert->getSubject() ? assert->getSubject()->getNameID() : nullptr;
if (!subject ||
!XMLString::equals(subject->getFormat(), NameID::ENTITY) ||
!XMLString::equals(subject->getName(), entityID)) {
}
}
- // Use a private holding area for filtering purposes.
- vector<Attribute*> holding2;
-
try {
// Set up and evaluate a policy for an AA asserting attributes to us.
shibsp::SecurityPolicy policy(application, &AttributeAuthorityDescriptor::ELEMENT_QNAME, false, m_policyId.c_str());
- Locker locker(m_metadata);
+ Locker locker(m_metadata.get());
if (m_metadata)
- policy.setMetadataProvider(m_metadata);
+ policy.setMetadataProvider(m_metadata.get());
if (m_trust)
- policy.setTrustEngine(m_trust);
+ policy.setTrustEngine(m_trust.get());
// Populate recipient as audience.
- const XMLCh* issuer = (*assert)->getIssuer() ? (*assert)->getIssuer()->getName() : nullptr;
+ const XMLCh* issuer = assert->getIssuer() ? assert->getIssuer()->getName() : nullptr;
policy.getAudiences().push_back(application.getRelyingParty(issuer)->getXMLString("entityID").second);
// Extract assertion information for policy.
- policy.setMessageID((*assert)->getID());
- policy.setIssueInstant((*assert)->getIssueInstantEpoch());
- policy.setIssuer((*assert)->getIssuer());
+ policy.setMessageID(assert->getID());
+ policy.setIssueInstant(assert->getIssueInstantEpoch());
+ policy.setIssuer(assert->getIssuer());
// Look up metadata for issuer.
if (policy.getIssuer() && policy.getMetadataProvider()) {
}
// Authenticate the assertion. We have to clone and marshall it to establish the signature for verification.
- auto_ptr<saml2::Assertion> tokencopy((*assert)->cloneAssertion());
+ scoped_ptr<saml2::Assertion> tokencopy(assert->cloneAssertion());
tokencopy->marshall();
policy.evaluate(*tokencopy);
if (!policy.isAuthenticated()) {
policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : nullptr;
auto_ptr_char inlineAssertingParty(inlineEntity ? inlineEntity->getEntityID() : nullptr);
relyingParty = application.getRelyingParty(inlineEntity)->getString("entityID").second;
+
+ // Use a private holding area for filtering purposes.
+ ptr_vector<Attribute> holding2;
const vector<saml2::Attribute*>& attrs2 =
const_cast<const saml2::AttributeStatement*>(tokencopy->getAttributeStatements().front())->getAttributes();
- for (vector<saml2::Attribute*>::const_iterator a = attrs2.begin(); a!=attrs2.end(); ++a)
- extractAttributes(application, inlineAssertingParty.get(), relyingParty, *(*a), holding2);
+ for_each(
+ make_indirect_iterator(attrs2.begin()), make_indirect_iterator(attrs2.end()),
+ boost::bind(extractV2Attr, this, boost::ref(application), inlineAssertingParty.get(), relyingParty, _1, boost::ref(holding2))
+ );
// Now we locally filter the attributes so that the actual issuer can be properly set.
// If we relied on outside filtering, the attributes couldn't be distinguished from the
// ones that come from the user's IdP.
if (m_filter && !holding2.empty()) {
- BasicFilteringContext fc(application, holding2, policy.getIssuerMetadata());
- Locker filtlocker(m_filter);
+
+ // The filter API uses an unsafe container, so we have to transfer everything into one and back.
+ vector<Attribute*> unsafe_holding2;
+
+ // Use a local exception context since the container is unsafe.
try {
- m_filter->filterAttributes(fc, holding2);
+ while (!holding2.empty()) {
+ ptr_vector<Attribute>::auto_type ptr = holding2.pop_back();
+ unsafe_holding2.push_back(ptr.get());
+ ptr.release();
+ }
+ BasicFilteringContext fc(application, unsafe_holding2, policy.getIssuerMetadata());
+ Locker filtlocker(m_filter.get());
+ m_filter->filterAttributes(fc, unsafe_holding2);
+
+ // Transfer back to safe container
+ while (!unsafe_holding2.empty()) {
+ auto_ptr<Attribute> ptr(unsafe_holding2.back());
+ unsafe_holding2.pop_back();
+ holding2.push_back(ptr);
+ }
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("caught exception filtering attributes: %s", ex.what());
m_log.error("dumping extracted attributes due to filtering exception");
- for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
- holding2.clear();
+ for_each(unsafe_holding2.begin(), unsafe_holding2.end(), xmltooling::cleanup<Attribute>());
+ holding2.clear(); // in case the exception was during transfer between containers
}
}
if (!holding2.empty()) {
- // Copy them over to the main holding tank.
- holding.insert(holding.end(), holding2.begin(), holding2.end());
+ // Copy them over to the main holding tank, which transfers ownership.
+ holding.transfer(holding.end(), holding2);
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
// Known exceptions are handled gracefully by skipping the assertion.
if (m_log.isDebugEnabled()) {
- auto_ptr_char tempid((*assert)->getID());
+ auto_ptr_char tempid(assert->getID());
auto_ptr_char eid(entityID);
m_log.debug(
"exception authenticating assertion (%s) in metadata extension for entity (%s): %s",
ex.what()
);
}
- for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
continue;
}
- catch (...) {
- // Unknown exceptions are fatal.
- if (useCache)
- m_attrLock->unlock();
- for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
- for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
- throw;
- }
}
}
if (!holding.empty()) {
if (useCache) {
+ locker.release(); // unguard to upgrade lock
m_attrLock->unlock();
m_attrLock->wrlock();
- SharedLock locker(m_attrLock, false); // pop the lock when we're done
+ SharedLock locker2(m_attrLock, false); // pop the lock when we're done
if (cacheEntry->second.count(container) == 0) {
- for (vector<Attribute*>::const_iterator held = holding.begin(); held != holding.end(); ++held)
- cacheEntry->second[container].push_back((*held)->marshall());
+ static void (vector<DDF>::* push_back)(DDF const &) = &vector<DDF>::push_back;
+ vector<DDF>& marshalled = cacheEntry->second[container];
+ for_each(
+ holding.begin(), holding.end(),
+ boost::bind(push_back, boost::ref(marshalled), boost::bind(&Attribute::marshall, _1))
+ );
}
}
- attributes.insert(attributes.end(), holding.begin(), holding.end());
- }
- else if (useCache) {
- m_attrLock->unlock();
+
+ // Copy them to the output parameter, which transfers ownership.
+ attributes.transfer(attributes.end(), holding);
}
+ // If the lock is held, it's guarded.
+
break; // only process a single extension element
}
}
if (!m_impl)
return;
+ ptr_vector<Attribute> holding;
+ extractAttributes(application, issuer, xmlObject, holding);
+
+ // Transfer ownership from the ptr_vector to the unsafe vector for API compatibility.
+ // Any throws should leave each container in a consistent state. The holding container
+ // is freed by us, and the result container by the caller.
+ while (!holding.empty()) {
+ ptr_vector<Attribute>::auto_type ptr = holding.pop_back();
+ attributes.push_back(ptr.get());
+ ptr.release();
+ }
+}
+
+void XMLExtractor::extractAttributes(
+ const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, ptr_vector<Attribute>& attributes
+ ) const
+{
+ static void (XMLExtractor::* extractEncrypted)(
+ const Application&, const RoleDescriptor*, const XMLObject&, ptr_vector<Attribute>&
+ ) const = &XMLExtractor::extractAttributes;
+ static void (XMLExtractorImpl::* extractV1Statement)(
+ const Application&, const char*, const char*, const saml1::AttributeStatement&, ptr_vector<Attribute>&
+ ) const = &XMLExtractorImpl::extractAttributes;
+
const EntityDescriptor* entity = issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent()) : nullptr;
const char* relyingParty = application.getRelyingParty(entity)->getString("entityID").second;
m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *statement2, attributes);
// Handle EncryptedAttributes inline so we have access to the role descriptor.
const vector<saml2::EncryptedAttribute*>& encattrs = statement2->getEncryptedAttributes();
- for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
- extractAttributes(application, issuer, *(*ea), attributes);
+ for_each(
+ make_indirect_iterator(encattrs.begin()), make_indirect_iterator(encattrs.end()),
+ boost::bind(extractEncrypted, this, boost::ref(application), issuer, _1, boost::ref(attributes))
+ );
return;
}
if (token2) {
auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();
- for (vector<saml2::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
- m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*s), attributes);
+ for (indirect_iterator<vector<saml2::AttributeStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
+ s != make_indirect_iterator(statements.end()); ++s) {
+ m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *s, attributes);
// Handle EncryptedAttributes inline so we have access to the role descriptor.
- const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement*>(*s)->getEncryptedAttributes();
- for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
- extractAttributes(application, issuer, *(*ea), attributes);
+ const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement&>(*s).getEncryptedAttributes();
+ for_each(
+ make_indirect_iterator(encattrs.begin()), make_indirect_iterator(encattrs.end()),
+ boost::bind(extractEncrypted, this, boost::ref(application), issuer, _1, boost::ref(attributes))
+ );
}
return;
}
if (token1) {
auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();
- for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s)
- m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*s), attributes);
+ for_each(make_indirect_iterator(statements.begin()), make_indirect_iterator(statements.end()),
+ boost::bind(extractV1Statement, m_impl.get(), boost::ref(application), assertingParty.get(), relyingParty, _1, boost::ref(attributes))
+ );
return;
}
Locker credlocker(cr);
if (issuer) {
MetadataCredentialCriteria mcc(*issuer);
- auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));
+ scoped_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));
if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted Attribute: " << *(decrypted.get()) << logging::eol;
- return extractAttributes(application, issuer, *(decrypted.get()), attributes);
+ m_log.debugStream() << "decrypted Attribute: " << *decrypted << logging::eol;
+ return extractAttributes(application, issuer, *decrypted, attributes);
}
else {
- auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));
+ scoped_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));
if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted Attribute: " << *(decrypted.get()) << logging::eol;
- return extractAttributes(application, issuer, *(decrypted.get()), attributes);
+ m_log.debugStream() << "decrypted Attribute: " << *decrypted << logging::eol;
+ return extractAttributes(application, issuer, *decrypted, attributes);
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("caught exception decrypting Attribute: %s", ex.what());
return;
}
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
- XMLExtractorImpl* impl = new XMLExtractorImpl(raw.second, m_log);
+ scoped_ptr<XMLExtractorImpl> impl(new XMLExtractorImpl(raw.second, m_log));
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_impl;
- m_impl = impl;
+ m_impl.swap(impl);
return make_pair(false,(DOMElement*)nullptr);
}
#include "util/SPConstants.h"
#include <map>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include <xmltooling/io/HTTPResponse.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ReloadableXMLFile.h>
using shibspconstants::SHIB2SPPROTOCOLS_NS;
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
-
static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
static const XMLCh Binding[] = UNICODE_LITERAL_7(B,i,n,d,i,n,g);
static const XMLCh Initiator[] = UNICODE_LITERAL_9(I,n,i,t,i,a,t,o,r);
public:
XMLProtocolProviderImpl(const DOMElement* e, Category& log);
~XMLProtocolProviderImpl() {
- for (protmap_t::iterator i = m_map.begin(); i != m_map.end(); ++i) {
- delete i->second.first;
- for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<PropertySet>());
- }
if (m_document)
m_document->release();
}
private:
DOMDocument* m_document;
// Map of protocol/service pair to an Initiator propset plus an array of Binding propsets.
- typedef map< pair<string,string>, pair< PropertySet*,vector<const PropertySet*> > > protmap_t;
+ typedef map< pair<string,string>, pair< const PropertySet*,vector<const PropertySet*> > > protmap_t;
protmap_t m_map;
+ vector< boost::shared_ptr<PropertySet> > m_propsetJanitor; // needed to maintain vector API
friend class SHIBSP_DLLLOCAL XMLProtocolProvider;
};
{
public:
XMLProtocolProvider(const DOMElement* e)
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".ProtocolProvider.XML")), m_impl(nullptr) {
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".ProtocolProvider.XML")) {
background_load(); // guarantees an exception or the policy is loaded
}
~XMLProtocolProvider() {
shutdown();
- delete m_impl;
}
const PropertySet* getInitiator(const char* protocol, const char* service) const {
private:
static vector<const PropertySet*> m_noBindings;
- XMLProtocolProviderImpl* m_impl;
+ scoped_ptr<XMLProtocolProviderImpl> m_impl;
};
#if defined (_MSC_VER)
#ifdef _DEBUG
xmltooling::NDC ndc("XMLProtocolProviderImpl");
#endif
- //typedef map< pair<string,string>, pair< PropertySet*,vector<const PropertySet*> > > protmap_t;
-
if (!XMLHelper::isNodeNamed(e, SHIB2SPPROTOCOLS_NS, Protocols))
throw ConfigurationException("XML ProtocolProvider requires prot:Protocols at root of configuration.");
while (svc) {
string svcid = XMLHelper::getAttrString(svc, nullptr, _id);
if (!svcid.empty() && m_map.count(make_pair(id,svcid)) == 0) {
- pair< PropertySet*,vector<const PropertySet*> >& entry = m_map[make_pair(id,svcid)];
+ pair< const PropertySet*,vector<const PropertySet*> >& entry = m_map[make_pair(id,svcid)];
// Wrap the Initiator in a propset, if any.
const DOMElement* child = XMLHelper::getFirstChildElement(svc, SHIB2SPPROTOCOLS_NS, Initiator);
if (child) {
- DOMPropertySet* initprop = new DOMPropertySet();
- entry.first = initprop;
+ boost::shared_ptr<DOMPropertySet> initprop(new DOMPropertySet());
initprop->load(child, nullptr, this);
+ m_propsetJanitor.push_back(initprop);
+ entry.first = initprop.get();
}
else {
entry.first = nullptr;
// Walk the Bindings.
child = XMLHelper::getFirstChildElement(svc, SHIB2SPPROTOCOLS_NS, Binding);
while (child) {
- DOMPropertySet* bindprop = new DOMPropertySet();
- entry.second.push_back(bindprop);
+ boost::shared_ptr<DOMPropertySet> bindprop(new DOMPropertySet());
bindprop->load(child, nullptr, this);
+ m_propsetJanitor.push_back(bindprop);
+ entry.second.push_back(bindprop.get());
child = XMLHelper::getNextSiblingElement(child, SHIB2SPPROTOCOLS_NS, Binding);
}
}
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
- XMLProtocolProviderImpl* impl = new XMLProtocolProviderImpl(raw.second, m_log);
+ scoped_ptr<XMLProtocolProviderImpl> impl(new XMLProtocolProviderImpl(raw.second, m_log));
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_impl;
- m_impl = impl;
+ m_impl.swap(impl);
return make_pair(false,(DOMElement*)nullptr);
return load(true);
throw;
}
- catch (exception&) {
+ catch (std::exception&) {
if (!m_loaded && !m_backing.empty())
return load(true);
throw;
#include "SPRequest.h"
#include <algorithm>
+#include <boost/ptr_container/ptr_vector.hpp>
#include <xmltooling/unicode.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
public:
ChainingAccessControl(const DOMElement* e);
- ~ChainingAccessControl() {
- for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
- }
+ ~ChainingAccessControl() {}
Lockable* lock() {
- for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));
+ for_each(m_ac.begin(), m_ac.end(), mem_fun_ref<Lockable*,Lockable>(&Lockable::lock));
return this;
}
void unlock() {
- for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));
+ for_each(m_ac.begin(), m_ac.end(), mem_fun_ref<void,Lockable>(&Lockable::unlock));
}
aclresult_t authorized(const SPRequest& request, const Session* session) const;
private:
enum operator_t { OP_AND, OP_OR } m_op;
- vector<AccessControl*> m_ac;
+ ptr_vector<AccessControl> m_ac;
};
AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)
{
const XMLCh* op = e ? e->getAttributeNS(nullptr, _operator) : nullptr;
if (XMLString::equals(op, AND))
- m_op=OP_AND;
+ m_op = OP_AND;
else if (XMLString::equals(op, OR))
- m_op=OP_OR;
+ m_op = OP_OR;
else
throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");
- try {
- e = XMLHelper::getFirstChildElement(e, _AccessControl);
- while (e) {
- string t(XMLHelper::getAttrString(e, nullptr, _type));
- if (!t.empty()) {
- Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", t.c_str());
- m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), e));
- }
- e = XMLHelper::getNextSiblingElement(e, _AccessControl);
+ e = XMLHelper::getFirstChildElement(e, _AccessControl);
+ while (e) {
+ string t(XMLHelper::getAttrString(e, nullptr, _type));
+ if (!t.empty()) {
+ Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", t.c_str());
+ m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), e));
}
- }
- catch (exception&) {
- for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
- throw;
+ e = XMLHelper::getNextSiblingElement(e, _AccessControl);
}
if (m_ac.empty())
throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
switch (m_op) {
case OP_AND:
{
- for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
- if ((*i)->authorized(request, session) != shib_acl_true) {
+ for (ptr_vector<AccessControl>::const_iterator i = m_ac.begin(); i != m_ac.end(); ++i) {
+ if (i->authorized(request, session) != shib_acl_true) {
request.log(SPRequest::SPDebug, "embedded AccessControl plugin unsuccessful, denying access");
return shib_acl_false;
}
case OP_OR:
{
- for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
- if ((*i)->authorized(request,session) == shib_acl_true)
+ for (ptr_vector<AccessControl>::const_iterator i = m_ac.begin(); i != m_ac.end(); ++i) {
+ if (i->authorized(request,session) == shib_acl_true)
return shib_acl_true;
}
request.log(SPRequest::SPDebug, "all embedded AccessControl plugins unsuccessful, denying access");
#include "util/SPConstants.h"
#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
#include <xmltooling/io/HTTPRequest.h>
#include <xmltooling/io/HTTPResponse.h>
#include <xmltooling/util/DateTime.h>
using namespace shibsp;
using namespace opensaml;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
string m_inboundHeader,m_outboundHeader;
// inproc means we buffer sessions in memory
- RWLock* m_lock;
+ scoped_ptr<RWLock> m_lock;
map<string,StoredSession*> m_hashtable;
// management of buffered sessions
- void dormant(const char* key);
- static void* cleanup_fn(void*);
+ void dormant(const char* key);
+ static void* cleanup_fn(void*);
bool shutdown;
- CondWait* shutdown_wait;
- Thread* cleanup_thread;
+ scoped_ptr<CondWait> shutdown_wait;
+ scoped_ptr<Thread> cleanup_thread;
};
class StoredSession : public virtual Session
{
public:
- StoredSession(SSCache* cache, DDF& obj) : m_obj(obj),
-#ifndef SHIBSP_LITE
- m_nameid(nullptr),
-#endif
- m_cache(cache), m_expires(0), m_lastAccess(time(nullptr)), m_lock(nullptr) {
+ StoredSession(SSCache* cache, DDF& obj) : m_obj(obj), m_cache(cache), m_expires(0), m_lastAccess(time(nullptr)) {
auto_ptr_XMLCh exp(m_obj["expires"].string());
if (exp.get()) {
DateTime iso(exp.get());
istringstream instr(nameid);
DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(instr);
XercesJanitor<DOMDocument> janitor(doc);
- auto_ptr<saml2::NameID> n(saml2::NameIDBuilder::buildNameID());
- n->unmarshall(doc->getDocumentElement(), true);
+ m_nameid.reset(saml2::NameIDBuilder::buildNameID());
+ m_nameid->unmarshall(doc->getDocumentElement(), true);
janitor.release();
- m_nameid = n.release();
}
#endif
if (cache->inproc)
- m_lock = Mutex::create();
+ m_lock.reset(Mutex::create());
}
~StoredSession() {
- delete m_lock;
m_obj.destroy();
for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<Attribute>());
-#ifndef SHIBSP_LITE
- delete m_nameid;
- for_each(m_tokens.begin(), m_tokens.end(), cleanup_pair<string,Assertion>());
-#endif
}
Lockable* lock() {
- if (m_lock)
+ if (m_lock.get())
m_lock->lock();
return this;
}
void unlock() {
- if (m_lock)
+ if (m_lock.get())
m_lock->unlock();
else
delete this;
}
#ifndef SHIBSP_LITE
const saml2::NameID* getNameID() const {
- return m_nameid;
+ return m_nameid.get();
}
#endif
const char* getSessionIndex() const {
DDF m_obj;
#ifndef SHIBSP_LITE
- saml2::NameID* m_nameid;
- mutable map<string,Assertion*> m_tokens;
+ scoped_ptr<saml2::NameID> m_nameid;
+ mutable map<string,boost::shared_ptr<Assertion>> m_tokens;
#endif
mutable vector<Attribute*> m_attributes;
mutable multimap<string,const Attribute*> m_attributeIndex;
SSCache* m_cache;
time_t m_expires,m_lastAccess;
- Mutex* m_lock;
+ scoped_ptr<Mutex> m_lock;
};
SessionCache* SHIBSP_DLLLOCAL StorageServiceCacheFactory(const DOMElement* const & e)
try {
m_cache->m_storage->updateContext(getID(), now + cacheTimeout);
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_cache->m_log.error("failed to update session expiration: %s", ex.what());
}
try {
ver = m_cache->m_storage->updateText(getID(), "session", record.c_str(), 0, m_obj["version"].integer()-1);
}
- catch (exception&) {
+ catch (std::exception&) {
// Roll back modification to record.
m_obj["version"].integer(m_obj["version"].integer()-1);
vector<Attribute*>::size_type count = attributes.size();
if (!m_cache->m_storage)
throw ConfigurationException("Assertion retrieval requires a StorageService.");
- map<string,Assertion*>::const_iterator i = m_tokens.find(id);
- if (i!=m_tokens.end())
- return i->second;
+ map< string,boost::shared_ptr<Assertion> >::const_iterator i = m_tokens.find(id);
+ if (i != m_tokens.end())
+ return i->second.get();
string tokenstr;
if (!m_cache->m_storage->readText(getID(), id, &tokenstr, nullptr))
istringstream instr(tokenstr);
DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(instr);
XercesJanitor<DOMDocument> janitor(doc);
- auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
+ boost::shared_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
janitor.release();
-
- Assertion* token = dynamic_cast<Assertion*>(xmlObject.get());
+
+ boost::shared_ptr<Assertion> token = dynamic_pointer_cast<Assertion,XMLObject>(xmlObject);
if (!token)
throw FatalProfileException("Request for cached assertion returned an unknown object type.");
- // Transfer ownership to us.
- xmlObject.release();
- m_tokens[id]=token;
- return token;
+ m_tokens[id] = token;
+ return token.get();
}
void StoredSession::addAssertion(Assertion* assertion)
try {
ver = m_cache->m_storage->updateText(getID(), "session", record.c_str(), 0, m_obj["version"].integer()-1);
}
- catch (exception&) {
+ catch (std::exception&) {
token.destroy();
m_obj["version"].integer(m_obj["version"].integer()-1);
m_cache->m_storage->deleteText(getID(), id.get());
#ifndef SHIBSP_LITE
m_storage(nullptr), m_storage_lite(nullptr), m_cacheAssertions(true),
#endif
- m_root(e), m_inprocTimeout(900), m_cacheTimeout(0), m_cacheAllowance(0),
- m_lock(nullptr), shutdown(false), shutdown_wait(nullptr), cleanup_thread(nullptr)
+ m_root(e), m_inprocTimeout(900), m_cacheTimeout(0), m_cacheAllowance(0), shutdown(false)
{
SPConfig& conf = SPConfig::getConfig();
inproc = conf.isEnabled(SPConfig::InProcess);
if (inproc) {
if (!conf.isEnabled(SPConfig::OutOfProcess) && !listener)
throw ConfigurationException("SessionCache requires a ListenerService, but none available.");
- m_lock = RWLock::create();
- shutdown_wait = CondWait::create();
- cleanup_thread = Thread::create(&cleanup_fn, this);
+ m_lock.reset(RWLock::create());
+ shutdown_wait.reset(CondWait::create());
+ cleanup_thread.reset(Thread::create(&cleanup_fn, this));
}
#ifndef SHIBSP_LITE
else {
if (inproc) {
// Shut down the cleanup thread and let it know...
shutdown = true;
- shutdown_wait->signal();
- cleanup_thread->join(nullptr);
+ if (shutdown_wait.get())
+ shutdown_wait->signal();
+ if (cleanup_thread.get())
+ cleanup_thread->join(nullptr);
for_each(m_hashtable.begin(),m_hashtable.end(),cleanup_pair<string,StoredSession>());
- delete m_lock;
-
- delete cleanup_thread;
- delete shutdown_wait;
}
#ifndef SHIBSP_LITE
else {
if (nameid)
insert(key.get(), expires, name.get(), index.get());
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error storing back mapping of NameID for logout: %s", ex.what());
}
throw IOException("Duplicate assertion ID ($1)", params(1, tokenid.get()));
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error storing assertion along with session: %s", ex.what());
}
}
}
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error while matching session: %s", ex.what());
}
return false;
try {
session = find(app, key.string());
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error locating session (%s): %s", key.string(), ex.what());
}
m_log.warn("logout mapping record changed behind us, leaving it alone");
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("error updating logout mapping record: %s", ex.what());
}
m_log.warn("unable to audit event, log event object was of an incorrect type");
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.warn("exception auditing event: %s", ex.what());
}
return nullptr;
if (timeout && *timeout > 0 && now - lastAccess >= *timeout) {
m_log.info("session timed out (ID: %s)", key);
- auto_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
+ scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
if (logout_event.get()) {
logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_INVALID;
logout_event->m_sessions.push_back(key);
try {
m_storage->updateContext(key, now + cacheTimeout);
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("failed to update session expiration: %s", ex.what());
}
}
}
catch (...) {
#ifndef SHIBSP_LITE
- auto_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
+ scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
if (logout_event.get()) {
logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_INVALID;
logout_event->m_session = session;
response->setCookie(shib_cookie.first.c_str(), exp.c_str());
}
}
- catch (exception&) {
+ catch (std::exception&) {
HTTPResponse* response = dynamic_cast<HTTPResponse*>(&request);
if (response) {
if (!m_outboundHeader.empty())
Thread::mask_all_signals();
#endif
- auto_ptr<Mutex> mutex(Mutex::create());
+ scoped_ptr<Mutex> mutex(Mutex::create());
// Load our configuration details...
static const XMLCh cleanupInterval[] = UNICODE_LITERAL_15(c,l,e,a,n,u,p,I,n,t,e,r,v,a,l);
pcache->m_log.debug("cleanup thread running");
pcache->m_lock->rdlock();
- for (map<string,StoredSession*>::const_iterator i=pcache->m_hashtable.begin(); i!=pcache->m_hashtable.end(); ++i) {
+ for (map<string,StoredSession*>::const_iterator i = pcache->m_hashtable.begin(); i != pcache->m_hashtable.end(); ++i) {
// If the last access was BEFORE the stale timeout...
i->second->lock();
time_t last=i->second->getLastAccess();
pcache->m_log.info("purging %d old sessions", stale_keys.size());
// Pass 2: walk through the list of stale entries and remove them from the cache
- for (vector<string>::const_iterator j = stale_keys.begin(); j != stale_keys.end(); ++j)
- pcache->dormant(j->c_str());
+ for_each(stale_keys.begin(), stale_keys.end(), boost::bind(&SSCache::dormant, pcache, boost::bind(&string::c_str, _1)));
}
pcache->m_log.debug("cleanup thread completed");
if (timeout > 0 && now - lastAccess >= timeout) {
m_log.info("session timed out (ID: %s)", key);
- auto_ptr<LogoutEvent> logout_event(newLogoutEvent(*app));
+ scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(*app));
if (logout_event.get()) {
logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_INVALID;
logout_event->m_sessions.push_back(key);
try {
m_storage->updateContext(key, now + cacheTimeout);
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("failed to update session expiration: %s", ex.what());
}
}
try {
m_storage->updateContext(key, now + cacheTimeout);
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
m_log.error("failed to update session expiration: %s", ex.what());
}
#include "attribute/Attribute.h"
#include <algorithm>
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
#include <xmltooling/unicode.h>
#include <xmltooling/util/ReloadableXMLFile.h>
#include <xmltooling/util/Threads.h>
using namespace shibsp;
using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
using namespace std;
namespace shibsp {
private:
string m_alias;
- vector <string> m_vals;
+ set <string> m_vals;
};
class RuleRegex : public AccessControl
{
public:
RuleRegex(const DOMElement* e);
- ~RuleRegex() {
- delete m_re;
- }
+ ~RuleRegex() {}
Lockable* lock() {return this;}
void unlock() {}
private:
string m_alias;
auto_arrayptr<char> m_exp;
- RegularExpression* m_re;
+ scoped_ptr<RegularExpression> m_re;
};
class Operator : public AccessControl
{
public:
Operator(const DOMElement* e);
- ~Operator();
+ ~Operator() {}
Lockable* lock() {return this;}
void unlock() {}
private:
enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
- vector<AccessControl*> m_operands;
+ ptr_vector<AccessControl> m_operands;
};
#if defined (_MSC_VER)
{
public:
XMLAccessControl(const DOMElement* e)
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(nullptr) {
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")) {
background_load(); // guarantees an exception or the policy is loaded
}
~XMLAccessControl() {
shutdown();
- delete m_rootAuthz;
}
aclresult_t authorized(const SPRequest& request, const Session* session) const;
pair<bool,DOMElement*> background_load();
private:
- AccessControl* m_rootAuthz;
+ scoped_ptr<AccessControl> m_rootAuthz;
};
#if defined (_MSC_VER)
bool listflag = XMLHelper::getAttrBool(e, true, _list);
if (!listflag) {
if (*vals.get())
- m_vals.push_back(vals.get());
+ m_vals.insert(vals.get());
return;
}
-#ifdef HAVE_STRTOK_R
- char* pos=nullptr;
- const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);
-#else
- const char* token=strtok(const_cast<char*>(vals.get())," ");
-#endif
- while (token) {
- m_vals.push_back(token);
-#ifdef HAVE_STRTOK_R
- token=strtok_r(nullptr," ",&pos);
-#else
- token=strtok(nullptr," ");
-#endif
- }
+ string temp(vals.get());
+ split(m_vals, temp, boost::is_space(), algorithm::token_compress_on);
}
AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const
return shib_acl_false;
}
if (m_alias == "user") {
- for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
- if (*i == request.getRemoteUser()) {
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");
- return shib_acl_true;
- }
+ if (m_vals.find(request.getRemoteUser()) != m_vals.end()) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + request.getRemoteUser() + "), authz granted");
+ return shib_acl_true;
}
return shib_acl_false;
}
else if (m_alias == "authnContextClassRef") {
const char* ref = session->getAuthnContextClassRef();
- for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
- if (!strcmp(i->c_str(),ref)) {
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");
- return shib_acl_true;
- }
+ if (ref && m_vals.find(ref) != m_vals.end()) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + ref + "), authz granted");
+ return shib_acl_true;
}
return shib_acl_false;
}
else if (m_alias == "authnContextDeclRef") {
const char* ref = session->getAuthnContextDeclRef();
- for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
- if (!strcmp(i->c_str(),ref)) {
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");
- return shib_acl_true;
- }
+ if (ref && m_vals.find(ref) != m_vals.end()) {
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + ref + "), authz granted");
+ return shib_acl_true;
}
return shib_acl_false;
}
// Now we have to intersect the attribute's values against the rule's list.
const vector<string>& vals = attrs.first->second->getSerializedValues();
- for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
- for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+ for (set<string>::const_iterator i = m_vals.begin(); i != m_vals.end(); ++i) {
+ for (vector<string>::const_iterator j = vals.begin(); j != vals.end(); ++j) {
if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {
request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");
return shib_acl_true;
bool ignore = XMLHelper::getAttrBool(e, false, ignoreCase);
try {
- m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
+ m_re.reset(new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)));
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
for (; attrs.first != attrs.second; ++attrs.first) {
// Now we have to intersect the attribute's values against the regular expression.
const vector<string>& vals = attrs.first->second->getSerializedValues();
- for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+ for (vector<string>::const_iterator j = vals.begin(); j != vals.end(); ++j) {
if (m_re->matches(j->c_str())) {
request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");
return shib_acl_true;
else
throw ConfigurationException("Unrecognized operator in access control rule");
- try {
- e=XMLHelper::getFirstChildElement(e);
+ e=XMLHelper::getFirstChildElement(e);
+ if (XMLString::equals(e->getLocalName(),_Rule))
+ m_operands.push_back(new Rule(e));
+ else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+ m_operands.push_back(new RuleRegex(e));
+ else
+ m_operands.push_back(new Operator(e));
+
+ if (m_op==OP_NOT)
+ return;
+
+ e=XMLHelper::getNextSiblingElement(e);
+ while (e) {
if (XMLString::equals(e->getLocalName(),_Rule))
m_operands.push_back(new Rule(e));
else if (XMLString::equals(e->getLocalName(),_RuleRegex))
m_operands.push_back(new RuleRegex(e));
else
m_operands.push_back(new Operator(e));
-
- if (m_op==OP_NOT)
- return;
-
e=XMLHelper::getNextSiblingElement(e);
- while (e) {
- if (XMLString::equals(e->getLocalName(),_Rule))
- m_operands.push_back(new Rule(e));
- else if (XMLString::equals(e->getLocalName(),_RuleRegex))
- m_operands.push_back(new RuleRegex(e));
- else
- m_operands.push_back(new Operator(e));
- e=XMLHelper::getNextSiblingElement(e);
- }
- }
- catch (exception&) {
- for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
- throw;
}
}
-Operator::~Operator()
-{
- for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
-}
-
AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const
{
switch (m_op) {
case OP_NOT:
- switch (m_operands.front()->authorized(request,session)) {
+ switch (m_operands.front().authorized(request,session)) {
case shib_acl_true:
return shib_acl_false;
case shib_acl_false:
case OP_AND:
{
- for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
- if ((*i)->authorized(request,session) != shib_acl_true)
- return shib_acl_false;
- }
- return shib_acl_true;
+ // Look for a rule that returns non-true.
+ ptr_vector<AccessControl>::const_iterator i = find_if(
+ m_operands.begin(), m_operands.end(),
+ lambda::bind(&AccessControl::authorized, _1, boost::ref(request), session) != shib_acl_true
+ );
+ return (i != m_operands.end()) ? shib_acl_false : shib_acl_true;
}
case OP_OR:
{
- for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
- if ((*i)->authorized(request,session) == shib_acl_true)
- return shib_acl_true;
- }
- return shib_acl_false;
+ // Look for a rule that returns true.
+ ptr_vector<AccessControl>::const_iterator i = find_if(
+ m_operands.begin(), m_operands.end(),
+ lambda::bind(&AccessControl::authorized, _1, boost::ref(request), session) == shib_acl_true
+ );
+ return (i != m_operands.end()) ? shib_acl_true : shib_acl_false;
}
}
request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");
if (XMLString::equals(raw.second->getLocalName(),_AccessControl))
raw.second = XMLHelper::getFirstChildElement(raw.second);
- AccessControl* authz;
+ scoped_ptr<AccessControl> authz;
if (XMLString::equals(raw.second->getLocalName(),_Rule))
- authz=new Rule(raw.second);
+ authz.reset(new Rule(raw.second));
else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))
- authz=new RuleRegex(raw.second);
+ authz.reset(new RuleRegex(raw.second));
else
- authz=new Operator(raw.second);
+ authz.reset(new Operator(raw.second));
// Perform the swap inside a lock.
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_rootAuthz;
- m_rootAuthz = authz;
+ m_rootAuthz.swap(authz);
return make_pair(false,(DOMElement*)nullptr);
}
#include "util/SPConstants.h"
#include <algorithm>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/algorithm/string.hpp>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ReloadableXMLFile.h>
#include <xmltooling/util/Threads.h>
using shibspconstants::SHIB2SPCONFIG_NS;
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
class Override : public DOMPropertySet, public DOMNodeFilter
{
public:
- Override(bool unicodeAware=false) : m_unicodeAware(unicodeAware), m_acl(nullptr) {}
+ Override(bool unicodeAware=false) : m_unicodeAware(unicodeAware) {}
Override(bool unicodeAware, const DOMElement* e, Category& log, const Override* base=nullptr);
- ~Override();
+ ~Override() {}
// Provides filter to exclude special config elements.
#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
}
const Override* locate(const HTTPRequest& request) const;
- AccessControl* getAC() const { return (m_acl ? m_acl : (getParent() ? dynamic_cast<const Override*>(getParent())->getAC() : nullptr)); }
+ AccessControl* getAC() const { return (m_acl ? m_acl.get() : (getParent() ? dynamic_cast<const Override*>(getParent())->getAC() : nullptr)); }
protected:
void loadACL(const DOMElement* e, Category& log);
bool m_unicodeAware;
- map<string,Override*> m_map;
- vector< pair<RegularExpression*,Override*> > m_regexps;
- vector< pair< pair<string,RegularExpression*>,Override*> > m_queries;
+ map< string,boost::shared_ptr<Override> > m_map;
+ vector< pair< boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > > m_regexps;
+ vector< tuple< string,boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > > m_queries;
private:
- AccessControl* m_acl;
+ scoped_ptr<AccessControl> m_acl;
};
class XMLRequestMapperImpl : public Override
const Override* findOverride(const char* vhost, const HTTPRequest& request) const;
private:
- map<string,Override*> m_extras;
DOMDocument* m_document;
};
class XMLRequestMapper : public RequestMapper, public ReloadableXMLFile
{
public:
- XMLRequestMapper(const DOMElement* e) : ReloadableXMLFile(e,Category::getInstance(SHIBSP_LOGCAT".RequestMapper")), m_impl(nullptr) {
+ XMLRequestMapper(const DOMElement* e) : ReloadableXMLFile(e,Category::getInstance(SHIBSP_LOGCAT".RequestMapper")) {
background_load();
}
~XMLRequestMapper() {
shutdown();
- delete m_impl;
}
Settings getSettings(const HTTPRequest& request) const;
pair<bool,DOMElement*> background_load();
private:
- XMLRequestMapperImpl* m_impl;
+ scoped_ptr<XMLRequestMapperImpl> m_impl;
};
#if defined (_MSC_VER)
void Override::loadACL(const DOMElement* e, Category& log)
{
try {
- const DOMElement* acl=XMLHelper::getFirstChildElement(e,htaccess);
+ const DOMElement* acl = XMLHelper::getFirstChildElement(e,htaccess);
if (acl) {
log.info("building Apache htaccess AccessControl provider...");
- m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(HT_ACCESS_CONTROL,acl);
+ m_acl.reset(SPConfig::getConfig().AccessControlManager.newPlugin(HT_ACCESS_CONTROL,acl));
}
else {
- acl=XMLHelper::getFirstChildElement(e,_AccessControl);
+ acl = XMLHelper::getFirstChildElement(e,_AccessControl);
if (acl) {
log.info("building XML-based AccessControl provider...");
- m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(XML_ACCESS_CONTROL,acl);
+ m_acl.reset(SPConfig::getConfig().AccessControlManager.newPlugin(XML_ACCESS_CONTROL,acl));
}
else {
- acl=XMLHelper::getFirstChildElement(e,AccessControlProvider);
+ acl = XMLHelper::getFirstChildElement(e,AccessControlProvider);
if (acl) {
string t(XMLHelper::getAttrString(acl, nullptr, _type));
if (!t.empty()) {
log.info("building AccessControl provider of type %s...", t.c_str());
- m_acl = SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acl);
+ m_acl.reset(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acl));
}
else {
throw ConfigurationException("<AccessControlProvider> missing type attribute.");
}
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.crit("exception building AccessControl provider: %s", ex.what());
- m_acl = new AccessControlDummy();
+ m_acl.reset(new AccessControlDummy());
}
}
Override::Override(bool unicodeAware, const DOMElement* e, Category& log, const Override* base)
- : m_unicodeAware(unicodeAware), m_acl(nullptr)
+ : m_unicodeAware(unicodeAware)
{
- try {
- // Load the property set.
- load(e,nullptr,this);
- setParent(base);
+ // Load the property set.
+ load(e, nullptr, this);
+ setParent(base);
- // Load any AccessControl provider.
- loadACL(e,log);
+ // Load any AccessControl provider.
+ loadACL(e, log);
- // Handle nested Paths.
- DOMElement* path = XMLHelper::getFirstChildElement(e,Path);
- for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Path)) {
- const XMLCh* n=path->getAttributeNS(nullptr,name);
+ // Handle nested Paths.
+ DOMElement* path = XMLHelper::getFirstChildElement(e, Path);
+ for (int i = 1; path; ++i, path = XMLHelper::getNextSiblingElement(path, Path)) {
+ const XMLCh* n = path->getAttributeNS(nullptr,name);
- // Skip any leading slashes.
- while (n && *n==chForwardSlash)
- n++;
+ // Skip any leading slashes.
+ while (n && *n == chForwardSlash)
+ n++;
- // Check for empty name.
- if (!n || !*n) {
- log.warn("skipping Path element (%d) with empty name attribute", i);
- continue;
- }
+ // Check for empty name.
+ if (!n || !*n) {
+ log.warn("skipping Path element (%d) with empty name attribute", i);
+ continue;
+ }
- // Check for an embedded slash.
- int slash=XMLString::indexOf(n,chForwardSlash);
- if (slash>0) {
- // Copy the first path segment.
- XMLCh* namebuf=new XMLCh[slash + 1];
- for (int pos=0; pos < slash; pos++)
- namebuf[pos]=n[pos];
- namebuf[slash]=chNull;
-
- // Move past the slash in the original pathname.
- n=n+slash+1;
-
- // Skip any leading slashes again.
- while (*n==chForwardSlash)
- n++;
-
- if (*n) {
- // Create a placeholder Path element for the first path segment and replant under it.
- DOMElement* newpath=path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,Path);
- newpath->setAttributeNS(nullptr,name,namebuf);
- path->setAttributeNS(nullptr,name,n);
- path->getParentNode()->replaceChild(newpath,path);
- newpath->appendChild(path);
-
- // Repoint our locals at the new parent.
- path=newpath;
- n=path->getAttributeNS(nullptr,name);
- }
- else {
- // All we had was a pathname with trailing slash(es), so just reset it without them.
- path->setAttributeNS(nullptr,name,namebuf);
- n=path->getAttributeNS(nullptr,name);
- }
- delete[] namebuf;
+ // Check for an embedded slash.
+ int slash = XMLString::indexOf(n, chForwardSlash);
+ if (slash > 0) {
+ // Copy the first path segment.
+ xstring namebuf;
+ for (int pos = 0; pos < slash; ++pos)
+ namebuf += n[pos];
+
+ // Move past the slash in the original pathname.
+ n = n + slash + 1;
+
+ // Skip any leading slashes again.
+ while (*n == chForwardSlash)
+ ++n;
+
+ if (*n) {
+ // Create a placeholder Path element for the first path segment and replant under it.
+ DOMElement* newpath = path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, Path);
+ newpath->setAttributeNS(nullptr, name, namebuf.c_str());
+ path->setAttributeNS(nullptr, name, n);
+ path->getParentNode()->replaceChild(newpath, path);
+ newpath->appendChild(path);
+
+ // Repoint our locals at the new parent.
+ path = newpath;
+ n = path->getAttributeNS(nullptr, name);
+ }
+ else {
+ // All we had was a pathname with trailing slash(es), so just reset it without them.
+ path->setAttributeNS(nullptr, name, namebuf.c_str());
+ n = path->getAttributeNS(nullptr, name);
}
+ }
- char* dup = nullptr;
- Override* o = new Override(m_unicodeAware, path, log, this);
+ char* dup = nullptr;
+ try {
+ boost::shared_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
if (m_unicodeAware) {
dup = toUTF8(o->getXMLString("name").second, true /* use malloc */);
}
*pch = tolower(*pch);
}
if (m_map.count(dup)) {
- log.warn("skipping duplicate Path element (%s)",dup);
- free(dup);
- delete o;
- continue;
+ log.warn("skipping duplicate Path element (%s)", dup);
+ }
+ else {
+ m_map[dup] = o;
+ log.debug("added Path mapping (%s)", dup);
}
- m_map[dup] = o;
- log.debug("added Path mapping (%s)", dup);
free(dup);
}
-
- if (!XMLString::equals(e->getLocalName(), PathRegex)) {
- // Handle nested PathRegexs.
- path = XMLHelper::getFirstChildElement(e,PathRegex);
- for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,PathRegex)) {
- const XMLCh* n=path->getAttributeNS(nullptr,regex);
- if (!n || !*n) {
- log.warn("skipping PathRegex element (%d) with empty regex attribute",i);
- continue;
- }
-
- auto_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
-
- const XMLCh* flag=path->getAttributeNS(nullptr,ignoreCase);
- try {
- auto_ptr<RegularExpression> re(
- new RegularExpression(n, (flag && (*flag==chLatin_f || *flag==chDigit_0)) ? &chNull : ignoreOption)
- );
- m_regexps.push_back(make_pair(re.release(), o.release()));
- }
- catch (XMLException& ex) {
- auto_ptr_char tmp(ex.getMessage());
- log.error("caught exception while parsing PathRegex regular expression (%d): %s", i, tmp.get());
- throw ConfigurationException("Invalid regular expression in PathRegex element.");
- }
-
- if (log.isDebugEnabled())
- log.debug("added <PathRegex> mapping (%s)", m_regexps.back().second->getString("regex").second);
- }
+ catch (std::exception&) {
+ free(dup);
+ throw;
}
+ }
- // Handle nested Querys.
- path = XMLHelper::getFirstChildElement(e,Query);
- for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Query)) {
- const XMLCh* n=path->getAttributeNS(nullptr,name);
+ if (!XMLString::equals(e->getLocalName(), PathRegex)) {
+ // Handle nested PathRegexs.
+ path = XMLHelper::getFirstChildElement(e, PathRegex);
+ for (int i = 1; path; ++i, path = XMLHelper::getNextSiblingElement(path, PathRegex)) {
+ const XMLCh* n = path->getAttributeNS(nullptr, regex);
if (!n || !*n) {
- log.warn("skipping Query element (%d) with empty name attribute",i);
+ log.warn("skipping PathRegex element (%d) with empty regex attribute",i);
continue;
}
- auto_ptr_char ntemp(n);
- const XMLCh* v=path->getAttributeNS(nullptr,regex);
- auto_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
+ boost::shared_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
+
+ bool flag = XMLHelper::getAttrBool(path, true, ignoreCase);
try {
- RegularExpression* re = nullptr;
- if (v && *v)
- re = new RegularExpression(v);
- m_queries.push_back(make_pair(make_pair(string(ntemp.get()),re), o.release()));
+ boost::shared_ptr<RegularExpression> re(new RegularExpression(n, flag ? &chNull : ignoreOption));
+ m_regexps.push_back(make_pair(re, o));
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
- log.error("caught exception while parsing Query regular expression (%d): %s", i, tmp.get());
- throw ConfigurationException("Invalid regular expression in Query element.");
+ log.error("caught exception while parsing PathRegex regular expression (%d): %s", i, tmp.get());
+ throw ConfigurationException("Invalid regular expression in PathRegex element.");
}
- log.debug("added <Query> mapping (%s)", ntemp.get());
+ if (log.isDebugEnabled())
+ log.debug("added <PathRegex> mapping (%s)", o->getString("regex").second);
}
}
- catch (exception&) {
- delete m_acl;
- for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());
- for (vector< pair<RegularExpression*,Override*> >::iterator i = m_regexps.begin(); i != m_regexps.end(); ++i) {
- delete i->first;
- delete i->second;
+
+ // Handle nested Querys.
+ path = XMLHelper::getFirstChildElement(e, Query);
+ for (int i = 1; path; ++i, path = XMLHelper::getNextSiblingElement(path, Query)) {
+ const XMLCh* n = path->getAttributeNS(nullptr, name);
+ if (!n || !*n) {
+ log.warn("skipping Query element (%d) with empty name attribute",i);
+ continue;
}
- for (vector< pair< pair<string,RegularExpression*>,Override*> >::iterator j = m_queries.begin(); j != m_queries.end(); ++j) {
- delete j->first.second;
- delete j->second;
+ auto_ptr_char ntemp(n);
+ const XMLCh* v = path->getAttributeNS(nullptr, regex);
+
+ try {
+ boost::shared_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
+ boost::shared_ptr<RegularExpression> re((v && *v) ? new RegularExpression(v) : nullptr);
+ m_queries.push_back(make_tuple(string(ntemp.get()), re, o));
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ log.error("caught exception while parsing Query regular expression (%d): %s", i, tmp.get());
+ throw ConfigurationException("Invalid regular expression in Query element.");
}
- throw;
- }
-}
-Override::~Override()
-{
- delete m_acl;
- for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());
- for (vector< pair<RegularExpression*,Override*> >::iterator i = m_regexps.begin(); i != m_regexps.end(); ++i) {
- delete i->first;
- delete i->second;
- }
- for (vector< pair< pair<string,RegularExpression*>,Override*> >::iterator j = m_queries.begin(); j != m_queries.end(); ++j) {
- delete j->first.second;
- delete j->second;
+ log.debug("added <Query> mapping (%s)", ntemp.get());
}
}
path++;
// Now we copy the path, chop the query string, and possibly lower case it.
- char* dup=strdup(path);
- char* sep=strchr(dup,'?');
- if (sep)
- *sep=0;
+ string dup(path);
+ string::size_type sep = dup.find('?');
+ if (sep != string::npos)
+ dup = dup.substr(0, sep);
if (!m_unicodeAware) {
- for (char* pch=dup; *pch; pch++)
- *pch=tolower(*pch);
+ to_lower(dup);
}
// Default is for the current object to provide settings.
- const Override* o=this;
+ const Override* o = this;
// Tokenize the path by segment and try and map each segment.
-#ifdef HAVE_STRTOK_R
- char* pos=nullptr;
- const char* token=strtok_r(dup,"/",&pos);
-#else
- const char* token=strtok(dup,"/");
-#endif
- while (token) {
- map<string,Override*>::const_iterator i=o->m_map.find(token);
- if (i==o->m_map.end())
+ tokenizer< char_separator<char> > tokens(dup, char_separator<char>("/"));
+ for (tokenizer< char_separator<char> >::iterator token = tokens.begin(); token != tokens.end(); ++token) {
+ map< string,boost::shared_ptr<Override> >::const_iterator i = o->m_map.find(*token);
+ if (i == o->m_map.end())
break; // Once there's no match, we've consumed as much of the path as possible here.
// We found a match, so reset the settings pointer.
- o=i->second;
+ o = i->second.get();
// We descended a step down the path, so we need to advance the original
// parameter for the regex step later.
- path += strlen(token);
+ path += token->length();
if (*path == '/')
path++;
-
- // Get the next segment, if any.
-#ifdef HAVE_STRTOK_R
- token=strtok_r(nullptr,"/",&pos);
-#else
- token=strtok(nullptr,"/");
-#endif
}
- free(dup);
-
// If there's anything left, we try for a regex match on the rest of the path minus the query string.
if (*path) {
string path2(path);
- path2 = path2.substr(0,path2.find('?'));
+ sep = path2.find('?');
+ if (sep != string::npos)
+ path2 = path2.substr(0, sep);
- for (vector< pair<RegularExpression*,Override*> >::const_iterator re = o->m_regexps.begin(); re != o->m_regexps.end(); ++re) {
+ for (vector< pair< boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > >::const_iterator re = o->m_regexps.begin(); re != o->m_regexps.end(); ++re) {
if (re->first->matches(path2.c_str())) {
- o = re->second;
+ o = re->second.get();
break;
}
}
CGIParser cgi(request, true);
do {
descended = false;
- for (vector< pair< pair<string,RegularExpression*>,Override*> >::const_iterator q = o->m_queries.begin(); !descended && q != o->m_queries.end(); ++q) {
- pair<CGIParser::walker,CGIParser::walker> vals = cgi.getParameters(q->first.first.c_str());
+ for (vector< tuple< string,boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > >::const_iterator q = o->m_queries.begin(); !descended && q != o->m_queries.end(); ++q) {
+ pair<CGIParser::walker,CGIParser::walker> vals = cgi.getParameters(q->get<0>().c_str());
if (vals.first != vals.second) {
- if (q->first.second) {
+ if (q->get<1>()) {
// We have to match one of the values.
while (vals.first != vals.second) {
- if (q->first.second->matches(vals.first->second)) {
- o = q->second;
+ if (q->get<1>()->matches(vals.first->second)) {
+ o = q->get<2>().get();
descended = true;
break;
}
}
else {
// The simple presence of the parameter is sufficient to match.
- o = q->second;
+ o = q->get<2>().get();
descended = true;
}
}
throw ConfigurationException("XML RequestMapper requires conf:RequestMap at root of configuration.");
// Load the property set.
- load(e,nullptr,this);
+ load(e, nullptr, this);
// Inject "default" app ID if not explicit.
if (!getString("applicationId").first)
setProperty("applicationId", "default");
// Load any AccessControl provider.
- loadACL(e,log);
+ loadACL(e, log);
pair<bool,bool> unicodeAware = getBool("unicodeAware");
m_unicodeAware = (unicodeAware.first && unicodeAware.second);
// Loop over the HostRegex elements.
- const DOMElement* host = XMLHelper::getFirstChildElement(e,HostRegex);
- for (int i=1; host; ++i, host=XMLHelper::getNextSiblingElement(host,HostRegex)) {
- const XMLCh* n=host->getAttributeNS(nullptr,regex);
+ const DOMElement* host = XMLHelper::getFirstChildElement(e, HostRegex);
+ for (int i = 1; host; ++i, host = XMLHelper::getNextSiblingElement(host, HostRegex)) {
+ const XMLCh* n = host->getAttributeNS(nullptr,regex);
if (!n || !*n) {
- log.warn("Skipping HostRegex element (%d) with empty regex attribute",i);
+ log.warn("Skipping HostRegex element (%d) with empty regex attribute", i);
continue;
}
- auto_ptr<Override> o(new Override(m_unicodeAware, host, log, this));
+ boost::shared_ptr<Override> o(new Override(m_unicodeAware, host, log, this));
- const XMLCh* flag=host->getAttributeNS(nullptr,ignoreCase);
+ const XMLCh* flag = host->getAttributeNS(nullptr,ignoreCase);
try {
- auto_ptr<RegularExpression> re(
+ boost::shared_ptr<RegularExpression> re(
new RegularExpression(n, (flag && (*flag==chLatin_f || *flag==chDigit_0)) ? &chNull : ignoreOption)
);
- m_regexps.push_back(make_pair(re.release(), o.release()));
+ m_regexps.push_back(make_pair(re, o));
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
}
// Loop over the Host elements.
- host = XMLHelper::getFirstChildElement(e,Host);
- for (int i=1; host; ++i, host=XMLHelper::getNextSiblingElement(host,Host)) {
+ host = XMLHelper::getFirstChildElement(e, Host);
+ for (int i = 1; host; ++i, host = XMLHelper::getNextSiblingElement(host, Host)) {
const XMLCh* n=host->getAttributeNS(nullptr,name);
if (!n || !*n) {
- log.warn("Skipping Host element (%d) with empty name attribute",i);
+ log.warn("Skipping Host element (%d) with empty name attribute", i);
continue;
}
- Override* o=new Override(m_unicodeAware, host, log, this);
+ boost::shared_ptr<Override> o(new Override(m_unicodeAware, host, log, this));
pair<bool,const char*> name=o->getString("name");
pair<bool,const char*> scheme=o->getString("scheme");
pair<bool,const char*> port=o->getString("port");
- char* dup=strdup(name.second);
- for (char* pch=dup; *pch; pch++)
- *pch=tolower(*pch);
- auto_ptr<char> dupwrap(dup);
+ string dup(name.first ? name.second : "");
+ to_lower(dup);
if (!scheme.first && port.first) {
// No scheme, but a port, so assume http.
(!strcmp(scheme.second,"ldap") && !strcmp(port.second,"389")) ||
(!strcmp(scheme.second,"ldaps") && !strcmp(port.second,"636"))) {
// First store a port-less version.
- if (m_map.count(url) || m_extras.count(url)) {
+ if (m_map.count(url)) {
log.warn("Skipping duplicate Host element (%s)",url.c_str());
- delete o;
continue;
}
- m_map[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
- // Now append the port. We use the extras vector, to avoid double freeing the object later.
+ // Now append the port. The shared_ptr should refcount the Override to avoid double deletes.
url=url + ':' + port.second;
- m_extras[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
}
else {
url=url + ':' + port.second;
- if (m_map.count(url) || m_extras.count(url)) {
+ if (m_map.count(url)) {
log.warn("Skipping duplicate Host element (%s)",url.c_str());
- delete o;
continue;
}
- m_map[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
}
}
else {
// No scheme or port, so we enter dual hosts on http:80 and https:443
string url("http://");
- url = url + dup;
- if (m_map.count(url) || m_extras.count(url)) {
+ url += dup;
+ if (m_map.count(url)) {
log.warn("Skipping duplicate Host element (%s)",url.c_str());
- delete o;
continue;
}
- m_map[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
- url = url + ":80";
- if (m_map.count(url) || m_extras.count(url)) {
+ url += ":80";
+ if (m_map.count(url)) {
log.warn("Skipping duplicate Host element (%s)",url.c_str());
continue;
}
- m_extras[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
- url = "https://";
- url = url + dup;
- if (m_map.count(url) || m_extras.count(url)) {
+ url = "https://" + dup;
+ if (m_map.count(url)) {
log.warn("Skipping duplicate Host element (%s)",url.c_str());
continue;
}
- m_extras[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
- url = url + ":443";
- if (m_map.count(url) || m_extras.count(url)) {
+ url += ":443";
+ if (m_map.count(url)) {
log.warn("Skipping duplicate Host element (%s)",url.c_str());
continue;
}
- m_extras[url]=o;
+ m_map[url] = o;
log.debug("Added <Host> mapping for %s",url.c_str());
}
}
const Override* XMLRequestMapperImpl::findOverride(const char* vhost, const HTTPRequest& request) const
{
- const Override* o=nullptr;
- map<string,Override*>::const_iterator i=m_map.find(vhost);
- if (i!=m_map.end())
- o=i->second;
+ const Override* o = nullptr;
+ map< string,boost::shared_ptr<Override> >::const_iterator i = m_map.find(vhost);
+ if (i != m_map.end())
+ o = i->second.get();
else {
- i=m_extras.find(vhost);
- if (i!=m_extras.end())
- o=i->second;
- else {
- for (vector< pair<RegularExpression*,Override*> >::const_iterator re = m_regexps.begin(); !o && re != m_regexps.end(); ++re) {
- if (re->first->matches(vhost))
- o=re->second;
- }
+ for (vector< pair< boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > >::const_iterator re = m_regexps.begin(); !o && re != m_regexps.end(); ++re) {
+ if (re->first->matches(vhost))
+ o=re->second.get();
}
}
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
- XMLRequestMapperImpl* impl = new XMLRequestMapperImpl(raw.second, m_log);
+ scoped_ptr<XMLRequestMapperImpl> impl(new XMLRequestMapperImpl(raw.second, m_log));
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_impl;
- m_impl = impl;
+ m_impl.swap(impl);
return make_pair(false,(DOMElement*)nullptr);
}
RequestMapper::Settings XMLRequestMapper::getSettings(const HTTPRequest& request) const
{
try {
- ostringstream vhost;
- vhost << request.getScheme() << "://" << request.getHostname() << ':' << request.getPort();
- const Override* o=m_impl->findOverride(vhost.str().c_str(), request);
- return Settings(o,o->getAC());
+ string vhost = string(request.getScheme()) + "://" + request.getHostname() + ':' + lexical_cast<string>(request.getPort());
+ const Override* o=m_impl->findOverride(vhost.c_str(), request);
+ return Settings(o, o->getAC());
}
catch (XMLException& ex) {
auto_ptr_char tmp(ex.getMessage());
#include "util/SPConstants.h"
#include <map>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include <saml/SAMLConfig.h>
#include <saml/binding/SecurityPolicyRule.h>
#include <xmltooling/io/HTTPResponse.h>
using opensaml::SecurityPolicyRule;
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
public:
XMLSecurityPolicyProviderImpl(const DOMElement* e, Category& log);
~XMLSecurityPolicyProviderImpl() {
- for (map< string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::iterator i = m_policyMap.begin(); i != m_policyMap.end(); ++i) {
- delete i->second.first;
- for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<SecurityPolicyRule>());
- }
if (m_document)
m_document->release();
}
private:
DOMDocument* m_document;
vector<xstring> m_whitelist,m_blacklist;
- map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
- map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator m_defaultPolicy;
+ vector< boost::shared_ptr<SecurityPolicyRule> > m_ruleJanitor; // need this to maintain vector type in API
+ typedef map< string,pair< boost::shared_ptr<PropertySet>,vector<const SecurityPolicyRule*> > > policymap_t;
+ policymap_t m_policyMap;
+ policymap_t::const_iterator m_defaultPolicy;
friend class SHIBSP_DLLLOCAL XMLSecurityPolicyProvider;
};
{
public:
XMLSecurityPolicyProvider(const DOMElement* e)
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".SecurityPolicyProvider.XML")), m_impl(nullptr) {
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".SecurityPolicyProvider.XML")) {
background_load(); // guarantees an exception or the policy is loaded
}
~XMLSecurityPolicyProvider() {
shutdown();
- delete m_impl;
}
const PropertySet* getPolicySettings(const char* id=nullptr) const {
if (!id || !*id)
- return m_impl->m_defaultPolicy->second.first;
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
+ return m_impl->m_defaultPolicy->second.first.get();
+ XMLSecurityPolicyProviderImpl::policymap_t::const_iterator i = m_impl->m_policyMap.find(id);
if (i != m_impl->m_policyMap.end())
- return i->second.first;
+ return i->second.first.get();
throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
}
const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id=nullptr) const {
if (!id || !*id)
return m_impl->m_defaultPolicy->second.second;
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
+ XMLSecurityPolicyProviderImpl::policymap_t::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));
pair<bool,DOMElement*> background_load();
private:
- XMLSecurityPolicyProviderImpl* m_impl;
+ scoped_ptr<XMLSecurityPolicyProviderImpl> m_impl;
};
#if defined (_MSC_VER)
e = XMLHelper::getFirstChildElement(e, Policy);
while (e) {
string id(XMLHelper::getAttrString(e, nullptr, _id));
- pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id];
- rules.first = nullptr;
- auto_ptr<DOMPropertySet> settings(new DOMPropertySet());
+ policymap_t::referent_type& rules = m_policyMap[id];
+ boost::shared_ptr<DOMPropertySet> settings(new DOMPropertySet());
settings->load(e, nullptr, &filter);
- rules.first = settings.release();
+ rules.first = settings;
// Set default policy if not set, or id is "default".
if (m_defaultPolicy == m_policyMap.end() || id == "default")
string t(XMLHelper::getAttrString(rule, nullptr, _type));
if (!t.empty()) {
try {
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+ boost::shared_ptr<SecurityPolicyRule> ptr(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+ m_ruleJanitor.push_back(ptr);
+ rules.second.push_back(ptr.get());
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.crit("error instantiating policy rule (%s) in policy (%s): %s", t.c_str(), id.c_str(), ex.what());
}
}
if (rules.second.size() == 0) {
// Process Rule elements.
- log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");
+ log.warn("detected deprecated Policy configuration, consider converting to new PolicyRule syntax");
rule = XMLHelper::getFirstChildElement(e, Rule);
while (rule) {
string t(XMLHelper::getAttrString(rule, nullptr, _type));
if (!t.empty()) {
try {
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+ boost::shared_ptr<SecurityPolicyRule> ptr(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+ m_ruleJanitor.push_back(ptr);
+ rules.second.push_back(ptr.get());
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.crit("error instantiating policy rule (%s) in policy (%s): %s", t.c_str(), id.c_str(), ex.what());
}
}
// Manually add a basic Conditions rule.
log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.c_str());
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, nullptr));
+ boost::shared_ptr<SecurityPolicyRule> cptr(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, nullptr));
+ m_ruleJanitor.push_back(cptr);
+ rules.second.push_back(cptr.get());
}
e = XMLHelper::getNextSiblingElement(e, Policy);
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
- XMLSecurityPolicyProviderImpl* impl = new XMLSecurityPolicyProviderImpl(raw.second, m_log);
+ scoped_ptr<XMLSecurityPolicyProviderImpl> impl(new XMLSecurityPolicyProviderImpl(raw.second, m_log));
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_impl;
- m_impl = impl;
-
+ m_impl.swap(impl);
return make_pair(false,(DOMElement*)nullptr);
}
return load(true);
throw;
}
- catch (exception&) {
+ catch (std::exception&) {
if (!m_loaded && !m_backing.empty())
return load(true);
throw;
# error "Supported logging library not available."
#endif
#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/tuple/tuple.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLStringTokenizer.hpp>
#include <xmltooling/XMLToolingConfig.h>
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
#ifndef min
{
public:
XMLApplication(const ServiceProvider*, const ProtocolProvider*, DOMElement*, const XMLApplication* base=nullptr);
- ~XMLApplication() { cleanup(); }
+ ~XMLApplication();
const char* getHash() const {return m_hash.c_str();}
MetadataProvider* getMetadataProvider(bool required=true) const {
if (required && !m_base && !m_metadata)
throw ConfigurationException("No MetadataProvider available.");
- return (!m_metadata && m_base) ? m_base->getMetadataProvider(required) : m_metadata;
+ return (!m_metadata && m_base) ? m_base->getMetadataProvider(required) : m_metadata.get();
}
TrustEngine* getTrustEngine(bool required=true) const {
if (required && !m_base && !m_trust)
throw ConfigurationException("No TrustEngine available.");
- return (!m_trust && m_base) ? m_base->getTrustEngine(required) : m_trust;
+ return (!m_trust && m_base) ? m_base->getTrustEngine(required) : m_trust.get();
}
AttributeExtractor* getAttributeExtractor() const {
- return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor;
+ return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor.get();
}
AttributeFilter* getAttributeFilter() const {
- return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter;
+ return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter.get();
}
AttributeResolver* getAttributeResolver() const {
- return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver;
+ return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver.get();
}
CredentialResolver* getCredentialResolver() const {
- return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver;
+ return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver.get();
}
const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;
const PropertySet* getRelyingParty(const XMLCh* entityID) const;
void doLogout(const ProtocolProvider&, set<string>&, DOMElement*, Category&);
void doNameIDMgmt(const ProtocolProvider&, set<string>&, DOMElement*, Category&);
void doArtifactResolution(const ProtocolProvider&, const char*, DOMElement*, Category&);
- void cleanup();
const XMLApplication* m_base;
string m_hash;
std::pair<std::string,std::string> m_attributePrefix;
#ifndef SHIBSP_LITE
- void doAttributePlugins(DOMElement* e, Category& log);
- MetadataProvider* m_metadata;
- TrustEngine* m_trust;
- AttributeExtractor* m_attrExtractor;
- AttributeFilter* m_attrFilter;
- AttributeResolver* m_attrResolver;
- CredentialResolver* m_credResolver;
+ void doAttributePlugins(DOMElement*, Category&);
+ scoped_ptr<MetadataProvider> m_metadata;
+ scoped_ptr<TrustEngine> m_trust;
+ scoped_ptr<AttributeExtractor> m_attrExtractor;
+ scoped_ptr<AttributeFilter> m_attrFilter;
+ scoped_ptr<AttributeResolver> m_attrResolver;
+ scoped_ptr<CredentialResolver> m_credResolver;
vector<const XMLCh*> m_audiences;
// RelyingParty properties
- map<xstring,PropertySet*> m_partyMap;
+ map< xstring,boost::shared_ptr<PropertySet> > m_partyMap;
#endif
vector<string> m_remoteUsers,m_frontLogout,m_backLogout;
// manage handler objects
- vector<Handler*> m_handlers;
+ vector< boost::shared_ptr<Handler> > m_handlers;
// maps location (path info) to applicable handlers
map<string,const Handler*> m_handlerMap;
{
public:
XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log);
- ~XMLConfigImpl();
+ ~XMLConfigImpl() {
+ if (m_document)
+ m_document->release();
+ }
- RequestMapper* m_requestMapper;
- map<string,Application*> m_appmap;
#ifndef SHIBSP_LITE
- TransactionLog* m_tranLog;
- SecurityPolicyProvider* m_policy;
- vector< pair< string, pair<string,string> > > m_transportOptions;
+ scoped_ptr<TransactionLog> m_tranLog;
+ scoped_ptr<SecurityPolicyProvider> m_policy;
+ vector< tuple<string,string,string> > m_transportOptions;
#endif
+ scoped_ptr<RequestMapper> m_requestMapper;
+ map< string,boost::shared_ptr<Application> > m_appmap;
// Provides filter to exclude special config elements.
#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
void doExtensions(const DOMElement*, const char*, Category&);
void doListener(const DOMElement*, XMLConfig*, Category&);
void doCaching(const DOMElement*, XMLConfig*, Category&);
- void cleanup();
DOMDocument* m_document;
};
#endif
{
public:
- XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),
- m_impl(nullptr), m_listener(nullptr), m_sessionCache(nullptr) {
- }
+ XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")) {}
void init() {
background_load();
~XMLConfig() {
shutdown();
- delete m_impl;
- delete m_sessionCache;
- delete m_listener;
#ifndef SHIBSP_LITE
SAMLConfig::getConfig().setArtifactMap(nullptr);
XMLToolingConfig::getConfig().setReplayCache(nullptr);
- for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());
#endif
}
TransactionLog* getTransactionLog() const {
if (m_impl->m_tranLog)
- return m_impl->m_tranLog;
+ return m_impl->m_tranLog.get();
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;
+ map< string,boost::shared_ptr<StorageService> >::const_iterator i = m_storage.find(id);
+ if (i != m_storage.end())
+ return i->second.get();
}
else if (!m_storage.empty())
- return m_storage.begin()->second;
+ return m_storage.begin()->second.get();
return nullptr;
}
#endif
ListenerService* getListenerService(bool required=true) const {
if (required && !m_listener)
throw ConfigurationException("No ListenerService available.");
- return m_listener;
+ return m_listener.get();
}
SessionCache* getSessionCache(bool required=true) const {
if (required && !m_sessionCache)
throw ConfigurationException("No SessionCache available.");
- return m_sessionCache;
+ return m_sessionCache.get();
}
RequestMapper* getRequestMapper(bool required=true) const {
if (required && !m_impl->m_requestMapper)
throw ConfigurationException("No RequestMapper available.");
- return m_impl->m_requestMapper;
+ return m_impl->m_requestMapper.get();
}
const Application* getApplication(const char* applicationId) const {
- map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId ? applicationId : "default");
- return (i!=m_impl->m_appmap.end()) ? i->second : nullptr;
+ map< string,boost::shared_ptr<Application> >::const_iterator i = m_impl->m_appmap.find(applicationId ? applicationId : "default");
+ return (i != m_impl->m_appmap.end()) ? i->second.get() : nullptr;
}
#ifndef SHIBSP_LITE
SecurityPolicyProvider* getSecurityPolicyProvider(bool required=true) const {
if (required && !m_impl->m_policy)
throw ConfigurationException("No SecurityPolicyProvider available.");
- return m_impl->m_policy;
+ return m_impl->m_policy.get();
}
const PropertySet* getPolicySettings(const char* id) const {
bool setTransportOptions(SOAPTransport& transport) const {
bool ret = true;
- vector< pair< string, pair<string,string> > >::const_iterator opt;
- for (opt = m_impl->m_transportOptions.begin(); opt != m_impl->m_transportOptions.end(); ++opt) {
- if (!transport.setProviderOption(opt->first.c_str(), opt->second.first.c_str(), opt->second.second.c_str())) {
- m_log.error("failed to set SOAPTransport option (%s)", opt->second.first.c_str());
+ for (vector< tuple<string,string,string> >::const_iterator opt = m_impl->m_transportOptions.begin();
+ opt != m_impl->m_transportOptions.end(); ++opt) {
+ if (!transport.setProviderOption(opt->get<0>().c_str(), opt->get<1>().c_str(), opt->get<2>().c_str())) {
+ m_log.error("failed to set SOAPTransport option (%s)", opt->get<1>().c_str());
ret = false;
}
}
private:
friend class XMLConfigImpl;
- XMLConfigImpl* m_impl;
- ListenerService* m_listener;
- SessionCache* m_sessionCache;
+ // The order of these members actually matters. If we want to rely on auto-destruction, then
+ // anything dependent on anything else has to come later in the object so it will pop first.
+ // Storage is the lowest, then remoting, then the cache, and finally the rest.
#ifndef SHIBSP_LITE
- map<string,StorageService*> m_storage;
+ map< string,boost::shared_ptr<StorageService> > m_storage;
#endif
+ scoped_ptr<ListenerService> m_listener;
+ scoped_ptr<SessionCache> m_sessionCache;
+ scoped_ptr<XMLConfigImpl> m_impl;
};
#if defined (_MSC_VER)
const ProtocolProvider* pp,
DOMElement* e,
const XMLApplication* base
- ) : Application(sp), m_base(base),
-#ifndef SHIBSP_LITE
- m_metadata(nullptr), m_trust(nullptr),
- m_attrExtractor(nullptr), m_attrFilter(nullptr), m_attrResolver(nullptr),
- m_credResolver(nullptr),
-#endif
- m_acsDefault(nullptr), m_sessionInitDefault(nullptr), m_artifactResolutionDefault(nullptr)
+ ) : Application(sp), m_base(base), m_acsDefault(nullptr), m_sessionInitDefault(nullptr), m_artifactResolutionDefault(nullptr)
{
#ifdef _DEBUG
xmltooling::NDC ndc("XMLApplication");
#endif
Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");
- try {
- // First load any property sets.
- load(e,nullptr,this);
- if (base)
- setParent(base);
+ // First load any property sets.
+ load(e, nullptr, this);
+ if (base)
+ setParent(base);
- SPConfig& conf=SPConfig::getConfig();
+ SPConfig& conf=SPConfig::getConfig();
#ifndef SHIBSP_LITE
- XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
+ XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
#endif
- // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec dependency.
- 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]);
- }
-
- doAttributeInfo();
-
- if (conf.isEnabled(SPConfig::Handlers))
- doHandlers(pp, e, log);
-
- // Notification.
- DOMNodeList* nlist = e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS, Notify);
- for (XMLSize_t i = 0; nlist && i < nlist->getLength(); ++i) {
- if (nlist->item(i)->getParentNode()->isSameNode(e)) {
- const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(nullptr, Channel);
- string loc(XMLHelper::getAttrString(static_cast<DOMElement*>(nlist->item(i)), nullptr, Location));
- if (!loc.empty()) {
- if (channel && *channel == chLatin_f)
- m_frontLogout.push_back(loc);
- else
- m_backLogout.push_back(loc);
- }
+ // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec dependency.
+ 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]);
+ }
+
+ doAttributeInfo();
+
+ if (conf.isEnabled(SPConfig::Handlers))
+ doHandlers(pp, e, log);
+
+ // Notification.
+ DOMNodeList* nlist = e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS, Notify);
+ for (XMLSize_t i = 0; nlist && i < nlist->getLength(); ++i) {
+ if (nlist->item(i)->getParentNode()->isSameNode(e)) {
+ const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(nullptr, Channel);
+ string loc(XMLHelper::getAttrString(static_cast<DOMElement*>(nlist->item(i)), nullptr, Location));
+ if (!loc.empty()) {
+ if (channel && *channel == chLatin_f)
+ m_frontLogout.push_back(loc);
+ else
+ m_backLogout.push_back(loc);
}
}
+ }
#ifndef SHIBSP_LITE
- nlist = e->getElementsByTagNameNS(samlconstants::SAML20_NS, Audience::LOCAL_NAME);
- if (nlist && nlist->getLength()) {
- log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
- for (XMLSize_t i = 0; i < nlist->getLength(); ++i)
- if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
- m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
- }
-
- if (conf.isEnabled(SPConfig::Metadata)) {
- auto_ptr<MetadataProvider> mp(
- doChainedPlugins(
- SAMLConfig::getConfig().MetadataProviderManager, "MetadataProvider", CHAINING_METADATA_PROVIDER, _MetadataProvider, e, log
- )
- );
- try {
- if (mp.get()) {
- mp->init();
- m_metadata = mp.release();
- }
- else if (!m_base) {
- log.crit("no MetadataProvider available, configuration is probably unusable");
- }
- }
- catch (exception& ex) {
- log.crit("error initializing MetadataProvider: %s", ex.what());
- }
+ nlist = e->getElementsByTagNameNS(samlconstants::SAML20_NS, Audience::LOCAL_NAME);
+ if (nlist && nlist->getLength()) {
+ log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
+ for (XMLSize_t i = 0; i < nlist->getLength(); ++i)
+ if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
+ m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
+ }
+
+ if (conf.isEnabled(SPConfig::Metadata)) {
+ m_metadata.reset(
+ doChainedPlugins(
+ SAMLConfig::getConfig().MetadataProviderManager, "MetadataProvider", CHAINING_METADATA_PROVIDER, _MetadataProvider, e, log
+ )
+ );
+ try {
+ if (m_metadata)
+ m_metadata->init();
+ else if (!m_base)
+ log.crit("no MetadataProvider available, configuration is probably unusable");
+ }
+ catch (std::exception& ex) {
+ log.crit("error initializing MetadataProvider: %s", ex.what());
}
+ }
- if (conf.isEnabled(SPConfig::Trust)) {
- m_trust = doChainedPlugins(xmlConf.TrustEngineManager, "TrustEngine", CHAINING_TRUSTENGINE, _TrustEngine, e, log);
- if (!m_trust && !m_base) {
- log.info(
- "no TrustEngine specified or installed, using default chain {%s, %s}",
- EXPLICIT_KEY_TRUSTENGINE, SHIBBOLETH_PKIX_TRUSTENGINE
- );
- m_trust = xmlConf.TrustEngineManager.newPlugin(CHAINING_TRUSTENGINE, nullptr);
- ChainingTrustEngine* trustchain = dynamic_cast<ChainingTrustEngine*>(m_trust);
- if (trustchain) {
- trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE, nullptr));
- trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(SHIBBOLETH_PKIX_TRUSTENGINE, nullptr));
- }
+ if (conf.isEnabled(SPConfig::Trust)) {
+ m_trust.reset(doChainedPlugins(xmlConf.TrustEngineManager, "TrustEngine", CHAINING_TRUSTENGINE, _TrustEngine, e, log));
+ if (!m_trust && !m_base) {
+ log.info(
+ "no TrustEngine specified or installed, using default chain {%s, %s}",
+ EXPLICIT_KEY_TRUSTENGINE, SHIBBOLETH_PKIX_TRUSTENGINE
+ );
+ m_trust.reset(xmlConf.TrustEngineManager.newPlugin(CHAINING_TRUSTENGINE, nullptr));
+ ChainingTrustEngine* trustchain = dynamic_cast<ChainingTrustEngine*>(m_trust.get());
+ if (trustchain) {
+ trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE, nullptr));
+ trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(SHIBBOLETH_PKIX_TRUSTENGINE, nullptr));
}
}
+ }
- if (conf.isEnabled(SPConfig::AttributeResolution))
- doAttributePlugins(e, log);
+ if (conf.isEnabled(SPConfig::AttributeResolution)) {
+ doAttributePlugins(e, log);
+ }
- if (conf.isEnabled(SPConfig::Credentials)) {
- m_credResolver = doChainedPlugins(
- xmlConf.CredentialResolverManager, "CredentialResolver", CHAINING_CREDENTIAL_RESOLVER, _CredentialResolver, e, log
- );
- }
+ if (conf.isEnabled(SPConfig::Credentials)) {
+ m_credResolver.reset(
+ doChainedPlugins(xmlConf.CredentialResolverManager, "CredentialResolver", CHAINING_CREDENTIAL_RESOLVER, _CredentialResolver, e, log)
+ );
+ }
- // Finally, load relying parties.
- const DOMElement* child = XMLHelper::getFirstChildElement(e, RelyingParty);
+ // Finally, load relying parties.
+ const DOMElement* child = XMLHelper::getFirstChildElement(e, RelyingParty);
+ while (child) {
+ if (child->hasAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)) {
+ boost::shared_ptr<DOMPropertySet> rp(new DOMPropertySet());
+ rp->load(child, nullptr, this);
+ rp->setParent(this);
+ m_partyMap[child->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp;
+ }
+ child = XMLHelper::getNextSiblingElement(child, RelyingParty);
+ }
+ if (base && m_partyMap.empty() && !base->m_partyMap.empty()) {
+ // For inheritance of RPs to work, we have to pull them in to the override by cloning the DOM.
+ child = XMLHelper::getFirstChildElement(base->getElement(), RelyingParty);
while (child) {
if (child->hasAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)) {
- auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
- rp->load(child, nullptr, this);
+ DOMElement* rpclone = static_cast<DOMElement*>(child->cloneNode(true));
+ boost::shared_ptr<DOMPropertySet> rp(new DOMPropertySet());
+ rp->load(rpclone, nullptr, this);
rp->setParent(this);
- m_partyMap[child->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp.release();
+ m_partyMap[rpclone->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp;
}
child = XMLHelper::getNextSiblingElement(child, RelyingParty);
}
- if (base && m_partyMap.empty() && !base->m_partyMap.empty()) {
- // For inheritance of RPs to work, we have to pull them in to the override by cloning the DOM.
- child = XMLHelper::getFirstChildElement(base->getElement(), RelyingParty);
- while (child) {
- if (child->hasAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)) {
- DOMElement* rpclone = static_cast<DOMElement*>(child->cloneNode(true));
- auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
- rp->load(rpclone, nullptr, this);
- rp->setParent(this);
- m_partyMap[rpclone->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp.release();
- }
- child = XMLHelper::getNextSiblingElement(child, RelyingParty);
- }
- }
+ }
#endif
- // Out of process only, we register a listener endpoint.
- if (!conf.isEnabled(SPConfig::InProcess)) {
- ListenerService* listener = sp->getListenerService(false);
- if (listener) {
- string addr=string(getId()) + "::getHeaders::Application";
- listener->regListener(addr.c_str(),this);
- }
- else {
- log.info("no ListenerService available, Application remoting disabled");
- }
+ // Out of process only, we register a listener endpoint.
+ if (!conf.isEnabled(SPConfig::InProcess)) {
+ ListenerService* listener = sp->getListenerService(false);
+ if (listener) {
+ string addr=string(getId()) + "::getHeaders::Application";
+ listener->regListener(addr.c_str(), this);
+ }
+ else {
+ log.info("no ListenerService available, Application remoting disabled");
}
}
- catch (exception&) {
- cleanup();
- throw;
- }
-#ifndef _DEBUG
- catch (...) {
- cleanup();
- throw;
+}
+
+XMLApplication::~XMLApplication()
+{
+ ListenerService* listener=getServiceProvider().getListenerService(false);
+ if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
+ string addr=string(getId()) + "::getHeaders::Application";
+ listener->unregListener(addr.c_str(), this);
}
-#endif
}
template <class T> T* XMLApplication::doChainedPlugins(
throw ConfigurationException("$1 element had no type attribute.", params(1, pluginType));
}
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.crit("error building %s: %s", pluginType, ex.what());
if (dummyType) {
// Install a dummy version as a safety valve.
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.push_back(start);
- start = pos ? pos+1 : nullptr;
- }
- free(dup);
+ string dup(attributes.second);
+ split(m_remoteUsers, dup, is_space(), algorithm::token_compress_on);
}
// Load attribute ID lists for REMOTE_USER and header clearing.
pch++;
}
}
- 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;
+ string dup(attributes.second);
+ vector<string> headerNames;
+ split(headerNames, dup, is_space(), algorithm::token_compress_on);
+ for (vector<string>::const_iterator h = headerNames.begin(); h != headerNames.end(); ++h) {
string transformed;
- pch = start;
+ const char* pch = h->c_str();
while (*pch) {
transformed += (isalnum(*pch) ? toupper(*pch) : '_');
pch++;
}
-
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *h, m_attributePrefix.second + transformed));
if (prefix.first)
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));
- start = pos ? pos+1 : nullptr;
+ m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *h, transformedprefix + transformed));
}
- free(dup);
m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
}
}
{
SPConfig& conf = SPConfig::getConfig();
- Handler* handler = nullptr;
const PropertySet* sessions = getPropertySet("Sessions");
// Process assertion export handler.
static const XMLCh _acl[] = UNICODE_LITERAL_9(e,x,p,o,r,t,A,C,L);
exportElement->setAttributeNS(nullptr,_acl,exportACL.second);
}
- handler = conf.HandlerManager.newPlugin(
- samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId())
+ boost::shared_ptr<Handler> exportHandler(
+ conf.HandlerManager.newPlugin(samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId()))
);
- m_handlers.push_back(handler);
+ m_handlers.push_back(exportHandler);
// Insert into location map. If it contains the handlerURL, we skip past that part.
const char* hurl = sessions->getString("handlerURL").second;
if (pch)
location.second = pch + strlen(hurl);
if (*location.second == '/')
- m_handlerMap[location.second]=handler;
+ m_handlerMap[location.second] = exportHandler.get();
else
- m_handlerMap[string("/") + location.second]=handler;
+ m_handlerMap[string("/") + location.second] = exportHandler.get();
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.error("caught exception installing assertion lookup handler: %s", ex.what());
}
}
continue;
}
try {
+ boost::shared_ptr<Handler> handler;
if (XMLString::equals(child->getLocalName(), _AssertionConsumerService)) {
string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
if (bindprop.empty()) {
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- handler = conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ handler.reset(conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
// Map by binding and protocol (may be > 1 per protocol and binding)
- m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
+ m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler.get());
const XMLCh* protfamily = handler->getProtocolFamily();
if (protfamily)
- m_acsProtocolMap[protfamily].push_back(handler);
- m_acsIndexMap[handler->getUnsignedInt("index").second] = handler;
+ m_acsProtocolMap[protfamily].push_back(handler.get());
+ m_acsIndexMap[handler->getUnsignedInt("index").second] = handler.get();
if (!hardACS) {
pair<bool,bool> defprop = handler->getBool("isDefault");
if (defprop.first) {
if (defprop.second) {
hardACS = true;
- m_acsDefault = handler;
+ m_acsDefault = handler.get();
}
}
else if (!m_acsDefault)
- m_acsDefault = handler;
+ m_acsDefault = handler.get();
}
}
else if (XMLString::equals(child->getLocalName(), _SessionInitiator)) {
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- SessionInitiator* sihandler = conf.SessionInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ boost::shared_ptr<SessionInitiator> sihandler(
+ conf.SessionInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(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;
+ m_sessionInitMap[si_id.second] = sihandler.get();
if (!hardSessionInit) {
pair<bool,bool> defprop = handler->getBool("isDefault");
if (defprop.first) {
if (defprop.second) {
hardSessionInit = true;
- m_sessionInitDefault = sihandler;
+ m_sessionInitDefault = sihandler.get();
}
}
else if (!m_sessionInitDefault) {
- m_sessionInitDefault = sihandler;
+ m_sessionInitDefault = sihandler.get();
}
}
}
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- handler = conf.LogoutInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ handler.reset(conf.LogoutInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId())));
}
else if (XMLString::equals(child->getLocalName(), _ArtifactResolutionService)) {
string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- handler = conf.ArtifactResolutionServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ handler.reset(conf.ArtifactResolutionServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
if (!hardArt) {
pair<bool,bool> defprop = handler->getBool("isDefault");
if (defprop.first) {
if (defprop.second) {
hardArt = true;
- m_artifactResolutionDefault = handler;
+ m_artifactResolutionDefault = handler.get();
}
}
else if (!m_artifactResolutionDefault)
- m_artifactResolutionDefault = handler;
+ m_artifactResolutionDefault = handler.get();
}
}
else if (XMLString::equals(child->getLocalName(), _SingleLogoutService)) {
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- handler = conf.SingleLogoutServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ handler.reset(conf.SingleLogoutServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
}
else if (XMLString::equals(child->getLocalName(), _ManageNameIDService)) {
string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- handler = conf.ManageNameIDServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ handler.reset(conf.ManageNameIDServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
}
else {
string t(XMLHelper::getAttrString(child, nullptr, _type));
child = XMLHelper::getNextSiblingElement(child);
continue;
}
- handler = conf.HandlerManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+ handler.reset(conf.HandlerManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId())));
}
m_handlers.push_back(handler);
// Insert into location map.
location = handler->getString("Location");
if (location.first && *location.second == '/')
- m_handlerMap[location.second] = handler;
+ m_handlerMap[location.second] = handler.get();
else if (location.first)
- m_handlerMap[string("/") + location.second] = handler;
+ m_handlerMap[string("/") + location.second] = handler.get();
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.error("caught exception processing handler element: %s", ex.what());
}
acsdom->setAttributeNS(nullptr, _index, indexbuf.c_str());
log.info("adding AssertionConsumerService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
- Handler* handler = conf.AssertionConsumerServiceManager.newPlugin(
- (*b)->getString("id").second, pair<const DOMElement*,const char*>(acsdom, getId())
+ boost::shared_ptr<Handler> handler(
+ conf.AssertionConsumerServiceManager.newPlugin(
+ (*b)->getString("id").second, pair<const DOMElement*,const char*>(acsdom, getId())
+ )
);
m_handlers.push_back(handler);
// Setup maps and defaults.
- m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
+ m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler.get());
const XMLCh* protfamily = handler->getProtocolFamily();
if (protfamily)
- m_acsProtocolMap[protfamily].push_back(handler);
- m_acsIndexMap[handler->getUnsignedInt("index").second] = handler;
+ m_acsProtocolMap[protfamily].push_back(handler.get());
+ m_acsIndexMap[handler->getUnsignedInt("index").second] = handler.get();
if (!m_acsDefault)
- m_acsDefault = handler;
+ m_acsDefault = handler.get();
// Insert into location map.
pair<bool,const char*> location = handler->getString("Location");
if (location.first && *location.second == '/')
- m_handlerMap[location.second] = handler;
+ m_handlerMap[location.second] = handler.get();
else if (location.first)
- m_handlerMap[string("/") + location.second] = handler;
+ m_handlerMap[string("/") + location.second] = handler.get();
}
else {
log.error("missing id or path property on Binding element, check config for protocol (%s)", prot.get());
e->setAttributeNS(nullptr, Location, _loc);
// Instantiate Chaining initiator around the SSO element.
- SessionInitiator* chain = conf.SessionInitiatorManager.newPlugin(
- CHAINING_SESSION_INITIATOR, pair<const DOMElement*,const char*>(e, getId())
+ boost::shared_ptr<SessionInitiator> chain(
+ conf.SessionInitiatorManager.newPlugin(CHAINING_SESSION_INITIATOR, pair<const DOMElement*,const char*>(e, getId()))
);
m_handlers.push_back(chain);
- m_sessionInitDefault = chain;
- m_handlerMap["/Login"] = chain;
+ m_sessionInitDefault = chain.get();
+ m_handlerMap["/Login"] = chain.get();
}
void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols, DOMElement* e, Category& log)
slodom->setAttributeNS(nullptr, Location, pathprop.second);
log.info("adding SingleLogoutService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
- Handler* handler = conf.SingleLogoutServiceManager.newPlugin(
- (*b)->getString("id").second, pair<const DOMElement*,const char*>(slodom, getId())
+ boost::shared_ptr<Handler> handler(
+ conf.SingleLogoutServiceManager.newPlugin((*b)->getString("id").second, pair<const DOMElement*,const char*>(slodom, 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;
+ m_handlerMap[location.second] = handler.get();
else if (location.first)
- m_handlerMap[string("/") + location.second] = handler;
+ m_handlerMap[string("/") + location.second] = handler.get();
}
else {
log.error("missing id or path property on Binding element, check config for protocol (%s)", prot.get());
e->setAttributeNS(nullptr, Location, _loc);
// Instantiate Chaining initiator around the SSO element.
- Handler* chain = conf.LogoutInitiatorManager.newPlugin(
- CHAINING_LOGOUT_INITIATOR, pair<const DOMElement*,const char*>(e, getId())
+ boost::shared_ptr<Handler> chain(
+ conf.LogoutInitiatorManager.newPlugin(CHAINING_LOGOUT_INITIATOR, pair<const DOMElement*,const char*>(e, getId()))
);
m_handlers.push_back(chain);
- m_handlerMap["/Logout"] = chain;
+ m_handlerMap["/Logout"] = chain.get();
}
void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& protocols, DOMElement* e, Category& log)
nimdom->setAttributeNS(nullptr, Location, pathprop.second);
log.info("adding ManageNameIDService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
- Handler* handler = conf.ManageNameIDServiceManager.newPlugin(
- (*b)->getString("id").second, pair<const DOMElement*,const char*>(nimdom, getId())
+ boost::shared_ptr<Handler> handler(
+ conf.ManageNameIDServiceManager.newPlugin((*b)->getString("id").second, pair<const DOMElement*,const char*>(nimdom, 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;
+ m_handlerMap[location.second] = handler.get();
else if (location.first)
- m_handlerMap[string("/") + location.second] = handler;
+ m_handlerMap[string("/") + location.second] = handler.get();
}
else {
log.error("missing id or path property on Binding element, check config for protocol (%s)", prot.get());
artdom->setAttributeNS(nullptr, _index, indexbuf.c_str());
log.info("adding ArtifactResolutionService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
- Handler* handler = conf.ArtifactResolutionServiceManager.newPlugin(
- (*b)->getString("id").second, pair<const DOMElement*,const char*>(artdom, getId())
+ boost::shared_ptr<Handler> handler(
+ conf.ArtifactResolutionServiceManager.newPlugin((*b)->getString("id").second, pair<const DOMElement*,const char*>(artdom, getId()))
);
m_handlers.push_back(handler);
if (!m_artifactResolutionDefault)
- m_artifactResolutionDefault = handler;
+ m_artifactResolutionDefault = handler.get();
// Insert into location map.
pair<bool,const char*> location = handler->getString("Location");
if (location.first && *location.second == '/')
- m_handlerMap[location.second] = handler;
+ m_handlerMap[location.second] = handler.get();
else if (location.first)
- m_handlerMap[string("/") + location.second] = handler;
+ m_handlerMap[string("/") + location.second] = handler.get();
}
else {
log.error("missing id or path property on Binding element, check config for protocol (%s)", protocol);
{
SPConfig& conf = SPConfig::getConfig();
- m_attrExtractor =
- doChainedPlugins(conf.AttributeExtractorManager, "AttributeExtractor", CHAINING_ATTRIBUTE_EXTRACTOR, _AttributeExtractor, e, log);
+ m_attrExtractor.reset(
+ doChainedPlugins(conf.AttributeExtractorManager, "AttributeExtractor", CHAINING_ATTRIBUTE_EXTRACTOR, _AttributeExtractor, e, log)
+ );
- m_attrFilter =
- doChainedPlugins(conf.AttributeFilterManager, "AttributeFilter", CHAINING_ATTRIBUTE_FILTER, _AttributeFilter, e, log, DUMMY_ATTRIBUTE_FILTER);
+ m_attrFilter.reset(
+ doChainedPlugins(conf.AttributeFilterManager, "AttributeFilter", CHAINING_ATTRIBUTE_FILTER, _AttributeFilter, e, log, DUMMY_ATTRIBUTE_FILTER)
+ );
- m_attrResolver =
- doChainedPlugins(conf.AttributeResolverManager, "AttributeResolver", CHAINING_ATTRIBUTE_RESOLVER, _AttributeResolver, e, log);
+ m_attrResolver.reset(
+ doChainedPlugins(conf.AttributeResolverManager, "AttributeResolver", CHAINING_ATTRIBUTE_RESOLVER, _AttributeResolver, e, log)
+ );
if (m_unsetHeaders.empty()) {
vector<string> unsetHeaders;
if (m_attrExtractor) {
- Locker extlock(m_attrExtractor);
+ Locker extlock(m_attrExtractor.get());
m_attrExtractor->getAttributeIds(unsetHeaders);
}
else if (m_base && m_base->m_attrExtractor) {
- Locker extlock(m_base->m_attrExtractor);
+ Locker extlock(m_base->m_attrExtractor.get());
m_base->m_attrExtractor->getAttributeIds(unsetHeaders);
}
if (m_attrResolver) {
- Locker reslock(m_attrResolver);
+ Locker reslock(m_attrResolver.get());
m_attrResolver->getAttributeIds(unsetHeaders);
}
else if (m_base && m_base->m_attrResolver) {
- Locker extlock(m_base->m_attrResolver);
+ Locker extlock(m_base->m_attrResolver.get());
m_base->m_attrResolver->getAttributeIds(unsetHeaders);
}
if (!unsetHeaders.empty()) {
transformed += (isalnum(*pch) ? toupper(*pch) : '_');
pch++;
}
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
+ m_unsetHeaders.push_back(make_pair(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
if (prefix.first)
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
+ m_unsetHeaders.push_back(make_pair(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
}
}
- m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
+ m_unsetHeaders.push_back(make_pair(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
}
}
#endif
-void XMLApplication::cleanup()
-{
- ListenerService* listener=getServiceProvider().getListenerService(false);
- if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
- string addr=string(getId()) + "::getHeaders::Application";
- listener->unregListener(addr.c_str(),this);
- }
- for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());
- m_handlers.clear();
-#ifndef SHIBSP_LITE
- for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());
- m_partyMap.clear();
- delete m_credResolver;
- m_credResolver = nullptr;
- delete m_attrResolver;
- m_attrResolver = nullptr;
- delete m_attrFilter;
- m_attrFilter = nullptr;
- delete m_attrExtractor;
- m_attrExtractor = nullptr;
- delete m_trust;
- m_trust = nullptr;
- delete m_metadata;
- m_metadata = nullptr;
-#endif
-}
-
#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
short
#else
if (!provider)
return this;
- map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());
- if (i!=m_partyMap.end())
- return i->second;
- const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
+ map< xstring,boost::shared_ptr<PropertySet> >::const_iterator i = m_partyMap.find(provider->getEntityID());
+ if (i != m_partyMap.end())
+ return i->second.get();
+ const EntitiesDescriptor* group = dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
while (group) {
if (group->getName()) {
- i=m_partyMap.find(group->getName());
- if (i!=m_partyMap.end())
- return i->second;
+ i = m_partyMap.find(group->getName());
+ if (i != m_partyMap.end())
+ return i->second.get();
}
- group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());
+ group = dynamic_cast<const EntitiesDescriptor*>(group->getParent());
}
return this;
}
{
if (!entityID)
return this;
-
- map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);
- if (i!=m_partyMap.end())
- return i->second;
- return this;
+ map< xstring,boost::shared_ptr<PropertySet> >::const_iterator i = m_partyMap.find(entityID);
+ return (i != m_partyMap.end()) ? i->second.get() : this;
}
#endif
#endif
throw ConfigurationException("Request URL was not absolute.");
- const char* handler=locs[index].c_str();
+ const char* handler = locs[index].c_str();
// Should never happen...
if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const
{
- map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);
- if (i!=m_sessionInitMap.end()) return i->second;
+ map<string,const SessionInitiator*>::const_iterator i = m_sessionInitMap.find(id);
+ if (i != m_sessionInitMap.end()) return i->second;
return m_base ? m_base->getSessionInitiatorById(id) : nullptr;
}
const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const
{
- map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);
+ map<unsigned int,const Handler*>::const_iterator i = m_acsIndexMap.find(index);
if (i != m_acsIndexMap.end()) return i->second;
return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : nullptr;
}
const Handler* XMLApplication::getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding) const
{
- ACSProtocolMap::const_iterator i=m_acsProtocolMap.find(protocol);
+ ACSProtocolMap::const_iterator i = m_acsProtocolMap.find(protocol);
if (i != m_acsProtocolMap.end() && !i->second.empty()) {
if (!binding || !*binding)
return i->second.front();
const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
{
- ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
+ ACSBindingMap::const_iterator i = m_acsBindingMap.find(binding);
if (i != m_acsBindingMap.end())
return i->second;
return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
const Handler* XMLApplication::getHandler(const char* path) const
{
string wrap(path);
- wrap = wrap.substr(0,wrap.find(';'));
- map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));
- if (i!=m_handlerMap.end())
+ wrap = wrap.substr(0, wrap.find(';'));
+ map<string,const Handler*>::const_iterator i = m_handlerMap.find(wrap.substr(0, wrap.find('?')));
+ if (i != m_handlerMap.end())
return i->second;
return m_base ? m_base->getHandler(path) : nullptr;
}
void XMLApplication::getHandlers(vector<const Handler*>& handlers) const
{
- handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end());
+ static void (vector<const Handler*>::* pb)(const Handler* const&) = &vector<const Handler*>::push_back;
+ for_each(m_handlers.begin(), m_handlers.end(), boost::bind(pb, boost::ref(handlers), boost::bind(&boost::shared_ptr<Handler>::get, _1)));
if (m_base) {
for (map<string,const Handler*>::const_iterator h = m_base->m_handlerMap.begin(); h != m_base->m_handlerMap.end(); ++h) {
if (m_handlerMap.count(h->first) == 0)
log.debug("loaded %s extension library (%s)", label, path.c_str());
}
}
- catch (exception& e) {
+ catch (std::exception& e) {
if (XMLHelper::getAttrBool(exts, false, _fatal)) {
log.fatal("unable to load mandatory %s extension library %s: %s", label, path.c_str(), e.what());
throw;
}
log.info("building ListenerService of type %s...", plugtype.c_str());
- conf->m_listener = SPConfig::getConfig().ListenerServiceManager.newPlugin(plugtype.c_str(), child);
+ conf->m_listener.reset(SPConfig::getConfig().ListenerServiceManager.newPlugin(plugtype.c_str(), child));
}
void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& log)
if (!t.empty()) {
try {
log.info("building StorageService (%s) of type %s...", id.c_str(), t.c_str());
- conf->m_storage[id] = xmlConf.StorageServiceManager.newPlugin(t.c_str(), child);
+ conf->m_storage[id] = boost::shared_ptr<StorageService>(xmlConf.StorageServiceManager.newPlugin(t.c_str(), child));
}
- catch (exception& ex) {
+ catch (std::exception& ex) {
log.crit("failed to instantiate StorageService (%s): %s", id.c_str(), ex.what());
}
}
if (conf->m_storage.empty()) {
log.info("no StorageService plugin(s) installed, using (mem) in-memory instance");
- conf->m_storage["mem"] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE, nullptr);
+ conf->m_storage["mem"] = boost::shared_ptr<StorageService>(xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE, nullptr));
}
// Replay cache.
if (!ssid.empty()) {
if (conf->m_storage.count(ssid)) {
log.info("building ReplayCache on top of StorageService (%s)...", ssid.c_str());
- replaySS = conf->m_storage[ssid];
+ replaySS = conf->m_storage[ssid].get();
}
else {
log.error("unable to locate StorageService (%s), using arbitrary instance for ReplayCache", ssid.c_str());
- replaySS = conf->m_storage.begin()->second;
+ replaySS = conf->m_storage.begin()->second.get();
}
}
else {
log.info("no StorageService specified for ReplayCache, using arbitrary instance");
- replaySS = conf->m_storage.begin()->second;
+ replaySS = conf->m_storage.begin()->second.get();
}
}
else {
log.info("no ReplayCache specified, using arbitrary StorageService instance");
- replaySS = conf->m_storage.begin()->second;
+ replaySS = conf->m_storage.begin()->second.get();
}
xmlConf.setReplayCache(new ReplayCache(replaySS));
if (!ssid.empty()) {
if (conf->m_storage.count(ssid)) {
log.info("building ArtifactMap on top of StorageService (%s)...", ssid.c_str());
- samlConf.setArtifactMap(new ArtifactMap(child, conf->m_storage[ssid]));
+ samlConf.setArtifactMap(new ArtifactMap(child, conf->m_storage[ssid].get()));
}
else {
log.error("unable to locate StorageService (%s), using in-memory ArtifactMap", ssid.c_str());
string t(XMLHelper::getAttrString(child, nullptr, _type));
if (!t.empty()) {
log.info("building SessionCache of type %s...", t.c_str());
- conf->m_sessionCache = spConf.SessionCacheManager.newPlugin(t.c_str(), child);
+ conf->m_sessionCache.reset(spConf.SessionCacheManager.newPlugin(t.c_str(), child));
}
}
if (!conf->m_sessionCache) {
log.info("no SessionCache specified, using StorageService-backed instance");
- conf->m_sessionCache = spConf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE, nullptr);
+ conf->m_sessionCache.reset(spConf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE, nullptr));
}
}
-XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log)
- : m_requestMapper(nullptr),
-#ifndef SHIBSP_LITE
- m_tranLog(nullptr),
- m_policy(nullptr),
-#endif
- m_document(nullptr)
+XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log) : m_document(nullptr)
{
#ifdef _DEBUG
xmltooling::NDC ndc("XMLConfigImpl");
#endif
-
- try {
- SPConfig& conf=SPConfig::getConfig();
- XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
- const DOMElement* SHAR=XMLHelper::getFirstChildElement(e, OutOfProcess);
- const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e, InProcess);
-
- // Initialize logging manually in order to redirect log messages as soon as possible.
- if (conf.isEnabled(SPConfig::Logging)) {
- string logconf;
- if (conf.isEnabled(SPConfig::OutOfProcess))
- logconf = XMLHelper::getAttrString(SHAR, nullptr, logger);
- else if (conf.isEnabled(SPConfig::InProcess))
- logconf = XMLHelper::getAttrString(SHIRE, nullptr, logger);
- if (logconf.empty())
- logconf = XMLHelper::getAttrString(e, nullptr, logger);
- if (logconf.empty() && !getenv("SHIBSP_LOGGING")) {
- // No properties found, so default them.
- if (conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess))
- logconf = "shibd.logger";
- else if (!conf.isEnabled(SPConfig::OutOfProcess) && conf.isEnabled(SPConfig::InProcess))
- logconf = "native.logger";
- else
- logconf = "shibboleth.logger";
- }
- if (!logconf.empty()) {
- log.debug("loading new logging configuration from (%s), check log destination for status of configuration", logconf.c_str());
- if (!XMLToolingConfig::getConfig().log_config(logconf.c_str()))
- log.crit("failed to load new logging configuration from (%s)", logconf.c_str());
- }
+ SPConfig& conf=SPConfig::getConfig();
+ XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
+ const DOMElement* SHAR=XMLHelper::getFirstChildElement(e, OutOfProcess);
+ const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e, InProcess);
+
+ // Initialize logging manually in order to redirect log messages as soon as possible.
+ if (conf.isEnabled(SPConfig::Logging)) {
+ string logconf;
+ if (conf.isEnabled(SPConfig::OutOfProcess))
+ logconf = XMLHelper::getAttrString(SHAR, nullptr, logger);
+ else if (conf.isEnabled(SPConfig::InProcess))
+ logconf = XMLHelper::getAttrString(SHIRE, nullptr, logger);
+ if (logconf.empty())
+ logconf = XMLHelper::getAttrString(e, nullptr, logger);
+ if (logconf.empty() && !getenv("SHIBSP_LOGGING")) {
+ // No properties found, so default them.
+ if (conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess))
+ logconf = "shibd.logger";
+ else if (!conf.isEnabled(SPConfig::OutOfProcess) && conf.isEnabled(SPConfig::InProcess))
+ logconf = "native.logger";
+ else
+ logconf = "shibboleth.logger";
+ }
+ if (!logconf.empty()) {
+ log.debug("loading new logging configuration from (%s), check log destination for status of configuration", logconf.c_str());
+ if (!XMLToolingConfig::getConfig().log_config(logconf.c_str()))
+ log.crit("failed to load new logging configuration from (%s)", logconf.c_str());
+ }
#ifndef SHIBSP_LITE
- m_tranLog = new TransactionLog(
+ m_tranLog.reset(
+ new TransactionLog(
XMLHelper::getAttrString(SHAR, nullptr, tranLogFormat).c_str(),
XMLHelper::getAttrString(SHAR, nullptr, tranLogFiller).c_str()
- );
+ )
+ );
#endif
- }
+ }
- // Re-log library versions now that logging is set up.
- log.info("Shibboleth SP Version %s", PACKAGE_VERSION);
+ // Re-log library versions now that logging is set up.
+ log.info("Shibboleth SP Version %s", PACKAGE_VERSION);
#ifndef SHIBSP_LITE
- log.info(
- "Library versions: %s %s, Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",
+ log.info(
+ "Library versions: %s %s, Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",
# if defined(LOG4SHIB_VERSION)
- "log4shib", LOG4SHIB_VERSION,
+ "log4shib", LOG4SHIB_VERSION,
# elif defined(LOG4CPP_VERSION)
- "log4cpp", LOG4CPP_VERSION,
+ "log4cpp", LOG4CPP_VERSION,
# else
- "", "",
+ "", "",
# endif
- XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, gXMLToolingDotVersionStr, gOpenSAMLDotVersionStr, gShibSPDotVersionStr
- );
+ XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, gXMLToolingDotVersionStr, gOpenSAMLDotVersionStr, gShibSPDotVersionStr
+ );
#else
- log.info(
- "Library versions: %s %s, Xerces-C %s, XMLTooling-C %s, Shibboleth %s",
+ log.info(
+ "Library versions: %s %s, Xerces-C %s, XMLTooling-C %s, Shibboleth %s",
# if defined(LOG4SHIB_VERSION)
- "log4shib", LOG4SHIB_VERSION,
+ "log4shib", LOG4SHIB_VERSION,
# elif defined(LOG4CPP_VERSION)
- "log4cpp", LOG4CPP_VERSION,
+ "log4cpp", LOG4CPP_VERSION,
# else
- "", "",
+ "", "",
# endif
- XERCES_FULLVERSIONDOT, gXMLToolingDotVersionStr, gShibSPDotVersionStr
- );
+ XERCES_FULLVERSIONDOT, gXMLToolingDotVersionStr, gShibSPDotVersionStr
+ );
#endif
- // First load any property sets.
- load(e,nullptr,this);
-
- DOMElement* child;
-
- // Much of the processing can only occur on the first instantiation.
- if (first) {
- // Set clock skew.
- pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
- if (skew.first)
- xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
-
- pair<bool,const char*> unsafe = getString("unsafeChars");
- if (unsafe.first)
- TemplateEngine::unsafe_chars = unsafe.second;
-
- unsafe = getString("allowedSchemes");
- if (unsafe.first) {
- HTTPResponse::getAllowedSchemes().clear();
- string schemes=unsafe.second;
- unsigned int j_sch=0;
- for (unsigned int i_sch=0; i_sch < schemes.length(); i_sch++) {
- if (schemes.at(i_sch)==' ') {
- HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, i_sch-j_sch));
- j_sch = i_sch + 1;
- }
- }
- HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, schemes.length()-j_sch));
- }
-
- // Extensions
- doExtensions(e, "global", log);
- if (conf.isEnabled(SPConfig::OutOfProcess))
- doExtensions(SHAR, "out of process", log);
+ // First load any property sets.
+ load(e, nullptr, this);
- if (conf.isEnabled(SPConfig::InProcess))
- doExtensions(SHIRE, "in process", log);
+ DOMElement* child;
- // Instantiate the ListenerService and SessionCache objects.
- if (conf.isEnabled(SPConfig::Listener))
- doListener(e, outer, log);
+ // Much of the processing can only occur on the first instantiation.
+ if (first) {
+ // Set clock skew.
+ pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
+ if (skew.first)
+ xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
-#ifndef SHIBSP_LITE
- if (outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
- outer->m_listener->regListener("set::RelayState", outer);
- outer->m_listener->regListener("get::RelayState", outer);
- outer->m_listener->regListener("set::PostData", outer);
- outer->m_listener->regListener("get::PostData", outer);
- }
-#endif
- if (conf.isEnabled(SPConfig::Caching))
- doCaching(e, outer, log);
- } // end of first-time-only stuff
+ pair<bool,const char*> unsafe = getString("unsafeChars");
+ if (unsafe.first)
+ TemplateEngine::unsafe_chars = unsafe.second;
- // Back to the fully dynamic stuff...next up is the RequestMapper.
- if (conf.isEnabled(SPConfig::RequestMapping)) {
- if (child = XMLHelper::getFirstChildElement(e, _RequestMapper)) {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (!t.empty()) {
- log.info("building RequestMapper of type %s...", t.c_str());
- m_requestMapper = conf.RequestMapperManager.newPlugin(t.c_str(), child);
- }
- }
- if (!m_requestMapper) {
- log.info("no RequestMapper specified, using 'Native' plugin with empty/default map");
- child = e->getOwnerDocument()->createElementNS(nullptr, _RequestMapper);
- DOMElement* mapperDummy = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, RequestMap);
- mapperDummy->setAttributeNS(nullptr, applicationId, _default);
- child->appendChild(mapperDummy);
- m_requestMapper = conf.RequestMapperManager.newPlugin(NATIVE_REQUEST_MAPPER, child);
- }
+ unsafe = getString("allowedSchemes");
+ if (unsafe.first) {
+ HTTPResponse::getAllowedSchemes().clear();
+ string schemes(unsafe.second);
+ split(HTTPResponse::getAllowedSchemes(), schemes, is_space(), algorithm::token_compress_on);
}
+ // Extensions
+ doExtensions(e, "global", log);
+ if (conf.isEnabled(SPConfig::OutOfProcess))
+ doExtensions(SHAR, "out of process", log);
+
+ if (conf.isEnabled(SPConfig::InProcess))
+ doExtensions(SHIRE, "in process", log);
+
+ // Instantiate the ListenerService and SessionCache objects.
+ if (conf.isEnabled(SPConfig::Listener))
+ doListener(e, outer, log);
+
#ifndef SHIBSP_LITE
- // Load security policies.
- if (child = XMLHelper::getLastChildElement(e, _SecurityPolicyProvider)) {
+ if (outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
+ outer->m_listener->regListener("set::RelayState", outer);
+ outer->m_listener->regListener("get::RelayState", outer);
+ outer->m_listener->regListener("set::PostData", outer);
+ outer->m_listener->regListener("get::PostData", outer);
+ }
+#endif
+ if (conf.isEnabled(SPConfig::Caching))
+ doCaching(e, outer, log);
+ } // end of first-time-only stuff
+
+ // Back to the fully dynamic stuff...next up is the RequestMapper.
+ if (conf.isEnabled(SPConfig::RequestMapping)) {
+ if (child = XMLHelper::getFirstChildElement(e, _RequestMapper)) {
string t(XMLHelper::getAttrString(child, nullptr, _type));
if (!t.empty()) {
- log.info("building SecurityPolicyProvider of type %s...", t.c_str());
- m_policy = conf.SecurityPolicyProviderManager.newPlugin(t.c_str(), child);
- }
- else {
- throw ConfigurationException("can't build SecurityPolicyProvider, no type specified");
+ log.info("building RequestMapper of type %s...", t.c_str());
+ m_requestMapper.reset(conf.RequestMapperManager.newPlugin(t.c_str(), child));
}
}
- else if (child = XMLHelper::getLastChildElement(e, SecurityPolicies)) {
- // For backward compatibility, wrap in a plugin element.
- DOMElement* polwrapper = e->getOwnerDocument()->createElementNS(nullptr, _SecurityPolicyProvider);
- polwrapper->appendChild(child);
- log.info("building SecurityPolicyProvider of type %s...", XML_SECURITYPOLICY_PROVIDER);
- m_policy = conf.SecurityPolicyProviderManager.newPlugin(XML_SECURITYPOLICY_PROVIDER, polwrapper);
+ if (!m_requestMapper) {
+ log.info("no RequestMapper specified, using 'Native' plugin with empty/default map");
+ child = e->getOwnerDocument()->createElementNS(nullptr, _RequestMapper);
+ DOMElement* mapperDummy = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, RequestMap);
+ mapperDummy->setAttributeNS(nullptr, applicationId, _default);
+ child->appendChild(mapperDummy);
+ m_requestMapper.reset(conf.RequestMapperManager.newPlugin(NATIVE_REQUEST_MAPPER, child));
+ }
+ }
+
+#ifndef SHIBSP_LITE
+ // Load security policies.
+ if (child = XMLHelper::getLastChildElement(e, _SecurityPolicyProvider)) {
+ string t(XMLHelper::getAttrString(child, nullptr, _type));
+ if (!t.empty()) {
+ log.info("building SecurityPolicyProvider of type %s...", t.c_str());
+ m_policy.reset(conf.SecurityPolicyProviderManager.newPlugin(t.c_str(), child));
}
else {
- log.fatal("can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
- throw ConfigurationException("Can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+ throw ConfigurationException("can't build SecurityPolicyProvider, no type specified");
}
+ }
+ else if (child = XMLHelper::getLastChildElement(e, SecurityPolicies)) {
+ // For backward compatibility, wrap in a plugin element.
+ DOMElement* polwrapper = e->getOwnerDocument()->createElementNS(nullptr, _SecurityPolicyProvider);
+ polwrapper->appendChild(child);
+ log.info("building SecurityPolicyProvider of type %s...", XML_SECURITYPOLICY_PROVIDER);
+ m_policy.reset(conf.SecurityPolicyProviderManager.newPlugin(XML_SECURITYPOLICY_PROVIDER, polwrapper));
+ }
+ else {
+ log.fatal("can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+ throw ConfigurationException("Can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+ }
- if (first) {
- if (!m_policy->getAlgorithmBlacklist().empty()) {
+ if (first) {
+ if (!m_policy->getAlgorithmBlacklist().empty()) {
#ifdef SHIBSP_XMLSEC_WHITELISTING
- for (vector<xstring>::const_iterator alg = m_policy->getAlgorithmBlacklist().begin(); alg != m_policy->getAlgorithmBlacklist().end(); ++alg)
- XSECPlatformUtils::blacklistAlgorithm(alg->c_str());
+ for_each(
+ m_policy->getAlgorithmBlacklist().begin(), m_policy->getAlgorithmBlacklist().end(),
+ boost::bind(&XSECPlatformUtils::blacklistAlgorithm, boost::bind(&xstring::c_str, _1))
+ );
#else
- log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
+ log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
#endif
- }
- else if (!m_policy->getAlgorithmWhitelist().empty()) {
+ }
+ else if (!m_policy->getAlgorithmWhitelist().empty()) {
#ifdef SHIBSP_XMLSEC_WHITELISTING
- for (vector<xstring>::const_iterator alg = m_policy->getAlgorithmWhitelist().begin(); alg != m_policy->getAlgorithmWhitelist().end(); ++alg)
- XSECPlatformUtils::whitelistAlgorithm(alg->c_str());
+ for_each(
+ m_policy->getAlgorithmWhitelist().begin(), m_policy->getAlgorithmWhitelist().end(),
+ boost::bind(&XSECPlatformUtils::whitelistAlgorithm, boost::bind(&xstring::c_str, _1))
+ );
#else
- log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
+ log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
#endif
- }
}
+ }
- // Process TransportOption elements.
- child = XMLHelper::getLastChildElement(e, TransportOption);
- while (child) {
- if (child->hasChildNodes()) {
- string provider(XMLHelper::getAttrString(child, nullptr, _provider));
- string option(XMLHelper::getAttrString(child, nullptr, _option));
- auto_ptr_char value(child->getFirstChild()->getNodeValue());
- if (!provider.empty() && !option.empty() && value.get() && *value.get()) {
- m_transportOptions.push_back(make_pair(provider, make_pair(option, string(value.get()))));
- }
+ // Process TransportOption elements.
+ child = XMLHelper::getLastChildElement(e, TransportOption);
+ while (child) {
+ if (child->hasChildNodes()) {
+ string provider(XMLHelper::getAttrString(child, nullptr, _provider));
+ string option(XMLHelper::getAttrString(child, nullptr, _option));
+ auto_ptr_char value(child->getFirstChild()->getNodeValue());
+ if (!provider.empty() && !option.empty() && value.get() && *value.get()) {
+ m_transportOptions.push_back(make_tuple(provider, option, string(value.get())));
}
- child = XMLHelper::getPreviousSiblingElement(child, TransportOption);
}
+ child = XMLHelper::getPreviousSiblingElement(child, TransportOption);
+ }
#endif
- ProtocolProvider* pp = nullptr;
- if (conf.isEnabled(SPConfig::Handlers)) {
- if (child = XMLHelper::getLastChildElement(e, _ProtocolProvider)) {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (!t.empty()) {
- log.info("building ProtocolProvider of type %s...", t.c_str());
- pp = conf.ProtocolProviderManager.newPlugin(t.c_str(), child);
- }
+ scoped_ptr<ProtocolProvider> pp;
+ if (conf.isEnabled(SPConfig::Handlers)) {
+ if (child = XMLHelper::getLastChildElement(e, _ProtocolProvider)) {
+ string t(XMLHelper::getAttrString(child, nullptr, _type));
+ if (!t.empty()) {
+ log.info("building ProtocolProvider of type %s...", t.c_str());
+ pp.reset(conf.ProtocolProviderManager.newPlugin(t.c_str(), child));
}
}
- auto_ptr<ProtocolProvider> ppwrapper(pp);
- Locker pplocker(pp);
+ }
+ Locker pplocker(pp.get());
- // Load the default application.
- child = XMLHelper::getLastChildElement(e, ApplicationDefaults);
- if (!child) {
- log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
- throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
- }
- XMLApplication* defapp = new XMLApplication(outer, pp, child);
- m_appmap[defapp->getId()] = defapp;
+ // Load the default application.
+ child = XMLHelper::getLastChildElement(e, ApplicationDefaults);
+ if (!child) {
+ log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
+ throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
+ }
+ boost::shared_ptr<XMLApplication> defapp(new XMLApplication(outer, pp.get(), child));
+ m_appmap[defapp->getId()] = defapp;
- // Load any overrides.
- child = XMLHelper::getFirstChildElement(child, ApplicationOverride);
- while (child) {
- auto_ptr<XMLApplication> iapp(new XMLApplication(outer, pp, child, defapp));
- if (m_appmap.count(iapp->getId()))
- log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
- else {
- const char* iappid=iapp->getId();
- m_appmap[iappid] = iapp.release();
- }
+ // Load any overrides.
+ child = XMLHelper::getFirstChildElement(child, ApplicationOverride);
+ while (child) {
+ boost::shared_ptr<XMLApplication> iapp(new XMLApplication(outer, pp.get(), child, defapp.get()));
+ if (m_appmap.count(iapp->getId()))
+ log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
+ else
+ m_appmap[iapp->getId()] = iapp;
- child = XMLHelper::getNextSiblingElement(child, ApplicationOverride);
- }
-
- // Check for extra AuthTypes to recognize.
- if (conf.isEnabled(SPConfig::InProcess)) {
- const PropertySet* inprocs = getPropertySet("InProcess");
- if (inprocs) {
- pair<bool,const char*> extraAuthTypes = inprocs->getString("extraAuthTypes");
- if (extraAuthTypes.first) {
- string types=extraAuthTypes.second;
- unsigned int j_types=0;
- for (unsigned int i_types=0; i_types < types.length(); i_types++) {
- if (types.at(i_types) == ' ') {
- outer->m_authTypes.insert(types.substr(j_types, i_types - j_types));
- j_types = i_types + 1;
- }
- }
- outer->m_authTypes.insert(types.substr(j_types, types.length() - j_types));
- }
+ child = XMLHelper::getNextSiblingElement(child, ApplicationOverride);
+ }
+
+ // Check for extra AuthTypes to recognize.
+ if (conf.isEnabled(SPConfig::InProcess)) {
+ const PropertySet* inprocs = getPropertySet("InProcess");
+ if (inprocs) {
+ pair<bool,const char*> extraAuthTypes = inprocs->getString("extraAuthTypes");
+ if (extraAuthTypes.first) {
+ string types(extraAuthTypes.second);
+ split(outer->m_authTypes, types, is_space(), algorithm::token_compress_on);
}
}
}
- catch (exception&) {
- cleanup();
- throw;
- }
-}
-
-XMLConfigImpl::~XMLConfigImpl()
-{
- cleanup();
-}
-
-void XMLConfigImpl::cleanup()
-{
- for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());
- m_appmap.clear();
-#ifndef SHIBSP_LITE
- delete m_policy;
- m_policy = nullptr;
- delete m_tranLog;
- m_tranLog = nullptr;
-#endif
- delete m_requestMapper;
- m_requestMapper = nullptr;
- if (m_document)
- m_document->release();
- m_document = nullptr;
}
#ifndef SHIBSP_LITE
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
- XMLConfigImpl* impl = new XMLConfigImpl(raw.second, (m_impl==nullptr), this, m_log);
+ scoped_ptr<XMLConfigImpl> impl(new XMLConfigImpl(raw.second, (m_impl==nullptr), this, m_log));
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_impl;
- m_impl = impl;
+ m_impl.swap(impl);
return make_pair(false,(DOMElement*)nullptr);
}
#include "ServiceProvider.h"
#include "metadata/MetadataProviderCriteria.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/regx/RegularExpression.hpp>
using namespace std;
namespace shibsp {
- class SAML_DLLLOCAL DummyCredentialResolver : public CredentialResolver
- {
- public:
- DummyCredentialResolver() {}
- ~DummyCredentialResolver() {}
-
- Lockable* lock() {return this;}
- void unlock() {}
-
- const Credential* resolve(const CredentialCriteria* criteria=nullptr) const {return nullptr;}
- vector<const Credential*>::size_type resolve(
- vector<const Credential*>& results, const CredentialCriteria* criteria=nullptr
- ) const {return 0;}
- };
-
class SHIBSP_DLLLOCAL DynamicMetadataProvider : public saml2md::DynamicMetadataProvider
{
public:
DynamicMetadataProvider(const xercesc::DOMElement* e=nullptr);
- virtual ~DynamicMetadataProvider() {
- delete m_trust;
- }
+ virtual ~DynamicMetadataProvider() {}
protected:
saml2md::EntityDescriptor* resolve(const saml2md::MetadataProvider::Criteria& criteria) const;
private:
bool m_verifyHost,m_ignoreTransport,m_encoded;
string m_subst, m_match, m_regex;
- X509TrustEngine* m_trust;
+ boost::scoped_ptr<X509TrustEngine> m_trust;
+ boost::scoped_ptr<CredentialResolver> m_dummyCR;
};
-
saml2md::MetadataProvider* SHIBSP_DLLLOCAL DynamicMetadataProviderFactory(const DOMElement* const & e)
{
return new DynamicMetadataProvider(e);
static const XMLCh Regex[] = UNICODE_LITERAL_5(R,e,g,e,x);
static const XMLCh Subst[] = UNICODE_LITERAL_5(S,u,b,s,t);
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 _type[] = UNICODE_LITERAL_4(t,y,p,e);
static const XMLCh verifyHost[] = UNICODE_LITERAL_10(v,e,r,i,f,y,H,o,s,t);
};
if (!m_ignoreTransport) {
child = XMLHelper::getFirstChildElement(e, _TrustEngine);
- string t = XMLHelper::getAttrString(child, nullptr, type);
+ string t = XMLHelper::getAttrString(child, nullptr, _type);
if (!t.empty()) {
TrustEngine* trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child);
- if (!(m_trust = dynamic_cast<X509TrustEngine*>(trust))) {
+ if (!dynamic_cast<X509TrustEngine*>(trust)) {
delete trust;
throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin.");
}
+ m_trust.reset(dynamic_cast<X509TrustEngine*>(trust));
+ m_dummyCR.reset(XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(DUMMY_CREDENTIAL_RESOLVER, nullptr));
}
- if (!m_trust)
+ if (!m_trust.get() || !m_dummyCR.get())
throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin unless ignoreTransport is true.");
}
}
// Possibly transform the input into a different URL to use.
if (!m_subst.empty()) {
- string::size_type pos = m_subst.find("$entityID");
- if (pos != string::npos) {
- string name2 = m_subst;
- name2.replace(pos, 9, m_encoded ? XMLToolingConfig::getConfig().getURLEncoder()->encode(name.c_str()) : name);
- log.info("transformed location from (%s) to (%s)", name.c_str(), name2.c_str());
- name = name2;
- }
+ string name2 = boost::replace_first_copy(m_subst, "$entityID",
+ m_encoded ? XMLToolingConfig::getConfig().getURLEncoder()->encode(name.c_str()) : name);
+ log.info("transformed location from (%s) to (%s)", name.c_str(), name2.c_str());
+ name = name2;
}
else if (!m_match.empty() && !m_regex.empty()) {
try {
if (!pch)
throw IOException("location was not a URL.");
string scheme(addr.m_endpoint, pch-addr.m_endpoint);
- SOAPTransport* transport=nullptr;
+ boost::scoped_ptr<SOAPTransport> transport;
try {
- transport = XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr);
+ transport.reset(XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr));
}
catch (exception& ex) {
log.error("exception while building transport object to resolve URL: %s", ex.what());
throw IOException("Unable to resolve entityID with a known transport protocol.");
}
- auto_ptr<SOAPTransport> transportwrapper(transport);
// Apply properties as directed.
transport->setVerifyHost(m_verifyHost);
- DummyCredentialResolver dcr;
- if (m_trust && !transport->setTrustEngine(m_trust, &dcr))
- throw IOException("Unable to install X509TrustEngine into metadata resolver.");
+ if (m_trust.get() && m_dummyCR.get() && !transport->setTrustEngine(m_trust.get(), m_dummyCR.get()))
+ throw IOException("Unable to install X509TrustEngine into transport object.");
Locker credlocker(nullptr, false);
CredentialResolver* credResolver = nullptr;
transport->setTimeout(timeout.first ? timeout.second : 20);
mpc->application.getServiceProvider().setTransportOptions(*transport);
- HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(transport);
+ HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(transport.get());
if (http) {
pair<bool,bool> flag = relyingParty->getBool("chunkedEncoding");
http->useChunkedEncoding(flag.first && flag.second);
http->setRequestHeader("Xerces-C", XERCES_FULLVERSIONDOT);
http->setRequestHeader("XML-Security-C", XSEC_FULLVERSIONDOT);
- http->setRequestHeader("OpenSAML-C", OPENSAML_FULLVERSIONDOT);
- http->setRequestHeader("User-Agent", PACKAGE_NAME);
+ http->setRequestHeader("OpenSAML-C", gOpenSAMLDotVersionStr);
http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
}
#include <boost/lexical_cast.hpp>
#include <boost/lambda/bind.hpp>
-#include <boost/lambda/casts.hpp>
#include <boost/lambda/if.hpp>
#include <boost/lambda/lambda.hpp>
#include <xmltooling/AbstractComplexElement.h>
DDF getmember(const char* path) const;
// debugging
- void dump(FILE* f=nullptr, int indent=0) const;
+ void dump(std::FILE* f=nullptr, int indent=0) const;
// serialization functions need private access
friend SHIBSP_API std::ostream& operator<<(std::ostream& os, const DDF& obj);
Category& m_log;
const SocketListener* m_listener;
- auto_ptr<Mutex> m_lock;
+ boost::scoped_ptr<Mutex> m_lock;
stack<SocketListener::ShibSocket> m_pool;
};
void SocketPool::put(SocketListener::ShibSocket s)
{
- m_lock->lock();
+ Lock lock(m_lock);
m_pool.push(s);
- m_lock->unlock();
}
SocketListener::SocketListener(const DOMElement* e)
- : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")), m_socketpool(nullptr),
- m_shutdown(nullptr), m_child_lock(nullptr), m_child_wait(nullptr), m_stackSize(0), m_socket((ShibSocket)0)
+ : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")),
+ m_shutdown(nullptr), m_stackSize(0), m_socket((ShibSocket)0)
{
// Are we a client?
if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
- m_socketpool=new SocketPool(*log,this);
+ m_socketpool.reset(new SocketPool(*log,this));
}
// Are we a server?
if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- m_child_lock = Mutex::create();
- m_child_wait = CondWait::create();
+ m_child_lock.reset(Mutex::create());
+ m_child_wait.reset(CondWait::create());
static const XMLCh stackSize[] = UNICODE_LITERAL_9(s,t,a,c,k,S,i,z,e);
m_stackSize = XMLHelper::getAttrInt(e, 0, stackSize) * 1024;
SocketListener::~SocketListener()
{
- delete m_socketpool;
- delete m_child_wait;
- delete m_child_lock;
}
bool SocketListener::init(bool force)
NDC ndc("run");
#endif
// Save flag to monitor for shutdown request.
- m_shutdown=shutdown;
+ m_shutdown = shutdown;
unsigned long count = 0;
while (!*m_shutdown) {
// We throw away the result because the children manage themselves...
try {
- new ServerThread(newsock,this,++count);
+ new ServerThread(newsock, this, ++count);
}
catch (exception& ex) {
log->crit("exception starting new server thread to service incoming request: %s", ex.what());
// Wait for all children to exit.
m_child_lock->lock();
while (!m_children.empty())
- m_child_wait->wait(m_child_lock);
+ m_child_wait->wait(m_child_lock.get());
m_child_lock->unlock();
return true;
throw ListenerException("Remote call failed with an unparsable exception.");
}
- auto_ptr<XMLToolingException> wrapper(except);
+ boost::scoped_ptr<XMLToolingException> wrapper(except);
wrapper->raise();
}
// Before starting up, make sure we fully "own" this socket.
m_listener->m_child_lock->lock();
- while (m_listener->m_children.find(m_sock)!=m_listener->m_children.end())
- m_listener->m_child_wait->wait(m_listener->m_child_lock);
+ while (m_listener->m_children.find(m_sock) != m_listener->m_children.end())
+ m_listener->m_child_wait->wait(m_listener->m_child_lock.get());
m_listener->m_children[m_sock] = m_child;
m_listener->m_child_lock->unlock();
#include <shibsp/remoting/ListenerService.h>
+#include <boost/scoped_ptr.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xmltooling/logging.h>
#include <xmltooling/util/Threads.h>
/// @endcond
private:
- mutable SocketPool* m_socketpool;
+ boost::scoped_ptr<SocketPool> m_socketpool;
bool* m_shutdown;
// Manage child threads
friend class ServerThread;
std::map<ShibSocket,xmltooling::Thread*> m_children;
- xmltooling::Mutex* m_child_lock;
- xmltooling::CondWait* m_child_wait;
+ boost::scoped_ptr<xmltooling::Mutex> m_child_lock;
+ boost::scoped_ptr<xmltooling::CondWait> m_child_wait;
unsigned int m_stackSize;
#include "remoting/impl/SocketListener.h"
#include "util/IPRange.h"
+#include <boost/bind.hpp>
+#include <boost/algorithm/string.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/unicode.h>
#include <xmltooling/util/XMLHelper.h>
using namespace shibsp;
using namespace xmltooling;
using namespace xercesc;
+using namespace boost;
using namespace std;
namespace shibsp {
m_port = 1600;
}
- int j = 0;
+ vector<string> rawacls;
string aclbuf = XMLHelper::getAttrString(e, "127.0.0.1", acl);
- for (unsigned int i = 0; i < aclbuf.length(); ++i) {
- if (aclbuf.at(i) == ' ') {
- try {
- m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
- }
- catch (exception& ex) {
- log->error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
- }
- j = i + 1;
+ boost::split(rawacls, aclbuf, boost::is_space(), algorithm::token_compress_on);
+ for (vector<string>::const_iterator i = rawacls.begin(); i < rawacls.end(); ++i) {
+ try {
+ m_acl.push_back(IPRange::parseCIDRBlock(i->c_str()));
+ }
+ catch (std::exception& ex) {
+ log->error("invalid CIDR block (%s): %s", i->c_str(), ex.what());
}
- }
- try {
- m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
- }
- catch (exception& ex) {
- log->error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
}
if (m_acl.empty()) {
if (s < 0)
#endif
return log_error("accept");
- bool found = false;
- for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
- found = acl->contains((const struct sockaddr*)&addr);
- }
- if (!found) {
+
+ static bool (IPRange::* contains)(const struct sockaddr*) const = &IPRange::contains;
+ if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, (const struct sockaddr*)&addr)) == m_acl.end()) {
close(s);
s = -1;
log->error("accept() rejected client with invalid address");
#include "internal.h"
#include "remoting/ddf.h"
-#ifdef WIN32
-# define snprintf _snprintf
-#endif
-
#include <stdexcept>
+#include <boost/lexical_cast.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xmltooling/XMLToolingConfig.h>
DDF& DDF::string(long val)
{
- char buf[20];
-
- sprintf(buf,"%ld",val);
- return string(buf);
+ std::string buf = boost::lexical_cast<std::string>(val);
+ return string(buf.c_str());
}
DDF& DDF::string(double val)
{
- char buf[40];
-
- snprintf(buf,39,"%f",val);
- return string(buf);
+ std::string buf = boost::lexical_cast<std::string>(val);
+ return string(buf.c_str());
}
DDF& DDF::integer(long val)
#include "metadata/MetadataExt.h"
#include "security/PKIXTrustEngine.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/saml2/metadata/ObservableMetadataProvider.h>
using namespace opensaml::saml2md;
using namespace xmlsignature;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace shibsp {
virtual ~PKIXTrustEngine() {
for (map<const ObservableMetadataProvider*,credmap_t>::iterator i=m_credentialMap.begin(); i!=m_credentialMap.end(); ++i) {
i->first->removeObserver(this);
- for (credmap_t::iterator creds = i->second.begin(); creds!=i->second.end(); ++creds)
- for_each(creds->second.begin(), creds->second.end(), xmltooling::cleanup<X509Credential>());
}
- delete m_credLock;
}
AbstractPKIXTrustEngine::PKIXValidationInfoIterator* getPKIXValidationInfoIterator(
void onEvent(const ObservableMetadataProvider& metadata) const {
// Destroy credentials we cached from this provider.
m_credLock->wrlock();
- credmap_t& cmap = m_credentialMap[&metadata];
- for (credmap_t::iterator creds = cmap.begin(); creds!=cmap.end(); ++creds)
- for_each(creds->second.begin(), creds->second.end(), xmltooling::cleanup<X509Credential>());
- cmap.clear();
- m_credLock->unlock();
+ SharedLock locker(m_credLock, false);
+ m_credentialMap[&metadata].clear();
}
const KeyInfoResolver* getKeyInfoResolver() const {
private:
friend class SHIBSP_DLLLOCAL MetadataPKIXIterator;
- mutable RWLock* m_credLock;
- typedef map< const KeyAuthority*,vector<X509Credential*> > credmap_t;
+ scoped_ptr<RWLock> m_credLock;
+ typedef map< const KeyAuthority*,vector< boost::shared_ptr<X509Credential> > > credmap_t;
mutable map<const ObservableMetadataProvider*,credmap_t> m_credentialMap;
};
virtual ~MetadataPKIXIterator() {
if (m_caching)
m_engine.m_credLock->unlock();
- for_each(m_ownedCreds.begin(), m_ownedCreds.end(), xmltooling::cleanup<Credential>());
}
bool next();
vector<XMLObject*>::const_iterator m_iter;
vector<XSECCryptoX509*> m_certs;
vector<XSECCryptoX509CRL*> m_crls;
- vector<X509Credential*> m_ownedCreds;
+ vector< boost::shared_ptr<X509Credential> > m_ownedCreds;
};
};
// While holding read lock, see if this metadata plugin has been seen before.
m_engine.m_credLock->rdlock();
m_credCache = m_engine.m_credentialMap.find(observable);
- if (m_credCache==m_engine.m_credentialMap.end()) {
+ if (m_credCache == m_engine.m_credentialMap.end()) {
// We need to elevate the lock and retry.
m_engine.m_credLock->unlock();
m_engine.m_credLock->wrlock();
m_credCache = m_engine.m_credentialMap.find(observable);
- if (m_credCache==m_engine.m_credentialMap.end()) {
+ if (m_credCache == m_engine.m_credentialMap.end()) {
+ try {
+ // It's still brand new, so hook it for cache activation.
+ observable->addObserver(&m_engine);
- // It's still brand new, so hook it for cache activation.
- observable->addObserver(&m_engine);
-
- // Prime the map reference with an empty credential map.
- m_credCache = m_engine.m_credentialMap.insert(make_pair(observable,PKIXTrustEngine::credmap_t())).first;
+ // Prime the map reference with an empty credential map.
+ m_credCache = m_engine.m_credentialMap.insert(make_pair(observable,PKIXTrustEngine::credmap_t())).first;
+ }
+ catch (std::exception&) {
+ // The destructor won't run if we throw here, so we need to unlock.
+ m_engine.m_credLock->unlock();
+ throw;
+ }
// Downgrade the lock.
// We don't have to recheck because we never erase the master map entry entirely, even on changes.
// Dump anything old.
m_certs.clear();
m_crls.clear();
- for_each(m_ownedCreds.begin(), m_ownedCreds.end(), xmltooling::cleanup<Credential>());
+ m_ownedCreds.clear();
if (m_caching) {
// We're holding a read lock. Search for "resolved" creds.
PKIXTrustEngine::credmap_t::iterator cached = m_credCache->second.find(m_current);
- if (cached!=m_credCache->second.end()) {
+ if (cached != m_credCache->second.end()) {
// Copy over the information.
- for (vector<X509Credential*>::const_iterator c=cached->second.begin(); c!=cached->second.end(); ++c) {
+ for (vector< boost::shared_ptr<X509Credential> >::const_iterator c = cached->second.begin(); c != cached->second.end(); ++c) {
m_certs.insert(m_certs.end(), (*c)->getEntityCertificateChain().begin(), (*c)->getEntityCertificateChain().end());
if ((*c)->getCRL())
m_crls.push_back((*c)->getCRL());
// We're either not caching or didn't find the results we need, so we have to resolve them.
const vector<KeyInfo*>& keyInfos = m_current->getKeyInfos();
- for (vector<KeyInfo*>::const_iterator k = keyInfos.begin(); k!=keyInfos.end(); ++k) {
- auto_ptr<Credential> cred (m_engine.getKeyInfoResolver()->resolve(*k, X509Credential::RESOLVE_CERTS | X509Credential::RESOLVE_CRLS));
- X509Credential* xcred = dynamic_cast<X509Credential*>(cred.get());
- if (xcred) {
+ for (vector<KeyInfo*>::const_iterator k = keyInfos.begin(); k != keyInfos.end(); ++k) {
+ boost::shared_ptr<Credential> cred(m_engine.getKeyInfoResolver()->resolve(*k, X509Credential::RESOLVE_CERTS | X509Credential::RESOLVE_CRLS));
+ boost::shared_ptr<X509Credential> xcred = boost::dynamic_pointer_cast<X509Credential>(cred);
+ if (xcred)
m_ownedCreds.push_back(xcred);
- cred.release();
- }
}
// Copy over the new information.
- for (vector<X509Credential*>::const_iterator c=m_ownedCreds.begin(); c!=m_ownedCreds.end(); ++c) {
+ for (vector< boost::shared_ptr<X509Credential> >::const_iterator c = m_ownedCreds.begin(); c != m_ownedCreds.end(); ++c) {
m_certs.insert(m_certs.end(), (*c)->getEntityCertificateChain().begin(), (*c)->getEntityCertificateChain().end());
if ((*c)->getCRL())
m_crls.push_back((*c)->getCRL());
if (m_caching) {
m_engine.m_credLock->unlock();
m_engine.m_credLock->wrlock();
- if (m_credCache->second.count(m_current)==0) {
+ if (m_credCache->second.count(m_current) == 0) {
// Transfer objects into cache.
m_credCache->second[m_current] = m_ownedCreds;
m_ownedCreds.clear();
#include "internal.h"
#include "util/CGIParser.h"
+#include <boost/bind.hpp>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/io/HTTPRequest.h>
#include <xmltooling/util/URLEncoder.h>
using namespace shibsp;
using namespace xmltooling;
+using namespace boost;
using namespace std;
namespace {
CGIParser::~CGIParser()
{
- for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
- free(i->second);
+ for_each(kvp_map.begin(), kvp_map.end(), boost::bind(&free, boost::bind(&multimap<string,char*>::value_type::second, _1)));
}
void CGIParser::parse(const char* pch)
DOMPropertySet::~DOMPropertySet()
{
- for (map<string,pair<char*,const XMLCh*> >::iterator i=m_map.begin(); i!=m_map.end(); i++)
+ for (map<string,pair<char*,const XMLCh*> >::iterator i = m_map.begin(); i != m_map.end(); ++i)
XMLString::release(&(i->second.first));
- for_each(m_nested.begin(),m_nested.end(),cleanup_pair<string,DOMPropertySet>());
}
const PropertySet* DOMPropertySet::getParent() const
}
// Process non-excluded elements as nested sets.
- DOMTreeWalker* walker=
+ DOMTreeWalker* walker =
static_cast<DOMDocumentTraversal*>(
m_root->getOwnerDocument())->createTreeWalker(const_cast<DOMElement*>(m_root),DOMNodeFilter::SHOW_ELEMENT,filter,false
);
- e=static_cast<DOMElement*>(walker->firstChild());
+ e = static_cast<DOMElement*>(walker->firstChild());
while (e) {
auto_ptr_char ns(e->getNamespaceURI());
auto_ptr_char name(e->getLocalName());
const char* realname=name.get();
map<string,string>::const_iterator remap;
if (remapper) {
- remap=remapper->find(realname);
- if (remap!=remapper->end()) {
- log->warn("deprecation - remapping nested property set (%s) to (%s)",realname,remap->second.c_str());
- realname=remap->second.c_str();
+ remap = remapper->find(realname);
+ if (remap != remapper->end()) {
+ log->warn("deprecation - remapping nested property set (%s) to (%s)", realname, remap->second.c_str());
+ realname = remap->second.c_str();
}
}
string key;
if (ns.get()) {
- if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
- key=string("{") + remap->second.c_str() + '}' + realname;
+ if (remapper && (remap = remapper->find(ns.get())) != remapper->end())
+ key = string("{") + remap->second.c_str() + '}' + realname;
else
- key=string("{") + ns.get() + '}' + realname;
+ key = string("{") + ns.get() + '}' + realname;
}
else
- key=realname;
- if (m_nested.find(key)!=m_nested.end())
- log->warn("load() skipping duplicate property set: %s",key.c_str());
+ key = realname;
+ if (m_nested.find(key) != m_nested.end())
+ log->warn("load() skipping duplicate property set: %s", key.c_str());
else {
- DOMPropertySet* set=new DOMPropertySet();
- set->load(e,log,filter,remapper);
- m_nested[key]=set;
- log->debug("added nested property set: %s",key.c_str());
+ boost::shared_ptr<DOMPropertySet> newset(new DOMPropertySet());
+ newset->load(e,log,filter,remapper);
+ m_nested[key] = newset;
+ log->debug("added nested property set: %s", key.c_str());
}
- e=static_cast<DOMElement*>(walker->nextSibling());
+ e = static_cast<DOMElement*>(walker->nextSibling());
}
walker->release();
}
const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
{
- map<string,DOMPropertySet*>::const_iterator i;
+ map<string,boost::shared_ptr<DOMPropertySet>>::const_iterator i;
if (ns)
- i=m_nested.find(string("{") + ns + '}' + name);
+ i = m_nested.find(string("{") + ns + '}' + name);
else
- i=m_nested.find(name);
+ i = m_nested.find(name);
- return (i!=m_nested.end()) ? i->second : (m_parent ? m_parent->getPropertySet(name,ns) : nullptr);
+ return (i != m_nested.end()) ? i->second.get() : (m_parent ? m_parent->getPropertySet(name,ns) : nullptr);
}
bool DOMPropertySet::setProperty(const char* name, const char* val, const char* ns)
#include <shibsp/util/PropertySet.h>
+#include <boost/shared_ptr.hpp>
#include <xmltooling/logging.h>
namespace shibsp {
const PropertySet* m_parent;
const xercesc::DOMElement* m_root;
std::map<std::string,std::pair<char*,const XMLCh*> > m_map;
- std::map<std::string,DOMPropertySet*> m_nested;
+ std::map<std::string,boost::shared_ptr<DOMPropertySet>> m_nested;
std::vector<xmltooling::xstring> m_injected;
};
string q;
const URLEncoder* enc = XMLToolingConfig::getConfig().getURLEncoder();
- for (map<string,string>::const_iterator i=m_map.begin(); i!=m_map.end(); i++)
+ for (map<string,string>::const_iterator i = m_map.begin(); i != m_map.end(); ++i)
q = q + '&' + i->first + '=' + enc->encode(i->second.c_str());
// Add in the exception content.