https://issues.shibboleth.net/jira/browse/SSPCPP-255
[shibboleth/cpp-sp.git] / fastcgi / shibauthorizer.cpp
index db811b4..745855d 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- *  Copyright 2001-2007 Internet2\r
+ *  Copyright 2001-2009 Internet2\r
  * \r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
@@ -32,6 +32,7 @@
 #include <fcgio.h>\r
 \r
 using namespace shibtarget;\r
+using namespace saml;\r
 using namespace std;\r
 \r
 typedef enum {\r
@@ -40,10 +41,21 @@ typedef enum {
     SHIB_RETURN_DONE\r
 } shib_return_t;\r
 \r
+set<string> g_allowedSchemes;\r
+\r
 class ShibTargetFCGIAuth : public ShibTarget\r
 {\r
     FCGX_Request* m_req;\r
     string m_cookie;\r
+\r
+    void checkString(const string& s, const char* msg) {\r
+        string::const_iterator e = s.end();\r
+        for (string::const_iterator i=s.begin(); i!=e; ++i) {\r
+            if (iscntrl(*i))\r
+                throw runtime_error(msg);\r
+        }\r
+    }\r
+\r
 public:\r
     map<string,string> m_headers;\r
 \r
@@ -143,9 +155,12 @@ public:
         const string& content_type="text/html",\r
         const saml::Iterator<header_t>& headers=EMPTY(header_t)) {\r
 \r
+        checkString(content_type, "Detected control character in a response header.");\r
         string hdr = m_cookie + "Connection: close\r\nContent-type: " + content_type + "\r\n";\r
         while (headers.hasNext()) {\r
             const header_t& h=headers.next();\r
+            checkString(h.first, "Detected control character in a response header.");\r
+            checkString(h.second, "Detected control character in a response header.");\r
             hdr += h.first + ": " + h.second + "\r\n";\r
         }\r
 \r
@@ -162,6 +177,9 @@ public:
     }\r
 \r
     virtual void* sendRedirect(const string& url) {\r
+        checkString(url, "Detected control character in an attempted redirect.");\r
+        if (g_allowedSchemes.find(url.substr(0, url.find(':'))) == g_allowedSchemes.end())\r
+            throw runtime_error("Invalid scheme in attempted redirect.");\r
         cout << "Status: 302 Please Wait" << "\r\n"\r
              << "Location: " << url << "\r\n"\r
              <<  m_cookie << "\r\n"\r
@@ -227,12 +245,36 @@ int main(void)
             cerr << "failed to load Shibboleth configuration" << endl;\r
             exit(1);\r
         }\r
+\r
+        IConfig* conf=g_Config->getINI();\r
+        Locker locker(conf);\r
+        const IPropertySet* props=conf->getPropertySet("Local");\r
+        if (props) {\r
+            pair<bool,const char*> str=props->getString("allowedSchemes");\r
+            if (str.first) {\r
+                string schemes=str.second;\r
+                unsigned int j=0;\r
+                for (unsigned int i=0;  i < schemes.length();  i++) {\r
+                    if (schemes.at(i)==' ') {\r
+                        g_allowedSchemes.insert(schemes.substr(j, i-j));\r
+                        j = i+1;\r
+                    }\r
+                }\r
+                g_allowedSchemes.insert(schemes.substr(j, schemes.length()-j));\r
+            }\r
+        }\r
+        if (g_allowedSchemes.empty()) {\r
+            g_allowedSchemes.insert("https");\r
+            g_allowedSchemes.insert("http");\r
+        }\r
     }\r
     catch (exception& e) {\r
         cerr << "exception while initializing Shibboleth configuration: " << e.what() << endl;\r
         exit(1);\r
     }\r
 \r
+\r
+\r
     // Load "authoritative" URL fields.\r
     char* var = getenv("SHIBSP_SERVER_NAME");\r
     if (var)\r