From d27718e70cdc13a314c5131f8ea19e369320625e Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Tue, 9 Jan 2007 21:58:53 +0000 Subject: [PATCH] Shell of new SP object interface to replace old IConfig layer. --- .cdtproject | 1 + shar/shar.cpp | 4 +- shar/test-client.cpp | 2 +- shib-target/internal.h | 5 ++- shib-target/shib-ccache.cpp | 10 ++--- shib-target/shib-config.cpp | 22 +++++++---- shib-target/shib-handlers.cpp | 13 ++----- shib-target/shib-ini.cpp | 11 ++++-- shib-target/shib-target.h | 9 +---- shibsp/Makefile.am | 2 + shibsp/SPConfig.cpp | 7 +++- shibsp/SPConfig.h | 5 +++ shibsp/ServiceProvider.cpp | 40 ++++++++++++++++++++ shibsp/ServiceProvider.h | 88 +++++++++++++++++++++++++++++++++++++++++++ shibsp/shibsp.vcproj | 8 ++++ 15 files changed, 190 insertions(+), 37 deletions(-) create mode 100644 shibsp/ServiceProvider.cpp create mode 100644 shibsp/ServiceProvider.h diff --git a/.cdtproject b/.cdtproject index 10e639b..e5bc816 100644 --- a/.cdtproject +++ b/.cdtproject @@ -10,6 +10,7 @@ + diff --git a/shar/shar.cpp b/shar/shar.cpp index 0fde514..42dadf5 100644 --- a/shar/shar.cpp +++ b/shar/shar.cpp @@ -143,7 +143,7 @@ int real_main(int preinit) if (!shar_checkonly) { // Run the listener. - if (!conf.getINI()->getListener()->run(&shibd_shutdown)) { + if (!conf.getINI()->getListenerService()->run(&shibd_shutdown)) { fprintf(stderr, "listener failed to enter listen loop\n"); return -3; } @@ -281,7 +281,7 @@ int main(int argc, char *argv[]) } // Run the listener - if (!conf.getINI()->getListener()->run(&shibd_shutdown)) { + if (!conf.getINI()->getListenerService()->run(&shibd_shutdown)) { fprintf(stderr, "listener failed to enter listen loop\n"); return -3; } diff --git a/shar/test-client.cpp b/shar/test-client.cpp index e04b823..1721ab3 100644 --- a/shar/test-client.cpp +++ b/shar/test-client.cpp @@ -52,7 +52,7 @@ int main (int argc, char *argv[]) DDFJanitor injan(in); in.integer(atol(argv[1])); - DDF out=conf.getINI()->getListener()->send(in); + DDF out=conf.getINI()->getListenerService()->send(in); DDFJanitor outjan(out); cerr << argv[1] << " -> " << out.integer() << "\n"; diff --git a/shib-target/internal.h b/shib-target/internal.h index 607429b..2dcbe4a 100644 --- a/shib-target/internal.h +++ b/shib-target/internal.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -86,8 +87,10 @@ namespace shibtarget { private: log4cpp::FixedContextCategory* m_tranLog; xmltooling::Mutex* m_tranLogLock; - static IConfig* ShibTargetConfigFactory(const DOMElement* e); }; + + // TODO: move this over to shibsp lib. + xmltooling::PluginManager::Factory XMLServiceProviderFactory; } #endif diff --git a/shib-target/shib-ccache.cpp b/shib-target/shib-ccache.cpp index 0d4e635..ab4eb3f 100644 --- a/shib-target/shib-ccache.cpp +++ b/shib-target/shib-ccache.cpp @@ -224,7 +224,7 @@ string StubCache::insert( os << *tokens; in.addmember("tokens.unfiltered").string(os.str().c_str()); - out=ShibTargetConfig::getConfig().getINI()->getListener()->send(in); + out=ShibTargetConfig::getConfig().getINI()->getListenerService()->send(in); if (out["key"].isstring()) return out["key"].string(); throw opensaml::RetryableProfileException("A remoted cache insertion operation did not return a usable session key."); @@ -240,7 +240,7 @@ ISessionCacheEntry* StubCache::find(const char* key, const IApplication* applica in.addmember("client_address").string(client_addr); try { - out=ShibTargetConfig::getConfig().getINI()->getListener()->send(in); + out=ShibTargetConfig::getConfig().getINI()->getListenerService()->send(in); if (!out.isstruct()) { out.destroy(); return NULL; @@ -264,7 +264,7 @@ void StubCache::remove(const char* key, const IApplication* application, const c in.addmember("application_id").string(application->getId()); in.addmember("client_address").string(client_addr); - ShibTargetConfig::getConfig().getINI()->getListener()->send(in); + ShibTargetConfig::getConfig().getINI()->getListenerService()->send(in); } /* @@ -1063,7 +1063,7 @@ MemorySessionCache::MemorySessionCache(const DOMElement* e) SAMLConfig::getConfig().conn_timeout = m_AAConnectTimeout; // Register for remoted messages. - ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListener(); + ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListenerService(false); if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { restoreInsert=listener->regListener("SessionCache::insert",this); restoreFind=listener->regListener("SessionCache::find",this); @@ -1085,7 +1085,7 @@ MemorySessionCache::~MemorySessionCache() cleanup_thread->join(NULL); // Unregister remoted messages. - ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListener(); + ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListenerService(false); if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { listener->unregListener("SessionCache::insert",this,restoreInsert); listener->unregListener("SessionCache::find",this,restoreFind); diff --git a/shib-target/shib-config.cpp b/shib-target/shib-config.cpp index 3e0321a..bb913b3 100644 --- a/shib-target/shib-config.cpp +++ b/shib-target/shib-config.cpp @@ -37,6 +37,7 @@ using namespace log4cpp; using namespace std; using xmltooling::XMLToolingConfig; +using xmltooling::PluginManager; namespace { STConfig g_Config; @@ -67,7 +68,7 @@ bool STConfig::init(const char* schemadir) #ifdef _DEBUG xmltooling::NDC ndc("init"); #endif - Category& log = Category::getInstance("shibtarget.Config"); + Category& log = Category::getInstance(SHIBT_LOGCAT".Config"); if (!schemadir) { log.fatal("XML schema directory not supplied"); @@ -79,20 +80,27 @@ bool STConfig::init(const char* schemadir) SAMLConfig& samlConf=SAMLConfig::getConfig(); if (schemadir) samlConf.schema_dir = schemadir; - if (!samlConf.init() || !SPConfig::getConfig().init(NULL)) { - log.fatal("failed to initialize SP library"); + if (!samlConf.init()) { + log.fatal("failed to initialize OpenSAML1 library"); return false; } ShibConfig& shibConf=ShibConfig::getConfig(); if (!shibConf.init()) { log.fatal("Failed to initialize Shib library"); - SPConfig::getConfig().term(); + samlConf.term(); + return false; + } + + if (!SPConfig::getConfig().init(NULL)) { + log.fatal("Failed to initialize SP library"); + shibConf.term(); samlConf.term(); return false; } // Register built-in plugin types. + SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory); samlConf.getPlugMgr().regFactory(MEMORY_SESSIONCACHE,&MemoryCacheFactory); samlConf.getPlugMgr().regFactory(LEGACY_REQUESTMAP_PROVIDER,&XMLRequestMapFactory); @@ -115,7 +123,7 @@ bool STConfig::load(const char* config) #ifdef _DEBUG xmltooling::NDC ndc("load"); #endif - Category& log = Category::getInstance("shibtarget.Config"); + Category& log = Category::getInstance(SHIBT_LOGCAT".Config"); if (!config) { log.fatal("path to configuration file not supplied"); @@ -134,7 +142,7 @@ bool STConfig::load(const char* config) auto_ptr_XMLCh src(config); dummy->setAttributeNS(NULL,path,src.get()); - m_ini=ShibTargetConfigFactory(dummy); + m_ini=dynamic_cast(SPConfig::getConfig().ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy)); m_ini->init(); pair skew=m_ini->getUnsignedInt("clockSkew"); @@ -168,7 +176,7 @@ void STConfig::shutdown() #ifdef _DEBUG xmltooling::NDC ndc("shutdown"); #endif - Category& log = Category::getInstance("shibtarget.Config"); + Category& log = Category::getInstance(SHIBT_LOGCAT".Config"); log.info("shutting down the library"); delete m_tranLogLock; m_tranLogLock = NULL; diff --git a/shib-target/shib-handlers.cpp b/shib-target/shib-handlers.cpp index 02e9271..313b0b5 100644 --- a/shib-target/shib-handlers.cpp +++ b/shib-target/shib-handlers.cpp @@ -247,18 +247,13 @@ SAML1Consumer::SAML1Consumer(const DOMElement* e) m_address += "::SAML1Consumer::run"; // Register for remoted messages. - if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { - ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListener(); - if (listener) - listener->regListener(m_address.c_str(),this); - else - throw ListenerException("Plugin requires a Listener service"); - } + if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) + ShibTargetConfig::getConfig().getINI()->getListenerService()->regListener(m_address.c_str(),this); } SAML1Consumer::~SAML1Consumer() { - ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListener(); + ListenerService* listener=ShibTargetConfig::getConfig().getINI()->getListenerService(false); if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) listener->unregListener(m_address.c_str(),this); counter--; @@ -514,7 +509,7 @@ pair SAML1Consumer::run(ShibTarget* st, bool isHandler) const in.addmember("application_id").string(st->getApplication()->getId()); in.addmember("client_address").string(st->getRemoteAddr()); - out=st->getConfig()->getListener()->send(in); + out=st->getConfig()->getListenerService()->send(in); if (!out["key"].isstring()) throw opensaml::FatalProfileException("Remote processing of SAML 1.x Browser profile did not return a usable session key."); string key=out["key"].string(); diff --git a/shib-target/shib-ini.cpp b/shib-target/shib-ini.cpp index d65b10d..de4c83a 100644 --- a/shib-target/shib-ini.cpp +++ b/shib-target/shib-ini.cpp @@ -203,8 +203,13 @@ namespace { const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const {return m_impl->getPropertySet(name,ns);} const DOMElement* getElement() const {return m_impl->getElement();} - // IConfig - ListenerService* getListener() const {return m_listener;} + // ServiceProvider + ListenerService* getListenerService(bool required=true) const { + if (required && !m_listener) + throw ConfigurationException("No ListenerService available."); + return m_listener; + } + ISessionCache* getSessionCache() const {return m_sessionCache;} IReplayCache* getReplayCache() const {return m_replayCache;} IRequestMapper* getRequestMapper() const {return m_impl->m_requestMapper;} @@ -272,7 +277,7 @@ namespace { } -IConfig* STConfig::ShibTargetConfigFactory(const DOMElement* e) +ServiceProvider* shibtarget::XMLServiceProviderFactory(const DOMElement* const & e) { return new XMLConfig(e); } diff --git a/shib-target/shib-target.h b/shib-target/shib-target.h index 1769593..321dd5e 100644 --- a/shib-target/shib-target.h +++ b/shib-target/shib-target.h @@ -26,12 +26,10 @@ #define SHIB_TARGET_H // New headers -#include #include -#include +#include #include #include -#include // Old headers #include @@ -293,15 +291,12 @@ namespace shibtarget { #define NATIVE_REQUESTMAP_PROVIDER "edu.internet2.middleware.shibboleth.sp.provider.NativeRequestMapProvider" #define LEGACY_REQUESTMAP_PROVIDER "edu.internet2.middleware.shibboleth.target.provider.XMLRequestMap" - struct SHIBTARGET_EXPORTS IConfig : public virtual xmltooling::Lockable, public virtual shibsp::PropertySet, public virtual saml::IPlugIn + struct SHIBTARGET_EXPORTS IConfig : public virtual shibsp::ServiceProvider { - virtual void init()=0; - virtual shibsp::ListenerService* getListener() const=0; virtual ISessionCache* getSessionCache() const=0; virtual saml::IReplayCache* getReplayCache() const=0; virtual IRequestMapper* getRequestMapper() const=0; virtual const IApplication* getApplication(const char* applicationId) const=0; - virtual xmlsignature::CredentialResolver* getCredentialResolver(const char* id) const=0; virtual ~IConfig() {} }; diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am index 24dc1a9..fefe2bf 100644 --- a/shibsp/Makefile.am +++ b/shibsp/Makefile.am @@ -18,6 +18,7 @@ libshibspinclude_HEADERS = \ PKIXTrustEngine.h \ PropertySet.h \ version.h \ + ServiceProvider.h \ SocketListener.h \ SPConfig.h \ SPConstants.h @@ -32,6 +33,7 @@ libshibsp_la_SOURCES = \ MetadataExtImpl.cpp \ MetadataExtSchemaValidators.cpp \ PKIXTrustEngine.cpp \ + ServiceProvider.cpp \ SPConfig.cpp \ SPConstants.cpp \ SocketListener.cpp \ diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp index d92bdca..3e98e04 100644 --- a/shibsp/SPConfig.cpp +++ b/shibsp/SPConfig.cpp @@ -26,6 +26,7 @@ #include "ListenerService.h" #include "MetadataExt.h" #include "PKIXTrustEngine.h" +#include "ServiceProvider.h" #include "SPConfig.h" #include @@ -91,9 +92,10 @@ bool SPInternalConfig::init(const char* catalog_path) REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ConfigurationException,shibsp); REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ListenerException,shibsp); - registerListenerServices(); registerMetadataExtClasses(); registerPKIXTrustEngine(); + registerListenerServices(); + registerServiceProviders(); log.info("library initialization complete"); return true; @@ -107,10 +109,11 @@ void SPInternalConfig::term() Category& log=Category::getInstance(SHIBSP_LOGCAT".Config"); log.info("shutting down the library"); - //delete m_serviceProvider; + delete m_serviceProvider; m_serviceProvider = NULL; ListenerServiceManager.deregisterFactories(); + ServiceProviderManager.deregisterFactories(); SAMLConfig::getConfig().term(); log.info("library shutdown complete"); diff --git a/shibsp/SPConfig.h b/shibsp/SPConfig.h index ca29cb9..9afcc5d 100644 --- a/shibsp/SPConfig.h +++ b/shibsp/SPConfig.h @@ -134,6 +134,11 @@ namespace shibsp { */ xmltooling::PluginManager ListenerServiceManager; + /** + * Manages factories for ServiceProvider plugins. + */ + xmltooling::PluginManager ServiceProviderManager; + protected: SPConfig() : m_serviceProvider(NULL) {} diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp new file mode 100644 index 0000000..34958bd --- /dev/null +++ b/shibsp/ServiceProvider.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * ServiceProvider.cpp + * + * Interface to a Shibboleth ServiceProvider instance. + */ + +#include "internal.h" +#include "ServiceProvider.h" + +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +namespace shibsp { + //SHIBSP_DLLLOCAL PluginManager::Factory XMLServiceProviderFactory; +}; + +void SHIBSP_API shibsp::registerServiceProviders() +{ + //SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory); +} diff --git a/shibsp/ServiceProvider.h b/shibsp/ServiceProvider.h new file mode 100644 index 0000000..3fc4228 --- /dev/null +++ b/shibsp/ServiceProvider.h @@ -0,0 +1,88 @@ +/* + * Copyright 2001-2006 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/ServiceProvider.h + * + * Interface to a Shibboleth ServiceProvider instance. + */ + +#ifndef __shibsp_sp_h__ +#define __shibsp_sp_h__ + +#include +#include + +namespace shibsp { + + class ListenerService; + + /** + * Interface to a Shibboleth ServiceProvider instance. + * + *

A ServiceProvider exposes configuration and infrastructure services required + * by the SP implementation, allowing a flexible configuration format. + */ + class SHIBSP_API ServiceProvider : public virtual xmltooling::Lockable, public virtual PropertySet + { + MAKE_NONCOPYABLE(ServiceProvider); + protected: + ServiceProvider() {} + public: + virtual ~ServiceProvider() {} + + /** + * Loads a configuration and prepares the instance for use. + * + *

Implemented as a separate method so that services can rely on + * other services while they initialize by accessing the ServiceProvider + * from the SPConfig singleton. + */ + virtual void init()=0; + + /** + * Returns a ListenerService instance. + * + * @param required true iff an exception should be thrown if no ListenerService is available + * @return a ListenerService if available, or NULL + */ + virtual ListenerService* getListenerService(bool required=true) const=0; + + /** + * Returns a CredentialResolver instance mapped to a key. + * + * @param id a NULL-terminated key identifying the CredentialResolver to the configuration + * @return a CredentialResolver if available, or NULL + */ + virtual xmlsignature::CredentialResolver* getCredentialResolver(const char* id) const=0; + + //virtual ISessionCache* getSessionCache() const=0; + + //virtual IRequestMapper* getRequestMapper() const=0; + + //virtual const IApplication* getApplication(const char* applicationId) const=0; + }; + + /** + * Registers ServiceProvider classes into the runtime. + */ + void SHIBSP_API registerServiceProviders(); + + /** SP based on integrated XML and native server configuration. */ + #define XML_SERVICE_PROVIDER "edu.internet2.middleware.shibboleth.sp.provider.XMLServiceProvider" +}; + +#endif /* __shibsp_sp_h__ */ diff --git a/shibsp/shibsp.vcproj b/shibsp/shibsp.vcproj index ba0d212..5614e43 100644 --- a/shibsp/shibsp.vcproj +++ b/shibsp/shibsp.vcproj @@ -209,6 +209,10 @@ > + + @@ -267,6 +271,10 @@ > + + -- 2.1.4