X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=shibsp%2Fimpl%2FXMLServiceProvider.cpp;h=5a985a973dfdb0c88e2249e2be10d00abd086661;hb=8fee4332ee3d9bef2eac996b36a2baf09a811318;hp=96f90f86e3bb37db801b345cbc07314da233b17c;hpb=4083058674431c9a71e746013d4f12e98c51411f;p=shibboleth%2Fcpp-sp.git diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp index 96f90f8..5a985a9 100644 --- a/shibsp/impl/XMLServiceProvider.cpp +++ b/shibsp/impl/XMLServiceProvider.cpp @@ -50,7 +50,7 @@ #endif #include #include -#include +#include #include #include #include @@ -70,13 +70,15 @@ # include "attribute/resolver/AttributeResolver.h" # include "security/PKIXTrustEngine.h" # include "security/SecurityPolicyProvider.h" -# include +# include # include +# include # include # include # include # include # include +# include # include # include # include @@ -162,6 +164,7 @@ namespace { } const PropertySet* getRelyingParty(const EntityDescriptor* provider) const; const PropertySet* getRelyingParty(const XMLCh* entityID) const; + const vector* getAudiences() const { return (m_audiences.empty() && m_base) ? m_base->getAudiences() : &m_audiences; } @@ -184,6 +187,7 @@ namespace { const vector& getAssertionConsumerServicesByBinding(const XMLCh* binding) const; const Handler* getHandler(const char* path) const; void getHandlers(vector& handlers) const; + void limitRedirect(const GenericRequest& request, const char* url) const; void receive(DDF& in, ostream& out) { // Only current function is to return the headers to clear. @@ -235,7 +239,8 @@ namespace { vector m_audiences; // RelyingParty properties - map< xstring,boost::shared_ptr > m_partyMap; + map< xstring,boost::shared_ptr > m_partyMap; // name-based matching + vector< pair< boost::shared_ptr,boost::shared_ptr > > m_partyVec; // plugin-based matching #endif vector m_remoteUsers,m_frontLogout,m_backLogout; @@ -272,6 +277,17 @@ namespace { if (m_artifactResolutionDefault) return m_artifactResolutionDefault->getInt("index"); return m_base ? m_base->getArtifactEndpointIndex() : make_pair(false,0); } + + enum { + REDIRECT_LIMIT_INHERIT, + REDIRECT_LIMIT_NONE, + REDIRECT_LIMIT_EXACT, + REDIRECT_LIMIT_HOST, + REDIRECT_LIMIT_WHITELIST, + REDIRECT_LIMIT_EXACT_WHITELIST, + REDIRECT_LIMIT_HOST_WHITELIST + } m_redirectLimit; + vector m_redirectWhitelist; }; // Top-level configuration implementation @@ -288,7 +304,7 @@ namespace { #ifndef SHIBSP_LITE scoped_ptr m_tranLog; scoped_ptr m_policy; - vector< tuple > m_transportOptions; + vector< boost::tuple > m_transportOptions; #endif scoped_ptr m_requestMapper; map< string,boost::shared_ptr > m_appmap; @@ -319,7 +335,7 @@ namespace { #endif { public: - XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")) {} + XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT ".Config")) {} void init() { background_load(); @@ -423,7 +439,7 @@ namespace { bool setTransportOptions(SOAPTransport& transport) const { bool ret = true; - for (vector< tuple >::const_iterator opt = m_impl->m_transportOptions.begin(); + for (vector< boost::tuple >::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()); @@ -487,6 +503,7 @@ namespace { 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 _policyId[] = UNICODE_LITERAL_8(p,o,l,i,c,y,I,d); static const XMLCh _ProtocolProvider[] = UNICODE_LITERAL_16(P,r,o,t,o,c,o,l,P,r,o,v,i,d,e,r); 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); @@ -527,10 +544,76 @@ XMLApplication::XMLApplication( #ifdef _DEBUG xmltooling::NDC ndc("XMLApplication"); #endif - Category& log=Category::getInstance(SHIBSP_LOGCAT".Application"); + Category& log = Category::getInstance(SHIBSP_LOGCAT ".Application"); // First load any property sets. - load(e, nullptr, this); + map remapper; + remapper["relayStateLimit"] = "redirectLimit"; + remapper["relayStateWhitelist"] = "redirectWhitelist"; + load(e, nullptr, this, &remapper); + + // Process redirect limit policy. Do this before assigning the parent pointer + // to ensure we get only our Sessions element. + const PropertySet* sessionProps = getPropertySet("Sessions"); + if (sessionProps) { + pair prop = sessionProps->getString("redirectLimit"); + if (prop.first) { + if (!strcmp(prop.second, "none")) + m_redirectLimit = REDIRECT_LIMIT_NONE; + else if (!strcmp(prop.second, "exact")) + m_redirectLimit = REDIRECT_LIMIT_EXACT; + else if (!strcmp(prop.second, "host")) + m_redirectLimit = REDIRECT_LIMIT_HOST; + else { + if (!strcmp(prop.second, "exact+whitelist")) + m_redirectLimit = REDIRECT_LIMIT_EXACT_WHITELIST; + else if (!strcmp(prop.second, "host+whitelist")) + m_redirectLimit = REDIRECT_LIMIT_HOST_WHITELIST; + else if (!strcmp(prop.second, "whitelist")) + m_redirectLimit = REDIRECT_LIMIT_WHITELIST; + else + throw ConfigurationException("Unrecognized redirectLimit setting ($1)", params(1, prop.second)); + prop = sessionProps->getString("redirectWhitelist"); + if (prop.first) { + string dup(prop.second); + trim(dup); + split(m_redirectWhitelist, dup, is_space(), algorithm::token_compress_on); + } + } + } + else { + m_redirectLimit = base ? REDIRECT_LIMIT_INHERIT : REDIRECT_LIMIT_NONE; + } + + // Audit some additional settings for logging purposes. + prop = sessionProps->getString("cookieProps"); + if (!prop.first) { + log.warn("empty/missing cookieProps setting, set to \"https\" for SSL/TLS-only usage"); + } + else if (!strcmp(prop.second, "http")) { + log.warn("insecure cookieProps setting, set to \"https\" for SSL/TLS-only usage"); + } + else if (strcmp(prop.second, "https")) { + if (!strstr(prop.second, "secure")) + log.warn("custom cookieProps setting should include \"; secure\" for SSL/TLS-only usage"); + else if (!strstr(prop.second, "HttpOnly")) + log.warn("custom cookieProps setting should include \"; HttpOnly\", site is vulnerable to client-side cookie theft"); + + while (*prop.second && isspace(*prop.second)) + ++prop.second; + if (*prop.second != ';') + log.warn("custom cookieProps setting must begin with a semicolon (;) as a delimiter"); + } + + pair handlerSSL = sessionProps->getBool("handlerSSL"); + if (handlerSSL.first && !handlerSSL.second) + log.warn("handlerSSL should be enabled for SSL/TLS-enabled web sites"); + } + else { + m_redirectLimit = base ? REDIRECT_LIMIT_INHERIT : REDIRECT_LIMIT_NONE; + } + + // Assign parent. if (base) setParent(base); @@ -587,7 +670,7 @@ XMLApplication::XMLApplication( if (m_metadata) m_metadata->init(); else if (!m_base) - log.crit("no MetadataProvider available, configuration is probably unusable"); + log.warn("no MetadataProvider available, configure at least one for standard SSO usage"); } catch (std::exception& ex) { log.crit("error initializing MetadataProvider: %s", ex.what()); @@ -629,9 +712,17 @@ XMLApplication::XMLApplication( rp->setParent(this); m_partyMap[child->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp; } + else if (child->hasAttributeNS(nullptr, _type)) { + string emtype(XMLHelper::getAttrString(child, nullptr, _type)); + boost::shared_ptr em(SAMLConfig::getConfig().EntityMatcherManager.newPlugin(emtype, child)); + boost::shared_ptr rp(new DOMPropertySet()); + rp->load(child, nullptr, this); + rp->setParent(this); + m_partyVec.push_back(make_pair(em, rp)); + } child = XMLHelper::getNextSiblingElement(child, RelyingParty); } - if (base && m_partyMap.empty() && !base->m_partyMap.empty()) { + if (base && m_partyMap.empty() && m_partyVec.empty() && (!base->m_partyMap.empty() || !base->m_partyVec.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) { @@ -642,6 +733,15 @@ XMLApplication::XMLApplication( rp->setParent(this); m_partyMap[rpclone->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp; } + else if (child->hasAttributeNS(nullptr, _type)) { + DOMElement* rpclone = static_cast(child->cloneNode(true)); + string emtype(XMLHelper::getAttrString(rpclone, nullptr, _type)); + boost::shared_ptr em(SAMLConfig::getConfig().EntityMatcherManager.newPlugin(emtype, rpclone)); + boost::shared_ptr rp(new DOMPropertySet()); + rp->load(rpclone, nullptr, this); + rp->setParent(this); + m_partyVec.push_back(make_pair(em, rp)); + } child = XMLHelper::getNextSiblingElement(child, RelyingParty); } } @@ -738,6 +838,7 @@ void XMLApplication::doAttributeInfo() pair attributes = getString("REMOTE_USER"); if (attributes.first) { string dup(attributes.second); + trim(dup); split(m_remoteUsers, dup, is_space(), algorithm::token_compress_on); } @@ -757,6 +858,7 @@ void XMLApplication::doAttributeInfo() } string dup(attributes.second); + trim(dup); vector headerNames; split(headerNames, dup, is_space(), algorithm::token_compress_on); for (vector::const_iterator h = headerNames.begin(); h != headerNames.end(); ++h) { @@ -986,9 +1088,13 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set& protocols, D { if (!e->hasChildNodes()) return; + DOMNamedNodeMap* ssoprops = e->getAttributes(); + XMLSize_t ssopropslen = ssoprops ? ssoprops->getLength() : 0; SPConfig& conf = SPConfig::getConfig(); + int index = 0; // track ACS indexes globally across all protocols + // Tokenize the protocol list inside the element. XMLStringTokenizer prottokens(e->getTextContent()); while (prottokens.hasMoreTokens()) { @@ -1018,16 +1124,29 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set& protocols, D const vector& bindings = pp.getBindings(prot.get(), "SSO"); if (!bindings.empty()) { log.info("auto-configuring SSO endpoints for protocol (%s)", prot.get()); - int index = 0; pair idprop,pathprop; for (vector::const_iterator b = bindings.begin(); b != bindings.end(); ++b, ++index) { idprop = (*b)->getXMLString("id"); pathprop = (*b)->getXMLString("path"); if (idprop.first && pathprop.first) { DOMElement* acsdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _AssertionConsumerService); + + // Copy in any attributes from the element so they can be accessed as properties in the ACS handler. + for (XMLSize_t p = 0; p < ssopropslen; ++p) { + DOMNode* ssoprop = ssoprops->item(p); + if (ssoprop->getNodeType() == DOMNode::ATTRIBUTE_NODE) { + acsdom->setAttributeNS( + ((DOMAttr*)ssoprop)->getNamespaceURI(), + ((DOMAttr*)ssoprop)->getLocalName(), + ((DOMAttr*)ssoprop)->getValue() + ); + } + } + + // Set necessary properties based on context. acsdom->setAttributeNS(nullptr, Binding, idprop.second); acsdom->setAttributeNS(nullptr, Location, pathprop.second); - xstring indexbuf(chDigit_1 + (index % 10), 1); + xstring indexbuf(1, chDigit_1 + (index % 10)); if (index / 10) indexbuf = (XMLCh)(chDigit_1 + (index / 10)) + indexbuf; acsdom->setAttributeNS(nullptr, _index, indexbuf.c_str()); @@ -1107,6 +1226,8 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set& protocols { if (!e->hasChildNodes()) return; + DOMNamedNodeMap* sloprops = e->getAttributes(); + XMLSize_t slopropslen = sloprops ? sloprops->getLength() : 0; SPConfig& conf = SPConfig::getConfig(); @@ -1147,8 +1268,24 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set& protocols pathprop = (*b)->getXMLString("path"); if (idprop.first && pathprop.first) { DOMElement* slodom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _SingleLogoutService); + + // Copy in any attributes from the element so they can be accessed as properties in the SLO handler. + for (XMLSize_t p = 0; p < slopropslen; ++p) { + DOMNode* sloprop = sloprops->item(p); + if (sloprop->getNodeType() == DOMNode::ATTRIBUTE_NODE) { + slodom->setAttributeNS( + ((DOMAttr*)sloprop)->getNamespaceURI(), + ((DOMAttr*)sloprop)->getLocalName(), + ((DOMAttr*)sloprop)->getValue() + ); + } + } + + // Set necessary properties based on context. slodom->setAttributeNS(nullptr, Binding, idprop.second); slodom->setAttributeNS(nullptr, Location, pathprop.second); + if (e->hasAttributeNS(nullptr, _policyId)) + slodom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId)); log.info("adding SingleLogoutService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second); boost::shared_ptr handler( @@ -1195,6 +1332,8 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set& proto { if (!e->hasChildNodes()) return; + DOMNamedNodeMap* nimprops = e->getAttributes(); + XMLSize_t nimpropslen = nimprops ? nimprops->getLength() : 0; SPConfig& conf = SPConfig::getConfig(); @@ -1213,8 +1352,24 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set& proto pathprop = (*b)->getXMLString("path"); if (idprop.first && pathprop.first) { DOMElement* nimdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _ManageNameIDService); + + // Copy in any attributes from the element so they can be accessed as properties in the NIM handler. + for (XMLSize_t p = 0; p < nimpropslen; ++p) { + DOMNode* nimprop = nimprops->item(p); + if (nimprop->getNodeType() == DOMNode::ATTRIBUTE_NODE) { + nimdom->setAttributeNS( + ((DOMAttr*)nimprop)->getNamespaceURI(), + ((DOMAttr*)nimprop)->getLocalName(), + ((DOMAttr*)nimprop)->getValue() + ); + } + } + + // Set necessary properties based on context. nimdom->setAttributeNS(nullptr, Binding, idprop.second); nimdom->setAttributeNS(nullptr, Location, pathprop.second); + if (e->hasAttributeNS(nullptr, _policyId)) + nimdom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId)); log.info("adding ManageNameIDService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second); boost::shared_ptr handler( @@ -1249,20 +1404,21 @@ void XMLApplication::doArtifactResolution(const ProtocolProvider& pp, const char { SPConfig& conf = SPConfig::getConfig(); + int index = 0; // track indexes globally across all protocols + // Look for incoming bindings. const vector& bindings = pp.getBindings(protocol, "ArtifactResolution"); if (!bindings.empty()) { log.info("auto-configuring ArtifactResolution endpoints for protocol (%s)", protocol); - int index = 0; pair idprop,pathprop; - for (vector::const_iterator b = bindings.begin(); b != bindings.end(); ++b) { + for (vector::const_iterator b = bindings.begin(); b != bindings.end(); ++b, ++index) { idprop = (*b)->getXMLString("id"); pathprop = (*b)->getXMLString("path"); if (idprop.first && pathprop.first) { DOMElement* artdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _ArtifactResolutionService); artdom->setAttributeNS(nullptr, Binding, idprop.second); artdom->setAttributeNS(nullptr, Location, pathprop.second); - xstring indexbuf(chDigit_1 + (index % 10), 1); + xstring indexbuf(1, chDigit_1 + (index % 10)); if (index / 10) indexbuf = (XMLCh)(chDigit_1 + (index / 10)) + indexbuf; artdom->setAttributeNS(nullptr, _index, indexbuf.c_str()); @@ -1393,9 +1549,19 @@ const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provi if (!provider) return this; + // Check for exact match on name. map< xstring,boost::shared_ptr >::const_iterator i = m_partyMap.find(provider->getEntityID()); if (i != m_partyMap.end()) return i->second.get(); + + // Check for extensible matching. + vector < pair< boost::shared_ptr,boost::shared_ptr > >::const_iterator j; + for (j = m_partyVec.begin(); j != m_partyVec.end(); ++j) { + if (j->first->matches(*provider)) + return j->second.get(); + } + + // Check for group match. const EntitiesDescriptor* group = dynamic_cast(provider->getParent()); while (group) { if (group->getName()) { @@ -1603,6 +1769,43 @@ void XMLApplication::getHandlers(vector& handlers) const } } +void XMLApplication::limitRedirect(const GenericRequest& request, const char* url) const +{ + if (!url || *url == '/') + return; + if (m_redirectLimit == REDIRECT_LIMIT_INHERIT) + return m_base->limitRedirect(request, url); + if (m_redirectLimit != REDIRECT_LIMIT_NONE) { + vector whitelist; + if (m_redirectLimit == REDIRECT_LIMIT_EXACT || m_redirectLimit == REDIRECT_LIMIT_EXACT_WHITELIST) { + // Scheme and hostname have to match. + if (request.isDefaultPort()) { + whitelist.push_back(string(request.getScheme()) + "://" + request.getHostname() + '/'); + } + whitelist.push_back(string(request.getScheme()) + "://" + request.getHostname() + ':' + lexical_cast(request.getPort()) + '/'); + } + else if (m_redirectLimit == REDIRECT_LIMIT_HOST || m_redirectLimit == REDIRECT_LIMIT_HOST_WHITELIST) { + // Allow any scheme or port. + whitelist.push_back(string("https://") + request.getHostname() + '/'); + whitelist.push_back(string("http://") + request.getHostname() + '/'); + whitelist.push_back(string("https://") + request.getHostname() + ':'); + whitelist.push_back(string("http://") + request.getHostname() + ':'); + } + + static bool (*startsWithI)(const char*,const char*) = XMLString::startsWithI; + if (!whitelist.empty() && find_if(whitelist.begin(), whitelist.end(), + boost::bind(startsWithI, url, boost::bind(&string::c_str, _1))) != whitelist.end()) { + return; + } + else if (!m_redirectWhitelist.empty() && find_if(m_redirectWhitelist.begin(), m_redirectWhitelist.end(), + boost::bind(startsWithI, url, boost::bind(&string::c_str, _1))) != m_redirectWhitelist.end()) { + return; + } + Category::getInstance(SHIBSP_LOGCAT ".Application").warn("redirectLimit policy enforced, blocked redirect to (%s)", url); + throw opensaml::SecurityPolicyException("Blocked unacceptable redirect location."); + } +} + #ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE short #else @@ -1799,6 +2002,8 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e, InProcess); // Initialize logging manually in order to redirect log messages as soon as possible. + // If no explicit config is supplied, we now assume the caller has done this, so that + // setuid processes can potentially do this as root. if (conf.isEnabled(SPConfig::Logging)) { string logconf; if (conf.isEnabled(SPConfig::OutOfProcess)) @@ -1807,15 +2012,6 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, 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())) @@ -1880,6 +2076,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, if (unsafe.first) { HTTPResponse::getAllowedSchemes().clear(); string schemes(unsafe.second); + trim(schemes); split(HTTPResponse::getAllowedSchemes(), schemes, is_space(), algorithm::token_compress_on); } @@ -1953,7 +2150,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, // 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); + log.warn("deprecated/legacy SecurityPolicy configuration, consider externalizing with "); m_policy.reset(conf.SecurityPolicyProviderManager.newPlugin(XML_SECURITYPOLICY_PROVIDER, polwrapper)); } else { @@ -1962,22 +2159,32 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, } if (first) { - if (!m_policy->getAlgorithmBlacklist().empty()) { + if (!m_policy->getAlgorithmWhitelist().empty()) { #ifdef SHIBSP_XMLSEC_WHITELISTING - for_each( - m_policy->getAlgorithmBlacklist().begin(), m_policy->getAlgorithmBlacklist().end(), - boost::bind(&XSECPlatformUtils::blacklistAlgorithm, boost::bind(&xstring::c_str, _1)) - ); + for (vector::const_iterator white = m_policy->getAlgorithmWhitelist().begin(); + white != m_policy->getAlgorithmWhitelist().end(); ++white) { + XSECPlatformUtils::whitelistAlgorithm(white->c_str()); + auto_ptr_char whitelog(white->c_str()); + log.info("explicitly whitelisting security algorithm (%s)", whitelog.get()); + } #else 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->getDefaultAlgorithmBlacklist().empty() || !m_policy->getAlgorithmBlacklist().empty()) { #ifdef SHIBSP_XMLSEC_WHITELISTING - for_each( - m_policy->getAlgorithmWhitelist().begin(), m_policy->getAlgorithmWhitelist().end(), - boost::bind(&XSECPlatformUtils::whitelistAlgorithm, boost::bind(&xstring::c_str, _1)) - ); + for (vector::const_iterator black = m_policy->getDefaultAlgorithmBlacklist().begin(); + black != m_policy->getDefaultAlgorithmBlacklist().end(); ++black) { + XSECPlatformUtils::blacklistAlgorithm(black->c_str()); + auto_ptr_char blacklog(black->c_str()); + log.info("automatically blacklisting security algorithm (%s)", blacklog.get()); + } + for (vector::const_iterator black = m_policy->getAlgorithmBlacklist().begin(); + black != m_policy->getAlgorithmBlacklist().end(); ++black) { + XSECPlatformUtils::blacklistAlgorithm(black->c_str()); + auto_ptr_char blacklog(black->c_str()); + log.info("explicitly blacklisting security algorithm (%s)", blacklog.get()); + } #else log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists"); #endif @@ -1992,7 +2199,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, 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()))); + m_transportOptions.push_back(boost::make_tuple(provider, option, string(value.get()))); } } child = XMLHelper::getPreviousSiblingElement(child, TransportOption); @@ -2039,7 +2246,9 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, pair extraAuthTypes = inprocs->getString("extraAuthTypes"); if (extraAuthTypes.first) { string types(extraAuthTypes.second); + trim(types); split(outer->m_authTypes, types, is_space(), algorithm::token_compress_on); + outer->m_authTypes.insert("shibboleth"); } } } @@ -2067,7 +2276,7 @@ void XMLConfig::receive(DDF& in, ostream& out) } } else { - Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error( + Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider").error( "Storage-backed RelayState with invalid StorageService ID (%s)", id ); } @@ -2094,7 +2303,7 @@ void XMLConfig::receive(DDF& in, ostream& out) storage->createText("RelayState", rsKey.c_str(), value, time(nullptr) + 600); } else { - Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error( + Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider").error( "Storage-backed RelayState with invalid StorageService ID (%s)", id ); } @@ -2118,7 +2327,7 @@ void XMLConfig::receive(DDF& in, ostream& out) } } else { - Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error( + Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider").error( "Storage-backed PostData with invalid StorageService ID (%s)", id ); } @@ -2148,7 +2357,7 @@ void XMLConfig::receive(DDF& in, ostream& out) storage->createText("PostData", rsKey.c_str(), params.str().c_str(), time(nullptr) + 600); } else { - Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error( + Category::getInstance(SHIBSP_LOGCAT ".ServiceProvider").error( "Storage-backed PostData with invalid StorageService ID (%s)", id ); }