#ifndef SHIBSP_LITE
# include <saml/SAMLConfig.h>
-# include <saml/binding/MessageEncoder.h>
# include <saml/saml2/core/Protocols.h>
# include <saml/saml2/metadata/EndpointManager.h>
# include <saml/saml2/metadata/Metadata.h>
using namespace shibsp;
using namespace opensaml;
using namespace xmltooling;
-using namespace log4cpp;
using namespace std;
namespace shibsp {
};
SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* appId)
- : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator")), m_appId(appId)
+ : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.SAML2")), m_appId(appId)
{
#ifndef SHIBSP_LITE
m_outgoing=NULL;
pair<bool,const XMLCh*> outgoing = getXMLString("outgoingBindings");
if (outgoing.first) {
m_outgoing = XMLString::replicate(outgoing.second);
+ XMLString::trim(m_outgoing);
}
else {
// No override, so we'll install a default binding precedence.
string prec = string(samlconstants::SAML20_BINDING_HTTP_REDIRECT) + ' ' + samlconstants::SAML20_BINDING_HTTP_POST + ' ' +
samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN + ' ' + samlconstants::SAML20_BINDING_HTTP_ARTIFACT;
m_outgoing = XMLString::transcode(prec.c_str());
- XMLString::trim(m_outgoing);
}
int pos;
m_bindings.push_back(start);
try {
auto_ptr_char b(start);
- MessageEncoder * encoder = SAMLConfig::getConfig().MessageEncoderManager.newPlugin(b.get(),e);
+ MessageEncoder * encoder = SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
+ b.get(),pair<const DOMElement*,const XMLCh*>(e,NULL)
+ );
m_encoders[start] = encoder;
- m_log.info("supporting outgoing binding (%s)", b.get());
+ m_log.debug("supporting outgoing binding (%s)", b.get());
}
catch (exception& ex) {
m_log.error("error building MessageEncoder: %s", ex.what());
if (option) {
ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
if (!ACS)
- throw ConfigurationException("AssertionConsumerService with index ($1) not found, check configuration.", params(1,option));
+ request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
}
option = request.getParameter("target");
m_log.debug("attempting to initiate session using SAML 2.0 with provider (%s)", entityID);
- // To invoke the request builder, the key requirement is to figure out how and whether
+ if (!ACS) {
+ pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+ if (index.first) {
+ ACS = app.getAssertionConsumerServiceByIndex(index.second);
+ if (!ACS)
+ request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+ }
+ if (!ACS)
+ ACS = app.getDefaultAssertionConsumerService();
+ }
+
+ // To invoke the request builder, the key requirement is to figure out how
// to express the ACS, by index or value, and if by value, where.
SPConfig& conf = SPConfig::getConfig();
if (conf.isEnabled(SPConfig::OutOfProcess)) {
if (!acsByIndex.first || acsByIndex.second) {
- // Pass by Index. This also allows for defaulting it entirely and sending nothing.
+ // Pass by Index.
if (isHandler) {
// We may already have RelayState set if we looped back here,
// but just in case target is a resource, we reset it back.
}
// Since we're not passing by index, we need to fully compute the return URL and binding.
- if (!ACS)
- ACS = app.getDefaultAssertionConsumerService();
-
// Compute the ACS URL. We add the ACS location to the base handlerURL.
string ACSloc=request.getHandlerURL(target.c_str());
pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
}
else {
// Since we're not passing by index, we need to fully compute the return URL and binding.
- if (!ACS)
- ACS = app.getDefaultAssertionConsumerService();
-
// Compute the ACS URL. We add the ACS location to the base handlerURL.
string ACSloc=request.getHandlerURL(target.c_str());
pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
throw MetadataException("Unable to locate metadata for identity provider ($entityID)",
namedparams(1, "entityID", entityID));
}
- const IDPSSODescriptor* role=entity->getIDPSSODescriptor(samlconstants::SAML20P_NS);
+ const IDPSSODescriptor* role=find_if(entity->getIDPSSODescriptors(), isValidForProtocol(samlconstants::SAML20P_NS));
if (!role) {
m_log.error("unable to locate SAML 2.0 identity provider role for provider (%s)", entityID);
return make_pair(false,0);
auto_ptr_char dest(ep->getLocation());
- // Check for signing.
- const PropertySet* relyingParty = app.getRelyingParty(entity);
- pair<bool,bool> flag = relyingParty->getBool("signRequests");
- if ((flag.first && flag.second) || role->WantAuthnRequestsSigned()) {
- CredentialResolver* credResolver=app.getCredentialResolver();
- if (credResolver) {
- Locker credLocker(credResolver);
- // Fill in criteria to use.
- MetadataCredentialCriteria mcc(*role);
- mcc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
- pair<bool,const XMLCh*> sigalg = relyingParty->getXMLString("signatureAlg");
- if (sigalg.first)
- mcc.setXMLAlgorithm(sigalg.second);
- const Credential* cred = credResolver->resolve(&mcc);
- if (cred) {
- // Signed request.
- long ret = encoder->encode(
- httpResponse,
- req.get(),
- dest.get(),
- entityID,
- relayState.c_str(),
- cred,
- sigalg.second,
- relyingParty->getXMLString("digestAlg").second
- );
- req.release(); // freed by encoder
- return make_pair(true,ret);
- }
- else {
- m_log.warn("no signing credential resolved, leaving AuthnRequest unsigned");
- }
- }
- }
-
- // Unsigned request.
- long ret = encoder->encode(httpResponse, req.get(), dest.get(), entityID, relayState.c_str());
+ long ret = sendMessage(
+ *encoder, req.get(), relayState.c_str(), dest.get(), role, app, httpResponse, role->WantAuthnRequestsSigned()
+ );
req.release(); // freed by encoder
return make_pair(true,ret);
#else