https://issues.shibboleth.net/jira/browse/SSPCPP-624
[shibboleth/cpp-sp.git] / shibsp / impl / XMLServiceProvider.cpp
index a3efbcc..73ef00a 100644 (file)
@@ -503,6 +503,7 @@ namespace {
     static const XMLCh _option[] =              UNICODE_LITERAL_6(o,p,t,i,o,n);
     static const XMLCh OutOfProcess[] =         UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);
     static const XMLCh _path[] =                UNICODE_LITERAL_4(p,a,t,h);
+    static const XMLCh _policyId[] =            UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
     static const XMLCh _ProtocolProvider[] =    UNICODE_LITERAL_16(P,r,o,t,o,c,o,l,P,r,o,v,i,d,e,r);
     static const XMLCh _provider[] =            UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);
     static const XMLCh RelyingParty[] =         UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);
@@ -575,6 +576,7 @@ XMLApplication::XMLApplication(
                 prop = sessionProps->getString("redirectWhitelist");
                 if (prop.first) {
                     string dup(prop.second);
+                    trim(dup);
                     split(m_redirectWhitelist, dup, is_space(), algorithm::token_compress_on);
                 }
             }
@@ -831,6 +833,7 @@ void XMLApplication::doAttributeInfo()
     pair<bool,const char*> attributes = getString("REMOTE_USER");
     if (attributes.first) {
         string dup(attributes.second);
+        trim(dup);
         split(m_remoteUsers, dup, is_space(), algorithm::token_compress_on);
     }
 
@@ -850,6 +853,7 @@ void XMLApplication::doAttributeInfo()
             }
 
             string dup(attributes.second);
+            trim(dup);
             vector<string> headerNames;
             split(headerNames, dup, is_space(), algorithm::token_compress_on);
             for (vector<string>::const_iterator h = headerNames.begin(); h != headerNames.end(); ++h) {
@@ -1079,6 +1083,8 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
 {
     if (!e->hasChildNodes())
         return;
+    DOMNamedNodeMap* ssoprops = e->getAttributes();
+    XMLSize_t ssopropslen = ssoprops ? ssoprops->getLength() : 0;
 
     SPConfig& conf = SPConfig::getConfig();
 
@@ -1119,6 +1125,20 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
                 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));
@@ -1201,6 +1221,8 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
 {
     if (!e->hasChildNodes())
         return;
+    DOMNamedNodeMap* sloprops = e->getAttributes();
+    XMLSize_t slopropslen = sloprops ? sloprops->getLength() : 0;
 
     SPConfig& conf = SPConfig::getConfig();
 
@@ -1241,8 +1263,24 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
                 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))
+                        slodom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId));
 
                     log.info("adding SingleLogoutService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
                     boost::shared_ptr<Handler> handler(
@@ -1289,6 +1327,8 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& proto
 {
     if (!e->hasChildNodes())
         return;
+    DOMNamedNodeMap* nimprops = e->getAttributes();
+    XMLSize_t nimpropslen = nimprops ? nimprops->getLength() : 0;
 
     SPConfig& conf = SPConfig::getConfig();
 
@@ -1307,8 +1347,24 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& proto
                 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))
+                        nimdom->setAttributeNS(shibspconstants::SHIB2SPCONFIG_NS, _policyId, e->getAttributeNS(nullptr, _policyId));
 
                     log.info("adding ManageNameIDService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
                     boost::shared_ptr<Handler> handler(
@@ -2015,6 +2071,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
         if (unsafe.first) {
             HTTPResponse::getAllowedSchemes().clear();
             string schemes(unsafe.second);
+            trim(schemes);
             split(HTTPResponse::getAllowedSchemes(), schemes, is_space(), algorithm::token_compress_on);
         }
 
@@ -2184,6 +2241,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
             pair<bool,const char*> extraAuthTypes = inprocs->getString("extraAuthTypes");
             if (extraAuthTypes.first) {
                 string types(extraAuthTypes.second);
+                trim(types);
                 split(outer->m_authTypes, types, is_space(), algorithm::token_compress_on);
                 outer->m_authTypes.insert("shibboleth");
             }