X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-opensaml.git;a=blobdiff_plain;f=saml%2FSAMLConfig.cpp;h=fdf3b9b61db982f7da73350576297adebcd2a9d2;hp=5d68230db40579daf0914329f8b26509942c457f;hb=HEAD;hpb=1114253f9e24bc8b77967551ce9bceb0032d3bc5 diff --git a/saml/SAMLConfig.cpp b/saml/SAMLConfig.cpp index 5d68230..fdf3b9b 100644 --- a/saml/SAMLConfig.cpp +++ b/saml/SAMLConfig.cpp @@ -1,55 +1,82 @@ - -/* - * 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 +/** + * 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. + * + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. + * 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. */ /** * SAMLConfig.cpp * - * Library configuration + * Library configuration. */ #include "internal.h" + +#if defined(XMLTOOLING_LOG4SHIB) +# ifndef OPENSAML_LOG4SHIB +# error "Logging library mismatch (XMLTooling is using log4shib)." +# endif +#elif defined(XMLTOOLING_LOG4CPP) +# ifndef OPENSAML_LOG4CPP +# error "Logging library mismatch (XMLTooling is using log4cpp)." +# endif +#else +# error "No supported logging library." +#endif + #include "exceptions.h" #include "SAMLConfig.h" #include "binding/ArtifactMap.h" +#include "binding/MessageDecoder.h" #include "binding/MessageEncoder.h" #include "binding/SAMLArtifact.h" -#include "binding/URLEncoder.h" +#include "binding/SecurityPolicyRule.h" #include "saml1/core/Assertions.h" #include "saml1/core/Protocols.h" #include "saml2/core/Protocols.h" +#include "saml2/metadata/EntityMatcher.h" #include "saml2/metadata/Metadata.h" +#include "saml2/metadata/MetadataFilter.h" #include "saml2/metadata/MetadataProvider.h" -#include "security/TrustEngine.h" #include "util/SAMLConstants.h" +#include #include +#include #include #include +#include +#include + +#include +#include +#include -#include #include #include #include -#include +#include using namespace opensaml; using namespace xmlsignature; +using namespace xmltooling::logging; using namespace xmltooling; -using namespace log4cpp; +using namespace boost::lambda; +using namespace boost; using namespace std; // Expose entry points when used as an extension library @@ -66,9 +93,14 @@ extern "C" void SAML_API xmltooling_extension_term() SAMLConfig::getConfig().term(false); } -DECL_EXCEPTION_FACTORY(ArtifactException,opensaml); -DECL_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md); -DECL_EXCEPTION_FACTORY(BindingException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(ArtifactException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(SecurityPolicyException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(MetadataException,opensaml::saml2md); +DECL_XMLTOOLING_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md); +DECL_XMLTOOLING_EXCEPTION_FACTORY(BindingException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(ProfileException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(FatalProfileException,opensaml); +DECL_XMLTOOLING_EXCEPTION_FACTORY(RetryableProfileException,opensaml); namespace opensaml { SAMLInternalConfig g_config; @@ -84,16 +116,32 @@ SAMLInternalConfig& SAMLInternalConfig::getInternalConfig() return g_config; } +SAMLConfig::SAMLConfig() : m_artifactMap(nullptr) +{ +} + +SAMLConfig::~SAMLConfig() +{ + delete m_artifactMap; +} + +ArtifactMap* SAMLConfig::getArtifactMap() const +{ + return m_artifactMap; +} + void SAMLConfig::setArtifactMap(ArtifactMap* artifactMap) { delete m_artifactMap; m_artifactMap = artifactMap; } -void SAMLConfig::setURLEncoder(URLEncoder* urlEncoder) +SAMLInternalConfig::SAMLInternalConfig() : m_initCount(0), m_lock(Mutex::create()) +{ +} + +SAMLInternalConfig::~SAMLInternalConfig() { - delete m_urlEncoder; - m_urlEncoder = urlEncoder; } bool SAMLInternalConfig::init(bool initXMLTooling) @@ -101,20 +149,37 @@ bool SAMLInternalConfig::init(bool initXMLTooling) #ifdef _DEBUG xmltooling::NDC ndc("init"); #endif - Category& log=Category::getInstance(SAML_LOGCAT".SAMLConfig"); + Category& log=Category::getInstance(SAML_LOGCAT ".Config"); + + Lock initLock(m_lock); + + if (m_initCount == INT_MAX) { + log.crit("library initialized too many times"); + return false; + } + + if (m_initCount >= 1) { + ++m_initCount; + return true; + } + log.debug("library initialization started"); - if (initXMLTooling) { - XMLToolingConfig::getConfig().init(); - log.debug("XMLTooling library initialized"); + if (initXMLTooling && !XMLToolingConfig::getConfig().init()) { + return false; } - REGISTER_EXCEPTION_FACTORY(ArtifactException,opensaml); - REGISTER_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md); - REGISTER_EXCEPTION_FACTORY(BindingException,opensaml); + XMLToolingConfig::getConfig().getPathResolver()->setDefaultPackageName("opensaml"); + + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ArtifactException,opensaml); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(SecurityPolicyException,opensaml); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(MetadataException,opensaml::saml2md); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(BindingException,opensaml); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ProfileException,opensaml); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(FatalProfileException,opensaml); + REGISTER_XMLTOOLING_EXCEPTION_FACTORY(RetryableProfileException,opensaml); - registerMessageEncoders(); - registerSAMLArtifacts(); saml1::registerAssertionClasses(); saml1p::registerProtocolClasses(); saml2::registerAssertionClasses(); @@ -122,11 +187,17 @@ bool SAMLInternalConfig::init(bool initXMLTooling) saml2md::registerMetadataClasses(); saml2md::registerMetadataProviders(); saml2md::registerMetadataFilters(); - registerTrustEngines(); - - m_urlEncoder = new URLEncoder(); + saml2md::registerEntityMatchers(); + registerSAMLArtifacts(); + registerMessageEncoders(); + registerMessageDecoders(); + registerSecurityPolicyRules(); + + m_contactPriority.push_back(saml2md::ContactPerson::CONTACT_SUPPORT); + m_contactPriority.push_back(saml2md::ContactPerson::CONTACT_TECHNICAL); - log.info("library initialization complete"); + log.info("%s library initialization complete", PACKAGE_STRING); + ++m_initCount; return true; } @@ -135,29 +206,31 @@ void SAMLInternalConfig::term(bool termXMLTooling) #ifdef _DEBUG xmltooling::NDC ndc("term"); #endif - Category& log=Category::getInstance(SAML_LOGCAT".SAMLConfig"); - saml1::AssertionSchemaValidators.destroyValidators(); - saml1p::ProtocolSchemaValidators.destroyValidators(); - saml2::AssertionSchemaValidators.destroyValidators(); - saml2md::MetadataSchemaValidators.destroyValidators(); - - TrustEngineManager.deregisterFactories(); + Lock initLock(m_lock); + if (m_initCount == 0) { + Category::getInstance(SAML_LOGCAT ".Config").crit("term without corresponding init"); + return; + } + else if (--m_initCount > 0) { + return; + } + + MessageDecoderManager.deregisterFactories(); + MessageEncoderManager.deregisterFactories(); + SecurityPolicyRuleManager.deregisterFactories(); + SAMLArtifactManager.deregisterFactories(); + EntityMatcherManager.deregisterFactories(); MetadataFilterManager.deregisterFactories(); MetadataProviderManager.deregisterFactories(); - SAMLArtifactManager.deregisterFactories(); - MessageEncoderManager.deregisterFactories(); delete m_artifactMap; - m_artifactMap = NULL; - delete m_urlEncoder; - m_urlEncoder = NULL; + m_artifactMap = nullptr; - if (termXMLTooling) { + if (termXMLTooling) XMLToolingConfig::getConfig().term(); - log.debug("XMLTooling library shut down"); - } - log.info("library shutdown complete"); + + Category::getInstance(SAML_LOGCAT ".Config").info("%s library shutdown complete", PACKAGE_STRING); } void SAMLInternalConfig::generateRandomBytes(void* buf, unsigned int len) @@ -174,8 +247,8 @@ void SAMLInternalConfig::generateRandomBytes(void* buf, unsigned int len) void SAMLInternalConfig::generateRandomBytes(std::string& buf, unsigned int len) { buf.erase(); - auto_ptr hold(new unsigned char[len]); - generateRandomBytes(hold.get(),len); + auto_arrayptr hold(new unsigned char[len]); + generateRandomBytes(const_cast(hold.get()), len); for (unsigned int i=0; i hasher(XSECPlatformUtils::g_cryptoProvider->hashSHA1()); - if (hasher.get()) { - auto_ptr dup(strdup(s)); - unsigned char buf[21]; - hasher->hash(reinterpret_cast(dup.get()),strlen(dup.get())); - if (hasher->finish(buf,20)==20) { - string ret; - if (toHex) { - for (unsigned int i=0; i<20; i++) { - ret+=(DIGITS[((unsigned char)(0xF0 & buf[i])) >> 4 ]); - ret+=(DIGITS[0x0F & buf[i]]); - } + return SecurityHelper::doHash("SHA1", s, strlen(s), toHex); +} + +void SAMLInternalConfig::setContactPriority(const XMLCh* contactTypes) +{ + const XMLCh* ctype; + m_contactPriority.clear(); + XMLStringTokenizer tokens(contactTypes); + while (tokens.hasMoreTokens()) { + ctype = tokens.nextToken(); + if (ctype && *ctype) + m_contactPriority.push_back(ctype); + } +} + +using namespace saml2md; + +const ContactPerson* SAMLInternalConfig::getContactPerson(const EntityDescriptor& entity) const +{ + for (vector::const_iterator ctype = m_contactPriority.begin(); ctype != m_contactPriority.end(); ++ctype) { + const ContactPerson* cp = find_if(entity.getContactPersons(), *ctype == lambda::bind(&ContactPerson::getContactType, _1)); + if (cp) + return cp; + } + return nullptr; +} + +const ContactPerson* SAMLInternalConfig::getContactPerson(const RoleDescriptor& role) const +{ + for (vector::const_iterator ctype = m_contactPriority.begin(); ctype != m_contactPriority.end(); ++ctype) { + const ContactPerson* cp = find_if(role.getContactPersons(), *ctype == lambda::bind(&ContactPerson::getContactType, _1)); + if (cp) + return cp; + } + return getContactPerson(*(dynamic_cast(role.getParent()))); +} + +SignableObject::SignableObject() +{ +} + +SignableObject::~SignableObject() +{ +} + +RootObject::RootObject() +{ +} + +RootObject::~RootObject() +{ +} + +Assertion::Assertion() +{ +} + +Assertion::~Assertion() +{ +} + +Status::Status() +{ +} + +Status::~Status() +{ +} + +void opensaml::annotateException(XMLToolingException* e, const EntityDescriptor* entity, const Status* status, bool rethrow) +{ + time_t now = time(nullptr); + const RoleDescriptor* role = nullptr; + static bool (TimeBoundSAMLObject::* isValid)(time_t) const = &TimeBoundSAMLObject::isValid; + + if (entity) { + const XMLObject* r = find_if( + entity->getOrderedChildren(), + (ll_dynamic_cast(_1) != ((const RoleDescriptor*)nullptr) && + lambda::bind(isValid, ll_dynamic_cast(_1), now)) + ); + if (r) + role = dynamic_cast(r); + } + + annotateException(e, role, status, rethrow); +} + +void opensaml::annotateException(XMLToolingException* e, const RoleDescriptor* role, const Status* status, bool rethrow) +{ + if (role) { + auto_ptr_char id(dynamic_cast(role->getParent())->getEntityID()); + e->addProperty("entityID",id.get()); + + const ContactPerson* cp = SAMLConfig::getConfig().getContactPerson(*role); + if (cp) { + GivenName* fname = cp->getGivenName(); + SurName* lname = cp->getSurName(); + auto_ptr_char first(fname ? fname->getName() : nullptr); + auto_ptr_char last(lname ? lname->getName() : nullptr); + if (first.get() && last.get()) { + string contact=string(first.get()) + ' ' + last.get(); + e->addProperty("contactName", contact.c_str()); } - else { - for (unsigned int i=0; i<20; i++) { - ret+=buf[i]; + else if (first.get()) + e->addProperty("contactName", first.get()); + else if (last.get()) + e->addProperty("contactName", last.get()); + const vector& emails=cp->getEmailAddresss(); + if (!emails.empty()) { + auto_ptr_char email(emails.front()->getAddress()); + if (email.get()) { + if (strstr(email.get(), "mailto:") == email.get()) { + e->addProperty("contactEmail", email.get()); + } + else { + string addr = string("mailto:") + email.get(); + e->addProperty("contactEmail", addr.c_str()); + } } } - return ret; } - } - throw XMLSecurityException("Unable to generate SHA-1 hash."); -} -void opensaml::log_openssl() -{ - const char* file; - const char* data; - int flags,line; + auto_ptr_char eurl(role->getErrorURL()); + if (eurl.get()) { + e->addProperty("errorURL",eurl.get()); + } + } - unsigned long code=ERR_get_error_line_data(&file,&line,&data,&flags); - while (code) { - Category& log=Category::getInstance("OpenSSL"); - log.errorStream() << "error code: " << code << " in " << file << ", line " << line << CategoryStream::ENDLINE; - if (data && (flags & ERR_TXT_STRING)) - log.errorStream() << "error data: " << data << CategoryStream::ENDLINE; - code=ERR_get_error_line_data(&file,&line,&data,&flags); + if (status) { + auto_ptr_char sc(status->getTopStatus()); + if (sc.get() && *sc.get()) + e->addProperty("statusCode", sc.get()); + if (status->getSubStatus()) { + auto_ptr_char sc2(status->getSubStatus()); + if (sc2.get() && *sc.get()) + e->addProperty("statusCode2", sc2.get()); + } + if (status->getMessage()) { + auto_ptr_char msg(status->getMessage()); + if (msg.get() && *msg.get()) + e->addProperty("statusMessage", msg.get()); + } } + + if (rethrow) + e->raise(); }