elementFormDefault="qualified"
attributeFormDefault="unqualified"
blockDefault="substitution"
- version="2.5">
+ version="2.5.1">
<import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" />
<import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>
</annotation>
<simpleContent>
<extension base="conf:listOfStrings">
+ <attribute name="policyId" type="conf:string"/>
+ <attribute name="ignoreNoPassive" type="boolean"/>
<attribute name="discoveryProtocol" type="conf:string"/>
<attribute name="discoveryURL" type="anyURI"/>
<attributeGroup ref="conf:SessionInitiatorGroup"/>
</annotation>
<simpleContent>
<extension base="conf:listOfStrings">
+ <attribute name="policyId" type="conf:string"/>
<attributeGroup ref="conf:LogoutInitiatorGroup"/>
</extension>
</simpleContent>
</complexType>
</element>
- <element name="NameIDMgmt" type="conf:listOfStrings" minOccurs="0">
- <annotation>
- <documentation>Implicitly configures ManageNameIDService handlers</documentation>
- </annotation>
+ <element name="NameIDMgmt" minOccurs="0">
+ <complexType>
+ <annotation>
+ <documentation>Implicitly configures ManageNameIDService handlers</documentation>
+ </annotation>
+ <simpleContent>
+ <extension base="conf:listOfStrings">
+ <attribute name="policyId" type="conf:string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
</element>
<choice minOccurs="0" maxOccurs="unbounded">
<element ref="conf:SessionInitiator"/>
</annotation>
</attribute>
+ <attribute name="ignoreNoPassive" type="boolean">
+ <annotation>
+ <documentation>Used to ignore NoPassive errors in AssertionConsumerService endpoints</documentation>
+ </annotation>
+ </attribute>
+
<attributeGroup name="SessionInitiatorGroup">
<annotation>
<documentation>Options common to explicit and implicit SessionInitiators</documentation>
{
#ifndef SHIBSP_LITE
// Locate policy key.
- pair<bool,const char*> prop = getString("policyId", m_configNS.get()); // namespace-qualified if inside handler element
+ pair<bool,const char*> prop = getString("policyId", m_configNS.get()); // may be namespace-qualified if inside handler element
+ if (!prop.first)
+ prop = getString("policyId"); // try unqualified
if (!prop.first)
prop = application.getString("policyId"); // unqualified in Application(s) element
return finalizeResponse(application, httpRequest, httpResponse, relayState);
}
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")) {
- pair<bool,bool> ignore = getBool("ignoreNoPassive", m_configNS.get()); // namespace-qualified if inside handler element
- if (ignore.first && ignore.second && !relayState.empty()) {
- m_log.debug("ignoring SAML status of NoPassive and redirecting to resource...");
- return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
- }
- }
+ // Recover relay state.
if (!relayState.empty()) {
try {
recoverRelayState(application, httpRequest, httpResponse, relayState, false);
}
catch (std::exception& rsex) {
m_log.warn("error recovering relay state: %s", rsex.what());
+ relayState.erase();
+ recoverRelayState(application, httpRequest, httpResponse, relayState, false);
}
- ex.addProperty("RelayState", relayState.c_str());
}
+ // Check for isPassive error condition.
+ const char* sc2 = ex.getProperty("statusCode2");
+ if (sc2 && !strcmp(sc2, "urn:oasis:names:tc:SAML:2.0:status:NoPassive")) {
+ pair<bool,bool> ignore = getBool("ignoreNoPassive", m_configNS.get()); // may be namespace-qualified inside handler element
+ if (!ignore.first)
+ ignore = getBool("ignoreNoPassive"); // try unqualified
+ if (ignore.first && ignore.second && !relayState.empty()) {
+ m_log.debug("ignoring SAML status of NoPassive and redirecting to resource...");
+ return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
+ }
+ }
+
+ ex.addProperty("RelayState", relayState.c_str());
+
// Log the error.
try {
scoped_ptr<TransactionLog::Event> event(SPConfig::getConfig().EventManager.newPlugin(LOGIN_EVENT, nullptr));
// If we get here, it's an external protocol message to decode.
// Locate policy key.
- pair<bool,const char*> policyId = getString("policyId", m_configNS.get()); // namespace-qualified if inside handler element
+ pair<bool,const char*> policyId = getString("policyId", m_configNS.get()); // may be namespace-qualified inside handler element
+ if (!policyId.first)
+ policyId = getString("policyId"); // try unqualified
if (!policyId.first)
policyId = application.getString("policyId"); // unqualified in Application(s) element
SessionCache* cache = application.getServiceProvider().getSessionCache();
// Locate policy key.
- pair<bool,const char*> policyId = getString("policyId", m_configNS.get()); // namespace-qualified if inside handler element
+ pair<bool,const char*> policyId = getString("policyId", m_configNS.get()); // may be namespace-qualified inside handler element
+ if (!policyId.first)
+ policyId = getString("policyId"); // try unqualified
if (!policyId.first)
policyId = application.getString("policyId"); // unqualified in Application(s) element
{
if (!e->hasChildNodes())
return;
+ DOMNamedNodeMap* ssoprops = e->getAttributes();
+ XMLSize_t ssopropslen = ssoprops ? ssoprops->getLength() : 0;
SPConfig& conf = SPConfig::getConfig();
pathprop = (*b)->getXMLString("path");
if (idprop.first && pathprop.first) {
DOMElement* acsdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _AssertionConsumerService);
+
+ // Copy in any attributes from the <SSO> element so they can be accessed as properties in the ACS handler.
+ for (XMLSize_t p = 0; p < ssopropslen; ++p) {
+ DOMNode* ssoprop = ssoprops->item(p);
+ if (ssoprop->getNodeType() == DOMNode::ATTRIBUTE_NODE) {
+ acsdom->setAttributeNS(
+ ((DOMAttr*)ssoprop)->getNamespaceURI(),
+ ((DOMAttr*)ssoprop)->getLocalName(),
+ ((DOMAttr*)ssoprop)->getValue()
+ );
+ }
+ }
+
+ // Set necessary properties based on context.
acsdom->setAttributeNS(nullptr, Binding, idprop.second);
acsdom->setAttributeNS(nullptr, Location, pathprop.second);
xstring indexbuf(1, chDigit_1 + (index % 10));
if (index / 10)
indexbuf = (XMLCh)(chDigit_1 + (index / 10)) + indexbuf;
acsdom->setAttributeNS(nullptr, _index, indexbuf.c_str());
- if (e->hasAttributeNS(nullptr, _policyId))
- acsdom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId));
log.info("adding AssertionConsumerService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
boost::shared_ptr<Handler> handler(
{
if (!e->hasChildNodes())
return;
+ DOMNamedNodeMap* sloprops = e->getAttributes();
+ XMLSize_t slopropslen = sloprops ? sloprops->getLength() : 0;
SPConfig& conf = SPConfig::getConfig();
pathprop = (*b)->getXMLString("path");
if (idprop.first && pathprop.first) {
DOMElement* slodom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _SingleLogoutService);
+
+ // Copy in any attributes from the <Logout> element so they can be accessed as properties in the SLO handler.
+ for (XMLSize_t p = 0; p < slopropslen; ++p) {
+ DOMNode* sloprop = sloprops->item(p);
+ if (sloprop->getNodeType() == DOMNode::ATTRIBUTE_NODE) {
+ slodom->setAttributeNS(
+ ((DOMAttr*)sloprop)->getNamespaceURI(),
+ ((DOMAttr*)sloprop)->getLocalName(),
+ ((DOMAttr*)sloprop)->getValue()
+ );
+ }
+ }
+
+ // Set necessary properties based on context.
slodom->setAttributeNS(nullptr, Binding, idprop.second);
slodom->setAttributeNS(nullptr, Location, pathprop.second);
if (e->hasAttributeNS(nullptr, _policyId))
{
if (!e->hasChildNodes())
return;
+ DOMNamedNodeMap* nimprops = e->getAttributes();
+ XMLSize_t nimpropslen = nimprops ? nimprops->getLength() : 0;
SPConfig& conf = SPConfig::getConfig();
pathprop = (*b)->getXMLString("path");
if (idprop.first && pathprop.first) {
DOMElement* nimdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _ManageNameIDService);
+
+ // Copy in any attributes from the <NameIDMgmt> element so they can be accessed as properties in the NIM handler.
+ for (XMLSize_t p = 0; p < nimpropslen; ++p) {
+ DOMNode* nimprop = nimprops->item(p);
+ if (nimprop->getNodeType() == DOMNode::ATTRIBUTE_NODE) {
+ nimdom->setAttributeNS(
+ ((DOMAttr*)nimprop)->getNamespaceURI(),
+ ((DOMAttr*)nimprop)->getLocalName(),
+ ((DOMAttr*)nimprop)->getValue()
+ );
+ }
+ }
+
+ // Set necessary properties based on context.
nimdom->setAttributeNS(nullptr, Binding, idprop.second);
nimdom->setAttributeNS(nullptr, Location, pathprop.second);
if (e->hasAttributeNS(nullptr, _policyId))