Start to clean up Unix build.
[shibboleth/cpp-sp.git] / isapi_shib / isapi_shib.cpp
index b1c1fad..9bc2e45 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2005 Internet2
+ *  Copyright 2001-2007 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
  * Shibboleth ISAPI filter
  */
 
+#define SHIBSP_LITE
 #include "config_win32.h"
 
 #define _CRT_NONSTDC_NO_DEPRECATE 1
 
 #include <shibsp/AbstractSPRequest.h>
 #include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
 
-// SAML Runtime
-#include <saml/saml.h>
-#include <shib/shib.h>
-#include <shib-target/shib-target.h>
-
+#include <set>
 #include <sstream>
 #include <fstream>
 #include <process.h>
 
+#include <windows.h>
 #include <httpfilt.h>
 #include <httpext.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace xercesc;
 using namespace std;
 
 // globals
 namespace {
+    static const XMLCh path[] =             UNICODE_LITERAL_4(p,a,t,h);
+    static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
     static const XMLCh name[] =             UNICODE_LITERAL_4(n,a,m,e);
     static const XMLCh port[] =             UNICODE_LITERAL_4(p,o,r,t);
     static const XMLCh sslport[] =          UNICODE_LITERAL_7(s,s,l,p,o,r,t);
@@ -83,7 +90,7 @@ namespace {
     };
     
     HINSTANCE g_hinstDLL;
-    shibtarget::ShibTargetConfig* g_Config = NULL;
+    SPConfig* g_Config = NULL;
     map<string,site_t> g_Sites;
     bool g_bNormalizeRequest = true;
 }
@@ -140,65 +147,65 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
         return TRUE;
     }
 
-#ifndef _DEBUG
-    try
-    {
-#endif
-        LPCSTR schemadir=getenv("SHIBSCHEMAS");
-        if (!schemadir)
-            schemadir=SHIB_SCHEMAS;
-        LPCSTR config=getenv("SHIBCONFIG");
-        if (!config)
-            config=SHIB_CONFIG;
-        g_Config=&shibtarget::ShibTargetConfig::getConfig();
-        SPConfig::getConfig().setFeatures(
-            SPConfig::Listener |
-            SPConfig::Caching |
-            SPConfig::Metadata |
-            SPConfig::AAP |
-            SPConfig::RequestMapping |
-            SPConfig::InProcess |
-            SPConfig::Logging
-            );
-        if (!g_Config->init(schemadir)) {
-            g_Config=NULL;
-            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                    "Filter startup failed during library initialization, check native log for help.");
-            return FALSE;
-        }
-        else if (!g_Config->load(config)) {
-            g_Config=NULL;
-            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                    "Filter startup failed to load configuration, check native log for help.");
-            return FALSE;
-        }
-        
-        // Access the implementation-specifics for site mappings.
-        ServiceProvider* conf=SPConfig::getConfig().getServiceProvider();
-        xmltooling::Locker locker(conf);
-        const PropertySet* props=conf->getPropertySet("Local");
-        if (props) {
-            const DOMElement* impl=XMLHelper::getFirstChildElement(props->getElement(),Implementation);
-            if (impl && (impl=XMLHelper::getFirstChildElement(impl,ISAPI))) {
-                const XMLCh* flag=impl->getAttributeNS(NULL,normalizeRequest);
-                g_bNormalizeRequest=(!flag || !*flag || *flag==chDigit_1 || *flag==chLatin_t);
-                impl=XMLHelper::getFirstChildElement(impl,Site);
-                while (impl) {
-                    auto_ptr_char id(impl->getAttributeNS(NULL,id));
-                    if (id.get())
-                        g_Sites.insert(pair<string,site_t>(id.get(),site_t(impl)));
-                    impl=XMLHelper::getNextSiblingElement(impl,Site);
-                }
-            }
-        }
-#ifndef _DEBUG
+    LPCSTR schemadir=getenv("SHIBSP_SCHEMAS");
+    if (!schemadir)
+        schemadir=SHIBSP_SCHEMAS;
+    LPCSTR config=getenv("SHIBSP_CONFIG");
+    if (!config)
+        config=SHIBSP_CONFIG;
+    g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging
+        );
+    if (!g_Config->init(schemadir)) {
+        g_Config=NULL;
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Filter startup failed during library initialization, check native log for help.");
+        return FALSE;
     }
-    catch (...)
-    {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Filter startup failed with an exception.");
+
+    try {
+        DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();
+        XercesJanitor<DOMDocument> docjanitor(dummydoc);
+        DOMElement* dummy = dummydoc->createElementNS(NULL,path);
+        auto_ptr_XMLCh src(config);
+        dummy->setAttributeNS(NULL,path,src.get());
+        dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);
+
+        g_Config->setServiceProvider(g_Config->ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));
+        g_Config->getServiceProvider()->init();
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        g_Config=NULL;
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+                "Filter startup failed to load configuration, check native log for details.");
         return FALSE;
     }
-#endif
+    
+    // Access the implementation-specifics for site mappings.
+    ServiceProvider* sp=g_Config->getServiceProvider();
+    xmltooling::Locker locker(sp);
+    const PropertySet* props=sp->getPropertySet("Local");
+    if (props) {
+        const DOMElement* impl=XMLHelper::getFirstChildElement(props->getElement(),Implementation);
+        if (impl && (impl=XMLHelper::getFirstChildElement(impl,ISAPI))) {
+            const XMLCh* flag=impl->getAttributeNS(NULL,normalizeRequest);
+            g_bNormalizeRequest=(!flag || !*flag || *flag==chDigit_1 || *flag==chLatin_t);
+            impl=XMLHelper::getFirstChildElement(impl,Site);
+            while (impl) {
+                auto_ptr_char id(impl->getAttributeNS(NULL,id));
+                if (id.get())
+                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(impl)));
+                impl=XMLHelper::getNextSiblingElement(impl,Site);
+            }
+        }
+    }
 
     pVer->dwFilterVersion=HTTP_FILTER_REVISION;
     strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);
@@ -214,7 +221,7 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
 extern "C" BOOL WINAPI TerminateFilter(DWORD)
 {
     if (g_Config)
-        g_Config->shutdown();
+        g_Config->term();
     g_Config = NULL;
     LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut down...");
     return TRUE;
@@ -333,7 +340,7 @@ class ShibTargetIsapiF : public AbstractSPRequest
   PHTTP_FILTER_CONTEXT m_pfc;
   PHTTP_FILTER_PREPROC_HEADERS m_pn;
   map<string,string> m_headers;
-  vector<XSECCryptoX509*> m_certs;
+  vector<string> m_certs;
   int m_port;
   string m_scheme,m_hostname,m_uri;
   mutable string m_remote_addr,m_content_type,m_method;
@@ -459,9 +466,9 @@ public:
     hdr += "\r\n";
     const char* codestr="200 OK";
     switch (status) {
-        case SAML_HTTP_STATUS_FORBIDDEN:codestr="403 Forbidden"; break;
-        case SAML_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;
-        case SAML_HTTP_STATUS_ERROR:    codestr="500 Server Error"; break;
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:codestr="403 Forbidden"; break;
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;
+        case XMLTOOLING_HTTP_STATUS_ERROR:    codestr="500 Server Error"; break;
     }
     m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);
     char buf[1024];
@@ -495,13 +502,13 @@ public:
     return SF_STATUS_REQ_NEXT_NOTIFICATION;
   }
 
-  const vector<XSECCryptoX509*>& getClientCertificates() const {
+  const vector<string>& getClientCertificates() const {
       return m_certs;
   }
   
   // The filter never processes the POST, so stub these methods.
-  const char* getQueryString() const { throw runtime_error("getQueryString not implemented"); }
-  const char* getRequestBody() const { throw runtime_error("getRequestBody not implemented"); }
+  const char* getQueryString() const { throw IOException("getQueryString not implemented"); }
+  const char* getRequestBody() const { throw IOException("getRequestBody not implemented"); }
 };
 
 DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
@@ -609,7 +616,7 @@ class ShibTargetIsapiE : public AbstractSPRequest
 {
   LPEXTENSION_CONTROL_BLOCK m_lpECB;
   map<string,string> m_headers;
-  vector<XSECCryptoX509*> m_certs;
+  vector<string> m_certs;
   mutable string m_body;
   mutable bool m_gotBody;
   int m_port;
@@ -750,8 +757,8 @@ public:
     if (m_gotBody)
         return m_body.c_str();
     if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
-        throw opensaml::BindingException("Size of POST request body exceeded limit.");
-    else if (m_lpECB->cbTotalBytes != m_lpECB->cbAvailable) {
+        throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");
+    else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {
       m_gotBody=true;
       char buf[8192];
       DWORD datalen=m_lpECB->cbTotalBytes;
@@ -759,12 +766,12 @@ public:
         DWORD buflen=8192;
         BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
         if (!ret || !buflen)
-            throw saml::SAMLException("Error reading POST request body from browser.");
+            throw IOException("Error reading request body from browser.");
         m_body.append(buf, buflen);
         datalen-=buflen;
       }
     }
-    else {
+    else if (m_lpECB->cbAvailable) {
         m_gotBody=true;
         m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
     }
@@ -777,9 +784,9 @@ public:
     hdr += "\r\n";
     const char* codestr="200 OK";
     switch (status) {
-        case SAML_HTTP_STATUS_FORBIDDEN:codestr="403 Forbidden"; break;
-        case SAML_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;
-        case SAML_HTTP_STATUS_ERROR:    codestr="500 Server Error"; break;
+        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:codestr="403 Forbidden"; break;
+        case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="404 Not Found"; break;
+        case XMLTOOLING_HTTP_STATUS_ERROR:    codestr="500 Server Error"; break;
     }
     m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());
     char buf[1024];
@@ -818,7 +825,7 @@ public:
       return HSE_STATUS_SUCCESS;
   }
 
-  const vector<XSECCryptoX509*>& getClientCertificates() const {
+  const vector<string>& getClientCertificates() const {
       return m_certs;
   }