/*
- * Copyright 2001-2007 Internet2
- *
+ * Copyright 2001-2009 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
/**
* AssertionConsumerService.cpp
- *
- * Base class for handlers that create sessions by consuming SSO protocol responses.
+ *
+ * Base class for handlers that create sessions by consuming SSO protocol responses.
*/
#include "internal.h"
# include "attribute/resolver/AttributeExtractor.h"
# include "attribute/resolver/AttributeResolver.h"
# include "attribute/resolver/ResolutionContext.h"
+# include "metadata/MetadataProviderCriteria.h"
# include "security/SecurityPolicy.h"
# include <saml/SAMLConfig.h>
# include <saml/saml1/core/Assertions.h>
{
string relayState;
SPConfig& conf = SPConfig::getConfig();
-
+
if (conf.isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively and directly process the message.
return processMessage(request.getApplication(), request, request);
m_log.error("couldn't find application (%s) for new session", aid ? aid : "(missing)");
throw ConfigurationException("Unable to locate application for new session, deleted?");
}
-
+
// Unpack the request.
auto_ptr<HTTPRequest> req(getRequest(in));
pair<bool,const char*> policyId = getString("policyId", m_configNS.get()); // namespace-qualified if inside handler element
if (!policyId.first)
policyId = application.getString("policyId"); // unqualified in Application(s) element
-
+
// Access policy properties.
const PropertySet* settings = application.getServiceProvider().getPolicySettings(policyId.second);
pair<bool,bool> validate = settings->getBool("validate");
Locker metadataLocker(application.getMetadataProvider());
// Create the policy.
- shibsp::SecurityPolicy policy(application, &m_role, validate.first && validate.second);
-
- string relayState;
+ auto_ptr<opensaml::SecurityPolicy> policy(
+ createSecurityPolicy(application, &m_role, validate.first && validate.second, policyId.second)
+ );
+ string relayState;
try {
// Decode the message and process it in a protocol-specific way.
- auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, policy));
+ auto_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, *(policy.get())));
if (!msg.get())
throw BindingException("Failed to decode an SSO protocol response.");
+ DDF postData = recoverPostData(application, httpRequest, httpResponse, relayState.c_str());
+ DDFJanitor postjan(postData);
recoverRelayState(application, httpRequest, httpResponse, relayState);
- implementProtocol(application, httpRequest, httpResponse, policy, settings, *msg.get());
+ implementProtocol(application, httpRequest, httpResponse, *(policy.get()), settings, *msg.get());
+
+ auto_ptr_char issuer(policy->getIssuer() ? policy->getIssuer()->getName() : NULL);
- auto_ptr_char issuer(policy.getIssuer() ? policy.getIssuer()->getName() : NULL);
-
// History cookie.
if (issuer.get() && *issuer.get())
maintainHistory(application, httpRequest, httpResponse, issuer.get());
// Now redirect to the state value. By now, it should be set to *something* usable.
- return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+ // First check for POST data.
+ if (!postData.islist()) {
+ m_log.debug("ACS returning via redirect to: %s", relayState.c_str());
+ return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+ }
+ else {
+ m_log.debug("ACS returning via POST to: %s", relayState.c_str());
+ return make_pair(true, sendPostResponse(application, httpResponse, relayState.c_str(), postData));
+ }
}
catch (XMLToolingException& ex) {
+ // Check for isPassive error condition.
+ const char* sc2 = ex.getProperty("statusCode2");
+ if (sc2 && !strcmp(sc2, "urn:oasis:names:tc:SAML:2.0:status:NoPassive")) {
+ validate = getBool("ignoreNoPassive", m_configNS.get()); // namespace-qualified if inside handler element
+ if (validate.first && validate.second && !relayState.empty()) {
+ m_log.debug("ignoring SAML status of NoPassive and redirecting to resource...");
+ return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+ }
+ }
if (!relayState.empty())
ex.addProperty("RelayState", relayState.c_str());
throw;
{
if (!issuedTo || !*issuedTo)
return;
-
+
const PropertySet* props=application.getPropertySet("Sessions");
pair<bool,bool> checkAddress = props ? props->getBool("checkAddress") : make_pair(false,true);
if (!checkAddress.first)
#ifndef SHIBSP_LITE
-void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
+void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const char* handlerURL) const
+{
const char* loc = getString("Location").second;
string hurl(handlerURL);
if (*loc != '/')
saml2md::AssertionConsumerService* ep = saml2md::AssertionConsumerServiceBuilder::buildAssertionConsumerService();
ep->setLocation(widen.get());
ep->setBinding(getXMLString("Binding").second);
- ep->setIndex(getXMLString("index").second);
+ if (!strncmp(handlerURL, "https", 5)) {
+ pair<bool,const XMLCh*> index = getXMLString("sslIndex", shibspconstants::ASCII_SHIB2SPCONFIG_NS);
+ if (index.first)
+ ep->setIndex(index.second);
+ else
+ ep->setIndex(getXMLString("index").second);
+ }
+ else {
+ ep->setIndex(getXMLString("index").second);
+ }
role.getAssertionConsumerServices().push_back(ep);
}
+opensaml::SecurityPolicy* AssertionConsumerService::createSecurityPolicy(
+ const Application& application, const xmltooling::QName* role, bool validate, const char* policyId
+ ) const
+{
+ return new SecurityPolicy(application, role, validate, policyId);
+}
+
class SHIBSP_DLLLOCAL DummyContext : public ResolutionContext
{
public:
}
}
}
-
+
try {
AttributeResolver* resolver = application.getAttributeResolver();
if (resolver) {
// Copy over any pushed attributes.
if (!resolvedAttributes.empty())
ctx->getResolvedAttributes().insert(ctx->getResolvedAttributes().end(), resolvedAttributes.begin(), resolvedAttributes.end());
-
- // Attach global prefix if needed.
- pair<bool,const char*> prefix = application.getString("attributePrefix");
- if (prefix.first) {
- for (vector<Attribute*>::iterator a = ctx->getResolvedAttributes().begin(); a != ctx->getResolvedAttributes().end(); ++a) {
- vector<string>& ids = (*a)->getAliases();
- for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
- *id = prefix.second + *id;
- }
- }
-
return ctx.release();
}
}
catch (exception& ex) {
m_log.error("attribute resolution failed: %s", ex.what());
}
-
- if (!resolvedAttributes.empty()) {
- // Attach global prefix if needed.
- pair<bool,const char*> prefix = application.getString("attributePrefix");
- if (prefix.first) {
- for (vector<Attribute*>::iterator a = resolvedAttributes.begin(); a != resolvedAttributes.end(); ++a) {
- vector<string>& ids = (*a)->getAliases();
- for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
- *id = prefix.second + *id;
- }
- }
+ if (!resolvedAttributes.empty())
return new DummyContext(resolvedAttributes);
- }
return NULL;
}
return;
}
m_log.debug("searching metadata for assertion issuer...");
- MetadataProvider::Criteria mc(policy.getIssuer()->getName(), &IDPSSODescriptor::ELEMENT_QNAME, protocol);
- pair<const EntityDescriptor*,const RoleDescriptor*> entity = policy.getMetadataProvider()->getEntityDescriptor(mc);
+ pair<const EntityDescriptor*,const RoleDescriptor*> entity;
+ MetadataProvider::Criteria& mc = policy.getMetadataProviderCriteria();
+ mc.entityID_unicode = policy.getIssuer()->getName();
+ mc.role = &IDPSSODescriptor::ELEMENT_QNAME;
+ mc.protocol = protocol;
+ entity = policy.getMetadataProvider()->getEntityDescriptor(mc);
if (!entity.first) {
auto_ptr_char iname(policy.getIssuer()->getName());
m_log.warn("no metadata found, can't establish identity of issuer (%s)", iname.get());
const PropertySet* sessionProps=application.getPropertySet("Sessions");
pair<bool,bool> idpHistory=sessionProps->getBool("idpHistory");
- if (!idpHistory.first || idpHistory.second) {
+ if (idpHistory.first && idpHistory.second) {
pair<bool,const char*> cookieProps=sessionProps->getString("cookieProps");
if (!cookieProps.first)
cookieProps.second=defProps;