From: Scott Cantor Date: Fri, 13 Aug 2010 04:23:23 +0000 (+0000) Subject: Initial draft of protocol bootstrapper, reworked ACS lookup (again). X-Git-Tag: 2.4RC1~71 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-sp.git;a=commitdiff_plain;h=c6700090390ccb108e96ec1123eb3c26f39e6573 Initial draft of protocol bootstrapper, reworked ACS lookup (again). --- diff --git a/Shibboleth.sln b/Shibboleth.sln index 72675b5..112d8f2 100644 --- a/Shibboleth.sln +++ b/Shibboleth.sln @@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Schemas", "Schemas", "{0F17 schemas\shibboleth-2.0-afp.xsd = schemas\shibboleth-2.0-afp.xsd schemas\shibboleth-2.0-attribute-map.xsd = schemas\shibboleth-2.0-attribute-map.xsd schemas\shibboleth-2.0-native-sp-config.xsd = schemas\shibboleth-2.0-native-sp-config.xsd + schemas\shibboleth-2.0-native-sp-protocols.xsd = schemas\shibboleth-2.0-native-sp-protocols.xsd schemas\shibboleth-2.0-sp-notify.xsd = schemas\shibboleth-2.0-sp-notify.xsd schemas\shibboleth-metadata-1.0.xsd = schemas\shibboleth-metadata-1.0.xsd schemas\shibboleth.xsd = schemas\shibboleth.xsd @@ -52,6 +53,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{2543BC configs\native.logger.in = configs\native.logger.in configs\partialLogout.html = configs\partialLogout.html configs\postTemplate.html = configs\postTemplate.html + configs\protocols.xml = configs\protocols.xml configs\security-policy.xml = configs\security-policy.xml configs\sessionError.html = configs\sessionError.html configs\shibboleth2.xml = configs\shibboleth2.xml diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp index c8f4bdd..cac8e85 100644 --- a/adfs/adfs.cpp +++ b/adfs/adfs.cpp @@ -370,24 +370,16 @@ pair ADFSSessionInitiator::run(SPRequest& request, string& entityID, if (!ACS) { pair index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED); - if (index.first) { + if (index.first) ACS = app.getAssertionConsumerServiceByIndex(index.second); - if (!ACS) - request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location"); - } - if (!ACS) { - ACS = app.getAssertionConsumerServiceByBinding(WSFED_NS); - if (!ACS) { - m_log.error("unable to locate a compatible ACS"); - throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration."); - } - } } // Validate the ACS for use with this protocol. - if (!XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) { - m_log.error("configured or requested ACS has non-ADFS binding"); - throw ConfigurationException("Configured or requested ACS has non-ADFS binding ($1).", params(1, ACS->getString("Binding").second)); + if (!ACS || !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) { + request.log(SPRequest::SPWarn, "invalid acsIndex property, or non-ADFS ACS, using default ADFS ACS"); + ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily()); + if (!ACS) + throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration."); } // Since we're not passing by index, we need to fully compute the return URL. diff --git a/configs/Makefile.am b/configs/Makefile.am index 3618623..3b3f8de 100644 --- a/configs/Makefile.am +++ b/configs/Makefile.am @@ -35,6 +35,7 @@ CONFIGFILES = \ shibboleth2.xml \ attribute-map.xml \ attribute-policy.xml \ + protocols.xml \ security-policy.xml \ example-metadata.xml \ example-shibboleth2.xml \ diff --git a/configs/protocols.xml b/configs/protocols.xml new file mode 100644 index 0000000..22d69c0 --- /dev/null +++ b/configs/protocols.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schemas/Makefile.am b/schemas/Makefile.am index 666c0e6..05bbace 100644 --- a/schemas/Makefile.am +++ b/schemas/Makefile.am @@ -8,11 +8,12 @@ schemafiles = \ shibboleth.xsd \ shibboleth-metadata-1.0.xsd \ shibboleth-2.0-native-sp-config.xsd \ + shibboleth-2.0-native-sp-protocols.xsd \ + shibboleth-2.0-sp-notify.xsd \ shibboleth-2.0-afp.xsd \ shibboleth-2.0-afp-mf-basic.xsd \ shibboleth-2.0-afp-mf-saml.xsd \ shibboleth-2.0-attribute-map.xsd \ - shibboleth-2.0-sp-notify.xsd \ WS-Trust.xsd pkgxml_DATA = \ diff --git a/schemas/catalog.xml.in b/schemas/catalog.xml.in index e59eb48..ca7c797 100644 --- a/schemas/catalog.xml.in +++ b/schemas/catalog.xml.in @@ -2,11 +2,12 @@ + + - diff --git a/schemas/shibboleth-2.0-native-sp-protocols.xsd b/schemas/shibboleth-2.0-native-sp-protocols.xsd new file mode 100644 index 0000000..b45ccc6 --- /dev/null +++ b/schemas/shibboleth-2.0-native-sp-protocols.xsd @@ -0,0 +1,59 @@ + + + + + + Schema for specifying protocols, services, and bindings, and defaults for the locations of handlers. + First appearing in Shibboleth 2.4 release. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shibsp/Application.cpp b/shibsp/Application.cpp index f13e1f1..d962cf1 100644 --- a/shibsp/Application.cpp +++ b/shibsp/Application.cpp @@ -134,7 +134,7 @@ void Application::clearAttributeHeaders(SPRequest& request) const request.clearHeader(i->first.c_str(), i->second.c_str()); } -const Handler* Application::getAssertionConsumerServiceByBinding(const char* binding) const +const Handler* Application::getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding) const { auto_ptr_XMLCh b(binding); const vector& handlers = getAssertionConsumerServicesByBinding(b.get()); diff --git a/shibsp/Application.h b/shibsp/Application.h index 29ae8e2..9b120ff 100644 --- a/shibsp/Application.h +++ b/shibsp/Application.h @@ -283,12 +283,13 @@ namespace shibsp { /** * Returns an AssertionConsumerService Handler that supports - * a particular protocol binding. + * a particular protocol "family" and optional binding. * - * @param binding a protocol binding identifier + * @param protocol a protocol identifier + * @param binding a binding identifier * @return a matching AssertionConsumerService, or nullptr */ - virtual const Handler* getAssertionConsumerServiceByBinding(const char* binding) const; + virtual const Handler* getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding=nullptr) const; /** * @deprecated diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am index 39ca0e2..b677beb 100644 --- a/shibsp/Makefile.am +++ b/shibsp/Makefile.am @@ -63,6 +63,7 @@ attrresinclude_HEADERS = \ bindinclude_HEADERS = \ binding/ArtifactResolver.h \ + binding/ProtocolProvider.h \ binding/SOAPClient.h handinclude_HEADERS = \ @@ -113,6 +114,7 @@ common_sources = \ attribute/SimpleAttribute.cpp \ attribute/ScopedAttribute.cpp \ attribute/XMLAttribute.cpp \ + binding/impl/XMLProtocolProvider.cpp \ handler/impl/AbstractHandler.cpp \ handler/impl/AssertionConsumerService.cpp \ handler/impl/AssertionLookup.cpp \ diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp index 55e15e5..44240f2 100644 --- a/shibsp/SPConfig.cpp +++ b/shibsp/SPConfig.cpp @@ -43,6 +43,7 @@ #include "SPConfig.h" #include "TransactionLog.h" #include "attribute/Attribute.h" +#include "binding/ProtocolProvider.h" #include "handler/LogoutInitiator.h" #include "handler/SessionInitiator.h" #include "remoting/ListenerService.h" @@ -241,9 +242,14 @@ bool SPConfig::init(const char* catalog_path, const char* inst_prefix) #endif registerAttributeFactories(); - registerHandlers(); - registerLogoutInitiators(); - registerSessionInitiators(); + + if (isEnabled(Handlers)) { + registerHandlers(); + registerLogoutInitiators(); + registerSessionInitiators(); + registerProtocolProviders(); + } + registerServiceProviders(); #ifndef SHIBSP_LITE @@ -294,13 +300,17 @@ void SPConfig::term() setArtifactResolver(nullptr); #endif - ArtifactResolutionServiceManager.deregisterFactories(); - AssertionConsumerServiceManager.deregisterFactories(); - LogoutInitiatorManager.deregisterFactories(); - ManageNameIDServiceManager.deregisterFactories(); - SessionInitiatorManager.deregisterFactories(); - SingleLogoutServiceManager.deregisterFactories(); - HandlerManager.deregisterFactories(); + if (isEnabled(Handlers)) { + ArtifactResolutionServiceManager.deregisterFactories(); + AssertionConsumerServiceManager.deregisterFactories(); + LogoutInitiatorManager.deregisterFactories(); + ManageNameIDServiceManager.deregisterFactories(); + SessionInitiatorManager.deregisterFactories(); + SingleLogoutServiceManager.deregisterFactories(); + HandlerManager.deregisterFactories(); + ProtocolProviderManager.deregisterFactories(); + } + ServiceProviderManager.deregisterFactories(); Attribute::deregisterFactories(); diff --git a/shibsp/SPConfig.h b/shibsp/SPConfig.h index ed3ddb5..918b102 100644 --- a/shibsp/SPConfig.h +++ b/shibsp/SPConfig.h @@ -44,6 +44,7 @@ namespace shibsp { class SHIBSP_API Handler; class SHIBSP_API ListenerService; class SHIBSP_API RequestMapper; + class SHIBSP_API ProtocolProvider; class SHIBSP_API ServiceProvider; class SHIBSP_API SessionCache; class SHIBSP_API SessionInitiator; @@ -251,6 +252,11 @@ namespace shibsp { xmltooling::PluginManager< Handler,std::string,std::pair > ManageNameIDServiceManager; /** + * Manages factories for ProtocolProvider plugins. + */ + xmltooling::PluginManager ProtocolProviderManager; + + /** * Manages factories for RequestMapper plugins. */ xmltooling::PluginManager RequestMapperManager; diff --git a/shibsp/binding/ProtocolProvider.h b/shibsp/binding/ProtocolProvider.h new file mode 100644 index 0000000..68f7f21 --- /dev/null +++ b/shibsp/binding/ProtocolProvider.h @@ -0,0 +1,74 @@ +/* + * Copyright 2010 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file shibsp/binding/ProtocolProvider.h + * + * Interface to protocol, binding, and default endpoint information. + */ + +#ifndef __shibsp_protprov_h__ +#define __shibsp_protprov_h__ + +#include + +#include +#include + +namespace shibsp { + + class SHIBSP_API PropertySet; + + /** + * Interface to protocol, binding, and default endpoint information. + */ + class SHIBSP_API ProtocolProvider : public virtual xmltooling::Lockable + { + MAKE_NONCOPYABLE(ProtocolProvider); + protected: + ProtocolProvider(); + public: + virtual ~ProtocolProvider(); + + /** + * Returns information about a service supported by a protocol, as a PropertySet. + * + * @param protocol the name of a protocol + * @param service the name of a service + * @return a PropertySet associated with a service + */ + virtual const PropertySet* getService(const char* protocol, const char* service) const=0; + + /** + * Returns an ordered array of protocol bindings available for a specified service. + * + * @param protocol the name of a protocol + * @param service name of the protocol service + * @return the array of bindings, each represented as a PropertySet + */ + virtual const std::vector& getBindings(const char* protocol, const char* service) const=0; + }; + + /** + * Registers ProtocolProvider classes into the runtime. + */ + void SHIBSP_API registerProtocolProviders(); + + /** ProtocolProvider based on an XML configuration format. */ + #define XML_PROTOCOL_PROVIDER "XML" +}; + +#endif /* __shibsp_protprov_h__ */ diff --git a/shibsp/binding/impl/XMLProtocolProvider.cpp b/shibsp/binding/impl/XMLProtocolProvider.cpp new file mode 100644 index 0000000..327a18f --- /dev/null +++ b/shibsp/binding/impl/XMLProtocolProvider.cpp @@ -0,0 +1,230 @@ +/* + * Copyright 2010 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * XMLProtocolProvider.cpp + * + * XML-based protocol provider. + */ + +#include "internal.h" +#include "exceptions.h" +#include "binding/ProtocolProvider.h" +#include "util/DOMPropertySet.h" +#include "util/SPConstants.h" + +#include +#include +#include +#include +#include +#include +#include + +using shibspconstants::SHIB2SPPROTOCOLS_NS; +using namespace shibsp; +using namespace xmltooling; +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 Protocol[] = UNICODE_LITERAL_8(P,r,o,t,o,c,o,l); + static const XMLCh Protocols[] = UNICODE_LITERAL_9(P,r,o,t,o,c,o,l,s); + static const XMLCh Service[] = UNICODE_LITERAL_7(S,e,r,v,i,c,e); + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + class SHIBSP_DLLLOCAL XMLProtocolProviderImpl : public DOMNodeFilter, DOMPropertySet + { + 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()); + } + if (m_document) + m_document->release(); + } + + void setDocument(DOMDocument* doc) { + m_document = doc; + } + +#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE + short +#else + FilterAction +#endif + acceptNode(const DOMNode* node) const { + return FILTER_REJECT; + } + + private: + DOMDocument* m_document; + // Map of protocol/service pair to a service propset plus an array of Binding propsets. + typedef map< pair, pair< PropertySet*,vector > > protmap_t; + protmap_t m_map; + + friend class SHIBSP_DLLLOCAL XMLProtocolProvider; + }; + + class XMLProtocolProvider : public ProtocolProvider, public ReloadableXMLFile + { + public: + XMLProtocolProvider(const DOMElement* e) + : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".ProtocolProvider.XML")), m_impl(nullptr) { + background_load(); // guarantees an exception or the policy is loaded + } + + ~XMLProtocolProvider() { + shutdown(); + delete m_impl; + } + + const PropertySet* getService(const char* protocol, const char* service) const { + XMLProtocolProviderImpl::protmap_t::const_iterator i = m_impl->m_map.find(pair(protocol,service)); + return (i != m_impl->m_map.end()) ? i->second.first : nullptr; + } + + const vector& getBindings(const char* protocol, const char* service) const { + XMLProtocolProviderImpl::protmap_t::const_iterator i = m_impl->m_map.find(pair(protocol,service)); + if (i != m_impl->m_map.end()) + return i->second.second; + throw ConfigurationException("ProtocolProvider can't return bindings for undefined protocol and service."); + } + + protected: + pair load(bool backup); + pair background_load(); + + private: + XMLProtocolProviderImpl* m_impl; + }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + + ProtocolProvider* SHIBSP_DLLLOCAL XMLProtocolProviderFactory(const DOMElement* const & e) + { + return new XMLProtocolProvider(e); + } +} + +void SHIBSP_API shibsp::registerProtocolProviders() +{ + SPConfig::getConfig().ProtocolProviderManager.registerFactory(XML_PROTOCOL_PROVIDER, XMLProtocolProviderFactory); +} + +ProtocolProvider::ProtocolProvider() +{ +} + +ProtocolProvider::~ProtocolProvider() +{ +} + +XMLProtocolProviderImpl::XMLProtocolProviderImpl(const DOMElement* e, Category& log) : m_document(nullptr) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("XMLProtocolProviderImpl"); +#endif + //typedef map< pair, pair< PropertySet*,vector > > protmap_t; + + if (!XMLHelper::isNodeNamed(e, SHIB2SPPROTOCOLS_NS, Protocols)) + throw ConfigurationException("XML ProtocolProvider requires prot:Protocols at root of configuration."); + + e = XMLHelper::getFirstChildElement(e, SHIB2SPPROTOCOLS_NS, Protocol); + while (e) { + string id = XMLHelper::getAttrString(e, nullptr, _id); + if (!id.empty()) { + const DOMElement* svc = XMLHelper::getFirstChildElement(e, SHIB2SPPROTOCOLS_NS, Service); + while (svc) { + string svcid = XMLHelper::getAttrString(svc, nullptr, _id); + if (!svcid.empty()) { + pair< PropertySet*,vector >& entry = m_map[make_pair(id,svcid)]; + if (!entry.first) { + // Wrap the Service in a propset. + DOMPropertySet* svcprop = new DOMPropertySet(); + entry.first = svcprop; + svcprop->load(svc, &log, this); + + // Walk the Bindings. + const DOMElement* bind = XMLHelper::getFirstChildElement(svc, SHIB2SPPROTOCOLS_NS, Binding); + while (bind) { + DOMPropertySet* bindprop = new DOMPropertySet(); + entry.second.push_back(bindprop); + bindprop->load(bind, &log, this); + bind = XMLHelper::getNextSiblingElement(bind, SHIB2SPPROTOCOLS_NS, Binding); + } + } + } + svc = XMLHelper::getNextSiblingElement(svc, SHIB2SPPROTOCOLS_NS, Service); + } + } + e = XMLHelper::getNextSiblingElement(e, SHIB2SPPROTOCOLS_NS, Protocol); + } +} + + +pair XMLProtocolProvider::load(bool backup) +{ + // Load from source using base class. + pair raw = ReloadableXMLFile::load(backup); + + // If we own it, wrap it. + XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr); + + 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()); + + // Perform the swap inside a lock. + if (m_lock) + m_lock->wrlock(); + SharedLock locker(m_lock, false); + delete m_impl; + m_impl = impl; + + + return make_pair(false,(DOMElement*)nullptr); +} + +pair XMLProtocolProvider::background_load() +{ + try { + return load(false); + } + catch (long& ex) { + if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) + m_log.info("remote resource (%s) unchanged", m_source.c_str()); + if (!m_loaded && !m_backing.empty()) + return load(true); + throw; + } + catch (exception&) { + if (!m_loaded && !m_backing.empty()) + return load(true); + throw; + } +} diff --git a/shibsp/handler/Handler.h b/shibsp/handler/Handler.h index 624d983..3c3d4b0 100644 --- a/shibsp/handler/Handler.h +++ b/shibsp/handler/Handler.h @@ -140,6 +140,21 @@ namespace shibsp { /** Registers Handler implementations. */ void SHIBSP_API registerHandlers(); + /** Handler for SAML 1.x SSO. */ + #define SAML1_ASSERTION_CONSUMER_SERVICE "SAML1" + + /** Handler for SAML 2.0 SSO. */ + #define SAML20_ASSERTION_CONSUMER_SERVICE "SAML2" + + /** Handler for SAML 2.0 SLO. */ + #define SAML20_LOGOUT_HANDLER "SAML2" + + /** Handler for SAML 2.0 NIM. */ + #define SAML20_NAMEID_MGMT_SERVICE "SAML2" + + /** Handler for SAML 2.0 Artifact Resolution. */ + #define SAML20_ARTIFACT_RESOLUTION_SERVICE "SAML2" + /** Handler for metadata generation. */ #define METADATA_GENERATOR_HANDLER "MetadataGenerator" diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp index 0763746..58210fc 100644 --- a/shibsp/handler/impl/AbstractHandler.cpp +++ b/shibsp/handler/impl/AbstractHandler.cpp @@ -118,13 +118,16 @@ void SHIBSP_API shibsp::registerHandlers() { SPConfig& conf=SPConfig::getConfig(); + conf.AssertionConsumerServiceManager.registerFactory(SAML1_ASSERTION_CONSUMER_SERVICE, SAML1ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory); + conf.AssertionConsumerServiceManager.registerFactory(SAML20_ASSERTION_CONSUMER_SERVICE, SAML2ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_PAOS, SAML2ConsumerFactory); + conf.ArtifactResolutionServiceManager.registerFactory(SAML20_ARTIFACT_RESOLUTION_SERVICE, SAML2ArtifactResolutionFactory); conf.ArtifactResolutionServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2ArtifactResolutionFactory); conf.HandlerManager.registerFactory(SAML20_BINDING_URI, AssertionLookupFactory); @@ -132,12 +135,14 @@ void SHIBSP_API shibsp::registerHandlers() conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory); conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory); + conf.SingleLogoutServiceManager.registerFactory(SAML20_LOGOUT_HANDLER, SAML2LogoutFactory); conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory); conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory); conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory); conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2LogoutFactory); conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2LogoutFactory); + conf.ManageNameIDServiceManager.registerFactory(SAML20_NAMEID_MGMT_SERVICE, SAML2NameIDMgmtFactory); conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2NameIDMgmtFactory); conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2NameIDMgmtFactory); conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2NameIDMgmtFactory); diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp index 9707700..3d903f3 100644 --- a/shibsp/handler/impl/SAML2SessionInitiator.cpp +++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp @@ -310,34 +310,24 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, if (!ACS) { if (ECP) { - ACS = app.getAssertionConsumerServiceByBinding(samlconstants::SAML20_BINDING_PAOS); + ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily(), samlconstants::SAML20_BINDING_PAOS); if (!ACS) throw ConfigurationException("Unable to locate PAOS response endpoint."); } else { - // Try fixed index property, or incoming binding set, or default, in order. + // Try fixed index property. pair index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED); - if (index.first) { + if (index.first) ACS = app.getAssertionConsumerServiceByIndex(index.second); - if (!ACS) - request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location"); - } - /* - for (vector::const_iterator b = m_incomingBindings.begin(); !ACS && b != m_incomingBindings.end(); ++b) { - ACS = app.getAssertionConsumerServiceByBinding(b->c_str()); - if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) - ACS = nullptr; - } - */ - if (!ACS) - ACS = app.getDefaultAssertionConsumerService(); } } - // Validate the ACS for use with this protocol. - if (!ECP && ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) { - m_log.error("configured or requested ACS has non-SAML 2.0 binding"); - throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACS->getString("Binding").second)); + // If we picked by index, validate the ACS for use with this protocol. + if (!ECP && (!ACS || !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily()))) { + request.log(SPRequest::SPWarn, "invalid acsIndex property, or non-SAML 2.0 ACS, using default SAML 2.0 ACS"); + ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily()); + if (!ACS) + throw ConfigurationException("Unable to locate a SAML 2.0 ACS endpoint to use for response."); } // To invoke the request builder, the key requirement is to figure out how @@ -361,21 +351,19 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, // Determine index to use. pair ix = pair(false,nullptr); - if (ACS) { - if (!strncmp(ACSloc.c_str(), "https", 5)) { - ix = ACS->getXMLString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS); - if (!ix.first) - ix = ACS->getXMLString("index"); - } - else { + if (!strncmp(ACSloc.c_str(), "https", 5)) { + ix = ACS->getXMLString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS); + if (!ix.first) ix = ACS->getXMLString("index"); - } + } + else { + ix = ACS->getXMLString("index"); } return doRequest( app, &request, request, entityID.c_str(), ix.second, - ACS ? XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) : false, + XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT), nullptr, nullptr, isPassive, forceAuthn, acClass.first ? acClass.second : nullptr, @@ -388,7 +376,7 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, // Since we're not passing by index, we need to fully compute the return URL and binding. // Compute the ACS URL. We add the ACS location to the base handlerURL. - prop = ACS ? ACS->getString("Location") : pair(false,nullptr); + prop = ACS->getString("Location"); if (prop.first) ACSloc += prop.second; @@ -404,8 +392,8 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, return doRequest( app, &request, request, entityID.c_str(), nullptr, - ACS ? XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) : false, - ACSloc.c_str(), ACS ? ACS->getXMLString("Binding").second : nullptr, + XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT), + ACSloc.c_str(), ACS->getXMLString("Binding").second, isPassive, forceAuthn, acClass.first ? acClass.second : nullptr, acComp.first ? acComp.second : nullptr, @@ -434,35 +422,31 @@ pair SAML2SessionInitiator::run(SPRequest& request, string& entityID, if (spQual.first) in.addmember("SPNameQualifier").string(spQual.second); if (acsByIndex.first && acsByIndex.second) { - if (ACS) { - // Determine index to use. - pair ix = pair(false,nullptr); - if (!strncmp(ACSloc.c_str(), "https", 5)) { - ix = ACS->getString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS); - if (!ix.first) - ix = ACS->getString("index"); - } - else { + // Determine index to use. + pair ix = pair(false,nullptr); + if (!strncmp(ACSloc.c_str(), "https", 5)) { + ix = ACS->getString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS); + if (!ix.first) ix = ACS->getString("index"); - } - in.addmember("acsIndex").string(ix.second); - if (XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT)) - in.addmember("artifact").integer(1); } + else { + ix = ACS->getString("index"); + } + in.addmember("acsIndex").string(ix.second); + if (XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT)) + in.addmember("artifact").integer(1); } else { // Since we're not passing by index, we need to fully compute the return URL and binding. // Compute the ACS URL. We add the ACS location to the base handlerURL. - prop = ACS ? ACS->getString("Location") : pair(false,nullptr); + prop = ACS->getString("Location"); if (prop.first) ACSloc += prop.second; in.addmember("acsLocation").string(ACSloc.c_str()); - if (ACS) { - prop = ACS->getString("Binding"); - in.addmember("acsBinding").string(prop.second); - if (XMLString::equals(prop.second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT)) - in.addmember("artifact").integer(1); - } + prop = ACS->getString("Binding"); + in.addmember("acsBinding").string(prop.second); + if (XMLString::equals(prop.second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT)) + in.addmember("artifact").integer(1); } if (isHandler) { diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp index e4ac2e8..6242c66 100644 --- a/shibsp/handler/impl/Shib1SessionInitiator.cpp +++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp @@ -149,35 +149,25 @@ pair Shib1SessionInitiator::run(SPRequest& request, string& entityID, target = request.getRequestURL(); } - // Since we're not passing by index, we need to fully compute the return URL. if (!ACS) { - // Try fixed index property, or incoming binding set, or default, in order. + // Try fixed index property. pair index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED); - if (index.first) { + if (index.first) ACS = app.getAssertionConsumerServiceByIndex(index.second); - if (!ACS) - request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location"); - } - /* - for (vector::const_iterator b = m_incomingBindings.begin(); !ACS && b != m_incomingBindings.end(); ++b) { - ACS = app.getAssertionConsumerServiceByBinding(b->c_str()); - if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) - ACS = nullptr; - } - */ - if (!ACS) - ACS = app.getDefaultAssertionConsumerService(); } - // Validate the ACS for use with this protocol. - if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) { - m_log.error("configured or requested ACS has non-SAML 1.x binding"); - throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACS->getString("Binding").second)); + // If we picked by index, validate the ACS for use with this protocol. + if (!ACS || !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) { + request.log(SPRequest::SPWarn, "invalid acsIndex property, or non-SAML 1.x ACS, using default SAML 1.x ACS"); + ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily()); + if (!ACS) + throw ConfigurationException("Unable to locate a SAML 1.x ACS endpoint to use for response."); } + // Since we're not passing by index, we need to fully compute the return URL. // Compute the ACS URL. We add the ACS location to the base handlerURL. string ACSloc = request.getHandlerURL(target.c_str()); - prop = ACS ? ACS->getString("Location") : pair(false,nullptr); + prop = ACS->getString("Location"); if (prop.first) ACSloc += prop.second; @@ -191,7 +181,7 @@ pair Shib1SessionInitiator::run(SPRequest& request, string& entityID, } // Is the in-bound binding artifact? - bool artifactInbound = ACS ? XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT) : false; + bool artifactInbound = XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT); m_log.debug("attempting to initiate session using Shibboleth with provider (%s)", entityID.c_str()); diff --git a/shibsp/handler/impl/WAYFSessionInitiator.cpp b/shibsp/handler/impl/WAYFSessionInitiator.cpp index 534a311..2947663 100644 --- a/shibsp/handler/impl/WAYFSessionInitiator.cpp +++ b/shibsp/handler/impl/WAYFSessionInitiator.cpp @@ -122,39 +122,29 @@ pair WAYFSessionInitiator::run(SPRequest& request, string& entityID, discoveryURL = request.getRequestSettings().first->getString("discoveryURL"); } - // Since we're not passing by index, we need to fully compute the return URL. if (!ACS) { - // Try fixed index property, or incoming binding set, or default, in order. + // Try fixed index property. pair index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED); - if (index.first) { + if (index.first) ACS = app.getAssertionConsumerServiceByIndex(index.second); - if (!ACS) - request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location"); - } - /* - for (vector::const_iterator b = m_incomingBindings.begin(); !ACS && b != m_incomingBindings.end(); ++b) { - ACS = app.getAssertionConsumerServiceByBinding(b->c_str()); - if (ACS && !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) - ACS = nullptr; - } - */ - if (!ACS) - ACS = app.getDefaultAssertionConsumerService(); } - // Validate the ACS for use with this protocol. - if (ACS && !XMLString::equals(samlconstants::SAML11_PROTOCOL_ENUM, ACS->getProtocolFamily())) { - m_log.error("configured or requested ACS has non-SAML 1.x binding"); - throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACS->getString("Binding").second)); + // If we picked by index, validate the ACS for use with this protocol. + if (!ACS || !XMLString::equals(samlconstants::SAML11_PROTOCOL_ENUM, ACS->getProtocolFamily())) { + request.log(SPRequest::SPWarn, "invalid acsIndex property, or non-SAML 1.x ACS, using default SAML 1.x ACS"); + ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily()); + if (!ACS) + throw ConfigurationException("Unable to locate a SAML 1.x ACS endpoint to use for response."); } if (!discoveryURL.first) discoveryURL.second = m_url; m_log.debug("sending request to WAYF (%s)", discoveryURL.second); + // Since we're not passing by index, we need to fully compute the return URL. // Compute the ACS URL. We add the ACS location to the base handlerURL. string ACSloc = request.getHandlerURL(target.c_str()); - prop = ACS ? ACS->getString("Location") : pair(false,nullptr); + prop = ACS->getString("Location"); if (prop.first) ACSloc += prop.second; diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp index dd9c294..9b997c2 100644 --- a/shibsp/impl/XMLServiceProvider.cpp +++ b/shibsp/impl/XMLServiceProvider.cpp @@ -168,7 +168,7 @@ namespace { const SessionInitiator* getSessionInitiatorById(const char* id) const; const Handler* getDefaultAssertionConsumerService() const; const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const; - const Handler* getAssertionConsumerServiceByBinding(const char* binding) const; + const Handler* getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding=nullptr) const; const vector& getAssertionConsumerServicesByBinding(const XMLCh* binding) const; const Handler* getHandler(const char* path) const; void getHandlers(vector& handlers) const; @@ -225,9 +225,13 @@ namespace { const Handler* m_acsDefault; // maps binding strings to supporting consumer service(s) - typedef map< string,vector > ACSBindingMap; + typedef map< xstring,vector > ACSBindingMap; ACSBindingMap m_acsBindingMap; + // maps protocol strings to supporting consumer service(s) + typedef map< xstring,vector > ACSProtocolMap; + ACSProtocolMap m_acsProtocolMap; + // pointer to default session initiator const SessionInitiator* m_sessionInitDefault; @@ -458,13 +462,14 @@ 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 _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); 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 RequestMap[] = UNICODE_LITERAL_10(R,e,q,u,e,s,t,M,a,p); 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 _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); @@ -648,8 +653,11 @@ XMLApplication::XMLApplication( continue; } handler = conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), make_pair(child, getId())); - // Map by binding (may be > 1 per binding) - m_acsBindingMap[bindprop].push_back(handler); + // Map by binding and protocol (may be > 1 per protocol and binding) + m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler); + const XMLCh* protfamily = handler->getProtocolFamily(); + if (protfamily) + m_acsProtocolMap[protfamily].push_back(handler); m_acsIndexMap[handler->getUnsignedInt("index").second] = handler; if (!hardACS) { @@ -1218,17 +1226,23 @@ const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : nullptr; } -const Handler* XMLApplication::getAssertionConsumerServiceByBinding(const char* binding) const +const Handler* XMLApplication::getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding) const { - ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding); - if (i != m_acsBindingMap.end()) return i->second.front(); - return m_base ? m_base->getAssertionConsumerServiceByBinding(binding) : nullptr; + ACSProtocolMap::const_iterator i=m_acsProtocolMap.find(protocol); + if (i != m_acsProtocolMap.end() && !i->second.empty()) { + if (!binding || !*binding) + return i->second.front(); + for (ACSProtocolMap::value_type::second_type::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { + if (!strcmp(binding, (*j)->getString("Binding").second)) + return *j; + } + } + return m_base ? m_base->getAssertionConsumerServiceByProtocol(protocol) : nullptr; } const vector& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const { - auto_ptr_char b(binding); - ACSBindingMap::const_iterator i=m_acsBindingMap.find(b.get()); + 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; @@ -1269,10 +1283,11 @@ XMLConfigImpl::acceptNode(const DOMNode* node) const XMLString::equals(name,_ArtifactMap) || XMLString::equals(name,_Extensions) || XMLString::equals(name,Listener) || + XMLString::equals(name,_ProtocolProvider) || XMLString::equals(name,_RequestMapper) || XMLString::equals(name,_ReplayCache) || XMLString::equals(name,SecurityPolicies) || - XMLString::equals(name,SecurityPolicyProvider) || + XMLString::equals(name,_SecurityPolicyProvider) || XMLString::equals(name,_SessionCache) || XMLString::equals(name,Site) || XMLString::equals(name,_StorageService) || @@ -1564,7 +1579,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o #ifndef SHIBSP_LITE // Load security policies. - if (child = XMLHelper::getLastChildElement(e, SecurityPolicyProvider)) { + 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()); @@ -1576,7 +1591,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o } else if (child = XMLHelper::getLastChildElement(e, SecurityPolicies)) { // For backward compatibility, wrap in a plugin element. - DOMElement* polwrapper = e->getOwnerDocument()->createElementNS(nullptr, SecurityPolicyProvider); + 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); diff --git a/shibsp/shibsp-lite.vcxproj b/shibsp/shibsp-lite.vcxproj index 51acf69..6fbf284 100644 --- a/shibsp/shibsp-lite.vcxproj +++ b/shibsp/shibsp-lite.vcxproj @@ -187,6 +187,7 @@ + @@ -238,6 +239,7 @@ + diff --git a/shibsp/shibsp-lite.vcxproj.filters b/shibsp/shibsp-lite.vcxproj.filters index 1b75218..745daf8 100644 --- a/shibsp/shibsp-lite.vcxproj.filters +++ b/shibsp/shibsp-lite.vcxproj.filters @@ -52,6 +52,15 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD02} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + {39717744-95cd-4251-8334-b2cb8a73a42c} + + + {b63c8dfb-c8d2-4717-a815-e554c72d43b1} + + + {c1c74fdd-021f-4003-a8eb-c68091b6eec6} + @@ -207,6 +216,9 @@ Source Files\handler\impl + + Source Files\binding\impl + @@ -320,6 +332,9 @@ Header Files\handler + + Header Files\binding + diff --git a/shibsp/shibsp.vcxproj b/shibsp/shibsp.vcxproj index 03e747d..8fc4d3c 100644 --- a/shibsp/shibsp.vcxproj +++ b/shibsp/shibsp.vcxproj @@ -181,6 +181,7 @@ + @@ -276,6 +277,7 @@ + diff --git a/shibsp/shibsp.vcxproj.filters b/shibsp/shibsp.vcxproj.filters index 696d2e7..c75241f 100644 --- a/shibsp/shibsp.vcxproj.filters +++ b/shibsp/shibsp.vcxproj.filters @@ -372,6 +372,9 @@ Source Files\handler\impl + + Source Files\binding\impl + @@ -530,6 +533,9 @@ Header Files\handler + + Header Files\binding + diff --git a/shibsp/util/SPConstants.cpp b/shibsp/util/SPConstants.cpp index 6614bad..4b62c9b 100644 --- a/shibsp/util/SPConstants.cpp +++ b/shibsp/util/SPConstants.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Internet2 + * Copyright 2001-2010 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ /** * SPConstants.cpp * - * SP XML namespace constants + * Shibboleth SP XML constants. */ #include "internal.h" @@ -48,6 +48,13 @@ const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:nat chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull }; +const XMLCh shibspconstants::SHIB2SPPROTOCOLS_NS[] = // urn:mace:shibboleth:2.0:native:sp:protocols +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon, + chLatin_s, chLatin_p, chColon, chLatin_p, chLatin_r, chLatin_o, chLatin_t, chLatin_o, chLatin_c, chLatin_o, chLatin_l, chLatin_s, chNull +}; + const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map { chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, diff --git a/shibsp/util/SPConstants.h b/shibsp/util/SPConstants.h index 20f9cc2..9e16675 100644 --- a/shibsp/util/SPConstants.h +++ b/shibsp/util/SPConstants.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Internet2 + * Copyright 2001-2010 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ /** * @file shibsp/util/SPConstants.h * - * Shibboleth SP XML constants. + * Shibboleth SP XML constants. */ #ifndef __shibsp_constants_h__ @@ -40,6 +40,9 @@ namespace shibspconstants { /** Shibboleth 2.0 SP configuration namespace ("urn:mace:shibboleth:2.0:native:sp:config") */ extern SHIBSP_API const XMLCh SHIB2SPCONFIG_NS[]; + /** Shibboleth 2.0 SP protocol provider namespace ("urn:mace:shibboleth:2.0:native:sp:protocols") */ + extern SHIBSP_API const XMLCh SHIB2SPPROTOCOLS_NS[]; + /** Shibboleth 2.0 attribute mapping namespace ("urn:mace:shibboleth:2.0:attribute-map") */ extern SHIBSP_API const XMLCh SHIB2ATTRIBUTEMAP_NS[];