X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=shibsp%2FSPConfig.cpp;h=e8b6d2f507a99971054cd87c13defb83997bb492;hb=c51bfd77603cf0ddb0b5e374c35586a8435895d6;hp=3c9ad7f697e13cac2fcda2400a5b9ccdd602360b;hpb=a640935c10e7f116089ec5671eea4207c445d206;p=shibboleth%2Fcpp-sp.git diff --git a/shibsp/SPConfig.cpp b/shibsp/SPConfig.cpp index 3c9ad7f..e8b6d2f 100644 --- a/shibsp/SPConfig.cpp +++ b/shibsp/SPConfig.cpp @@ -1,34 +1,53 @@ - -/* - * Copyright 2001-2007 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 +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. * - * http://www.apache.org/licenses/LICENSE-2.0 + * UCAID licenses this file to you 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 * - * 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. + * 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. */ /** * SPConfig.cpp - * - * Library configuration + * + * Library configuration. */ #include "internal.h" -#include "AccessControl.h" + +#if defined(XMLTOOLING_LOG4SHIB) +# ifndef SHIBSP_LOG4SHIB +# error "Logging library mismatch (XMLTooling is using log4shib)." +# endif +#elif defined(XMLTOOLING_LOG4CPP) +# ifndef SHIBSP_LOG4CPP +# error "Logging library mismatch (XMLTooling is using log4cpp)." +# endif +#else +# error "No supported logging library." +#endif + #include "exceptions.h" +#include "version.h" +#include "AccessControl.h" #include "RequestMapper.h" #include "ServiceProvider.h" #include "SessionCache.h" #include "SPConfig.h" #include "attribute/Attribute.h" +#include "binding/ProtocolProvider.h" +#include "handler/LogoutInitiator.h" #include "handler/SessionInitiator.h" #include "remoting/ListenerService.h" @@ -41,19 +60,27 @@ # include "binding/ArtifactResolver.h" # include "metadata/MetadataExt.h" # include "security/PKIXTrustEngine.h" +# include "security/SecurityPolicyProvider.h" +# include # include -#else -# include #endif -#include +#include +#include +#include +#include #include +#include +#include #include +#include +#include using namespace shibsp; using namespace opensaml; using namespace xmltooling; -using namespace log4cpp; +using namespace boost; +using namespace std; DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeException,shibsp); DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeExtractionException,shibsp); @@ -63,15 +90,30 @@ DECL_XMLTOOLING_EXCEPTION_FACTORY(ConfigurationException,shibsp); DECL_XMLTOOLING_EXCEPTION_FACTORY(ListenerException,shibsp); #ifdef SHIBSP_LITE -DECL_XMLTOOLING_EXCEPTION_FACTORY(MetadataException,opensaml::saml2md); +DECL_XMLTOOLING_EXCEPTION_FACTORY(BindingException,opensaml); DECL_XMLTOOLING_EXCEPTION_FACTORY(SecurityPolicyException,opensaml); DECL_XMLTOOLING_EXCEPTION_FACTORY(ProfileException,opensaml); DECL_XMLTOOLING_EXCEPTION_FACTORY(FatalProfileException,opensaml); DECL_XMLTOOLING_EXCEPTION_FACTORY(RetryableProfileException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(MetadataException,opensaml::saml2md); #endif namespace shibsp { - SPInternalConfig g_config; + class SHIBSP_DLLLOCAL SPInternalConfig : public SPConfig + { + public: + SPInternalConfig() : m_initCount(0), m_lock(Mutex::create()) {} + ~SPInternalConfig() {} + + bool init(const char* catalog_path=nullptr, const char* inst_prefix=nullptr); + void term(); + + private: + int m_initCount; + scoped_ptr m_lock; + }; + + SPInternalConfig g_config; } SPConfig& SPConfig::getConfig() @@ -79,9 +121,35 @@ SPConfig& SPConfig::getConfig() return g_config; } -SPInternalConfig& SPInternalConfig::getInternalConfig() +SPConfig::SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(nullptr), +#ifndef SHIBSP_LITE + m_artifactResolver(nullptr), +#endif + m_features(0), m_configDoc(nullptr) { - return g_config; +} + +SPConfig::~SPConfig() +{ +} + +void SPConfig::setFeatures(unsigned long enabled) +{ + m_features = enabled; +} + +unsigned long SPConfig::getFeatures() const { + return m_features; +} + +bool SPConfig::isEnabled(components_t feature) const +{ + return (m_features & feature)>0; +} + +ServiceProvider* SPConfig::getServiceProvider() const +{ + return m_serviceProvider; } void SPConfig::setServiceProvider(ServiceProvider* serviceProvider) @@ -90,40 +158,118 @@ void SPConfig::setServiceProvider(ServiceProvider* serviceProvider) m_serviceProvider = serviceProvider; } -bool SPInternalConfig::init(const char* catalog_path) +#ifndef SHIBSP_LITE +void SPConfig::setArtifactResolver(MessageDecoder::ArtifactResolver* artifactResolver) { -#ifdef _DEBUG - NDC ndc("init"); + delete m_artifactResolver; + m_artifactResolver = artifactResolver; +} + +const MessageDecoder::ArtifactResolver* SPConfig::getArtifactResolver() const +{ + return m_artifactResolver; +} #endif - Category& log=Category::getInstance(SHIBSP_LOGCAT".Config"); - log.debug("library initialization started"); - const char* loglevel=getenv("SHIBSP_LOGGING"); - if (!loglevel) - loglevel = SHIBSP_LOGGING; - XMLToolingConfig::getConfig().log_config(loglevel); +bool SPConfig::init(const char* catalog_path, const char* inst_prefix) +{ + if (!inst_prefix) + inst_prefix = getenv("SHIBSP_PREFIX"); + if (!inst_prefix) + inst_prefix = SHIBSP_PREFIX; + std::string inst_prefix2; + while (*inst_prefix) { + inst_prefix2.push_back((*inst_prefix=='\\') ? ('/') : (*inst_prefix)); + ++inst_prefix; + } - if (!catalog_path) - catalog_path = getenv("SHIBSP_SCHEMAS"); - if (!catalog_path) - catalog_path = SHIBSP_SCHEMAS; - XMLToolingConfig::getConfig().catalog_path = catalog_path; + const char* logconf = getenv("SHIBSP_LOGGING"); + if (!logconf || !*logconf) { + if (isEnabled(SPConfig::Logging) && isEnabled(SPConfig::OutOfProcess) && !isEnabled(SPConfig::InProcess)) + logconf = SHIBSP_OUTOFPROC_LOGGING; + else if (isEnabled(SPConfig::Logging) && isEnabled(SPConfig::InProcess) && !isEnabled(SPConfig::OutOfProcess)) + logconf = SHIBSP_INPROC_LOGGING; + else + logconf = SHIBSP_LOGGING; + } + PathResolver localpr; + localpr.setDefaultPrefix(inst_prefix2.c_str()); + inst_prefix = getenv("SHIBSP_CFGDIR"); + if (!inst_prefix || !*inst_prefix) + inst_prefix = SHIBSP_CFGDIR; + localpr.setCfgDir(inst_prefix); + std::string lc(logconf); + XMLToolingConfig::getConfig().log_config(localpr.resolve(lc, PathResolver::XMLTOOLING_CFG_FILE, PACKAGE_NAME).c_str()); + + Category& log=Category::getInstance(SHIBSP_LOGCAT ".Config"); + log.debug("%s library initialization started", PACKAGE_STRING); #ifndef SHIBSP_LITE + XMLToolingConfig::getConfig().user_agent = string(PACKAGE_NAME) + '/' + PACKAGE_VERSION + + " OpenSAML/" + gOpenSAMLDotVersionStr + + " XMLTooling/" + gXMLToolingDotVersionStr + + " XML-Security-C/" + XSEC_FULLVERSIONDOT + + " Xerces-C/" + XERCES_FULLVERSIONDOT + +#if defined(LOG4SHIB_VERSION) + " log4shib/" + LOG4SHIB_VERSION; +#elif defined(LOG4CPP_VERSION) + " log4cpp/" + LOG4CPP_VERSION; +#endif if (!SAMLConfig::getConfig().init()) { log.fatal("failed to initialize OpenSAML library"); return false; } #else + XMLToolingConfig::getConfig().user_agent = string(PACKAGE_NAME) + '/' + PACKAGE_VERSION + + " XMLTooling/" + gXMLToolingDotVersionStr + + " Xerces-C/" + XERCES_FULLVERSIONDOT + +#if defined(LOG4SHIB_VERSION) + " log4shib/" + LOG4SHIB_VERSION; +#elif defined(LOG4CPP_VERSION) + " log4cpp/" + LOG4CPP_VERSION; +#endif if (!XMLToolingConfig::getConfig().init()) { log.fatal("failed to initialize XMLTooling library"); return false; } #endif + PathResolver* pr = XMLToolingConfig::getConfig().getPathResolver(); + pr->setDefaultPackageName(PACKAGE_NAME); + pr->setDefaultPrefix(inst_prefix2.c_str()); + pr->setCfgDir(inst_prefix); + inst_prefix = getenv("SHIBSP_LIBDIR"); + if (!inst_prefix || !*inst_prefix) + inst_prefix = SHIBSP_LIBDIR; + pr->setLibDir(inst_prefix); + inst_prefix = getenv("SHIBSP_LOGDIR"); + if (!inst_prefix || !*inst_prefix) + inst_prefix = SHIBSP_LOGDIR; + pr->setLogDir(inst_prefix); + inst_prefix = getenv("SHIBSP_RUNDIR"); + if (!inst_prefix || !*inst_prefix) + inst_prefix = SHIBSP_RUNDIR; + pr->setRunDir(inst_prefix); + inst_prefix = getenv("SHIBSP_CACHEDIR"); + if (!inst_prefix || !*inst_prefix) + inst_prefix = SHIBSP_CACHEDIR; + pr->setCacheDir(inst_prefix); + inst_prefix = getenv("SHIBSP_XMLDIR"); + if (!inst_prefix || !*inst_prefix) + inst_prefix = SHIBSP_XMLDIR; + pr->setXMLDir(inst_prefix); + + if (!catalog_path) + catalog_path = getenv("SHIBSP_SCHEMAS"); + if (!catalog_path || !*catalog_path) + catalog_path = SHIBSP_SCHEMAS; + if (!XMLToolingConfig::getConfig().getValidatingParser().loadCatalogs(catalog_path)) { + log.warn("failed to load schema catalogs into validating parser"); + } + XMLToolingConfig::getConfig().setTemplateEngine(new TemplateEngine()); XMLToolingConfig::getConfig().getTemplateEngine()->setTagPrefix("shibmlp"); - + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeException,shibsp); REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeExtractionException,shibsp); REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeFilteringException,shibsp); @@ -132,6 +278,7 @@ bool SPInternalConfig::init(const char* catalog_path) REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ListenerException,shibsp); #ifdef SHIBSP_LITE + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(BindingException,opensaml); REGISTER_XMLTOOLING_EXCEPTION_FACTORY(SecurityPolicyException,opensaml); REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ProfileException,opensaml); REGISTER_XMLTOOLING_EXCEPTION_FACTORY(FatalProfileException,opensaml); @@ -147,8 +294,14 @@ bool SPInternalConfig::init(const char* catalog_path) #endif registerAttributeFactories(); - registerHandlers(); - registerSessionInitiators(); + + if (isEnabled(Handlers)) { + registerHandlers(); + registerLogoutInitiators(); + registerSessionInitiators(); + registerProtocolProviders(); + } + registerServiceProviders(); #ifndef SHIBSP_LITE @@ -159,6 +312,10 @@ bool SPInternalConfig::init(const char* catalog_path) registerAttributeFilters(); registerMatchFunctors(); } + if (isEnabled(Logging)) { + registerEvents(); + } + registerSecurityPolicyProviders(); #endif if (isEnabled(Listener)) @@ -176,35 +333,44 @@ bool SPInternalConfig::init(const char* catalog_path) if (isEnabled(OutOfProcess)) m_artifactResolver = new ArtifactResolver(); #endif + srand(static_cast(std::time(nullptr))); - log.info("library initialization complete"); + log.info("%s library initialization complete", PACKAGE_STRING); return true; } -void SPInternalConfig::term() +void SPConfig::term() { -#ifdef _DEBUG - NDC ndc("term"); -#endif - Category& log=Category::getInstance(SHIBSP_LOGCAT".Config"); - log.info("shutting down the library"); + Category& log=Category::getInstance(SHIBSP_LOGCAT ".Config"); + log.info("%s library shutting down", PACKAGE_STRING); - setServiceProvider(NULL); + setServiceProvider(nullptr); + if (m_configDoc) + m_configDoc->release(); + m_configDoc = nullptr; #ifndef SHIBSP_LITE - setArtifactResolver(NULL); + 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(); #ifndef SHIBSP_LITE + SecurityPolicyProviderManager.deregisterFactories(); + if (isEnabled(Logging)) { + EventManager.deregisterFactories(); + } if (isEnabled(AttributeResolution)) { MatchFunctorManager.deregisterFactories(); AttributeFilterManager.deregisterFactories(); @@ -230,5 +396,105 @@ void SPInternalConfig::term() #else XMLToolingConfig::getConfig().term(); #endif - log.info("library shutdown complete"); + log.info("%s library shutdown complete", PACKAGE_STRING); +} + +bool SPConfig::instantiate(const char* config, bool rethrow) +{ +#ifdef _DEBUG + NDC ndc("instantiate"); +#endif + if (!config) + config = getenv("SHIBSP_CONFIG"); + if (!config) + config = SHIBSP_CONFIG; + try { + xercesc::DOMDocument* dummydoc; + if (*config == '"' || *config == '\'') { + throw ConfigurationException("The value of SHIBSP_CONFIG started with a quote."); + } + else if (*config != '<') { + + // Mock up some XML. + string resolved(config); + stringstream snippet; + snippet + << ""; + dummydoc = XMLToolingConfig::getConfig().getParser().parse(snippet); + XercesJanitor docjanitor(dummydoc); + setServiceProvider(ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER, dummydoc->getDocumentElement())); + if (m_configDoc) + m_configDoc->release(); + m_configDoc = docjanitor.release(); + } + else { + stringstream snippet(config); + dummydoc = XMLToolingConfig::getConfig().getParser().parse(snippet); + XercesJanitor docjanitor(dummydoc); + static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); + auto_ptr_char type(dummydoc->getDocumentElement()->getAttributeNS(nullptr,_type)); + if (type.get() && *type.get()) + setServiceProvider(ServiceProviderManager.newPlugin(type.get(), dummydoc->getDocumentElement())); + else + throw ConfigurationException("The supplied XML bootstrapping configuration did not include a type attribute."); + if (m_configDoc) + m_configDoc->release(); + m_configDoc = docjanitor.release(); + } + + getServiceProvider()->init(); + return true; + } + catch (exception& ex) { + if (rethrow) + throw; + Category::getInstance(SHIBSP_LOGCAT ".Config").fatal("caught exception while loading configuration: %s", ex.what()); + } + return false; +} + +bool SPInternalConfig::init(const char* catalog_path, const char* inst_prefix) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("init"); +#endif + + Lock initLock(m_lock); + + if (m_initCount == INT_MAX) { + Category::getInstance(SHIBSP_LOGCAT ".Config").crit("library initialized too many times"); + return false; + } + + if (m_initCount >= 1) { + ++m_initCount; + return true; + } + + if (!SPConfig::init(catalog_path, inst_prefix)) { + return false; + } + + ++m_initCount; + return true; +} + +void SPInternalConfig::term() +{ +#ifdef _DEBUG + xmltooling::NDC ndc("term"); +#endif + + Lock initLock(m_lock); + if (m_initCount == 0) { + Category::getInstance(SHIBSP_LOGCAT ".Config").crit("term without corresponding init"); + return; + } + else if (--m_initCount > 0) { + return; + } + + SPConfig::term(); }