https://issues.shibboleth.net/jira/browse/SSPCPP-519
[shibboleth/cpp-sp.git] / shibsp / impl / XMLServiceProvider.cpp
index 648dbd6..4ee2205 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);
@@ -555,26 +556,26 @@ XMLApplication::XMLApplication(
     // to ensure we get only our Sessions element.
     const PropertySet* sessionProps = getPropertySet("Sessions");
     if (sessionProps) {
-        pair<bool,const char*> redirectLimit = sessionProps->getString("redirectLimit");
-        if (redirectLimit.first) {
-            if (!strcmp(redirectLimit.second, "none"))
+        pair<bool,const char*> prop = sessionProps->getString("redirectLimit");
+        if (prop.first) {
+            if (!strcmp(prop.second, "none"))
                 m_redirectLimit = REDIRECT_LIMIT_NONE;
-            else if (!strcmp(redirectLimit.second, "exact"))
+            else if (!strcmp(prop.second, "exact"))
                 m_redirectLimit = REDIRECT_LIMIT_EXACT;
-            else if (!strcmp(redirectLimit.second, "host"))
+            else if (!strcmp(prop.second, "host"))
                 m_redirectLimit = REDIRECT_LIMIT_HOST;
             else {
-                if (!strcmp(redirectLimit.second, "exact+whitelist"))
+                if (!strcmp(prop.second, "exact+whitelist"))
                     m_redirectLimit = REDIRECT_LIMIT_EXACT_WHITELIST;
-                else if (!strcmp(redirectLimit.second, "exact+host"))
+                else if (!strcmp(prop.second, "host+whitelist"))
                     m_redirectLimit = REDIRECT_LIMIT_HOST_WHITELIST;
-                else if (!strcmp(redirectLimit.second, "exact+host"))
+                else if (!strcmp(prop.second, "whitelist"))
                     m_redirectLimit = REDIRECT_LIMIT_WHITELIST;
                 else
-                    throw ConfigurationException("Unrecognized redirectLimit setting ($1)", params(1, redirectLimit.second));
-                redirectLimit = sessionProps->getString("redirectWhitelist");
-                if (redirectLimit.first) {
-                    string dup(redirectLimit.second);
+                    throw ConfigurationException("Unrecognized redirectLimit setting ($1)", params(1, prop.second));
+                prop = sessionProps->getString("redirectWhitelist");
+                if (prop.first) {
+                    string dup(prop.second);
                     split(m_redirectWhitelist, dup, is_space(), algorithm::token_compress_on);
                 }
             }
@@ -582,6 +583,25 @@ XMLApplication::XMLApplication(
         else {
             m_redirectLimit = base ? REDIRECT_LIMIT_INHERIT : REDIRECT_LIMIT_NONE;
         }
+
+        // Audit some additional settings for logging purposes.
+        prop = sessionProps->getString("cookieProps");
+        if (!prop.first) {
+            log.warn("empty/missing cookieProps setting, set to \"https\" for SSL/TLS-only usage");
+        }
+        else if (!strcmp(prop.second, "http")) {
+            log.warn("insecure cookieProps setting, set to \"https\" for SSL/TLS-only usage");
+        }
+        else if (strcmp(prop.second, "https")) {
+            if (!strstr(prop.second, ";secure") && !strstr(prop.second, "; secure"))
+                log.warn("custom cookieProps setting should include \"; secure\" for SSL/TLS-only usage");
+            else if (!strstr(prop.second, ";HttpOnly") && !strstr(prop.second, "; HttpOnly"))
+                log.warn("custom cookieProps setting should include \"; HttpOnly\", site is vulnerable to client-side cookie theft");
+        }
+
+        pair<bool,bool> handlerSSL = sessionProps->getBool("handlerSSL");
+        if (handlerSSL.first && !handlerSSL.second)
+            log.warn("handlerSSL should be enabled for SSL/TLS-enabled web sites");
     }
     else {
         m_redirectLimit = base ? REDIRECT_LIMIT_INHERIT : REDIRECT_LIMIT_NONE;
@@ -644,7 +664,7 @@ XMLApplication::XMLApplication(
             if (m_metadata)
                 m_metadata->init();
             else if (!m_base)
-                log.crit("no MetadataProvider available, configuration is probably unusable");
+                log.warn("no MetadataProvider available, configure at least one for standard SSO usage");
         }
         catch (std::exception& ex) {
             log.crit("error initializing MetadataProvider: %s", ex.what());
@@ -1106,6 +1126,8 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
                     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(
@@ -1224,6 +1246,8 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
                     DOMElement* slodom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _SingleLogoutService);
                     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(
@@ -1290,6 +1314,8 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& proto
                     DOMElement* nimdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _ManageNameIDService);
                     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(
@@ -2069,7 +2095,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
         // For backward compatibility, wrap in a plugin element.
         DOMElement* polwrapper = e->getOwnerDocument()->createElementNS(nullptr, _SecurityPolicyProvider);
         polwrapper->appendChild(child);
-        log.info("building SecurityPolicyProvider of type %s...", XML_SECURITYPOLICY_PROVIDER);
+        log.warn("deprecated/legacy SecurityPolicy configuration, consider externalizing with <SecurityPolicyProvider>");
         m_policy.reset(conf.SecurityPolicyProviderManager.newPlugin(XML_SECURITYPOLICY_PROVIDER, polwrapper));
     }
     else {
@@ -2078,22 +2104,32 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
     }
 
     if (first) {
-        if (!m_policy->getAlgorithmBlacklist().empty()) {
+        if (!m_policy->getAlgorithmWhitelist().empty()) {
 #ifdef SHIBSP_XMLSEC_WHITELISTING
-            for_each(
-                m_policy->getAlgorithmBlacklist().begin(), m_policy->getAlgorithmBlacklist().end(),
-                boost::bind(&XSECPlatformUtils::blacklistAlgorithm, boost::bind(&xstring::c_str, _1))
-                );
+            for (vector<xstring>::const_iterator white = m_policy->getAlgorithmWhitelist().begin();
+                    white != m_policy->getAlgorithmWhitelist().end(); ++white) {
+                XSECPlatformUtils::whitelistAlgorithm(white->c_str());
+                auto_ptr_char whitelog(white->c_str());
+                log.info("explicitly whitelisting security algorithm (%s)", whitelog.get());
+            }
 #else
             log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
 #endif
         }
-        else if (!m_policy->getAlgorithmWhitelist().empty()) {
+        else if (!m_policy->getDefaultAlgorithmBlacklist().empty() || !m_policy->getAlgorithmBlacklist().empty()) {
 #ifdef SHIBSP_XMLSEC_WHITELISTING
-            for_each(
-                m_policy->getAlgorithmWhitelist().begin(), m_policy->getAlgorithmWhitelist().end(),
-                boost::bind(&XSECPlatformUtils::whitelistAlgorithm, boost::bind(&xstring::c_str, _1))
-                );
+            for (vector<xstring>::const_iterator black = m_policy->getDefaultAlgorithmBlacklist().begin();
+                    black != m_policy->getDefaultAlgorithmBlacklist().end(); ++black) {
+                XSECPlatformUtils::blacklistAlgorithm(black->c_str());
+                auto_ptr_char blacklog(black->c_str());
+                log.info("automatically blacklisting security algorithm (%s)", blacklog.get());
+            }
+            for (vector<xstring>::const_iterator black = m_policy->getAlgorithmBlacklist().begin();
+                    black != m_policy->getAlgorithmBlacklist().end(); ++black) {
+                XSECPlatformUtils::blacklistAlgorithm(black->c_str());
+                auto_ptr_char blacklog(black->c_str());
+                log.info("explicitly blacklisting security algorithm (%s)", blacklog.get());
+            }
 #else
             log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
 #endif