https://issues.shibboleth.net/jira/browse/SSPCPP-326
[shibboleth/cpp-sp.git] / shibsp / handler / impl / AssertionLookup.cpp
index 94b491f..65312e8 100644 (file)
@@ -32,6 +32,7 @@
 #include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/RemotedHandler.h"
+#include "util/IPRange.h"
 #include "util/SPConstants.h"
 
 #ifndef SHIBSP_LITE
@@ -84,7 +85,7 @@ namespace shibsp {
     private:
         pair<bool,long> processMessage(const Application& application, HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
 
-        set<string> m_acl;
+        vector<IPRange> m_acl;
     };
 
 #if defined (_MSC_VER)
@@ -101,31 +102,51 @@ namespace shibsp {
 AssertionLookup::AssertionLookup(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".AssertionLookup"), &g_Blocker)
 {
-    setAddress("run::AssertionLookup");
     if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
         pair<bool,const char*> acl = getString("exportACL");
-        if (!acl.first) {
-            m_acl.insert("127.0.0.1");
-            return;
-        }
-        string aclbuf=acl.second;
-        int j = 0;
-        for (unsigned int i=0;  i < aclbuf.length();  i++) {
-            if (aclbuf.at(i)==' ') {
-                m_acl.insert(aclbuf.substr(j, i-j));
-                j = i+1;
+        if (acl.first) {
+            string aclbuf=acl.second;
+            int j = 0;
+            for (unsigned int i=0;  i < aclbuf.length();  i++) {
+                if (aclbuf.at(i)==' ') {
+                    try {
+                        m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
+                    }
+                    catch (exception& ex) {
+                        m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
+                    }
+                    j = i+1;
+                }
+            }
+            try {
+                m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
+            }
+            catch (exception& ex) {
+                m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
+            }
+
+            if (m_acl.empty()) {
+                m_log.warn("invalid CIDR range(s) in acl property, allowing 127.0.0.1 as a fall back");
+                m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
             }
         }
-        m_acl.insert(aclbuf.substr(j, aclbuf.length()-j));
+        else {
+            m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
+        }
     }
+
+    setAddress("run::AssertionLookup");
 }
 
 pair<bool,long> AssertionLookup::run(SPRequest& request, bool isHandler) const
 {
-    string relayState;
     SPConfig& conf = SPConfig::getConfig();
-    if (conf.isEnabled(SPConfig::InProcess)) {
-        if (m_acl.count(request.getRemoteAddr()) == 0) {
+    if (conf.isEnabled(SPConfig::InProcess) && !m_acl.empty()) {
+        bool found = false;
+        for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
+            found = acl->contains(request.getRemoteAddr().c_str());
+        }
+        if (!found) {
             m_log.error("request for assertion lookup blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Assertion Lookup Blocked");
             return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));