[cpp-sp] branch main updated: Remove handlers for functions we won't support.
Scott Cantor
cantor.2 at osu.edu
Fri Nov 1 18:00:30 UTC 2024
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=22d6d46c5ec8bc74f269765f6a6ae44ac51ef470
The following commit(s) were added to refs/heads/main by this push:
new 22d6d46c Remove handlers for functions we won't support.
22d6d46c is described below
commit 22d6d46c5ec8bc74f269765f6a6ae44ac51ef470
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Nov 1 14:00:26 2024 -0400
Remove handlers for functions we won't support.
---
Projects/vc15/shibsp/shibsp.vcxproj | 4 -
shibsp/Makefile.am | 4 -
shibsp/handler/impl/AbstractHandler.cpp | 34 +--
shibsp/handler/impl/SAML1Consumer.cpp | 360 ------------------------
shibsp/handler/impl/SAML2ArtifactResolution.cpp | 357 -----------------------
shibsp/handler/impl/SessionInitiator.cpp | 4 -
shibsp/handler/impl/Shib1SessionInitiator.cpp | 347 -----------------------
shibsp/handler/impl/WAYFSessionInitiator.cpp | 202 -------------
8 files changed, 1 insertion(+), 1311 deletions(-)
diff --git a/Projects/vc15/shibsp/shibsp.vcxproj b/Projects/vc15/shibsp/shibsp.vcxproj
index dff3bcdf..cd05b177 100644
--- a/Projects/vc15/shibsp/shibsp.vcxproj
+++ b/Projects/vc15/shibsp/shibsp.vcxproj
@@ -238,8 +238,6 @@
<ClCompile Include="..\..\..\shibsp\handler\impl\LogoutHandler.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\MetadataGenerator.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\RemotedHandler.cpp" />
- <ClCompile Include="..\..\..\shibsp\handler\impl\SAML1Consumer.cpp" />
- <ClCompile Include="..\..\..\shibsp\handler\impl\SAML2ArtifactResolution.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\SAML2Consumer.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\SAML2Logout.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\SAML2LogoutInitiator.cpp" />
@@ -247,10 +245,8 @@
<ClCompile Include="..\..\..\shibsp\handler\impl\SAMLDSSessionInitiator.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\SessionHandler.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\SessionInitiator.cpp" />
- <ClCompile Include="..\..\..\shibsp\handler\impl\Shib1SessionInitiator.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\StatusHandler.cpp" />
<ClCompile Include="..\..\..\shibsp\handler\impl\TransformSessionInitiator.cpp" />
- <ClCompile Include="..\..\..\shibsp\handler\impl\WAYFSessionInitiator.cpp" />
<ClCompile Include="..\..\..\shibsp\lite\CommonDomainCookie.cpp" />
<ClCompile Include="..\..\..\shibsp\lite\SAMLConstants.cpp" />
<ClCompile Include="..\..\..\shibsp\version.cpp" />
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index 002486b9..9db3deb5 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -97,9 +97,7 @@ libshibsp_la_SOURCES = \
handler/impl/LogoutInitiator.cpp \
handler/impl/MetadataGenerator.cpp \
handler/impl/RemotedHandler.cpp \
- handler/impl/SAML1Consumer.cpp \
handler/impl/SAML2Consumer.cpp \
- handler/impl/SAML2ArtifactResolution.cpp \
handler/impl/SAML2Logout.cpp \
handler/impl/SAML2LogoutInitiator.cpp \
handler/impl/SAML2SessionInitiator.cpp \
@@ -107,10 +105,8 @@ libshibsp_la_SOURCES = \
handler/impl/SecuredHandler.cpp \
handler/impl/SessionHandler.cpp \
handler/impl/SessionInitiator.cpp \
- handler/impl/Shib1SessionInitiator.cpp \
handler/impl/StatusHandler.cpp \
handler/impl/TransformSessionInitiator.cpp \
- handler/impl/WAYFSessionInitiator.cpp \
impl/ChainingAccessControl.cpp \
impl/StoredSession.cpp \
impl/StorageServiceSessionCache.cpp \
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 14a2bf6f..bc0f8d3b 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -47,23 +47,7 @@
#include <xmltooling/util/URLEncoder.h>
-#ifndef SHIBSP_LITE
-# include <saml/exceptions.h>
-# include <saml/SAMLConfig.h>
-# include <saml/binding/SAMLArtifact.h>
-# include <saml/saml1/core/Protocols.h>
-# include <saml/saml2/core/Protocols.h>
-# include <saml/saml2/metadata/Metadata.h>
-# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-# include <saml/util/SAMLConstants.h>
-# include <xmltooling/security/Credential.h>
-# include <xmltooling/security/CredentialResolver.h>
-# include <xmltooling/util/StorageService.h>
-using namespace opensaml::saml2md;
-using namespace opensaml;
-#else
-# include "lite/SAMLConstants.h"
-#endif
+#include "lite/SAMLConstants.h"
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/URLEncoder.h>
@@ -76,9 +60,7 @@ using namespace boost;
using namespace std;
namespace shibsp {
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;
SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;
- SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;
SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;
SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;
SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AttributeCheckerFactory;
@@ -110,18 +92,12 @@ 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);
conf.HandlerManager.registerFactory(ATTR_CHECKER_HANDLER, AttributeCheckerFactory);
conf.HandlerManager.registerFactory(DISCOVERY_FEED_HANDLER, DiscoveryFeedFactory);
@@ -146,14 +122,6 @@ Handler::~Handler()
{
}
-#ifndef SHIBSP_LITE
-
-void Handler::generateMetadata(SPSSODescriptor&, const char*) const
-{
-}
-
-#endif
-
const XMLCh* Handler::getProtocolFamily() const
{
return nullptr;
diff --git a/shibsp/handler/impl/SAML1Consumer.cpp b/shibsp/handler/impl/SAML1Consumer.cpp
deleted file mode 100644
index d5e8324c..00000000
--- a/shibsp/handler/impl/SAML1Consumer.cpp
+++ /dev/null
@@ -1,360 +0,0 @@
-/**
- * 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
- *
- * 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.
- */
-
-/**
- * SAML1Consumer.cpp
- *
- * SAML 1.x assertion consumer service.
- */
-
-#include "internal.h"
-#include "handler/AssertionConsumerService.h"
-
-#ifndef SHIBSP_LITE
-# include "Application.h"
-# include "ServiceProvider.h"
-# include "SessionCache.h"
-# include "attribute/resolver/ResolutionContext.h"
-# include <boost/iterator/indirect_iterator.hpp>
-# include <saml/exceptions.h>
-# include <saml/SAMLConfig.h>
-# include <saml/binding/SecurityPolicy.h>
-# include <saml/binding/SecurityPolicyRule.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml1/core/Protocols.h>
-# include <saml/saml2/metadata/Metadata.h>
-# include <xmltooling/XMLToolingConfig.h>
-# include <xmltooling/io/HTTPRequest.h>
-using namespace opensaml::saml1;
-using namespace opensaml::saml1p;
-using namespace opensaml;
-using namespace boost;
-using saml2::NameID;
-using saml2::NameIDBuilder;
-using saml2md::EntityDescriptor;
-using saml2md::SPSSODescriptor;
-using saml2md::MetadataException;
-#else
-# include "lite/SAMLConstants.h"
-#endif
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class SHIBSP_DLLLOCAL SAML1Consumer : public AssertionConsumerService
- {
- public:
- SAML1Consumer(const DOMElement* e, const char* appId, bool deprecationSupport=true)
- : AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT ".SSO.SAML1"), nullptr, nullptr, deprecationSupport) {
-#ifndef SHIBSP_LITE
- m_post = XMLString::equals(getString("Binding").second, samlconstants::SAML1_PROFILE_BROWSER_POST);
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess))
- m_ssoRule.reset(SAMLConfig::getConfig().SecurityPolicyRuleManager.newPlugin(SAML1BROWSERSSO_POLICY_RULE, e, deprecationSupport));
-#endif
- }
- virtual ~SAML1Consumer() {}
-
-#ifndef SHIBSP_LITE
- void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
- AssertionConsumerService::generateMetadata(role, handlerURL);
- role.addSupport(samlconstants::SAML11_PROTOCOL_ENUM);
- role.addSupport(samlconstants::SAML10_PROTOCOL_ENUM);
- }
-
- private:
- const char* getProfile() const {
- return m_post ? samlconstants::SAML1_PROFILE_BROWSER_POST : samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT;
- }
-
- void implementProtocol(
- const Application& application,
- const HTTPRequest& httpRequest,
- HTTPResponse& httpResponse,
- SecurityPolicy& policy,
- const PropertySet*,
- const XMLObject& xmlObject
- ) const;
-
- bool m_post;
- scoped_ptr<SecurityPolicyRule> m_ssoRule;
-#else
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML11_PROTOCOL_ENUM;
- }
-#endif
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- Handler* SHIBSP_DLLLOCAL SAML1ConsumerFactory(const pair<const DOMElement*,const char*>& p, bool deprecationSupport)
- {
- return new SAML1Consumer(p.first, p.second, deprecationSupport);
- }
-
-#ifndef SHIBSP_LITE
- class SHIBSP_DLLLOCAL _rulenamed : std::unary_function<const SecurityPolicyRule*,bool>
- {
- public:
- _rulenamed(const char* name) : m_name(name) {}
- bool operator()(const SecurityPolicyRule* rule) const {
- return rule ? !strcmp(m_name, rule->getType()) : false;
- }
- private:
- const char* m_name;
- };
-#endif
-};
-
-#ifndef SHIBSP_LITE
-
-void SAML1Consumer::implementProtocol(
- const Application& application,
- const HTTPRequest& httpRequest,
- HTTPResponse& httpResponse,
- SecurityPolicy& policy,
- const PropertySet*,
- const XMLObject& xmlObject
- ) const
-{
- // Implementation of SAML 1.x SSO profile(s).
- m_log.debug("processing message against SAML 1.x SSO profile");
-
- // Check for errors...this will throw if it's not a successful message.
- checkError(&xmlObject, policy.getIssuerMetadata());
-
- // With the binding aspects now moved out to the MessageDecoder,
- // the focus here is on the assertion content. For SAML 1.x POST,
- // all the security comes from the protocol layer, and signing
- // the assertion isn't sufficient. So we can check the policy
- // object now and bail if it's not a secured message.
- if (m_post && !policy.isAuthenticated()) {
- if (policy.getIssuer() && !policy.getIssuerMetadata())
- throw MetadataException("Security of SAML 1.x SSO POST response not established.");
- throw SecurityPolicyException("Security of SAML 1.x SSO POST response not established.");
- }
-
- // Remember whether we already established trust.
- bool alreadySecured = policy.isAuthenticated();
-
- const Response* response = dynamic_cast<const Response*>(&xmlObject);
- if (!response)
- throw FatalProfileException("Incoming message was not a samlp:Response.");
-
- const vector<saml1::Assertion*>& assertions = response->getAssertions();
- if (assertions.empty())
- throw FatalProfileException("Incoming message contained no SAML assertions.");
-
- pair<bool,int> minor = response->getMinorVersion();
-
- // Maintain list of "legit" tokens to feed to SP subsystems.
- const AuthenticationStatement* ssoStatement=nullptr;
- vector<const opensaml::Assertion*> tokens;
-
- // Also track "bad" tokens that we'll cache but not use.
- // This is necessary because there may be valid tokens not aimed at us.
- vector<const opensaml::Assertion*> badtokens;
-
- // With this flag on, we ignore any unsigned assertions.
- const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : nullptr;
- pair<bool,bool> flag = application.getRelyingParty(entity)->getBool("requireSignedAssertions");
-
- // authnskew allows rejection of SSO if AuthnInstant is too old.
- const PropertySet* sessionProps = application.getPropertySet("Sessions");
- pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
-
- // Saves off error messages potentially helpful for users.
- string contextualError;
-
- // Ensure the BrowserSSO rule is in the policy set.
- if (find_if(policy.getRules(), _rulenamed(SAML1BROWSERSSO_POLICY_RULE)) == nullptr)
- policy.getRules().push_back(m_ssoRule.get());
-
- // Populate recipient as audience.
- policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
-
- time_t now = time(nullptr);
- for (indirect_iterator<vector<saml1::Assertion*>::const_iterator> a = make_indirect_iterator(assertions.begin());
- a != make_indirect_iterator(assertions.end()); ++a) {
- try {
- // Skip unsigned assertion?
- if (!a->getSignature() && flag.first && flag.second)
- throw SecurityPolicyException("The incoming assertion was unsigned, violating local security policy.");
-
- // We clear the security flag, so we can tell whether the token was secured on its own.
- policy.setAuthenticated(false);
- policy.reset(true);
-
- // Extract message bits and re-verify Issuer information.
- extractMessageDetails(
- *a, (minor.first && minor.second==0) ? samlconstants::SAML10_PROTOCOL_ENUM : samlconstants::SAML11_PROTOCOL_ENUM, policy
- );
-
- // Run the policy over the assertion. Handles replay, freshness, and
- // signature verification, assuming the relevant rules are configured,
- // along with condition and profile enforcement.
- policy.evaluate(*a, &httpRequest);
-
- // If no security is in place now, we kick it.
- if (!alreadySecured && !policy.isAuthenticated())
- throw SecurityPolicyException("Unable to establish security of incoming assertion.");
-
- // Track it as a valid token.
- tokens.push_back(&(*a));
-
- // Save off the first valid SSO statement.
- const vector<AuthenticationStatement*>& statements =
- const_cast<const saml1::Assertion&>(*a).getAuthenticationStatements();
- for (indirect_iterator<vector<AuthenticationStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
- s != make_indirect_iterator(statements.end()); ++s) {
- if (s->getAuthenticationInstant() &&
- s->getAuthenticationInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
- contextualError = "The login time at your identity provider was future-dated.";
- }
- else if (authnskew.first && authnskew.second && s->getAuthenticationInstant() &&
- s->getAuthenticationInstantEpoch() <= now && (now - s->getAuthenticationInstantEpoch() > authnskew.second)) {
- contextualError = "The gap between now and the time you logged into your identity provider exceeds the allowed limit.";
- }
- else if (authnskew.first && authnskew.second && s->getAuthenticationInstant() == nullptr) {
- contextualError = "Your identity provider did not supply a time of login, violating local policy.";
- }
- else if (!ssoStatement) {
- ssoStatement = &(*s);
- break;
- }
- }
- }
- catch (std::exception& ex) {
- m_log.warn("detected a problem with assertion: %s", ex.what());
- if (!ssoStatement)
- contextualError = ex.what();
- badtokens.push_back(&(*a));
- }
- }
-
- if (!ssoStatement) {
- if (contextualError.empty())
- throw FatalProfileException("A valid authentication statement was not found in the incoming message.");
- throw FatalProfileException(contextualError.c_str());
- }
-
- // Address checking.
- SubjectLocality* locality = ssoStatement->getSubjectLocality();
- if (locality && locality->getIPAddress()) {
- auto_ptr_char ip(locality->getIPAddress());
- checkAddress(application, httpRequest, ip.get());
- }
-
- m_log.debug("SSO profile processing completed successfully");
-
- NameIdentifier* n = ssoStatement->getSubject()->getNameIdentifier();
-
- // Now we have to extract the authentication details for attribute and session setup.
-
- // Session expiration for SAML 1.x is purely SP-driven, and the method is mapped to a ctx class.
- pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
- if (!lifetime.first || lifetime.second == 0)
- lifetime.second = 28800;
-
- // We've successfully "accepted" at least one SSO token, along with any additional valid tokens.
- // To complete processing, we need to extract and resolve attributes and then create the session.
-
- // Normalize the SAML 1.x NameIdentifier...
- scoped_ptr<NameID> nameid(n ? NameIDBuilder::buildNameID() : nullptr);
- if (n) {
- nameid->setName(n->getName());
- nameid->setFormat(n->getFormat());
- nameid->setNameQualifier(n->getNameQualifier());
- }
-
- // The context will handle deleting attributes and new tokens.
- scoped_ptr<ResolutionContext> ctx(
- resolveAttributes(
- application,
- &httpRequest,
- policy.getIssuerMetadata(),
- (!response->getMinorVersion().first || response->getMinorVersion().second==1) ?
- samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM,
- response,
- n,
- ssoStatement,
- nameid.get(),
- nullptr,
- ssoStatement->getAuthenticationMethod(),
- nullptr,
- &tokens
- )
- );
-
- if (ctx) {
- // Copy over any new tokens, but leave them in the context for cleanup.
- tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
- }
-
- // Now merge in bad tokens for caching.
- tokens.insert(tokens.end(), badtokens.begin(), badtokens.end());
-
- string session_id;
- application.getServiceProvider().getSessionCache()->insert(
- session_id,
- application,
- httpRequest,
- httpResponse,
- now + lifetime.second,
- entity,
- (!response->getMinorVersion().first || response->getMinorVersion().second==1) ?
- samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM,
- nameid.get(),
- ssoStatement->getAuthenticationInstant() ? ssoStatement->getAuthenticationInstant()->getRawData() : nullptr,
- nullptr,
- ssoStatement->getAuthenticationMethod(),
- nullptr,
- &tokens,
- ctx ? &ctx->getResolvedAttributes() : nullptr
- );
-
- scoped_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
- if (login_event) {
- login_event->m_sessionID = session_id.c_str();
- login_event->m_peer = entity;
- auto_ptr_char prot(
- (!response->getMinorVersion().first || response->getMinorVersion().second==1) ?
- samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM
- );
- login_event->m_protocol = prot.get();
- login_event->m_nameID = nameid.get();
- login_event->m_saml1AuthnStatement = ssoStatement;
- login_event->m_saml1Response = response;
- if (ctx)
- login_event->m_attributes = &ctx->getResolvedAttributes();
- application.getServiceProvider().getTransactionLog()->write(*login_event);
- }
-}
-
-#endif
diff --git a/shibsp/handler/impl/SAML2ArtifactResolution.cpp b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
deleted file mode 100644
index 48eeaa40..00000000
--- a/shibsp/handler/impl/SAML2ArtifactResolution.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-/**
- * 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
- *
- * 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.
- */
-
-/**
- * SAML2ArtifactResolution.cpp
- *
- * Handler for resolving SAML 2.0 artifacts.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "SPRequest.h"
-#include "handler/AbstractHandler.h"
-#include "handler/RemotedHandler.h"
-#include "util/SPConstants.h"
-
-#ifndef SHIBSP_LITE
-# include "security/SecurityPolicy.h"
-# include "security/SecurityPolicyProvider.h"
-# include <saml/exceptions.h>
-# include <saml/SAMLConfig.h>
-# include <saml/binding/ArtifactMap.h>
-# include <saml/binding/MessageEncoder.h>
-# include <saml/binding/MessageDecoder.h>
-# include <saml/binding/SAMLArtifact.h>
-# include <saml/saml2/core/Assertions.h>
-# include <saml/saml2/core/Protocols.h>
-# include <saml/saml2/metadata/Metadata.h>
-using namespace opensaml::saml2md;
-using namespace opensaml::saml2p;
-using namespace opensaml::saml2;
-using namespace opensaml;
-#else
-# include "lite/SAMLConstants.h"
-#endif
-
-#include <boost/scoped_ptr.hpp>
-#include <xmltooling/soap/SOAP.h>
-
-using namespace shibspconstants;
-using namespace shibsp;
-using namespace soap11;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class SHIBSP_API SAML2ArtifactResolution : public AbstractHandler, public RemotedHandler
- {
- public:
- SAML2ArtifactResolution(const DOMElement* e, const char* appId, bool deprecationSupport=true);
- virtual ~SAML2ArtifactResolution() {}
-
- pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
- void receive(DDF& in, ostream& out);
-
-#ifndef SHIBSP_LITE
- const char* getType() const {
- return "ArtifactResolutionService";
- }
-
- void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
- // Initial guess at index to use.
- pair<bool,unsigned int> ix = pair<bool,unsigned int>(false,0);
- if (!strncmp(handlerURL, "https", 5))
- ix = getUnsignedInt("sslIndex", shibspconstants::ASCII_SHIBSPCONFIG_NS);
- if (!ix.first)
- ix = getUnsignedInt("index");
- if (!ix.first)
- ix.second = 1;
-
- // Find maximum index in use and go one higher.
- const vector<ArtifactResolutionService*>& services = const_cast<const SPSSODescriptor&>(role).getArtifactResolutionServices();
- if (!services.empty() && ix.second <= services.back()->getIndex().second)
- ix.second = services.back()->getIndex().second + 1;
-
- const char* loc = getString("Location").second;
- string hurl(handlerURL);
- if (*loc != '/')
- hurl += '/';
- hurl += loc;
- auto_ptr_XMLCh widen(hurl.c_str());
-
- auto_ptr<ArtifactResolutionService> ep(ArtifactResolutionServiceBuilder::buildArtifactResolutionService());
- ep->setLocation(widen.get());
- ep->setBinding(getXMLString("Binding").second);
- ep->setIndex(ix.second);
- role.getArtifactResolutionServices().push_back(ep.get());
- ep.release();
- }
-#endif
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML20P_NS;
- }
-
- private:
- pair<bool,long> processMessage(const Application& application, HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
-#ifndef SHIBSP_LITE
- pair<bool,long> emptyResponse(
- const Application& app, const ArtifactResolve& request, HTTPResponse& httpResponse, const EntityDescriptor* recipient
- ) const;
-
- scoped_ptr<MessageEncoder> m_encoder;
- scoped_ptr<MessageDecoder> m_decoder;
-#endif
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- Handler* SHIBSP_DLLLOCAL SAML2ArtifactResolutionFactory(const pair<const DOMElement*,const char*>& p, bool deprecationSupport)
- {
- return new SAML2ArtifactResolution(p.first, p.second, deprecationSupport);
- }
-
-};
-
-SAML2ArtifactResolution::SAML2ArtifactResolution(const DOMElement* e, const char* appId, bool deprecationSupport)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".ArtifactResolution.SAML2"))
-{
-#ifndef SHIBSP_LITE
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- m_encoder.reset(SAMLConfig::getConfig().MessageEncoderManager.newPlugin(getString("Binding").second, e, deprecationSupport));
- m_decoder.reset(SAMLConfig::getConfig().MessageDecoderManager.newPlugin(getString("Binding").second, e, deprecationSupport));
- }
-#endif
- string address(appId);
- address += getString("Location").second;
- address += "::run::SAML2Artifact";
- setAddress(address.c_str());
-}
-
-pair<bool,long> SAML2ArtifactResolution::run(SPRequest& request, bool isHandler) const
-{
- string relayState;
- SPConfig& conf = SPConfig::getConfig();
-
- try {
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
- // When out of process, we run natively and directly process the message.
- return processMessage(request.getApplication(), request, request);
- }
- else {
- // When not out of process, we remote all the message processing.
- DDF out,in = wrap(request, nullptr, true);
- DDFJanitor jin(in), jout(out);
-
- out = send(request, in);
- return unwrap(request, out);
- }
- }
- catch (std::exception& ex) {
- m_log.error("error while processing request: %s", ex.what());
-
- // Build a SOAP fault around the error.
- auto_ptr<Fault> fault(FaultBuilder::buildFault());
- Faultcode* code = FaultcodeBuilder::buildFaultcode();
- fault->setFaultcode(code);
- code->setCode(&Faultcode::SERVER);
- Faultstring* fs = FaultstringBuilder::buildFaultstring();
- fault->setFaultstring(fs);
- pair<bool,bool> flag = getBool("detailedErrors", shibspconstants::ASCII_SHIBSPCONFIG_NS);
- auto_ptr_XMLCh msg((flag.first && flag.second) ? ex.what() : "Error processing request.");
- fs->setString(msg.get());
-#ifndef SHIBSP_LITE
- // Use MessageEncoder to send back the fault.
- long ret = m_encoder->encode(request, fault.get(), nullptr);
- fault.release();
- return make_pair(true, ret);
-#else
- // Brute force the fault to avoid library dependency.
- scoped_ptr<Envelope> env(EnvelopeBuilder::buildEnvelope());
- Body* body = BodyBuilder::buildBody();
- env->setBody(body);
- body->getUnknownXMLObjects().push_back(fault.get());
- fault.release();
- string xmlbuf;
- XMLHelper::serialize(env->marshall(), xmlbuf);
- istringstream s(xmlbuf);
- request.setContentType("text/xml");
- return make_pair(true, request.sendError(s));
-#endif
- }
-}
-
-void SAML2ArtifactResolution::receive(DDF& in, ostream& out)
-{
- // Find application.
- const char* aid=in["application_id"].string();
- const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
- if (!app) {
- // Something's horribly wrong.
- m_log.error("couldn't find application (%s) for artifact resolution", aid ? aid : "(missing)");
- throw ConfigurationException("Unable to locate application for artifact resolution, deleted?");
- }
-
- // Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(*app, in));
- //m_log.debug("found %d client certificates", req->getClientCertificates().size());
-
- // Wrap a response shim.
- DDF ret(nullptr);
- DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
-
- try {
- // Since we're remoted, the result should either be a throw, a false/0 return,
- // which we just return as an empty structure, or a response/redirect,
- // which we capture in the facade and send back.
- processMessage(*app, *req, *resp);
- out << ret;
- }
- catch (std::exception& ex) {
-#ifndef SHIBSP_LITE
- m_log.error("error while processing request: %s", ex.what());
-
- // Use MessageEncoder to send back a SOAP fault.
- auto_ptr<Fault> fault(FaultBuilder::buildFault());
- Faultcode* code = FaultcodeBuilder::buildFaultcode();
- fault->setFaultcode(code);
- code->setCode(&Faultcode::SERVER);
- Faultstring* fs = FaultstringBuilder::buildFaultstring();
- fault->setFaultstring(fs);
- pair<bool,bool> flag = getBool("detailedErrors", shibspconstants::ASCII_SHIBSPCONFIG_NS);
- auto_ptr_XMLCh msg((flag.first && flag.second) ? ex.what() : "Error processing request.");
- fs->setString(msg.get());
- m_encoder->encode(*resp, fault.get(), nullptr);
- fault.release();
- out << ret;
-#else
- throw; // should never happen anyway
-#endif
- }
-}
-
-pair<bool,long> SAML2ArtifactResolution::processMessage(const Application& application, HTTPRequest& httpRequest, HTTPResponse& httpResponse) const
-{
-#ifndef SHIBSP_LITE
- m_log.debug("processing SAML 2.0 ArtifactResolve request");
-
- ArtifactMap* artmap = SAMLConfig::getConfig().getArtifactMap();
- if (!artmap)
- throw ConfigurationException("No ArtifactMap instance installed.");
-
- // Locate policy key.
- pair<bool,const char*> policyId = getString("policyId", shibspconstants::ASCII_SHIBSPCONFIG_NS); // namespace-qualified if inside handler element
- if (!policyId.first)
- policyId = application.getString("policyId"); // unqualified in Application(s) element
-
- // Lock metadata for use by policy.
- Locker metadataLocker(application.getMetadataProvider());
-
- // Create the policy.
- scoped_ptr<SecurityPolicy> policy(
- application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(
- samlconstants::SAML20_PROFILE_ARTIFACT, application, &IDPSSODescriptor::ELEMENT_QNAME, policyId.second
- )
- );
-
- // Decode the message and verify that it's a secured ArtifactResolve request.
- string relayState;
- scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, &httpResponse, *policy));
- if (!msg)
- throw BindingException("Failed to decode a SAML request.");
- const ArtifactResolve* req = dynamic_cast<const ArtifactResolve*>(msg.get());
- if (!req)
- throw FatalProfileException("Decoded message was not a samlp::ArtifactResolve request.");
-
- const EntityDescriptor* entity = policy->getIssuerMetadata() ? dynamic_cast<EntityDescriptor*>(policy->getIssuerMetadata()->getParent()) : nullptr;
-
- try {
- auto_ptr_char artifact(req->getArtifact() ? req->getArtifact()->getArtifact() : nullptr);
- if (!artifact.get() || !*artifact.get())
- return emptyResponse(application, *req, httpResponse, entity);
- auto_ptr_char issuer(policy->getIssuer() ? policy->getIssuer()->getName() : nullptr);
-
- m_log.info("resolving artifact (%s) for (%s)", artifact.get(), issuer.get() ? issuer.get() : "unknown");
-
- // Parse the artifact and retrieve the object.
- scoped_ptr<SAMLArtifact> artobj(SAMLArtifact::parse(artifact.get()));
- auto_ptr<XMLObject> payload(artmap->retrieveContent(artobj.get(), issuer.get()));
-
- if (!policy->isAuthenticated()) {
- m_log.error("request for artifact was unauthenticated, purging the artifact mapping");
- return emptyResponse(application, *req, httpResponse, entity);
- }
-
- m_log.debug("artifact resolved, preparing response");
-
- // Wrap it in a response.
- auto_ptr<ArtifactResponse> resp(ArtifactResponseBuilder::buildArtifactResponse());
- resp->setInResponseTo(req->getID());
- Issuer* me = IssuerBuilder::buildIssuer();
- resp->setIssuer(me);
- me->setName(application.getRelyingParty(entity)->getXMLString("entityID").second);
- resp->setPayload(payload.get());
- payload.release();
- fillStatus(*resp, StatusCode::SUCCESS);
-
- long ret = sendMessage(
- *m_encoder, resp.get(), relayState.c_str(), nullptr, policy->getIssuerMetadata(), application, httpResponse, "conditional"
- );
- resp.release(); // freed by encoder
- return make_pair(true, ret);
- }
- catch (std::exception& ex) {
- // Trap localized errors.
- m_log.error("error processing artifact request: %s", ex.what());
- return emptyResponse(application, *req, httpResponse, entity);
- }
-#else
- return make_pair(false,0L);
-#endif
-}
-
-#ifndef SHIBSP_LITE
-pair<bool,long> SAML2ArtifactResolution::emptyResponse(
- const Application& app, const ArtifactResolve& request, HTTPResponse& httpResponse, const EntityDescriptor* recipient
- ) const
-{
- auto_ptr<ArtifactResponse> resp(ArtifactResponseBuilder::buildArtifactResponse());
- resp->setInResponseTo(request.getID());
- Issuer* me = IssuerBuilder::buildIssuer();
- resp->setIssuer(me);
- me->setName(app.getRelyingParty(recipient)->getXMLString("entityID").second);
- fillStatus(*resp, StatusCode::SUCCESS);
- long ret = m_encoder->encode(httpResponse, resp.get(), nullptr);
- resp.release(); // freed by encoder
- return make_pair(true, ret);
-}
-#endif
diff --git a/shibsp/handler/impl/SessionInitiator.cpp b/shibsp/handler/impl/SessionInitiator.cpp
index ba3ece86..5fdd0401 100644
--- a/shibsp/handler/impl/SessionInitiator.cpp
+++ b/shibsp/handler/impl/SessionInitiator.cpp
@@ -40,9 +40,7 @@ using namespace opensaml::saml2md;
namespace shibsp {
SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory ChainingSessionInitiatorFactory;
- SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory Shib1SessionInitiatorFactory;
SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory SAML2SessionInitiatorFactory;
- SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory WAYFSessionInitiatorFactory;
SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory SAMLDSSessionInitiatorFactory;
SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory TransformSessionInitiatorFactory;
SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory FormSessionInitiatorFactory;
@@ -53,9 +51,7 @@ void SHIBSP_API shibsp::registerSessionInitiators()
{
SPConfig& conf=SPConfig::getConfig();
conf.SessionInitiatorManager.registerFactory(CHAINING_SESSION_INITIATOR, ChainingSessionInitiatorFactory);
- conf.SessionInitiatorManager.registerFactory(SHIB1_SESSION_INITIATOR, Shib1SessionInitiatorFactory);
conf.SessionInitiatorManager.registerFactory(SAML2_SESSION_INITIATOR, SAML2SessionInitiatorFactory);
- conf.SessionInitiatorManager.registerFactory(WAYF_SESSION_INITIATOR, WAYFSessionInitiatorFactory);
conf.SessionInitiatorManager.registerFactory(SAMLDS_SESSION_INITIATOR, SAMLDSSessionInitiatorFactory);
conf.SessionInitiatorManager.registerFactory(TRANSFORM_SESSION_INITIATOR, TransformSessionInitiatorFactory);
conf.SessionInitiatorManager.registerFactory(FORM_SESSION_INITIATOR, FormSessionInitiatorFactory);
diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp
deleted file mode 100644
index ba4f47e2..00000000
--- a/shibsp/handler/impl/Shib1SessionInitiator.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/**
- * 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
- *
- * 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.
- */
-
-/**
- * Shib1SessionInitiator.cpp
- *
- * Shibboleth 1.x AuthnRequest support.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "exceptions.h"
-#include "ServiceProvider.h"
-#include "handler/AbstractHandler.h"
-#include "handler/RemotedHandler.h"
-#include "handler/SessionInitiator.h"
-#include "util/SPConstants.h"
-
-#ifndef SHIBSP_LITE
-# include "metadata/MetadataProviderCriteria.h"
-# include <boost/lexical_cast.hpp>
-# include <saml/saml2/metadata/Metadata.h>
-# include <saml/saml2/metadata/EndpointManager.h>
-# include <saml/util/SAMLConstants.h>
-#else
-# include "lite/SAMLConstants.h"
-#endif
-#include <boost/scoped_ptr.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/URLEncoder.h>
-
-using namespace shibsp;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class SHIBSP_DLLLOCAL Shib1SessionInitiator : public SessionInitiator, public AbstractHandler, public RemotedHandler
- {
- public:
- Shib1SessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.Shib1"), nullptr, this), m_appId(appId) {
- // If Location isn't set, defer address registration until the setParent call.
- pair<bool,const char*> loc = getString("Location");
- if (loc.first) {
- string address = m_appId + loc.second + "::run::Shib1SI";
- setAddress(address.c_str());
- }
- }
- virtual ~Shib1SessionInitiator() {}
-
- void setParent(const PropertySet* parent);
- void receive(DDF& in, ostream& out);
- pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
- pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
-
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML11_PROTOCOL_ENUM;
- }
-
-#ifndef SHIBSP_LITE
- void generateMetadata(saml2md::SPSSODescriptor& role, const char* handlerURL) const {
- doGenerateMetadata(role, handlerURL);
- }
-#endif
-
- private:
- pair<bool,long> doRequest(
- const Application& application,
- const HTTPRequest* httpRequest,
- HTTPResponse& httpResponse,
- const char* entityID,
- const char* acsLocation,
- bool artifact,
- string& relayState
- ) const;
- string m_appId;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- SessionInitiator* SHIBSP_DLLLOCAL Shib1SessionInitiatorFactory(const pair<const DOMElement*,const char*>& p, bool)
- {
- return new Shib1SessionInitiator(p.first, p.second);
- }
-
-};
-
-void Shib1SessionInitiator::setParent(const PropertySet* parent)
-{
- DOMPropertySet::setParent(parent);
- pair<bool,const char*> loc = getString("Location");
- if (loc.first) {
- string address = m_appId + loc.second + "::run::Shib1SI";
- setAddress(address.c_str());
- }
- else {
- m_log.warn("no Location property in Shib1 SessionInitiator (or parent), can't register as remoted handler");
- }
-}
-
-pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID, bool isHandler) const
-{
- // We have to know the IdP to function.
- if (entityID.empty() || !checkCompatibility(request, isHandler))
- return make_pair(false, 0L);
-
- string target;
- pair<bool,const char*> prop;
- const Handler* ACS = nullptr;
- const Application& app = request.getApplication();
-
- if (isHandler) {
- prop.second = request.getParameter("acsIndex");
- if (prop.second && *prop.second) {
- SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
- ACS = app.getAssertionConsumerServiceByIndex(atoi(prop.second));
- if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
- }
-
- prop = getString("target", request);
- if (prop.first)
- target = prop.second;
-
- // Since we're passing the ACS by value, we need to compute the return URL,
- // so we'll need the target resource for real.
- recoverRelayState(app, request, request, target, false);
- app.limitRedirect(request, target.c_str());
- }
- else {
- // Check for a hardwired target value in the map or handler.
- prop = getString("target", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- if (prop.first)
- target = prop.second;
- else
- target = request.getRequestURL();
- }
-
- if (!ACS) {
- // Try fixed index property.
- pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- if (index.first) {
- SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
- ACS = app.getAssertionConsumerServiceByIndex(index.second);
- }
- }
-
- // If we picked by index, validate the ACS for use with this protocol.
- if (!ACS || !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) {
- if (ACS)
- 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->getString("Location");
- if (prop.first)
- ACSloc += prop.second;
-
- if (isHandler) {
- // We may already have RelayState set if we looped back here,
- // but we've turned it back into a resource by this point, so if there's
- // a target on the URL, reset to that value.
- prop.second = request.getParameter("target");
- if (prop.second && *prop.second)
- target = prop.second;
- }
-
- // Is the in-bound binding artifact?
- 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());
-
- if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
- // Out of process means the POST data via the request can be exposed directly to the private method.
- // The method will handle POST preservation if necessary *before* issuing the response, but only if
- // it dispatches to an IdP.
- return doRequest(app, &request, request, entityID.c_str(), ACSloc.c_str(), artifactInbound, target);
- }
-
- // Remote the call.
- DDF out,in = DDF(m_address.c_str()).structure();
- DDFJanitor jin(in), jout(out);
- in.addmember("application_id").string(app.getId());
- in.addmember("entity_id").string(entityID.c_str());
- in.addmember("acsLocation").string(ACSloc.c_str());
- if (artifactInbound)
- in.addmember("artifact").integer(1);
- if (!target.empty())
- in.addmember("RelayState").unsafe_string(target.c_str());
-
- // Remote the processing. Our unwrap method will handle POST data if necessary.
- out = send(request, in);
- return unwrap(request, out);
-}
-
-pair<bool,long> Shib1SessionInitiator::unwrap(SPRequest& request, DDF& out) const
-{
- // See if there's any response to send back.
- if (!out["redirect"].isnull() || !out["response"].isnull()) {
- // If so, we're responsible for handling the POST data, probably by dropping a cookie.
- preservePostData(request.getApplication(), request, request, out["RelayState"].string());
- }
- return RemotedHandler::unwrap(request, out);
-}
-
-void Shib1SessionInitiator::receive(DDF& in, ostream& out)
-{
- // Find application.
- const char* aid = in["application_id"].string();
- const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
- if (!app) {
- // Something's horribly wrong.
- m_log.error("couldn't find application (%s) to generate AuthnRequest", aid ? aid : "(missing)");
- throw ConfigurationException("Unable to locate application for new session, deleted?");
- }
-
- const char* entityID = in["entity_id"].string();
- const char* acsLocation = in["acsLocation"].string();
- if (!entityID || !acsLocation)
- throw ConfigurationException("No entityID or acsLocation parameter supplied to remoted SessionInitiator.");
-
- DDF ret(nullptr);
- DDFJanitor jout(ret);
-
- // Wrap the outgoing object with a Response facade.
- scoped_ptr<HTTPResponse> http(getResponse(*app, ret));
-
- string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
-
- // Since we're remoted, the result should either be a throw, which we pass on,
- // a false/0 return, which we just return as an empty structure, or a response/redirect,
- // which we capture in the facade and send back.
- doRequest(*app, nullptr, *http, entityID, acsLocation, (in["artifact"].integer() != 0), relayState);
- if (!ret.isstruct())
- ret.structure();
- ret.addmember("RelayState").unsafe_string(relayState.c_str());
- out << ret;
-}
-
-pair<bool,long> Shib1SessionInitiator::doRequest(
- const Application& app,
- const HTTPRequest* httpRequest,
- HTTPResponse& httpResponse,
- const char* entityID,
- const char* acsLocation,
- bool artifact,
- string& relayState
- ) const
-{
-#ifndef SHIBSP_LITE
- // Use metadata to invoke the SSO service directly.
- MetadataProvider* m = app.getMetadataProvider();
- Locker locker(m);
- MetadataProviderCriteria mc(app, entityID, &IDPSSODescriptor::ELEMENT_QNAME, shibspconstants::SHIB1_PROTOCOL_ENUM);
- pair<const EntityDescriptor*,const RoleDescriptor*> entity = m->getEntityDescriptor(mc);
- if (!entity.first) {
- m_log.warn("unable to locate metadata for provider (%s)", entityID);
- throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
- }
- else if (!entity.second) {
- m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate Shibboleth-aware identity provider role for provider (%s)", entityID);
- if (getParent())
- return make_pair(false, 0L);
- throw MetadataException("Unable to locate Shibboleth-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
- }
- else if (artifact && !SPConfig::getConfig().getArtifactResolver()->isSupported(dynamic_cast<const SSODescriptorType&>(*entity.second))) {
- m_log.warn("artifact profile selected for response, but identity provider lacks support");
- if (getParent())
- return make_pair(false, 0L);
- throw MetadataException("Identity provider ($entityID) lacks SAML artifact support.", namedparams(1, "entityID", entityID));
- }
-
- const EndpointType* ep = EndpointManager<SingleSignOnService>(
- dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleSignOnServices()
- ).getByBinding(shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI);
- if (!ep) {
- m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
- if (getParent())
- return make_pair(false, 0L);
- throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
- }
-
- preserveRelayState(app, httpResponse, relayState);
-
- scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
- if (ar_event) {
- auto_ptr_char prot(getProtocolFamily());
- ar_event->m_protocol = prot.get();
- auto_ptr_char b(shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI);
- ar_event->m_binding = b.get();
- ar_event->m_peer = entity.first;
- app.getServiceProvider().getTransactionLog()->write(*ar_event);
- }
-
- // Shib 1.x requires a target value.
- if (relayState.empty())
- relayState = "default";
-
- const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
- auto_ptr_char dest(ep->getLocation());
- string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "shire=" + urlenc->encode(acsLocation) +
- "&time=" + lexical_cast<string>(time(nullptr)) + "&target=" + urlenc->encode(relayState.c_str()) +
- "&providerId=" + urlenc->encode(app.getRelyingParty(entity.first)->getString("entityID").second);
-
- if (httpRequest) {
- // If the request object is available, we're responsible for the POST data.
- preservePostData(app, *httpRequest, httpResponse, relayState.c_str());
- }
-
- return make_pair(true, httpResponse.sendRedirect(req.c_str()));
-#else
- return make_pair(false, 0L);
-#endif
-}
diff --git a/shibsp/handler/impl/WAYFSessionInitiator.cpp b/shibsp/handler/impl/WAYFSessionInitiator.cpp
deleted file mode 100644
index 0247ee92..00000000
--- a/shibsp/handler/impl/WAYFSessionInitiator.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * 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
- *
- * 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.
- */
-
-/**
- * WAYFSessionInitiator.cpp
- *
- * Shibboleth WAYF support.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "exceptions.h"
-#include "SPRequest.h"
-#include "handler/AbstractHandler.h"
-#include "handler/SessionInitiator.h"
-
-#ifndef SHIBSP_LITE
-# include <saml/util/SAMLConstants.h>
-#else
-# include "lite/SAMLConstants.h"
-#endif
-
-#include <ctime>
-#include <boost/lexical_cast.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/URLEncoder.h>
-
-using namespace shibsp;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class SHIBSP_DLLLOCAL WAYFSessionInitiator : public SessionInitiator, public AbstractHandler
- {
- public:
- WAYFSessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.WAYF"), nullptr, this), m_url(nullptr) {
- pair<bool,const char*> url = getString("URL");
- if (!url.first)
- throw ConfigurationException("WAYF SessionInitiator requires a URL property.");
- m_url = url.second;
- }
- virtual ~WAYFSessionInitiator() {}
-
- pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
-
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML11_PROTOCOL_ENUM;
- }
-
- private:
- const char* m_url;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- SessionInitiator* SHIBSP_DLLLOCAL WAYFSessionInitiatorFactory(const pair<const DOMElement*,const char*>& p, bool)
- {
- return new WAYFSessionInitiator(p.first, p.second);
- }
-
-};
-
-pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID, bool isHandler) const
-{
- // The IdP CANNOT be specified for us to run. Otherwise, we'd be redirecting to a WAYF
- // anytime the IdP's metadata was wrong.
- if (!entityID.empty() || !checkCompatibility(request, isHandler))
- return make_pair(false, 0L);
-
- string target;
- pair<bool,const char*> prop;
- const Handler* ACS = nullptr;
- const Application& app = request.getApplication();
- pair<bool,const char*> discoveryURL = pair<bool,const char*>(false, nullptr);
-
- if (isHandler) {
- prop.second = request.getParameter("acsIndex");
- if (prop.second && *prop.second) {
- SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
- ACS = app.getAssertionConsumerServiceByIndex(atoi(prop.second));
- if (!ACS)
- request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
- }
-
- prop = getString("target", request);
- if (prop.first)
- target = prop.second;
-
- // Since we're passing the ACS by value, we need to compute the return URL,
- // so we'll need the target resource for real.
- recoverRelayState(request.getApplication(), request, request, target, false);
- request.getApplication().limitRedirect(request, target.c_str());
-
- discoveryURL = getString("discoveryURL", request, HANDLER_PROPERTY_MAP);
- }
- else {
- // Check for a hardwired target value in the map or handler.
- prop = getString("target", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- if (prop.first)
- target = prop.second;
- else
- target = request.getRequestURL();
-
- discoveryURL = request.getRequestSettings().first->getString("discoveryURL");
- }
-
- if (!discoveryURL.first)
- discoveryURL.second = m_url;
- m_log.debug("sending request to WAYF (%s)", discoveryURL.second);
-
- if (!ACS) {
- // Try fixed index property.
- pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
- if (index.first) {
- SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
- ACS = app.getAssertionConsumerServiceByIndex(index.second);
- }
- }
-
- // If we picked by index, validate the ACS for use with this protocol.
- if (!ACS || !XMLString::equals(samlconstants::SAML11_PROTOCOL_ENUM, ACS->getProtocolFamily())) {
- if (ACS)
- 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->getString("Location");
- if (prop.first)
- ACSloc += prop.second;
-
- if (isHandler) {
- // We may already have RelayState set if we looped back here,
- // but we've turned it back into a resource by this point, so if there's
- // a target on the URL, reset to that value.
- prop.second = request.getParameter("target");
- if (prop.second && *prop.second)
- target = prop.second;
- }
-
- preserveRelayState(app, request, target);
- if (!isHandler)
- preservePostData(app, request, request, target.c_str());
-
- // WAYF requires a target value.
- if (target.empty())
- target = "default";
-
- // Check for content-specific SP entityID before falling back to app default.
- string transformed;
- prop = getString("entityIDSelf", request, HANDLER_PROPERTY_MAP);
- if (prop.first) {
- transformed = prop.second;
- string::size_type pos = transformed.find("$hostname");
- if (pos != string::npos) {
- transformed.replace(pos, 9, request.getHostname());
- prop.second = transformed.c_str();
- }
- }
- else {
- prop = app.getString("entityID");
- }
-
- const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
- string req=string(discoveryURL.second) + (strchr(discoveryURL.second,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
- "&time=" + lexical_cast<string>(time(nullptr)) + "&target=" + urlenc->encode(target.c_str()) +
- "&providerId=" + urlenc->encode(prop.second);
-
- return make_pair(true, request.sendRedirect(req.c_str()));
-}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list