# include "attribute/resolver/AttributeExtractor.h"
# include "attribute/resolver/AttributeResolver.h"
# include "security/PKIXTrustEngine.h"
+# include "security/SecurityPolicyProvider.h"
# include <saml/SAMLConfig.h>
# include <saml/version.h>
# include <saml/binding/ArtifactMap.h>
# include <saml/binding/SAMLArtifact.h>
-# include <saml/binding/SecurityPolicyRule.h>
# include <saml/saml1/core/Assertions.h>
# include <saml/saml2/core/Assertions.h>
# include <saml/saml2/binding/SAML2ArtifactType0004.h>
# include <xmltooling/security/TrustEngine.h>
# include <xmltooling/util/ReplayCache.h>
# include <xmltooling/util/StorageService.h>
-# include <xercesc/util/XMLStringTokenizer.hpp>
# include <xsec/utils/XSECPlatformUtils.hpp>
using namespace opensaml::saml2;
using namespace opensaml::saml2p;
RequestMapper* m_requestMapper;
map<string,Application*> m_appmap;
#ifndef SHIBSP_LITE
- map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
+ SecurityPolicyProvider* m_policy;
vector< pair< string, pair<string,string> > > m_transportOptions;
#endif
#endif
}
+#ifndef SHIBSP_LITE
+ // Lockable
+ Lockable* lock() {
+ ReloadableXMLFile::lock();
+ if (m_impl->m_policy)
+ m_impl->m_policy->lock();
+ return this;
+ }
+ void unlock() {
+ if (m_impl->m_policy)
+ m_impl->m_policy->unlock();
+ ReloadableXMLFile::unlock();
+ }
+#endif
+
// PropertySet
const PropertySet* getParent() const { return m_impl->getParent(); }
void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}
}
#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;
+ }
+
const PropertySet* getPolicySettings(const char* id) const {
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
- if (i!=m_impl->m_policyMap.end())
- return i->second.first;
- throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
+ return getSecurityPolicyProvider()->getPolicySettings(id);
}
const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {
- map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
- if (i!=m_impl->m_policyMap.end())
- return i->second.second;
- throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
+ return getSecurityPolicyProvider()->getPolicyRules(id);
}
bool setTransportOptions(SOAPTransport& transport) const {
#pragma warning( pop )
#endif
- static const XMLCh AlgorithmBlacklist[] = UNICODE_LITERAL_18(A,l,g,o,r,i,t,h,m,B,l,a,c,k,l,i,s,t);
- static const XMLCh AlgorithmWhitelist[] = UNICODE_LITERAL_18(A,l,g,o,r,i,t,h,m,W,h,i,t,e,l,i,s,t);
static const XMLCh ApplicationOverride[] = UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,O,v,e,r,r,i,d,e);
static const XMLCh ApplicationDefaults[] = UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,D,e,f,a,u,l,t,s);
static const XMLCh _ArtifactMap[] = UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);
static const XMLCh _option[] = UNICODE_LITERAL_6(o,p,t,i,o,n);
static const XMLCh OutOfProcess[] = UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);
static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h);
- static const XMLCh Policy[] = UNICODE_LITERAL_6(P,o,l,i,c,y);
- static const XMLCh PolicyRule[] = UNICODE_LITERAL_10(P,o,l,i,c,y,R,u,l,e);
static const XMLCh _provider[] = UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);
static const XMLCh RelyingParty[] = UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);
static const XMLCh _ReplayCache[] = UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);
static const XMLCh _RequestMapper[] = UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);
- static const XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e);
static const XMLCh SecurityPolicies[] = UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);
+ static const XMLCh SecurityPolicyProvider[] = UNICODE_LITERAL_22(S,e,c,u,r,i,t,y,P,o,l,i,c,y,P,r,o,v,i,d,e,r);
static const XMLCh _SessionCache[] = UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);
static const XMLCh _SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);
static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
static const XMLCh UnixListener[] = UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);
-
-#ifndef SHIBSP_LITE
- class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter
- {
- public:
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
- short
-#else
- FilterAction
-#endif
- acceptNode(const DOMNode* node) const {
- return FILTER_REJECT;
- }
- };
-#endif
};
namespace shibsp {
XMLString::equals(name,_RequestMapper) ||
XMLString::equals(name,_ReplayCache) ||
XMLString::equals(name,SecurityPolicies) ||
+ XMLString::equals(name,SecurityPolicyProvider) ||
XMLString::equals(name,_SessionCache) ||
XMLString::equals(name,Site) ||
XMLString::equals(name,_StorageService) ||
void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Category& log)
{
- const DOMElement* exts=XMLHelper::getFirstChildElement(e,_Extensions);
+ const DOMElement* exts = XMLHelper::getFirstChildElement(e, _Extensions);
if (exts) {
- exts=XMLHelper::getFirstChildElement(exts,Library);
+ exts = XMLHelper::getFirstChildElement(exts, Library);
while (exts) {
- auto_ptr_char path(exts->getAttributeNS(nullptr,_path));
+ string path(XMLHelper::getAttrString(exts, nullptr, _path));
try {
- if (path.get()) {
- if (!XMLToolingConfig::getConfig().load_library(path.get(),(void*)exts))
+ if (!path.empty()) {
+ if (!XMLToolingConfig::getConfig().load_library(path.c_str(), (void*)exts))
throw ConfigurationException("XMLToolingConfig::load_library failed.");
- log.debug("loaded %s extension library (%s)", label, path.get());
+ log.debug("loaded %s extension library (%s)", label, path.c_str());
}
}
catch (exception& e) {
- const XMLCh* fatal=exts->getAttributeNS(nullptr,_fatal);
- if (fatal && (*fatal==chLatin_t || *fatal==chDigit_1)) {
- log.fatal("unable to load mandatory %s extension library %s: %s", label, path.get(), e.what());
+ if (XMLHelper::getAttrBool(exts, false, _fatal)) {
+ log.fatal("unable to load mandatory %s extension library %s: %s", label, path.c_str(), e.what());
throw;
}
else {
- log.crit("unable to load optional %s extension library %s: %s", label, path.get(), e.what());
+ log.crit("unable to load optional %s extension library %s: %s", label, path.c_str(), e.what());
}
}
- exts=XMLHelper::getNextSiblingElement(exts,Library);
+ exts = XMLHelper::getNextSiblingElement(exts, Library);
}
}
}
XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log)
- : m_requestMapper(nullptr), m_outer(outer), m_document(nullptr)
+ : m_requestMapper(nullptr),
+#ifndef SHIBSP_LITE
+ m_policy(nullptr),
+#endif
+ m_outer(outer), m_document(nullptr)
{
#ifdef _DEBUG
xmltooling::NDC ndc("XMLConfigImpl");
SAMLConfig& samlConf=SAMLConfig::getConfig();
#endif
XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
- const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess);
- const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e,InProcess);
+ const DOMElement* SHAR=XMLHelper::getFirstChildElement(e, OutOfProcess);
+ const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e, InProcess);
- // Initialize log4cpp manually in order to redirect log messages as soon as possible.
+ // Initialize logging manually in order to redirect log messages as soon as possible.
if (conf.isEnabled(SPConfig::Logging)) {
- const XMLCh* logconf=nullptr;
+ string logconf;
if (conf.isEnabled(SPConfig::OutOfProcess))
- logconf=SHAR->getAttributeNS(nullptr,logger);
+ logconf = XMLHelper::getAttrString(SHAR, nullptr, logger);
else if (conf.isEnabled(SPConfig::InProcess))
- logconf=SHIRE->getAttributeNS(nullptr,logger);
- if (!logconf || !*logconf)
- logconf=e->getAttributeNS(nullptr,logger);
- if (logconf && *logconf) {
- auto_ptr_char logpath(logconf);
- log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get());
- if (!XMLToolingConfig::getConfig().log_config(logpath.get()))
- log.crit("failed to load new logging configuration from (%s)", logpath.get());
+ 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
// First load any property sets.
load(e,nullptr,this);
- const DOMElement* child;
- string plugtype;
+ DOMElement* child;
// Much of the processing can only occur on the first instantiation.
if (first) {
// Instantiate the ListenerService and SessionCache objects.
if (conf.isEnabled(SPConfig::Listener)) {
- child=XMLHelper::getFirstChildElement(e,UnixListener);
+#ifdef WIN32
+ string plugtype(TCP_LISTENER_SERVICE);
+#else
+ string plugtype(UNIX_LISTENER_SERVICE);
+#endif
+ child = XMLHelper::getFirstChildElement(e, UnixListener);
if (child)
- plugtype=UNIX_LISTENER_SERVICE;
+ plugtype = UNIX_LISTENER_SERVICE;
else {
- child=XMLHelper::getFirstChildElement(e,TCPListener);
+ child = XMLHelper::getFirstChildElement(e, TCPListener);
if (child)
- plugtype=TCP_LISTENER_SERVICE;
+ plugtype = TCP_LISTENER_SERVICE;
else {
- child=XMLHelper::getFirstChildElement(e,Listener);
+ child = XMLHelper::getFirstChildElement(e, Listener);
if (child) {
- auto_ptr_char type(child->getAttributeNS(nullptr,_type));
- if (type.get())
- plugtype=type.get();
+ auto_ptr_char type(child->getAttributeNS(nullptr, _type));
+ if (type.get() && *type.get())
+ plugtype = type.get();
}
}
}
- if (child) {
- log.info("building ListenerService of type %s...", plugtype.c_str());
- m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(), child);
- }
- else {
- log.fatal("can't build ListenerService, missing conf:Listener element?");
- throw ConfigurationException("Can't build ListenerService, missing conf:Listener element?");
- }
+
+ log.info("building ListenerService of type %s...", plugtype.c_str());
+ m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(), child);
}
#ifndef SHIBSP_LITE
throw ConfigurationException("Can't build SessionCache, missing conf:SessionCache element?");
}
}
-
-#ifndef SHIBSP_LITE
- child = XMLHelper::getLastChildElement(e, SecurityPolicies);
- if (child) {
- const XMLCh* algs = nullptr;
- const DOMElement* alglist = XMLHelper::getLastChildElement(child, AlgorithmBlacklist);
- if (alglist && alglist->hasChildNodes()) {
- algs = alglist->getFirstChild()->getNodeValue();
- }
- else if ((alglist = XMLHelper::getLastChildElement(child, AlgorithmWhitelist)) && alglist->hasChildNodes()) {
- algs = alglist->getFirstChild()->getNodeValue();
- }
- if (algs) {
-#ifdef SHIBSP_XMLSEC_WHITELISTING
- const XMLCh* token;
- XMLStringTokenizer tokenizer(algs);
- while (tokenizer.hasMoreTokens()) {
- token = tokenizer.nextToken();
- if (token) {
- if (XMLString::equals(alglist->getLocalName(), AlgorithmBlacklist))
- XSECPlatformUtils::blacklistAlgorithm(token);
- else
- XSECPlatformUtils::whitelistAlgorithm(token);
- }
- }
-#else
- log.fatal("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
- throw ConfigurationException("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists.");
-#endif
- }
- }
-#endif
} // end of first-time-only stuff
// Back to the fully dynamic stuff...next up is the RequestMapper.
if (conf.isEnabled(SPConfig::RequestMapping)) {
- child=XMLHelper::getFirstChildElement(e,_RequestMapper);
- if (child) {
+ if (child = XMLHelper::getFirstChildElement(e,_RequestMapper)) {
auto_ptr_char type(child->getAttributeNS(nullptr,_type));
log.info("building RequestMapper of type %s...",type.get());
m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child);
#ifndef SHIBSP_LITE
// Load security policies.
- child = XMLHelper::getLastChildElement(e,SecurityPolicies);
- if (child) {
- PolicyNodeFilter filter;
- child = XMLHelper::getFirstChildElement(child,Policy);
- while (child) {
- auto_ptr_char id(child->getAttributeNS(nullptr,_id));
- pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id.get()];
- rules.first = nullptr;
- auto_ptr<DOMPropertySet> settings(new DOMPropertySet());
- settings->load(child, nullptr, &filter);
- rules.first = settings.release();
-
- // Process PolicyRule elements.
- const DOMElement* rule = XMLHelper::getFirstChildElement(child,PolicyRule);
- while (rule) {
- auto_ptr_char type(rule->getAttributeNS(nullptr,_type));
- try {
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));
- }
- catch (exception& ex) {
- log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());
- }
- rule = XMLHelper::getNextSiblingElement(rule,PolicyRule);
- }
-
- if (rules.second.size() == 0) {
- // Process Rule elements.
- log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");
- rule = XMLHelper::getFirstChildElement(child,Rule);
- while (rule) {
- auto_ptr_char type(rule->getAttributeNS(nullptr,_type));
- try {
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));
- }
- catch (exception& ex) {
- log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());
- }
- rule = XMLHelper::getNextSiblingElement(rule,Rule);
- }
-
- // Manually add a basic Conditions rule.
- log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.get());
- rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, nullptr));
- }
+ if (child = XMLHelper::getLastChildElement(e, SecurityPolicyProvider)) {
+ auto_ptr_char type(child->getAttributeNS(nullptr, _type));
+ log.info("building SecurityPolicyProvider of type %s...", type.get());
+ m_policy = conf.SecurityPolicyProviderManager.newPlugin(type.get(), 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);
+ }
+ else {
+ log.fatal("can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+ throw ConfigurationException("Can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+ }
- child = XMLHelper::getNextSiblingElement(child,Policy);
+ if (first) {
+#ifdef SHIBSP_XMLSEC_WHITELISTING
+ vector<xstring>::const_iterator alg;
+ if (!m_policy->getAlgorithmBlacklist().empty()) {
+ for (alg = m_policy->getAlgorithmBlacklist().begin(); alg != m_policy->getAlgorithmBlacklist().end(); ++alg)
+ XSECPlatformUtils::blacklistAlgorithm(alg->c_str());
}
+ else if (!m_policy->getAlgorithmWhitelist().empty()) {
+ for (alg = m_policy->getAlgorithmWhitelist().begin(); alg != m_policy->getAlgorithmWhitelist().end(); ++alg)
+ XSECPlatformUtils::whitelistAlgorithm(alg->c_str());
+ }
+#else
+ log.fatal("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
+ throw ConfigurationException("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists.");
+#endif
}
// Process TransportOption elements.
for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());
m_appmap.clear();
#ifndef SHIBSP_LITE
- 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>());
- }
- m_policyMap.clear();
+ delete m_policy;
+ m_policy = nullptr;
#endif
delete m_requestMapper;
m_requestMapper = nullptr;