From b6df8f101cf7d287f1fb8813558372e808a45438 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Thu, 19 Apr 2007 17:22:58 +0000 Subject: [PATCH] Additional AuthnRequest creation options. --- configs/shibboleth.xml.in | 2 + schemas/shibboleth-spconfig-2.0.xsd | 4 +- shibsp/handler/impl/SAML2SessionInitiator.cpp | 84 ++++++++++++++++++++++----- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/configs/shibboleth.xml.in b/configs/shibboleth.xml.in index e269647..ffe9625 100644 --- a/configs/shibboleth.xml.in +++ b/configs/shibboleth.xml.in @@ -1,5 +1,7 @@ + @@ -268,7 +270,7 @@ - + diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp index 2fc3cd9..ae09b9b 100644 --- a/shibsp/handler/impl/SAML2SessionInitiator.cpp +++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp @@ -61,6 +61,7 @@ namespace shibsp { if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { XMLString::release(&m_outgoing); for_each(m_encoders.begin(), m_encoders.end(), cleanup_pair()); + delete m_requestTemplate; } } @@ -78,6 +79,8 @@ namespace shibsp { const XMLCh* acsBinding, bool isPassive, bool forceAuthn, + const char* authnContextClassRef, + const char* authnContextComparison, string& relayState ) const; @@ -85,6 +88,7 @@ namespace shibsp { XMLCh* m_outgoing; vector m_bindings; map m_encoders; + AuthnRequest* m_requestTemplate; }; #if defined (_MSC_VER) @@ -99,16 +103,15 @@ namespace shibsp { }; SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* appId) - : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator")), m_appId(appId), m_outgoing(NULL) + : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator")), m_appId(appId), m_outgoing(NULL), m_requestTemplate(NULL) { - // If Location isn't set, defer address registration until the setParent call. - pair loc = getString("Location"); - if (loc.first) { - string address = m_appId + loc.second + "::run::SAML2SI"; - setAddress(address.c_str()); - } - if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { + // Check for a template AuthnRequest to build from. + DOMElement* child = XMLHelper::getFirstChildElement(e, samlconstants::SAML20P_NS, AuthnRequest::LOCAL_NAME); + if (child) + m_requestTemplate = dynamic_cast(AuthnRequestBuilder::buildOneFromElement(child)); + + // Handle outgoing binding setup. pair outgoing = getXMLString("outgoingBindings"); if (outgoing.first) { m_outgoing = XMLString::replicate(outgoing.second); @@ -143,6 +146,13 @@ SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* ap break; } } + + // If Location isn't set, defer address registration until the setParent call. + pair loc = getString("Location"); + if (loc.first) { + string address = m_appId + loc.second + "::run::SAML2SI"; + setAddress(address.c_str()); + } } void SAML2SessionInitiator::setParent(const PropertySet* parent) @@ -234,7 +244,12 @@ pair SAML2SessionInitiator::run(SPRequest& request, const char* entit target = option; } return doRequest( - app, request, entityID, ACS ? ACS->getXMLString("index").second : NULL, NULL, NULL, isPassive, forceAuthn, target + app, request, entityID, + ACS ? ACS->getXMLString("index").second : NULL, NULL, NULL, + isPassive, forceAuthn, + acClass.first ? acClass.second : NULL, + acComp.first ? acComp.second : NULL, + target ); } @@ -257,7 +272,12 @@ pair SAML2SessionInitiator::run(SPRequest& request, const char* entit } return doRequest( - app, request, entityID, NULL, ACSloc.c_str(), ACS ? ACS->getXMLString("Binding").second : NULL, isPassive, forceAuthn, target + app, request, entityID, + NULL, ACSloc.c_str(), ACS ? ACS->getXMLString("Binding").second : NULL, + isPassive, forceAuthn, + acClass.first ? acClass.second : NULL, + acComp.first ? acComp.second : NULL, + target ); } @@ -341,6 +361,7 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out) *app, *http.get(), entityID, index.get(), in["acsLocation"].string(), bind.get(), in["isPassive"].integer()==1, in["forceAuthn"].integer()==1, + in["authnContextClassRef"].string(), in["authnContextComparison"].string(), relayState ); out << ret; @@ -355,6 +376,8 @@ pair SAML2SessionInitiator::doRequest( const XMLCh* acsBinding, bool isPassive, bool forceAuthn, + const char* authnContextClassRef, + const char* authnContextComparison, string& relayState ) const { @@ -391,8 +414,13 @@ pair SAML2SessionInitiator::doRequest( preserveRelayState(app, httpResponse, relayState); - // For now just build a dummy AuthnRequest. - auto_ptr req(AuthnRequestBuilder::buildAuthnRequest()); + auto_ptr req(m_requestTemplate ? m_requestTemplate->cloneAuthnRequest() : AuthnRequestBuilder::buildAuthnRequest()); + if (m_requestTemplate) { + // Freshen TS and ID. + req->setID(NULL); + req->setIssueInstant(time(NULL)); + } + req->setDestination(ep->getLocation()); if (acsIndex) req->setAssertionConsumerServiceIndex(acsIndex); @@ -406,9 +434,35 @@ pair SAML2SessionInitiator::doRequest( req->IsPassive(isPassive); else if (forceAuthn) req->ForceAuthn(forceAuthn); - Issuer* issuer = IssuerBuilder::buildIssuer(); - req->setIssuer(issuer); - issuer->setName(app.getXMLString("providerId").second); + if (!req->getIssuer()) { + Issuer* issuer = IssuerBuilder::buildIssuer(); + req->setIssuer(issuer); + issuer->setName(app.getXMLString("providerId").second); + } + if (!req->getNameIDPolicy()) { + NameIDPolicy* namepol = NameIDPolicyBuilder::buildNameIDPolicy(); + req->setNameIDPolicy(namepol); + namepol->AllowCreate(true); + } + if (authnContextClassRef || authnContextComparison) { + RequestedAuthnContext* reqContext = req->getRequestedAuthnContext(); + if (!reqContext) { + reqContext = RequestedAuthnContextBuilder::buildRequestedAuthnContext(); + req->setRequestedAuthnContext(reqContext); + } + if (authnContextClassRef) { + reqContext->getAuthnContextDeclRefs().clear(); + auto_ptr_XMLCh wideclass(authnContextClassRef); + AuthnContextClassRef* cref = AuthnContextClassRefBuilder::buildAuthnContextClassRef(); + cref->setReference(wideclass.get()); + reqContext->getAuthnContextClassRefs().push_back(cref); + } + if (authnContextComparison && + (!reqContext->getAuthnContextClassRefs().empty() || !reqContext->getAuthnContextDeclRefs().empty())) { + auto_ptr_XMLCh widecomp(authnContextComparison); + reqContext->setComparison(widecomp.get()); + } + } auto_ptr_char dest(ep->getLocation()); -- 2.1.4