Add hooks for protecting headers and redirects.
[shibboleth/cpp-sp.git] / fastcgi / shibauthorizer.cpp
index f0fd99e..4d9a4e5 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
- *  Copyright 2001-2007 Internet2\r
- * \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
  * You may obtain a copy of the License at\r
@@ -115,6 +115,9 @@ public:
         return s ? atol(s) : 0;\r
     }\r
     string getRemoteAddr() const {\r
+        string ret = AbstractSPRequest::getRemoteAddr();\r
+        if (!ret.empty())\r
+            return ret;\r
         const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
         return s ? s : "";\r
     }\r
@@ -124,7 +127,7 @@ public:
             cerr << "shib: " << msg;\r
     }\r
     void clearHeader(const char* rawname, const char* cginame) {\r
-        // no need, since request headers turn into actual environment variables\r
+        // No need, since we use environment variables.\r
     }\r
     void setHeader(const char* name, const char* value) {\r
         if (value)\r
@@ -132,12 +135,28 @@ public:
         else\r
             m_request_headers.erase(name);\r
     }\r
-    virtual string getHeader(const char* name) const {\r
+    string getHeader(const char* name) const {\r
+        // Look in the local map first.\r
         map<string,string>::const_iterator i = m_request_headers.find(name);\r
         if (i != m_request_headers.end())\r
             return i->second;\r
-        else\r
-            return "";\r
+        // Nothing set locally and this isn't a "secure" call, so check the request.\r
+        string hdr("HTTP_");\r
+        for (; *name; ++name) {\r
+            if (*name=='-')\r
+                hdr += '_';\r
+            else\r
+                hdr += toupper(*name);\r
+        }\r
+        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
+        return s ? s : "";\r
+    }\r
+    string getSecureHeader(const char* name) const {\r
+        // Look in the local map only.\r
+        map<string,string>::const_iterator i = m_request_headers.find(name);\r
+        if (i != m_request_headers.end())\r
+            return i->second;\r
+        return "";\r
     }\r
     void setRemoteUser(const char* user) {\r
         if (user)\r
@@ -156,7 +175,25 @@ public:
         }\r
         return "";\r
     }\r
+    void setAuthType(const char* authtype) {\r
+        if (authtype)\r
+            m_request_headers["AUTH_TYPE"] = authtype;\r
+        else\r
+            m_request_headers.erase("AUTH_TYPE");\r
+    }\r
+    string getAuthType() const {\r
+        map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");\r
+        if (i != m_request_headers.end())\r
+            return i->second;\r
+        else {\r
+            char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);\r
+            if (auth_type)\r
+                return auth_type;\r
+        }\r
+        return "";\r
+    }\r
     void setResponseHeader(const char* name, const char* value) {\r
+        AbstractSPRequest::setResponseHeader(name, value);\r
         // Set for later.\r
         if (value)\r
             m_response_headers.insert(make_pair(name,value));\r
@@ -169,7 +206,7 @@ public:
     const char* getRequestBody() const {\r
         throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");\r
     }\r
\r
+\r
     long sendResponse(istream& in, long status) {\r
         string hdr = string("Connection: close\r\n");\r
         for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
@@ -193,6 +230,7 @@ public:
     }\r
 \r
     long sendRedirect(const char* url) {\r
+        AbstractSPRequest::sendRedirect(url);\r
         string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
           "Content-Type: text/html\r\n"\r
           "Content-Length: 40\r\n"\r
@@ -206,7 +244,7 @@ public:
         return SHIB_RETURN_DONE;\r
     }\r
 \r
-    long returnDecline() { \r
+    long returnDecline() {\r
         return SHIB_RETURN_KO;\r
     }\r
 \r
@@ -236,16 +274,6 @@ static void print_error(const char* msg)
 \r
 int main(void)\r
 {\r
-    const char* schemadir=getenv("SHIBSP_SCHEMAS");\r
-    if (!schemadir)\r
-        schemadir=SHIBSP_SCHEMAS;\r
-    const char* config=getenv("SHIBSP_CONFIG");\r
-    if (!config)\r
-        config=SHIBSP_CONFIG;\r
-\r
-    cerr << "SHIBSP_CONFIG = " << config << endl\r
-         << "SHIBSP_SCHEMAS = " << schemadir << endl;\r
-\r
     SPConfig* g_Config=&SPConfig::getConfig();\r
     g_Config->setFeatures(\r
         SPConfig::Listener |\r
@@ -255,21 +283,14 @@ int main(void)
         SPConfig::Logging |\r
         SPConfig::Handlers\r
         );\r
-    if (!g_Config->init(schemadir)) {\r
+    if (!g_Config->init()) {\r
         cerr << "failed to initialize Shibboleth libraries" << endl;\r
         exit(1);\r
     }\r
 \r
     try {\r
-        DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();\r
-        XercesJanitor<DOMDocument> docjanitor(dummydoc);\r
-        DOMElement* dummy = dummydoc->createElementNS(NULL,path);\r
-        auto_ptr_XMLCh src(config);\r
-        dummy->setAttributeNS(NULL,path,src.get());\r
-        dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);\r
-\r
-        g_Config->setServiceProvider(g_Config->ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));\r
-        g_Config->getServiceProvider()->init();\r
+        if (!g_Config->instantiate(NULL, true))\r
+            throw runtime_error("unknown error");\r
     }\r
     catch (exception& ex) {\r
         g_Config->term();\r
@@ -299,7 +320,7 @@ int main(void)
 \r
     FCGX_Init();\r
     FCGX_InitRequest(&request, 0, 0);\r
-    \r
+\r
     cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
     while (FCGX_Accept_r(&request) == 0)\r
     {\r
@@ -315,48 +336,44 @@ int main(void)
         try {\r
             xmltooling::NDC ndc("FastCGI shibauthorizer");\r
             ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-          \r
+\r
             pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);\r
             if (res.first) {\r
-#ifdef _DEBUG\r
-                cerr << "shib: doAuthentication handled the request" << endl;\r
-#endif\r
+                sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");\r
                 switch(res.second) {\r
                     case SHIB_RETURN_OK:\r
                         print_ok(sta.m_request_headers);\r
                         continue;\r
-              \r
+\r
                     case SHIB_RETURN_KO:\r
                         print_ok(sta.m_request_headers);\r
                         continue;\r
 \r
                     case SHIB_RETURN_DONE:\r
                         continue;\r
-              \r
+\r
                     default:\r
                         cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;\r
                         print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
                         continue;\r
                 }\r
             }\r
-          \r
+\r
             res = sta.getServiceProvider().doExport(sta);\r
             if (res.first) {\r
-#ifdef _DEBUG\r
-                cerr << "shib: doExport handled request" << endl;\r
-#endif\r
+                sta.log(SPRequest::SPDebug, "shib: doExport handled request");\r
                 switch(res.second) {\r
                     case SHIB_RETURN_OK:\r
                         print_ok(sta.m_request_headers);\r
                         continue;\r
-              \r
+\r
                     case SHIB_RETURN_KO:\r
                         print_ok(sta.m_request_headers);\r
                         continue;\r
 \r
                     case SHIB_RETURN_DONE:\r
                         continue;\r
-              \r
+\r
                     default:\r
                         cerr << "shib: doExport returned an unexpected result: " << res.second << endl;\r
                         print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
@@ -366,21 +383,19 @@ int main(void)
 \r
             res = sta.getServiceProvider().doAuthorization(sta);\r
             if (res.first) {\r
-#ifdef _DEBUG\r
-                cerr << "shib: doAuthorization handled request" << endl;\r
-#endif\r
+                sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");\r
                 switch(res.second) {\r
                     case SHIB_RETURN_OK:\r
                         print_ok(sta.m_request_headers);\r
                         continue;\r
-              \r
+\r
                     case SHIB_RETURN_KO:\r
                         print_ok(sta.m_request_headers);\r
                         continue;\r
 \r
                     case SHIB_RETURN_DONE:\r
                         continue;\r
-              \r
+\r
                     default:\r
                         cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;\r
                         print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
@@ -389,7 +404,7 @@ int main(void)
             }\r
 \r
             print_ok(sta.m_request_headers);\r
-          \r
+\r
         }\r
         catch (exception& e) {\r
             cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;\r
@@ -408,6 +423,6 @@ int main(void)
 \r
     if (g_Config)\r
         g_Config->term();\r
\r
+\r
     return 0;\r
 }\r