Large reorg of shibsp lib, new SPRequest API, ported modules, shifted code out of...
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Sat, 13 Jan 2007 03:45:18 +0000 (03:45 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Sat, 13 Jan 2007 03:45:18 +0000 (03:45 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2125 cb58f699-b61c-0410-a6fe-9272a202ed29

58 files changed:
.cdtproject
apache/mod_apache.cpp
apache/mod_shib_20.cpp
apache/mod_shib_22.cpp
isapi_shib/isapi_shib.cpp
nsapi_shib/nsapi_shib.cpp
shar/shar.cpp
shib-target/Makefile.am
shib-target/internal.h
shib-target/shib-ccache.cpp
shib-target/shib-config.cpp
shib-target/shib-handlers.cpp
shib-target/shib-ini.cpp
shib-target/shib-target.cpp
shib-target/shib-target.h
shib-target/shibtarget.vcproj
shibsp/AbstractSPRequest.cpp [new file with mode: 0644]
shibsp/AbstractSPRequest.h [new file with mode: 0644]
shibsp/AccessControl.h [new file with mode: 0644]
shibsp/Application.cpp [new file with mode: 0644]
shibsp/Application.h [new file with mode: 0644]
shibsp/Makefile.am
shibsp/RequestMapper.h [new file with mode: 0644]
shibsp/SPConfig.cpp
shibsp/SPConfig.h
shibsp/SPRequest.h [new file with mode: 0644]
shibsp/ServiceProvider.cpp
shibsp/ServiceProvider.h
shibsp/SessionCache.h [new file with mode: 0644]
shibsp/impl/XMLAccessControl.cpp [moved from xmlproviders/XMLAccessControl.cpp with 75% similarity]
shibsp/impl/XMLRequestMapper.cpp [moved from shib-target/XMLRequestMapper.cpp with 85% similarity]
shibsp/metadata/MetadataExt.h [moved from shibsp/MetadataExt.h with 95% similarity]
shibsp/metadata/MetadataExtImpl.cpp [moved from shibsp/MetadataExtImpl.cpp with 99% similarity]
shibsp/metadata/MetadataExtSchemaValidators.cpp [moved from shibsp/MetadataExtSchemaValidators.cpp with 97% similarity]
shibsp/remoting/ListenerService.h [moved from shibsp/ListenerService.h with 98% similarity]
shibsp/remoting/ddf.h [moved from shibsp/ddf.h with 99% similarity]
shibsp/remoting/impl/ListenerService.cpp [moved from shibsp/ListenerService.cpp with 98% similarity]
shibsp/remoting/impl/SocketListener.cpp [moved from shibsp/SocketListener.cpp with 99% similarity]
shibsp/remoting/impl/SocketListener.h [moved from shibsp/SocketListener.h with 97% similarity]
shibsp/remoting/impl/TCPListener.cpp [moved from shibsp/TCPListener.cpp with 99% similarity]
shibsp/remoting/impl/UnixListener.cpp [moved from shibsp/UnixListener.cpp with 95% similarity]
shibsp/remoting/impl/ddf.cpp [moved from shibsp/ddf.cpp with 99% similarity]
shibsp/security/PKIXTrustEngine.cpp [moved from shibsp/PKIXTrustEngine.cpp with 98% similarity]
shibsp/security/PKIXTrustEngine.h [moved from shibsp/PKIXTrustEngine.h with 96% similarity]
shibsp/shibsp.vcproj
shibsp/util/CGIParser.cpp [new file with mode: 0644]
shibsp/util/CGIParser.h [new file with mode: 0644]
shibsp/util/DOMPropertySet.cpp [moved from shibsp/DOMPropertySet.cpp with 99% similarity]
shibsp/util/DOMPropertySet.h [moved from shibsp/DOMPropertySet.h with 97% similarity]
shibsp/util/PropertySet.h [moved from shibsp/PropertySet.h with 99% similarity]
shibsp/util/SPConstants.cpp [moved from shibsp/SPConstants.cpp with 97% similarity]
shibsp/util/SPConstants.h [moved from shibsp/SPConstants.h with 98% similarity]
test/posttest.cpp
test/shibtest.cpp
xmlproviders/Makefile.am
xmlproviders/XMLAAP.cpp
xmlproviders/XMLProviders.cpp
xmlproviders/xmlproviders.vcproj

index e5bc816..be8b1cf 100644 (file)
@@ -7,10 +7,16 @@
 <data>
         
     <item id="org.eclipse.cdt.core.pathentry">
-<pathentry kind="src" path="shibsp"/>
+<pathentry kind="src" path="apache"/>
 <pathentry kind="out" path=""/>
 <pathentry kind="src" path="odbc-store"/>
-<pathentry kind="src" path="apache"/>
+<pathentry excluding="util/|impl/|security/|metadata/|remoting/|remoting/impl/" kind="src" path="shibsp"/>
+<pathentry kind="src" path="shibsp/impl"/>
+<pathentry kind="src" path="shibsp/metadata"/>
+<pathentry excluding="impl/" kind="src" path="shibsp/remoting"/>
+<pathentry kind="src" path="shibsp/remoting/impl"/>
+<pathentry kind="src" path="shibsp/security"/>
+<pathentry kind="src" path="shibsp/util"/>
 </item>
 </data>
 </cdtproject>
index 8875906..381cdd9 100644 (file)
@@ -31,7 +31,9 @@
 # define _CRT_SECURE_NO_DEPRECATE 1
 #endif
 
+#include <shibsp/AccessControl.h>
 #include <shibsp/exceptions.h>
+#include <shibsp/RequestMapper.h>
 #include <shibsp/SPConfig.h>
 
 // SAML Runtime
@@ -39,6 +41,7 @@
 #include <shib/shib.h>
 #include <shib-target/shib-target.h>
 #include <xercesc/util/regx/RegularExpression.hpp>
+#include <xmltooling/util/NDC.h>
 #include <xmltooling/util/Threads.h>
 
 #ifdef WIN32
@@ -222,7 +225,7 @@ static shib_request_config *init_request_config(request_rec *r)
     shib_request_config* rc=(shib_request_config*)ap_pcalloc(r->pool,sizeof(shib_request_config));
     ap_set_module_config (r->request_config, &mod_shib, rc);
     memset(rc, 0, sizeof(shib_request_config));
-    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_init_rc\n");
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_init_rc");
     return rc;
 }
 
@@ -260,6 +263,7 @@ class ShibTargetApache : public ShibTarget
 {
   mutable string m_body;
   mutable bool m_gotBody;
+  vector<XSECCryptoX509*> m_certs;
 
 public:
   request_rec* m_req;
@@ -271,6 +275,7 @@ public:
     m_sc = (shib_server_config*)ap_get_module_config(req->server->module_config, &mod_shib);
     m_dc = (shib_dir_config*)ap_get_module_config(req->per_dir_config, &mod_shib);
     m_rc = (shib_request_config*)ap_get_module_config(req->request_config, &mod_shib);
+    m_req = req;
 
     init(
         m_sc->szScheme ? m_sc->szScheme : ap_http_method(req),
@@ -281,46 +286,57 @@ public:
            req->connection->remote_ip,
         req->method
         );
-
-    m_req = req;
   }
   virtual ~ShibTargetApache() {}
 
-  virtual void log(ShibLogLevel level, const string &msg) {
-    ShibTarget::log(level,msg);
-#ifdef SHIB_APACHE_13
-    ap_log_rerror(APLOG_MARK,
-        (level == LogLevelDebug ? APLOG_DEBUG :
-            (level == LogLevelInfo ? APLOG_INFO :
-            (level == LogLevelWarn ? APLOG_WARNING : APLOG_ERR)))|APLOG_NOERRNO, SH_AP_R(m_req), msg.c_str());
-#else
-    if (level == LogLevelError)
-        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(m_req), msg.c_str());
-#endif
+  const char* getScheme() const {
+    return m_sc->szScheme ? m_sc->szScheme : ap_http_method(m_req);
   }
-  virtual string getCookies(void) const {
-    const char *c = ap_table_get(m_req->headers_in, "Cookie");
-    return string(c ? c : "");
+  const char* getHostname() const {
+    return ap_get_server_name(m_req);
   }
-  virtual void setCookie(const string &name, const string &value) {
-    char* val = ap_psprintf(m_req->pool, "%s=%s", name.c_str(), value.c_str());
-#ifdef SHIB_DEFERRED_HEADERS
-    ap_table_addn(m_rc->hdr_err, "Set-Cookie", val);
-#else
-    ap_table_addn(m_req->err_headers_out, "Set-Cookie", val);
-#endif
+  int getPort() const {
+    return ap_get_server_port(m_req);
+  }
+  const char* getRequestURI() const {
+    return m_req->unparsed_uri;
+  }
+  const char* getMethod() const {
+    return m_req->method;
+  }
+  string getContentType() const {
+    const char* type = ap_table_get(m_req->headers_in, "Content-Type");
+    return type ? type : "";
+  }
+  long getContentLength() const {
+      return m_gotBody ? m_body.length() : m_req->remaining;
+  }
+  string getRemoteAddr() const {
+    return m_req->connection->remote_ip;
+  }
+  void log(SPLogLevel level, const string& msg) const {
+    AbstractSPRequest::log(level,msg);
+    ap_log_rerror(
+        APLOG_MARK,
+        (level == SPDebug ? APLOG_DEBUG :
+        (level == SPInfo ? APLOG_INFO :
+        (level == SPWarn ? APLOG_WARNING :
+        (level == SPError ? APLOG_ERR : APLOG_CRIT))))|APLOG_NOERRNO,
+        SH_AP_R(m_req),
+        msg.c_str()
+        );
   }
-  virtual const char* getQueryString() const { return m_req->args; }
-  virtual const char* getRequestBody() const {
+  const char* getQueryString() const { return m_req->args; }
+  const char* getRequestBody() const {
     if (m_gotBody)
         return m_body.c_str();
     // Read the posted data
     if (ap_setup_client_block(m_req, REQUEST_CHUNKED_ERROR))
-        throw saml::SAMLException("Apache function (setup_client_block) failed while reading POST request body.");
+        throw opensaml::BindingException("Apache function (setup_client_block) failed while reading POST request body.");
     if (!ap_should_client_block(m_req))
-        throw saml::SAMLException("Apache function (should_client_block) failed while reading POST request body.");
+        throw opensaml::BindingException("Apache function (should_client_block) failed while reading POST request body.");
     if (m_req->remaining > 1024*1024)
-        throw saml::SAMLException("Blocked POST request body larger than size limit.");
+        throw opensaml::BindingException("Blocked POST request body larger than size limit.");
     m_gotBody=true;
     char buff[HUGE_STRING_LEN];
     ap_hard_timeout("[mod_shib] getRequestBody", m_req);
@@ -333,17 +349,17 @@ public:
     ap_kill_timeout(m_req);
     return m_body.c_str();
   }
-  virtual void clearHeader(const string &name) {
+  void clearHeader(const char* name) {
     if (m_dc->bUseEnvVars!=0) {
        // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_clear_header: env\n");
-       if (m_rc && m_rc->env) ap_table_unset(m_rc->env, name.c_str());
+       if (m_rc && m_rc->env) ap_table_unset(m_rc->env, name);
     } else {
        // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_clear_header: hdr\n");
-       ap_table_unset(m_req->headers_in, name.c_str());
-       ap_table_set(m_req->headers_in, name.c_str(), g_unsetHeaderValue.c_str());
+       ap_table_unset(m_req->headers_in, name);
+       ap_table_set(m_req->headers_in, name, g_unsetHeaderValue.c_str());
     }
   }
-  virtual void setHeader(const string &name, const string &value) {
+  void setHeader(const char* name, const char* value) {
     if (m_dc->bUseEnvVars!=0) {
        if (!m_rc) {
           // this happens on subrequests
@@ -351,52 +367,66 @@ public:
           m_rc = init_request_config(m_req);
        }
        if (!m_rc->env) m_rc->env = ap_make_table(m_req->pool, 10);
-       // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_set_env: %s=%s\n", name.c_str(), value.c_str()?value.c_str():"Null");
-       ap_table_set(m_rc->env, name.c_str(), value.c_str()?value.c_str():"");
-    } else {
-       // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_set_hdr: %s=%s\n", name.c_str(), value.c_str()?value.c_str():"Null");
-       ap_table_set(m_req->headers_in, name.c_str(), value.c_str());
+       // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_set_env: %s=%s\n", name, value?value:"Null");
+       ap_table_set(m_rc->env, name, value?value:"");
+    }
+    else {
+       ap_table_set(m_req->headers_in, name, value);
     }
   }
-  virtual string getHeader(const string &name) {
-    const char *hdr;
+  string getHeader(const char* name) const {
+    const char* hdr = ap_table_get(m_req->headers_in, name);
+    return string(hdr ? hdr : "");
+  }
+  string getSecureHeader(const char* name) const {
     if (m_dc->bUseEnvVars!=0) {
-       if (m_rc && m_rc->env) hdr = ap_table_get(m_rc->env, name.c_str());
-       else hdr = NULL;
-       // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_get_hdr_env: %s=%s\n", name.c_str(), hdr?hdr:"NULL");
-    } else {
-       hdr = ap_table_get(m_req->headers_in, name.c_str());
-       // ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(m_req), "shib_get_hdr: %s=%s\n", name.c_str(), hdr?hdr:"NULL");
+       const char *hdr;
+       if (m_rc && m_rc->env)
+           hdr = ap_table_get(m_rc->env, name);
+       else
+           hdr = NULL;
+       return string(hdr ? hdr : "");
     }
-    return string(hdr ? hdr : "");
+    return getHeader(name);
   }
-  virtual void setRemoteUser(const string &user) {
-    SH_AP_USER(m_req) = ap_pstrdup(m_req->pool, user.c_str());
+  void setRemoteUser(const char* user) {
+      SH_AP_USER(m_req) = user ? ap_pstrdup(m_req->pool, user) : NULL;
   }
-  virtual string getRemoteUser(void) {
+  string getRemoteUser() const {
     return string(SH_AP_USER(m_req) ? SH_AP_USER(m_req) : "");
   }
-  virtual void* sendPage(
-    const string& msg,
-    int code=200,
-    const string& content_type="text/html",
-    const saml::Iterator<header_t>& headers=EMPTY(header_t)
-    ) {
-    m_req->content_type = ap_psprintf(m_req->pool, content_type.c_str());
-    while (headers.hasNext()) {
-        const header_t& h=headers.next();
-        ap_table_set(m_req->headers_out, h.first.c_str(), h.second.c_str());
-    }
+  void setContentType(const char* type) {
+      m_req->content_type = ap_psprintf(m_req->pool, type);
+  }
+  void setResponseHeader(const char* name, const char* value) {
+#ifdef SHIB_DEFERRED_HEADERS
+   if (!m_rc)
+      // this happens on subrequests
+      m_rc = init_request_config(m_req);
+    ap_table_add(m_rc->hdr_err, name, value);
+    ap_table_add(m_rc->hdr_out, name, value);
+#else
+    ap_table_add(m_req->err_headers_out, name, value);
+#endif
+  }
+  long sendResponse(istream& in, long status) {
     ap_send_http_header(m_req);
-    ap_rprintf(m_req, msg.c_str());
-    return (void*)((code==200) ? DONE : code);
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        ap_rwrite(buf,in.gcount(),m_req);
+    }
+    return ((status==SAML_HTTP_STATUS_OK) ? DONE : status);
+  }
+  long sendRedirect(const char* url) {
+    ap_table_set(m_req->headers_out, "Location", url);
+    return REDIRECT;
   }
-  virtual void* sendRedirect(const string& url) {
-    ap_table_set(m_req->headers_out, "Location", url.c_str());
-    return (void*)REDIRECT;
+  const vector<XSECCryptoX509*>& getClientCertificates() const {
+      return m_certs;
   }
-  virtual void* returnDecline(void) { return (void*)DECLINED; }
-  virtual void* returnOK(void) { return (void*)OK; }
+  long returnDecline(void) { return DECLINED; }
+  long returnOK(void) { return OK; }
 };
 
 /********************************************************************************/
@@ -412,24 +442,24 @@ extern "C" int shib_check_user(request_rec* r)
 
   ostringstream threadid;
   threadid << "[" << getpid() << "] shib_check_user" << '\0';
-  saml::NDC ndc(threadid.str().c_str());
+  xmltooling::NDC ndc(threadid.str().c_str());
 
   try {
     ShibTargetApache sta(r);
 
     // Check user authentication and export information, then set the handler bypass
-    pair<bool,void*> res = sta.doCheckAuthN(true);
+    pair<bool,long> res = sta.doCheckAuthN(true);
     apr_pool_userdata_setn((const void*)42,g_UserDataKey,NULL,r->pool);
-    if (res.first) return (int)(long)res.second;
+    if (res.first) return res.second;
 
     // user auth was okay -- export the assertions now
     res = sta.doExportAssertions();
-    if (res.first) return (int)(long)res.second;
+    if (res.first) return res.second;
 
     // export happened successfully..  this user is ok.
     return OK;
   }
-  catch (saml::SAMLException& e) {
+  catch (exception& e) {
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_check_user threw an exception: %s", e.what());
     return SERVER_ERROR;
   }
@@ -449,7 +479,7 @@ extern "C" int shib_handler(request_rec* r)
 
   ostringstream threadid;
   threadid << "[" << getpid() << "] shib_handler" << '\0';
-  saml::NDC ndc(threadid.str().c_str());
+  xmltooling::NDC ndc(threadid.str().c_str());
 
 #ifndef SHIB_APACHE_13
   // With 2.x, this handler always runs, though last.
@@ -468,13 +498,13 @@ extern "C" int shib_handler(request_rec* r)
   try {
     ShibTargetApache sta(r);
 
-    pair<bool,void*> res = sta.doHandler();
-    if (res.first) return (int)(long)res.second;
+    pair<bool,long> res = sta.doHandler();
+    if (res.first) return res.second;
 
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "doHandler() did not do anything.");
     return SERVER_ERROR;
   }
-  catch (saml::SAMLException& e) {
+  catch (exception& e) {
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_handler threw an exception: %s", e.what());
     return SERVER_ERROR;
   }
@@ -500,18 +530,18 @@ extern "C" int shib_auth_checker(request_rec* r)
 
   ostringstream threadid;
   threadid << "[" << getpid() << "] shib_auth_checker" << '\0';
-  saml::NDC ndc(threadid.str().c_str());
+  xmltooling::NDC ndc(threadid.str().c_str());
 
   try {
     ShibTargetApache sta(r);
 
-    pair<bool,void*> res = sta.doCheckAuthZ();
-    if (res.first) return (int)(long)res.second;
+    pair<bool,long> res = sta.doCheckAuthZ();
+    if (res.first) return res.second;
 
     // We're all okay.
     return OK;
   }
-  catch (saml::SAMLException& e) {
+  catch (exception& e) {
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_auth_checker threw an exception: %s", e.what());
     return SERVER_ERROR;
   }
@@ -524,32 +554,29 @@ extern "C" int shib_auth_checker(request_rec* r)
 }
 
 // Access control plugin that enforces htaccess rules
-class htAccessControl : virtual public IAccessControl
+class htAccessControl : virtual public AccessControl
 {
 public:
     htAccessControl() {}
     ~htAccessControl() {}
     Lockable* lock() {return this;}
     void unlock() {}
-    bool authorized(
-        ShibTarget* st,
-        ISessionCacheEntry* entry
-    ) const;
+    bool authorized(SPRequest& request, Session* session) const;
 };
 
-saml::IPlugIn* htAccessFactory(const DOMElement* e)
+AccessControl* htAccessFactory(const DOMElement* const & e)
 {
     return new htAccessControl();
 }
 
-class ApacheRequestMapper : public virtual IRequestMapper, public virtual PropertySet
+class ApacheRequestMapper : public virtual RequestMapper, public virtual PropertySet
 {
 public:
     ApacheRequestMapper(const DOMElement* e);
     ~ApacheRequestMapper() { delete m_mapper; delete m_htaccess; delete m_staKey; delete m_propsKey; }
     Lockable* lock() { return m_mapper->lock(); }
     void unlock() { m_staKey->setData(NULL); m_propsKey->setData(NULL); m_mapper->unlock(); }
-    Settings getSettings(ShibTarget* st) const;
+    Settings getSettings(const SPRequest& request) const;
     
     pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;
     pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;
@@ -560,41 +587,36 @@ public:
     const DOMElement* getElement() const;
 
 private:
-    IRequestMapper* m_mapper;
+    RequestMapper* m_mapper;
     ThreadKey* m_staKey;
     ThreadKey* m_propsKey;
-    IAccessControl* m_htaccess;
+    AccessControl* m_htaccess;
 };
 
-saml::IPlugIn* ApacheRequestMapFactory(const DOMElement* e)
+RequestMapper* ApacheRequestMapFactory(const DOMElement* const & e)
 {
     return new ApacheRequestMapper(e);
 }
 
 ApacheRequestMapper::ApacheRequestMapper(const DOMElement* e) : m_mapper(NULL), m_staKey(NULL), m_propsKey(NULL), m_htaccess(NULL)
 {
-    saml::IPlugIn* p=saml::SAMLConfig::getConfig().getPlugMgr().newPlugin(XML_REQUESTMAP_PROVIDER,e);
-    m_mapper=dynamic_cast<IRequestMapper*>(p);
-    if (!m_mapper) {
-        delete p;
-        throw saml::UnsupportedExtensionException("Embedded request mapper plugin was not of correct type.");
-    }
+    m_mapper=SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e);
     m_htaccess=new htAccessControl();
     m_staKey=ThreadKey::create(NULL);
     m_propsKey=ThreadKey::create(NULL);
 }
 
-IRequestMapper::Settings ApacheRequestMapper::getSettings(ShibTarget* st) const
+RequestMapper::Settings ApacheRequestMapper::getSettings(const SPRequest& request) const
 {
-    Settings s=m_mapper->getSettings(st);
-    m_staKey->setData(dynamic_cast<ShibTargetApache*>(st));
+    Settings s=m_mapper->getSettings(request);
+    m_staKey->setData((void*)dynamic_cast<const ShibTargetApache*>(&request));
     m_propsKey->setData((void*)s.first);
-    return pair<const PropertySet*,IAccessControl*>(this,s.second ? s.second : m_htaccess);
+    return pair<const PropertySet*,AccessControl*>(this,s.second ? s.second : m_htaccess);
 }
 
 pair<bool,bool> ApacheRequestMapper::getBool(const char* name, const char* ns) const
 {
-    ShibTargetApache* sta=reinterpret_cast<ShibTargetApache*>(m_staKey->getData());
+    const ShibTargetApache* sta=reinterpret_cast<const ShibTargetApache*>(m_staKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (sta && !ns) {
         // Override Apache-settable boolean properties.
@@ -608,7 +630,7 @@ pair<bool,bool> ApacheRequestMapper::getBool(const char* name, const char* ns) c
 
 pair<bool,const char*> ApacheRequestMapper::getString(const char* name, const char* ns) const
 {
-    ShibTargetApache* sta=reinterpret_cast<ShibTargetApache*>(m_staKey->getData());
+    const ShibTargetApache* sta=reinterpret_cast<const ShibTargetApache*>(m_staKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (sta && !ns) {
         // Override Apache-settable string properties.
@@ -639,7 +661,7 @@ pair<bool,const XMLCh*> ApacheRequestMapper::getXMLString(const char* name, cons
 
 pair<bool,unsigned int> ApacheRequestMapper::getUnsignedInt(const char* name, const char* ns) const
 {
-    ShibTargetApache* sta=reinterpret_cast<ShibTargetApache*>(m_staKey->getData());
+    const ShibTargetApache* sta=reinterpret_cast<const ShibTargetApache*>(m_staKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (sta && !ns) {
         // Override Apache-settable int properties.
@@ -651,7 +673,7 @@ pair<bool,unsigned int> ApacheRequestMapper::getUnsignedInt(const char* name, co
 
 pair<bool,int> ApacheRequestMapper::getInt(const char* name, const char* ns) const
 {
-    ShibTargetApache* sta=reinterpret_cast<ShibTargetApache*>(m_staKey->getData());
+    const ShibTargetApache* sta=reinterpret_cast<const ShibTargetApache*>(m_staKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (sta && !ns) {
         // Override Apache-settable int properties.
@@ -721,13 +743,10 @@ static SH_AP_TABLE* groups_for_user(request_rec* r, const char* user, char* grpf
     return grps;
 }
 
-bool htAccessControl::authorized(
-    ShibTarget* st,
-    ISessionCacheEntry* entry
-) const
+bool htAccessControl::authorized(SPRequest& request, Session* session) const
 {
     // Make sure the object is our type.
-    ShibTargetApache* sta=dynamic_cast<ShibTargetApache*>(st);
+    ShibTargetApache* sta=dynamic_cast<ShibTargetApache*>(&request);
     if (!sta)
         throw ConfigurationException("Request wrapper object was not of correct type.");
 
@@ -760,7 +779,7 @@ bool htAccessControl::authorized(
         if (!(reqs[x].method_mask & (1 << m)))
             continue;
         method_restricted=true;
-        string remote_user = st->getRemoteUser();
+        string remote_user = request.getRemoteUser();
 
         t = reqs[x].requirement;
         w = ap_getword_white(sta->m_req->pool, &t);
@@ -771,12 +790,12 @@ bool htAccessControl::authorized(
             SHIB_AP_CHECK_IS_OK;
         }
         else if (!strcmp(w,"valid-user")) {
-            if (entry) {
-                st->log(ShibTarget::LogLevelDebug,"htAccessControl plugin accepting valid-user based on active session");
+            if (session) {
+                request.log(SPRequest::SPDebug,"htAccessControl plugin accepting valid-user based on active session");
                 SHIB_AP_CHECK_IS_OK;
             }
             else
-                st->log(ShibTarget::LogLevelError,"htAccessControl plugin rejecting access for valid-user rule, no session is active");
+                request.log(SPRequest::SPError,"htAccessControl plugin rejecting access for valid-user rule, no session is active");
         }
         else if (!strcmp(w,"user") && !remote_user.empty()) {
             bool regexp=false;
@@ -794,18 +813,18 @@ bool htAccessControl::authorized(
                         RegularExpression re(trans.get());
                         auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
                         if (re.matches(trans2.get())) {
-                            st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin accepting user (") + w + ")");
+                            request.log(SPRequest::SPDebug, string("htAccessControl plugin accepting user (") + w + ")");
                             SHIB_AP_CHECK_IS_OK;
                         }
                     }
                     catch (XMLException& ex) {
                         auto_ptr_char tmp(ex.getMessage());
-                        st->log(ShibTarget::LogLevelError,
+                        request.log(SPRequest::SPError,
                             string("htAccessControl plugin caught exception while parsing regular expression (") + w + "): " + tmp.get());
                     }
                 }
                 else if (remote_user==w) {
-                    st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin accepting user (") + w + ")");
+                    request.log(SPRequest::SPDebug, string("htAccessControl plugin accepting user (") + w + ")");
                     SHIB_AP_CHECK_IS_OK;
                 }
             }
@@ -813,7 +832,7 @@ bool htAccessControl::authorized(
         else if (!strcmp(w,"group")) {
             SH_AP_TABLE* grpstatus=NULL;
             if (sta->m_dc->szAuthGrpFile && !remote_user.empty()) {
-                st->log(ShibTarget::LogLevelDebug,string("htAccessControl plugin using groups file: ") + sta->m_dc->szAuthGrpFile);
+                request.log(SPRequest::SPDebug,string("htAccessControl plugin using groups file: ") + sta->m_dc->szAuthGrpFile);
                 grpstatus=groups_for_user(sta->m_req,remote_user.c_str(),sta->m_dc->szAuthGrpFile);
             }
             if (!grpstatus)
@@ -822,16 +841,16 @@ bool htAccessControl::authorized(
             while (*t) {
                 w=ap_getword_conf(sta->m_req->pool,&t);
                 if (ap_table_get(grpstatus,w)) {
-                    st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin accepting group (") + w + ")");
+                    request.log(SPRequest::SPDebug, string("htAccessControl plugin accepting group (") + w + ")");
                     SHIB_AP_CHECK_IS_OK;
                 }
             }
         }
         else {
-            saml::Iterator<shibboleth::IAAP*> provs=st->getApplication()->getAAPProviders();
+            saml::Iterator<shibboleth::IAAP*> provs=dynamic_cast<const IApplication&>(request.getSPApplication()).getAAPProviders();
             shibboleth::AAP wrapper(provs,w);
             if (wrapper.fail()) {
-                st->log(ShibTarget::LogLevelWarn, string("htAccessControl plugin didn't recognize require rule: ") + w);
+                request.log(SPRequest::SPWarn, string("htAccessControl plugin didn't recognize require rule: ") + w);
                 continue;
             }
 
@@ -868,7 +887,7 @@ bool htAccessControl::authorized(
                     for (unsigned int i = 0;  i < vals_str.length();  i++) {
                         if (vals_str.at(i) == ';') {
                             if (i == 0) {
-                                st->log(ShibTarget::LogLevelError, string("htAccessControl plugin found invalid header encoding (") +
+                                request.log(SPRequest::SPError, string("htAccessControl plugin found invalid header encoding (") +
                                     vals + "): starts with a semicolon");
                                 throw saml::SAMLException("Invalid information supplied to authorization plugin.");
                             }
@@ -884,18 +903,18 @@ bool htAccessControl::authorized(
                             if (regexp) {
                                 auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
                                 if (re->matches(trans.get())) {
-                                    st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+                                    request.log(SPRequest::SPDebug, string("htAccessControl plugin expecting ") + w +
                                        ", got " + val + ": authorization granted");
                                     SHIB_AP_CHECK_IS_OK;
                                 }
                             }
                             else if ((wrapper->getCaseSensitive() && val==w) || (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
-                                st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+                                request.log(SPRequest::SPDebug, string("htAccessControl plugin expecting ") + w +
                                     ", got " + val + ": authorization granted.");
                                 SHIB_AP_CHECK_IS_OK;
                             }
                             else {
-                                st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+                                request.log(SPRequest::SPDebug, string("htAccessControl plugin expecting ") + w +
                                     ", got " + val + ": authoritzation not granted.");
                             }
                         }
@@ -905,24 +924,24 @@ bool htAccessControl::authorized(
                     if (regexp) {
                         auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
                         if (re->matches(trans.get())) {
-                            st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+                            request.log(SPRequest::SPDebug, string("htAccessControl plugin expecting ") + w +
                                 ", got " + val + ": authorization granted.");
                             SHIB_AP_CHECK_IS_OK;
                         }
                     }
                     else if ((wrapper->getCaseSensitive() && val==w) || (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
-                        st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+                        request.log(SPRequest::SPDebug, string("htAccessControl plugin expecting ") + w +
                             ", got " + val + ": authorization granted");
                         SHIB_AP_CHECK_IS_OK;
                     }
                     else {
-                            st->log(ShibTarget::LogLevelDebug, string("htAccessControl plugin expecting ") + w +
+                            request.log(SPRequest::SPDebug, string("htAccessControl plugin expecting ") + w +
                                 ", got " + val + ": authorization not granted");
                     }
                 }
                 catch (XMLException& ex) {
                     auto_ptr_char tmp(ex.getMessage());
-                    st->log(ShibTarget::LogLevelError, string("htAccessControl plugin caught exception while parsing regular expression (")
+                    request.log(SPRequest::SPError, string("htAccessControl plugin caught exception while parsing regular expression (")
                         + w + "): " + tmp.get());
                 }
             }
@@ -951,7 +970,7 @@ extern "C" apr_status_t shib_exit(void* data)
         g_Config->shutdown();
         g_Config = NULL;
     }
-    ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,NULL,"shib_exit() done\n");
+    ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,NULL,"shib_exit() done");
     return OK;
 }
 #endif
@@ -962,7 +981,7 @@ static int shib_post_read(request_rec *r)
 {
     shib_request_config* rc = init_request_config(r);
 
-    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_post_read: E=%s\n", rc->env?"env":"hdr");
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_post_read: E=%s", rc->env?"env":"hdr");
 
 #ifdef SHIB_DEFERRED_HEADERS
     rc->hdr_out = ap_make_table(r->pool, 5);
@@ -980,12 +999,12 @@ extern "C" int shib_fixups(request_rec* r)
   if (dc->bOff==1 || dc->bUseEnvVars==0)
     return DECLINED;
 
-  ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_fixup(%d): ENTER\n", (int)getpid());
+  ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_fixup(%d): ENTER", (int)getpid());
 
   if (rc==NULL || rc->env==NULL || ap_is_empty_table(rc->env))
         return DECLINED;
 
-  ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_fixup adding %d vars\n", ap_table_elts(rc->env)->nelts);
+  ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_fixup adding %d vars", ap_table_elts(rc->env)->nelts);
   r->subprocess_env = ap_overlay_tables(r->pool, r->subprocess_env, rc->env);
 
   return OK;
@@ -1007,7 +1026,7 @@ extern "C" apr_status_t shib_child_exit(void* data)
     ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_exit(%d) dealing with g_Config..", (int)getpid());
     g_Config->shutdown();
     g_Config = NULL;
-    ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_exit() done\n");
+    ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_exit() done");
 
 #ifndef SHIB_APACHE_13
     return OK;
@@ -1041,7 +1060,7 @@ extern "C" void shib_child_init(apr_pool_t* p, server_rec* s)
             SPConfig::Listener |
             SPConfig::Metadata |
             SPConfig::AAP |
-            SPConfig::RequestMapper |
+            SPConfig::RequestMapping |
             SPConfig::InProcess |
             SPConfig::Logging
             );
@@ -1049,10 +1068,8 @@ extern "C" void shib_child_init(apr_pool_t* p, server_rec* s)
             ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to initialize libraries");
             exit(1);
         }
-        saml::SAMLConfig::getConfig().getPlugMgr().regFactory(HTACCESS_ACCESSCONTROL,&htAccessFactory);
-        saml::SAMLConfig::getConfig().getPlugMgr().regFactory(NATIVE_REQUESTMAP_PROVIDER,&ApacheRequestMapFactory);
-        // We hijack the legacy type so that 1.2 config files will load this plugin
-        saml::SAMLConfig::getConfig().getPlugMgr().regFactory(LEGACY_REQUESTMAP_PROVIDER,&ApacheRequestMapFactory);
+        SPConfig::getConfig().AccessControlManager.registerFactory(HT_ACCESS_CONTROL,&htAccessFactory);
+        SPConfig::getConfig().RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER,&ApacheRequestMapFactory);
         
         if (!g_Config->load(g_szSHIBConfig)) {
             ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to load configuration");
index a45ce6f..247af2f 100644 (file)
@@ -39,6 +39,7 @@
 #define ap_pstrcat apr_pstrcat
 #define ap_psprintf apr_psprintf
 #define ap_table_get apr_table_get
+#define ap_table_add apr_table_add
 #define ap_table_addn apr_table_addn
 #define ap_table_setn apr_table_setn
 #define ap_table_unset apr_table_unset
index e9c2644..7c11527 100644 (file)
@@ -39,6 +39,7 @@
 #define ap_pstrcat apr_pstrcat
 #define ap_psprintf apr_psprintf
 #define ap_table_get apr_table_get
+#define ap_table_add apr_table_add
 #define ap_table_addn apr_table_addn
 #define ap_table_setn apr_table_setn
 #define ap_table_unset apr_table_unset
index 2b9a60e..1b71250 100644 (file)
  * limitations under the License.
  */
 
-/* isapi_shib.cpp - Shibboleth ISAPI filter
-
-   Scott Cantor
-   8/23/02
-*/
+/**
+ * isapi_shib.cpp
+ * 
+ * Shibboleth ISAPI filter
+ */
 
 #include "config_win32.h"
 
 #define _CRT_SECURE_NO_DEPRECATE 1
 
 #include <shibsp/SPConfig.h>
+#include <xmltooling/util/NDC.h>
 
 // SAML Runtime
 #include <saml/saml.h>
 #include <shib/shib.h>
 #include <shib-target/shib-target.h>
 
-#include <ctime>
-#include <fstream>
 #include <sstream>
-#include <stdexcept>
+#include <fstream>
 #include <process.h>
 
 #include <httpfilt.h>
@@ -48,15 +47,14 @@ using namespace std;
 
 // globals
 namespace {
-    static const XMLCh name[] = { chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull };
-    static const XMLCh port[] = { chLatin_p, chLatin_o, chLatin_r, chLatin_t, chNull };
-    static const XMLCh sslport[] = { chLatin_s, chLatin_s, chLatin_l, chLatin_p, chLatin_o, chLatin_r, chLatin_t, chNull };
-    static const XMLCh scheme[] = { chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_e, chNull };
-    static const XMLCh id[] = { chLatin_i, chLatin_d, chNull };
-    static const XMLCh Implementation[] =
-    { chLatin_I, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull };
-    static const XMLCh ISAPI[] = { chLatin_I, chLatin_S, chLatin_A, chLatin_P, chLatin_I, chNull };
-    static const XMLCh Alias[] = { chLatin_A, chLatin_l, chLatin_i, chLatin_a, chLatin_s, chNull };
+    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);
+    static const XMLCh scheme[] =           UNICODE_LITERAL_6(s,c,h,e,m,e);
+    static const XMLCh id[] =               UNICODE_LITERAL_2(i,d);
+    static const XMLCh Implementation[] =   UNICODE_LITERAL_14(I,m,p,l,e,m,e,n,t,a,t,i,o,n);
+    static const XMLCh ISAPI[] =            UNICODE_LITERAL_5(I,S,A,P,I);
+    static const XMLCh Alias[] =            UNICODE_LITERAL_5(A,l,i,a,s);
     static const XMLCh normalizeRequest[] = UNICODE_LITERAL_16(n,o,r,m,a,l,i,z,e,R,e,q,u,e,s,t);
     static const XMLCh Site[] =             UNICODE_LITERAL_4(S,i,t,e);
 
@@ -116,8 +114,7 @@ extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
     if (!pVer)
         return FALSE;
         
-    if (!g_Config)
-    {
+    if (!g_Config) {
         LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
                 "Extension mode startup not possible, is the DLL loaded as a filter?");
         return FALSE;
@@ -159,7 +156,7 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
             SPConfig::Caching |
             SPConfig::Metadata |
             SPConfig::AAP |
-            SPConfig::RequestMapper |
+            SPConfig::RequestMapping |
             SPConfig::InProcess |
             SPConfig::Logging
             );
@@ -274,14 +271,12 @@ bool dynabuf::operator==(const char* s) const
 }
 
 void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
-    throw (bad_alloc, DWORD)
 {
     s.reserve(size);
     s.erase();
     size=s.size();
 
-    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size))
-    {
+    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {
         // Grumble. Check the error.
         DWORD e=GetLastError();
         if (e==ERROR_INSUFFICIENT_BUFFER)
@@ -294,14 +289,12 @@ void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s,
 }
 
 void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
-    throw (bad_alloc, DWORD)
 {
     s.reserve(size);
     s.erase();
     size=s.size();
 
-    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size))
-    {
+    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {
         // Grumble. Check the error.
         DWORD e=GetLastError();
         if (e==ERROR_INSUFFICIENT_BUFFER)
@@ -315,14 +308,12 @@ void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dyna
 
 void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
                LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
-    throw (bad_alloc, DWORD)
 {
     s.reserve(size);
     s.erase();
     size=s.size();
 
-    while (!pn->GetHeader(pfc,lpszName,s,&size))
-    {
+    while (!pn->GetHeader(pfc,lpszName,s,&size)) {
         // Grumble. Check the error.
         DWORD e=GetLastError();
         if (e==ERROR_INSUFFICIENT_BUFFER)
@@ -341,10 +332,15 @@ class ShibTargetIsapiF : public ShibTarget
 {
   PHTTP_FILTER_CONTEXT m_pfc;
   PHTTP_FILTER_PREPROC_HEADERS m_pn;
-  string m_cookie;
+  map<string,string> m_headers;
+  vector<XSECCryptoX509*> m_certs;
+
 public:
   ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site) {
 
+    m_pfc = pfc;
+    m_pn = pn;
+
     // URL path always come from IIS.
     dynabuf url(256);
     GetHeader(pn,pfc,"url",url,256,false);
@@ -380,91 +376,117 @@ public:
         host=site.m_name.c_str();
 
     init(scheme, host, atoi(port), url, content_type, remote_addr, method); 
-
-    m_pfc = pfc;
-    m_pn = pn;
   }
   ~ShibTargetIsapiF() { }
 
-  virtual void log(ShibLogLevel level, const string &msg) {
-    ShibTarget::log(level,msg);
-    if (level == LogLevelError)
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
+  const char* getScheme() const {
+    return m_scheme.c_str();
   }
-  virtual string getCookies() const {
-    dynabuf buf(128);
-    GetHeader(m_pn, m_pfc, "Cookie:", buf, 128, false);
-    return buf.empty() ? "" : buf;
+  const char* getHostname() const {
+    return m_hostname.c_str();
   }
-  
-  virtual void clearHeader(const string &name) {
-    string hdr = (name=="REMOTE_USER" ? "remote-user" : name) + ":";
+  int getPort() const {
+    return m_port;
+  }
+  const char* getRequestURI() const {
+    return m_uri.c_str();
+  }
+  const char* getMethod() const {
+    return m_method.c_str();
+  }
+  string getContentType() const {
+    return m_content_type;
+  }
+  long getContentLength() const {
+      return 0;
+  }
+  string getRemoteAddr() const {
+    return m_remote_addr;
+  }
+  void log(SPLogLevel level, const string& msg) {
+    AbstractSPRequest::log(level,msg);
+    if (level >= SPError)
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
+  }
+  void clearHeader(const char* name) {
+    string hdr(!strcmp(name,"REMOTE_USER") ? "remote-user" : name);
+    hdr += ':';
     m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), "");
   }
-  virtual void setHeader(const string &name, const string &value) {
-    string hdr = name + ":";
-    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()),
-                   const_cast<char*>(value.c_str()));
+  void setHeader(const char* name, const char* value) {
+    string hdr(name);
+    hdr += ':';
+    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
   }
-  virtual string getHeader(const string &name) {
-    string hdr = name + ":";
+  string getHeader(const char* name) const {
+    string hdr(name);
+    hdr += ':';
     dynabuf buf(1024);
     GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 1024, false);
     return string(buf);
   }
-  virtual void setRemoteUser(const string &user) {
-    setHeader(string("remote-user"), user);
+  void setRemoteUser(const char* user) {
+    setHeader("remote-user", user);
   }
-  virtual string getRemoteUser(void) {
-    return getHeader(string("remote-user"));
+  string getRemoteUser() const {
+    return getHeader("remote-user");
   }
-  virtual void* sendPage(
-    const string& msg,
-    int code=200,
-    const string& content_type="text/html",
-    const saml::Iterator<header_t>& headers=EMPTY(header_t)) {
-    string hdr = string ("Connection: close\r\nContent-type: ") + content_type + "\r\n";
-    while (headers.hasNext()) {
-        const header_t& h=headers.next();
-        hdr += h.first + ": " + h.second + "\r\n";
-    }
+  void setResponseHeader(const char* name, const char* value) {
+    // Set for later.
+    if (value)
+        m_headers[name] = value;
+    else
+        m_headers.erase(name);
+  }
+  long sendResponse(istream& in, long status) {
+    string hdr = string("Connection: close\r\n");
+    for (map<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
     hdr += "\r\n";
     const char* codestr="200 OK";
-    switch (code) {
-        case 403:   codestr="403 Forbidden"; break;
-        case 404:   codestr="404 Not Found"; break;
-        case 500:   codestr="500 Server Error"; break;
+    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;
     }
     m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);
-    DWORD resplen = msg.size();
-    m_pfc->WriteClient(m_pfc, (LPVOID)msg.c_str(), &resplen, 0);
-    return (void*)SF_STATUS_REQ_FINISHED;
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        DWORD resplen = in.gcount();
+        m_pfc->WriteClient(m_pfc, buf, &resplen, 0);
+    }
+    return SF_STATUS_REQ_FINISHED;
   }
-  virtual void* sendRedirect(const string& url) {
+  long sendRedirect(const char* url) {
     // XXX: Don't support the httpRedirect option, yet.
-    string hdrs=m_cookie + string("Location: ") + url + "\r\n"
+    string hdr=string("Location: ") + url + "\r\n"
       "Content-Type: text/html\r\n"
       "Content-Length: 40\r\n"
       "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
-      "Cache-Control: private,no-store,no-cache\r\n\r\n";
-    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER,
-                                "302 Please Wait", (DWORD)hdrs.c_str(), 0);
+      "Cache-Control: private,no-store,no-cache\r\n";
+    for (map<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (DWORD)hdr.c_str(), 0);
     static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
     DWORD resplen=40;
     m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
-    return reinterpret_cast<void*>(SF_STATUS_REQ_FINISHED);
+    return SF_STATUS_REQ_FINISHED;
   }
   // XXX: We might not ever hit the 'decline' status in this filter.
-  //virtual void* returnDecline(void) { }
-  virtual void* returnOK(void) { return (void*) SF_STATUS_REQ_NEXT_NOTIFICATION; }
+  //long returnDecline(void) { }
+  long returnOK(void) {
+    return SF_STATUS_REQ_NEXT_NOTIFICATION;
+  }
 
-  // The filter never processes the POST, so stub these methods.
-  virtual void setCookie(const string &name, const string &value) {
-    // Set the cookie for later.  Use it during the redirect.
-    m_cookie += "Set-Cookie: " + name + "=" + value + "\r\n";
+  const vector<XSECCryptoX509*>& getClientCertificates() const {
+      return m_certs;
   }
-  virtual const char* getQueryString() const { throw runtime_error("getQueryString not implemented"); }
-  virtual const char* getRequestBody() const { throw runtime_error("getRequestBody not implemented"); }
+  
+  // 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"); }
 };
 
 DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
@@ -508,20 +530,20 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
             
         ostringstream threadid;
         threadid << "[" << getpid() << "] isapi_shib" << '\0';
-        saml::NDC ndc(threadid.str().c_str());
+        xmltooling::NDC ndc(threadid.str().c_str());
 
         ShibTargetIsapiF stf(pfc, pn, map_i->second);
 
         // "false" because we don't override the Shib settings
-        pair<bool,void*> res = stf.doCheckAuthN();
-        if (res.first) return (DWORD)res.second;
+        pair<bool,long> res = stf.doCheckAuthN();
+        if (res.first) return res.second;
 
         // "false" because we don't override the Shib settings
         res = stf.doExportAssertions();
-        if (res.first) return (DWORD)res.second;
+        if (res.first) return res.second;
 
         res = stf.doCheckAuthZ();
-        if (res.first) return (DWORD)res.second;
+        if (res.first) return res.second;
 
         return SF_STATUS_REQ_NEXT_NOTIFICATION;
     }
@@ -534,7 +556,7 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
         else
             return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");
     }
-    catch (saml::SAMLException& e) {
+    catch (exception& e) {
         LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
         return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
     }
@@ -571,12 +593,13 @@ DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
 class ShibTargetIsapiE : public ShibTarget
 {
   LPEXTENSION_CONTROL_BLOCK m_lpECB;
-  string m_cookie;
+  map<string,string> m_headers;
+  vector<XSECCryptoX509*> m_certs;
   mutable string m_body;
   mutable bool m_gotBody;
   
 public:
-  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site) : m_gotBody(false) {
+  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site) : m_lpECB(lpECB), m_gotBody(false) {
     dynabuf ssl(5);
     GetServerVariable(lpECB,"HTTPS",ssl,5);
     bool SSL=(ssl=="on" || ssl=="ON");
@@ -650,33 +673,65 @@ public:
         fullurl+=lpECB->lpszQueryString;
     }
     init(scheme, host, atoi(port), fullurl.c_str(), lpECB->lpszContentType, remote_addr, lpECB->lpszMethod);
-
-    m_lpECB = lpECB;
   }
   ~ShibTargetIsapiE() { }
 
-  virtual void log(ShibLogLevel level, const string &msg) {
-      ShibTarget::log(level,msg);
-      if (level == LogLevelError)
+  const char* getScheme() const {
+    return m_scheme.c_str();
+  }
+  const char* getHostname() const {
+    return m_hostname.c_str();
+  }
+  int getPort() const {
+    return m_port;
+  }
+  const char* getRequestURI() const {
+    return m_uri.c_str();
+  }
+  const char* getMethod() const {
+    return m_lpECB->lpszMethod ? m_lpECB->lpszMethod : "";
+  }
+  string getContentType() const {
+    return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";
+  }
+  long getContentLength() const {
+      return m_lpECB->cbTotalBytes;
+  }
+  string getRemoteAddr() const {
+    return m_remote_addr;
+  }
+  void log(SPLogLevel level, const string& msg) {
+      AbstractSPRequest::log(level,msg);
+      if (level >= SPError)
           LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
   }
-  virtual string getCookies() const {
+  string getHeader(const char* name) const {
+    string hdr("HTTP_");
+    for (; *name; ++name) {
+        if (*name=='-')
+            hdr += '_';
+        else
+            hdr += toupper(*name);
+    }
     dynabuf buf(128);
-    GetServerVariable(m_lpECB, "HTTP_COOKIE", buf, 128, false);
+    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
     return buf.empty() ? "" : buf;
   }
-  virtual void setCookie(const string &name, const string &value) {
-    // Set the cookie for later.  Use it during the redirect.
-    m_cookie += "Set-Cookie: " + name + "=" + value + "\r\n";
+  void setResponseHeader(const char* name, const char* value) {
+    // Set for later.
+    if (value)
+        m_headers[name] = value;
+    else
+        m_headers.erase(name);
   }
-  virtual const char* getQueryString() const {
+  const char* getQueryString() const {
     return m_lpECB->lpszQueryString;
   }
-  virtual const char* getRequestBody() const {
+  const char* getRequestBody() const {
     if (m_gotBody)
         return m_body.c_str();
     if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
-        throw saml::SAMLException("Size of POST request body exceeded limit.");
+        throw opensaml::BindingException("Size of POST request body exceeded limit.");
     else if (m_lpECB->cbTotalBytes != m_lpECB->cbAvailable) {
       m_gotBody=true;
       char buf[8192];
@@ -696,56 +751,63 @@ public:
     }
     return m_body.c_str();
   }
-  virtual void* sendPage(
-    const string &msg,
-    int code=200,
-    const string& content_type="text/html",
-    const saml::Iterator<header_t>& headers=EMPTY(header_t)) {
-    string hdr = string ("Connection: close\r\nContent-type: ") + content_type + "\r\n";
-    for (unsigned int k = 0; k < headers.size(); k++) {
-      hdr += headers[k].first + ": " + headers[k].second + "\r\n";
-    }
+  long sendResponse(istream& in, long status) {
+    string hdr = string("Connection: close\r\n");
+    for (map<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
     hdr += "\r\n";
     const char* codestr="200 OK";
-    switch (code) {
-        case 403:   codestr="403 Forbidden"; break;
-        case 404:   codestr="404 Not Found"; break;
-        case 500:   codestr="500 Server Error"; break;
+    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;
     }
     m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());
-    DWORD resplen = msg.size();
-    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)msg.c_str(), &resplen, HSE_IO_SYNC);
-    return (void*)HSE_STATUS_SUCCESS;
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        DWORD resplen = in.gcount();
+        m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);
+    }
+    return HSE_STATUS_SUCCESS;
   }
-  virtual void* sendRedirect(const string& url) {
-    // XXX: Don't support the httpRedirect option, yet.
-    string hdrs = m_cookie + "Location: " + url + "\r\n"
+  long sendRedirect(const char* url) {
+    string hdr=string("Location: ") + url + "\r\n"
       "Content-Type: text/html\r\n"
       "Content-Length: 40\r\n"
       "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
-      "Cache-Control: private,no-store,no-cache\r\n\r\n";
-    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
-                                "302 Moved", 0, (LPDWORD)hdrs.c_str());
+      "Cache-Control: private,no-store,no-cache\r\n";
+    for (map<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+        hdr += i->first + ": " + i->second + "\r\n";
+    hdr += "\r\n";
+    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());
     static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
     DWORD resplen=40;
     m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
-    return (void*)HSE_STATUS_SUCCESS;
+    return HSE_STATUS_SUCCESS;
   }
   // Decline happens in the POST processor if this isn't the shire url
   // Note that it can also happen with HTAccess, but we don't support that, yet.
-  virtual void* returnDecline(void) {
-    return (void*)
-      WriteClientError(m_lpECB, "ISAPI extension can only be invoked to process Shibboleth protocol requests."
-                      "Make sure the mapped file extension doesn't match actual content.");
+  long returnDecline() {
+    return WriteClientError(
+        m_lpECB,
+        "ISAPI extension can only be invoked to process Shibboleth protocol requests."
+               "Make sure the mapped file extension doesn't match actual content."
+        );
+  }
+  long returnOK() {
+      return HSE_STATUS_SUCCESS;
+  }
+
+  const vector<XSECCryptoX509*>& getClientCertificates() const {
+      return m_certs;
   }
-  virtual void* returnOK(void) { return (void*) HSE_STATUS_SUCCESS; }
 
   // Not used in the extension.
-  virtual void clearHeader(const string &name) { throw runtime_error("clearHeader not implemented"); }
-  virtual void setHeader(const string &name, const string &value) { throw runtime_error("setHeader not implemented"); }
-  virtual string getHeader(const string &name) { throw runtime_error("getHeader not implemented"); }
-  virtual void setRemoteUser(const string &user) { throw runtime_error("setRemoteUser not implemented"); }
-  virtual string getRemoteUser(void) { throw runtime_error("getRemoteUser not implemented"); }
+  virtual void clearHeader(const char* name) { throw runtime_error("clearHeader not implemented"); }
+  virtual void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }
+  virtual void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }
+  virtual string getRemoteUser() const { throw runtime_error("getRemoteUser not implemented"); }
 };
 
 extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
@@ -755,7 +817,7 @@ extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
     try {
         ostringstream threadid;
         threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
-        saml::NDC ndc(threadid.str().c_str());
+        xmltooling::NDC ndc(threadid.str().c_str());
 
         // Determine web site number. This can't really fail, I don't think.
         dynabuf buf(128);
@@ -767,8 +829,8 @@ extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
             return WriteClientError(lpECB, "Shibboleth Extension not configured for this web site.");
 
         ShibTargetIsapiE ste(lpECB, map_i->second);
-        pair<bool,void*> res = ste.doHandler();
-        if (res.first) return (DWORD)res.second;
+        pair<bool,long> res = ste.doHandler();
+        if (res.first) return res.second;
         
         return WriteClientError(lpECB, "Shibboleth Extension failed to process request");
 
@@ -782,7 +844,7 @@ extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
         else
             return WriteClientError(lpECB,"Server detected unexpected IIS error.");
     }
-    catch (saml::SAMLException& e) {
+    catch (exception& e) {
         LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
         return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
     }
index 9b44df1..991149c 100644 (file)
  * limitations under the License.
  */
 
-/* nsapi_shib.cpp - Shibboleth NSAPI filter
-
-   Scott Cantor
-   12/13/04
-*/
+/**
+ * nsapi_shib.cpp
+ * 
+ * Shibboleth NSAPI filter
+ */
 
 #if defined (_MSC_VER) || defined(__BORLANDC__)
 # include "config_win32.h"
@@ -31,7 +31,9 @@
 # define _CRT_SECURE_NO_DEPRECATE 1
 #endif
 
+#include <shibsp/RequestMapper.h>
 #include <shibsp/SPConfig.h>
+#include <xmltooling/util/NDC.h>
 #include <xmltooling/util/Threads.h>
 
 // SAML Runtime
 #include <shib/shib.h>
 #include <shib-target/shib-target.h>
 
-#include <ctime>
 #include <fstream>
 #include <sstream>
-#include <stdexcept>
 
 #ifdef WIN32
 # include <process.h>
@@ -61,7 +61,6 @@ extern "C"
 
 using namespace shibsp;
 using namespace shibtarget;
-using namespace saml;
 using namespace xmltooling;
 using namespace std;
 
@@ -73,9 +72,10 @@ namespace {
     ShibTargetConfig* g_Config=NULL;
     string g_ServerName;
     string g_ServerScheme;
+    string g_unsetHeaderValue;
 }
 
-PlugManager::Factory SunRequestMapFactory;
+PluginManager<RequestMapper,const DOMElement*>::Factory SunRequestMapFactory;
 
 extern "C" NSAPI_PUBLIC void nsapi_shib_exit(void*)
 {
@@ -131,7 +131,7 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, Session* sn, Request* rq
             SPConfig::Caching |
             SPConfig::Metadata |
             SPConfig::AAP |
-            SPConfig::RequestMapper |
+            SPConfig::RequestMapping |
             SPConfig::InProcess |
             SPConfig::Logging
             );
@@ -141,9 +141,7 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, Session* sn, Request* rq
             return REQ_ABORTED;
         }
 
-        SAMLConfig::getConfig().getPlugMgr().regFactory(NATIVE_REQUESTMAP_PROVIDER,&SunRequestMapFactory);
-        // We hijack the legacy type so that 1.2 config files will load this plugin
-        SAMLConfig::getConfig().getPlugMgr().regFactory(LEGACY_REQUESTMAP_PROVIDER,&SunRequestMapFactory);
+        SPConfig::getConfig().RequestMapperManager.registerFactory(XML_REQUEST_MAPPER,&SunRequestMapFactory);
 
         if (!g_Config->load(config)) {
             g_Config=NULL;
@@ -152,6 +150,15 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, Session* sn, Request* rq
         }
 
         daemon_atrestart(nsapi_shib_exit,NULL);
+
+        IConfig* conf=g_Config->getINI();
+        Locker locker(conf);
+        const PropertySet* props=conf->getPropertySet("Local");
+        if (props) {
+            pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+            if (unsetValue.first)
+                g_unsetHeaderValue = unsetValue.second;
+        }
 #ifndef _DEBUG
     }
     catch (...) {
@@ -168,8 +175,10 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, Session* sn, Request* rq
 
 class ShibTargetNSAPI : public ShibTarget
 {
-    mutable string m_body;
-    mutable bool m_gotBody;
+  mutable string m_body;
+  mutable bool m_gotBody;
+  vector<XSECCryptoX509*> m_certs;
+
 public:
   ShibTargetNSAPI(pblock* pb, Session* sn, Request* rq) : m_gotBody(false) {
     m_pb = pb;
@@ -210,31 +219,60 @@ public:
   }
   ~ShibTargetNSAPI() {}
 
-  virtual void log(ShibLogLevel level, const string &msg) {
-    ShibTarget::log(level,msg);
-    if (level==LogLevelError)
-        log_error(LOG_FAILURE, "nsapi_shib", m_sn, m_rq, const_cast<char*>(msg.c_str()));
+  const char* getScheme() const {
+    return security_active ? "https" : "http";
+  }
+  const char* getHostname() const {
+#ifdef vs_is_default_vs
+    // This is 6.0 or later, so we can distinguish requests to name-based vhosts.
+    if (!vs_is_default_vs)
+        // The beauty here is, a non-default vhost can *only* be accessed if the client
+        // specified the exact name in the Host header. So we can trust the Host header.
+        return pblock_findval("host", m_rq->headers);
+    else
+#endif
+    // In other cases, we're going to rely on the initialization process...
+    return g_ServerName.c_str();
+  }
+  int getPort() const {
+    return server_portnum;
+  }
+  const char* getRequestURI() const {
+    return m_uri.c_str();
   }
-  virtual string getCookies(void) const {
-    char *cookies = NULL;
-    if (request_header("cookie", &cookies, m_sn, m_rq) == REQ_ABORTED)
-      throw("error accessing cookie header");
-    return string(cookies ? cookies : "");
+  const char* getMethod() const {
+    return pblock_findval("method", m_rq->reqpb);
   }
-  virtual void setCookie(const string &name, const string &value) {
-    string cookie = name + '=' + value;
-    pblock_nvinsert("Set-Cookie", cookie.c_str(), m_rq->srvhdrs);
+  string getContentType() const {
+    char* content_type = "";
+    request_header("content-type", &content_type, m_sn, m_rq);
+    return content_type;
+  }
+  long getContentLength() const {
+    if (m_gotBody)
+        return m_body.length();
+    char* content_length="";
+    request_header("content-length", &content_length, m_sn, m_rq);
+    return atoi(content_length);
   }
-  virtual const char* getQueryString() const { 
+  string getRemoteAddr() const {
+    return pblock_findval("ip", m_sn->client);
+  }
+  void log(SPLogLevel level, const string& msg) {
+    AbstractSPRequest::log(level,msg);
+    if (level>=SPError)
+        log_error(LOG_FAILURE, "nsapi_shib", m_sn, m_rq, const_cast<char*>(msg.c_str()));
+  }
+  const char* getQueryString() const { 
     return pblock_findval("query", m_rq->reqpb);
   }
-  virtual const char* getRequestBody() const {
+  const char* getRequestBody() const {
     if (m_gotBody)
         return m_body.c_str();
     char* content_length=NULL;
     if (request_header("content-length", &content_length, m_sn, m_rq)!=REQ_PROCEED ||
          atoi(content_length) > 1024*1024) // 1MB?
-      throw SAMLException("Blocked POST request body exceeding size limit.");
+      throw opensaml::BindingException("Blocked POST request body exceeding size limit.");
     else {
       char ch=IO_EOF+1;
       int cl=atoi(content_length);
@@ -248,67 +286,70 @@ public:
         cl--;
       }
       if (cl)
-        throw SAMLException("Error reading POST request body from browser.");
+        throw opensaml::BindingException("Error reading POST request body from browser.");
       return m_body.c_str();
     }
   }
-  virtual void clearHeader(const string &name) {
-    if (name=="REMOTE_USER") {
+  void clearHeader(const char* name) {
+    if (!strcmp(name,"REMOTE_USER")) {
         param_free(pblock_remove("auth-user",m_rq->vars));
         param_free(pblock_remove("remote-user",m_rq->headers));
     }
-    else
-        param_free(pblock_remove(name.c_str(), m_rq->headers));
+    else {
+        param_free(pblock_remove(name, m_rq->headers));
+        pblock_nvinsert(name, g_unsetHeaderValue.c_str() ,m_rq->headers);
+    }
   }
-  virtual void setHeader(const string &name, const string &value) {
-    pblock_nvinsert(name.c_str(), value.c_str() ,m_rq->headers);
+  void setHeader(const char* name, const char* value) {
+    pblock_nvinsert(name, value, m_rq->headers);
   }
-  virtual string getHeader(const string &name) {
-    char *hdr = NULL;
-    if (request_header(const_cast<char*>(name.c_str()), &hdr, m_sn, m_rq) != REQ_PROCEED)
+  string getHeader(const char* name) const {
+    charhdr = NULL;
+    if (request_header(const_cast<char*>(name), &hdr, m_sn, m_rq) != REQ_PROCEED)
       hdr = NULL;
     return string(hdr ? hdr : "");
   }
-  virtual void setRemoteUser(const string &user) {
-    pblock_nvinsert("remote-user", user.c_str(), m_rq->headers);
-    pblock_nvinsert("auth-user", user.c_str(), m_rq->vars);
+  void setRemoteUser(const char* user) {
+    pblock_nvinsert("remote-user", user, m_rq->headers);
+    pblock_nvinsert("auth-user", user, m_rq->vars);
   }
-  virtual string getRemoteUser(void) {
+  string getRemoteUser() const {
     return getHeader("remote-user");
   }
+  void setResponseHeader(const char* name, const char* value) {
+    pblock_nvinsert(name, value, m_rq->srvhdrs);
+  }
 
-  virtual void* sendPage(
-    const string& msg,
-    int code=200,
-    const string& content_type="text/html",
-    const saml::Iterator<header_t>& headers=EMPTY(header_t)
-    ) {
-    param_free(pblock_remove("content-type", m_rq->srvhdrs));
-    pblock_nvinsert("content-type", content_type.c_str(), m_rq->srvhdrs);
-    pblock_nninsert("content-length", msg.length(), m_rq->srvhdrs);
-    pblock_nvinsert("connection","close",m_rq->srvhdrs);
-    while (headers.hasNext()) {
-        const header_t& h=headers.next();
-        pblock_nvinsert(h.first.c_str(), h.second.c_str(), m_rq->srvhdrs);
+  long sendResponse(istream& in, long status) {
+    string msg;
+    char buf[1024];
+    while (in) {
+        in.read(buf,1024);
+        msg.append(buf,in.gcount());
     }
-    protocol_status(m_sn, m_rq, code, NULL);
+    pblock_nvinsert("connection","close",m_rq->srvhdrs);
+    pblock_nninsert("content-length", msg.length(), m_rq->srvhdrs);
+    protocol_status(m_sn, m_rq, status, NULL);
     protocol_start_response(m_sn, m_rq);
     net_write(m_sn->csd,const_cast<char*>(msg.c_str()),msg.length());
-    return (void*)REQ_EXIT;
+    return REQ_EXIT;
   }
-  virtual void* sendRedirect(const string& url) {
+  long sendRedirect(const char* url) {
     param_free(pblock_remove("content-type", m_rq->srvhdrs));
     pblock_nninsert("content-length", 0, m_rq->srvhdrs);
     pblock_nvinsert("expires", "01-Jan-1997 12:00:00 GMT", m_rq->srvhdrs);
     pblock_nvinsert("cache-control", "private,no-store,no-cache", m_rq->srvhdrs);
-    pblock_nvinsert("location", url.c_str(), m_rq->srvhdrs);
+    pblock_nvinsert("location", url, m_rq->srvhdrs);
     pblock_nvinsert("connection","close",m_rq->srvhdrs);
     protocol_status(m_sn, m_rq, PROTOCOL_REDIRECT, NULL);
     protocol_start_response(m_sn, m_rq);
-    return (void*)REQ_ABORTED;
+    return REQ_ABORTED;
+  }
+  long returnDecline() { return REQ_NOACTION; }
+  long returnOK() { return REQ_PROCEED; }
+  const vector<XSECCryptoX509*>& getClientCertificates() const {
+      return m_certs;
   }
-  virtual void* returnDecline(void) { return (void*)REQ_NOACTION; }
-  virtual void* returnOK(void) { return (void*)REQ_PROCEED; }
 
   pblock* m_pb;
   Session* m_sn;
@@ -330,13 +371,13 @@ extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, Session* sn, Request* rq)
 {
   ostringstream threadid;
   threadid << "[" << getpid() << "] nsapi_shib" << '\0';
-  saml::NDC ndc(threadid.str().c_str());
+  xmltooling::NDC ndc(threadid.str().c_str());
 
   try {
     ShibTargetNSAPI stn(pb, sn, rq);
 
     // Check user authentication
-    pair<bool,void*> res = stn.doCheckAuthN();
+    pair<bool,long> res = stn.doCheckAuthN();
     if (res.first) return (int)res.second;
 
     // user authN was okay -- export the assertions now
@@ -354,13 +395,13 @@ extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, Session* sn, Request* rq)
     // this user is ok.
     return REQ_PROCEED;
   }
-  catch (SAMLException& e) {
+  catch (exception& e) {
     log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>(e.what()));
-    return WriteClientError(sn, rq, FUNC, "Shibboleth filter threw an exception, see web server log for error.");
+    return WriteClientError(sn, rq, FUNC, "Shibboleth module threw an exception, see web server log for error.");
   }
 #ifndef _DEBUG
   catch (...) {
-    return WriteClientError(sn, rq, FUNC, "Shibboleth filter threw an uncaught exception.");
+    return WriteClientError(sn, rq, FUNC, "Shibboleth module threw an uncaught exception.");
   }
 #endif
 }
@@ -372,17 +413,17 @@ extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, Session* sn, Request* rq)
 {
   ostringstream threadid;
   threadid << "[" << getpid() << "] shib_handler" << '\0';
-  saml::NDC ndc(threadid.str().c_str());
+  xmltooling::NDC ndc(threadid.str().c_str());
 
   try {
     ShibTargetNSAPI stn(pb, sn, rq);
 
-    pair<bool,void*> res = stn.doHandler();
+    pair<bool,long> res = stn.doHandler();
     if (res.first) return (int)res.second;
 
     return WriteClientError(sn, rq, FUNC, "Shibboleth handler did not do anything.");
   }
-  catch (SAMLException& e) {
+  catch (exception& e) {
     log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>(e.what()));
     return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an exception, see web server log for error.");
   }
@@ -394,14 +435,14 @@ extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, Session* sn, Request* rq)
 }
 
 
-class SunRequestMapper : public virtual IRequestMapper, public virtual PropertySet
+class SunRequestMapper : public virtual RequestMapper, public virtual PropertySet
 {
 public:
     SunRequestMapper(const DOMElement* e);
     ~SunRequestMapper() { delete m_mapper; delete m_stKey; delete m_propsKey; }
     Lockable* lock() { return m_mapper->lock(); }
     void unlock() { m_stKey->setData(NULL); m_propsKey->setData(NULL); m_mapper->unlock(); }
-    Settings getSettings(ShibTarget* st) const;
+    Settings getSettings(const SPRequest& request) const;
     
     pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;
     pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;
@@ -412,39 +453,34 @@ public:
     const DOMElement* getElement() const;
 
 private:
-    IRequestMapper* m_mapper;
+    RequestMapper* m_mapper;
     ThreadKey* m_stKey;
     ThreadKey* m_propsKey;
 };
 
-IPlugIn* SunRequestMapFactory(const DOMElement* e)
+RequestMapper* SunRequestMapFactory(const DOMElement* const & e)
 {
     return new SunRequestMapper(e);
 }
 
 SunRequestMapper::SunRequestMapper(const DOMElement* e) : m_mapper(NULL), m_stKey(NULL), m_propsKey(NULL)
 {
-    IPlugIn* p=SAMLConfig::getConfig().getPlugMgr().newPlugin(XML_REQUESTMAP_PROVIDER,e);
-    m_mapper=dynamic_cast<IRequestMapper*>(p);
-    if (!m_mapper) {
-        delete p;
-        throw UnsupportedExtensionException("Embedded request mapper plugin was not of correct type.");
-    }
+    m_mapper = SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e);
     m_stKey=ThreadKey::create(NULL);
     m_propsKey=ThreadKey::create(NULL);
 }
 
-IRequestMapper::Settings SunRequestMapper::getSettings(ShibTarget* st) const
+RequestMapper::Settings SunRequestMapper::getSettings(const SPRequest& request) const
 {
-    Settings s=m_mapper->getSettings(st);
-    m_stKey->setData(dynamic_cast<ShibTargetNSAPI*>(st));
+    Settings s=m_mapper->getSettings(request);
+    m_stKey->setData((void*)dynamic_cast<const ShibTargetNSAPI*>(&request));
     m_propsKey->setData((void*)s.first);
-    return pair<const PropertySet*,IAccessControl*>(this,s.second);
+    return pair<const PropertySet*,AccessControl*>(this,s.second);
 }
 
 pair<bool,bool> SunRequestMapper::getBool(const char* name, const char* ns) const
 {
-    ShibTargetNSAPI* stn=reinterpret_cast<ShibTargetNSAPI*>(m_stKey->getData());
+    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (stn && !ns && name) {
         // Override boolean properties.
@@ -457,7 +493,7 @@ pair<bool,bool> SunRequestMapper::getBool(const char* name, const char* ns) cons
 
 pair<bool,const char*> SunRequestMapper::getString(const char* name, const char* ns) const
 {
-    ShibTargetNSAPI* stn=reinterpret_cast<ShibTargetNSAPI*>(m_stKey->getData());
+    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (stn && !ns && name) {
         // Override string properties.
@@ -480,7 +516,7 @@ pair<bool,const XMLCh*> SunRequestMapper::getXMLString(const char* name, const c
 
 pair<bool,unsigned int> SunRequestMapper::getUnsignedInt(const char* name, const char* ns) const
 {
-    ShibTargetNSAPI* stn=reinterpret_cast<ShibTargetNSAPI*>(m_stKey->getData());
+    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (stn && !ns && name) {
         // Override int properties.
@@ -493,7 +529,7 @@ pair<bool,unsigned int> SunRequestMapper::getUnsignedInt(const char* name, const
 
 pair<bool,int> SunRequestMapper::getInt(const char* name, const char* ns) const
 {
-    ShibTargetNSAPI* stn=reinterpret_cast<ShibTargetNSAPI*>(m_stKey->getData());
+    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
     if (stn && !ns && name) {
         // Override int properties.
index 42dadf5..c224b3c 100644 (file)
@@ -114,7 +114,7 @@ int real_main(int preinit)
             SPConfig::Credentials |
             SPConfig::AAP |
             SPConfig::OutOfProcess |
-            (shar_checkonly ? (SPConfig::InProcess | SPConfig::RequestMapper) : SPConfig::Logging)
+            (shar_checkonly ? (SPConfig::InProcess | SPConfig::RequestMapping) : SPConfig::Logging)
             );
         if (!shar_config)
             shar_config=getenv("SHIBCONFIG");
@@ -258,7 +258,7 @@ int main(int argc, char *argv[])
         SPConfig::Credentials |
         SPConfig::AAP |
         SPConfig::OutOfProcess |
-        (shar_checkonly ? (SPConfig::InProcess | SPConfig::RequestMapper) : SPConfig::Logging)
+        (shar_checkonly ? (SPConfig::InProcess | SPConfig::RequestMapping) : SPConfig::Logging)
         );
     if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
         fprintf(stderr, "configuration is invalid, check console for specific problems\n");
index 4da6550..0206667 100644 (file)
@@ -18,8 +18,7 @@ libshib_target_la_SOURCES = \
        shib-config.cpp \
        shib-handlers.cpp \
        shib-ini.cpp \
-       shib-target.cpp \
-       XMLRequestMapper.cpp
+       shib-target.cpp
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
index 2dcbe4a..6fa7945 100644 (file)
@@ -41,7 +41,7 @@
 # include "config.h"
 #endif
 
-#include <shibsp/SPConstants.h>
+#include <shibsp/util/SPConstants.h>
 
 #include "shib-target.h"
 #include "hresult.h"
index ab4eb3f..925a069 100644 (file)
@@ -1157,7 +1157,7 @@ DDF MemorySessionCache::receive(const DDF& in)
     // Find application.
     xmltooling::Locker confLocker(ShibTargetConfig::getConfig().getINI());
     const char* aid=in["application_id"].string();
-    const IApplication* app=aid ? ShibTargetConfig::getConfig().getINI()->getApplication(aid) : NULL;
+    const IApplication* app=aid ? dynamic_cast<const IApplication*>(ShibTargetConfig::getConfig().getINI()->getApplication(aid)) : NULL;
     if (!app) {
         // Something's horribly wrong.
         m_log->error("couldn't find application (%s) for session", aid ? aid : "(missing)");
@@ -1318,7 +1318,7 @@ ISessionCacheEntry* MemorySessionCache::find(const char* key, const IApplication
             m_log->error("cache store returned failure during search");
             return NULL;
         }
-        const IApplication* eapp=ShibTargetConfig::getConfig().getINI()->getApplication(appid.c_str());
+        const IApplication* eapp=dynamic_cast<const IApplication*>(ShibTargetConfig::getConfig().getINI()->getApplication(appid.c_str()));
         if (!eapp) {
             // Something's horribly wrong.
             m_log->error("couldn't find application (%s) for session", appid.c_str());
index bb913b3..5be3052 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "internal.h"
 #include <shibsp/SPConfig.h>
-#include <shibsp/SPConstants.h>
 #include <xmltooling/XMLToolingConfig.h>
 
 #include <log4cpp/OstreamAppender.hh>
@@ -51,7 +50,6 @@ PlugManager::Factory UnixListenerFactory;
 PlugManager::Factory TCPListenerFactory;
 //PlugManager::Factory MemoryListenerFactory;
 PlugManager::Factory MemoryCacheFactory;
-PlugManager::Factory XMLRequestMapFactory;
 PlugManager::Factory ShibSessionInitiatorFactory;
 PlugManager::Factory SAML1POSTFactory;
 PlugManager::Factory SAML1ArtifactFactory;
@@ -103,9 +101,6 @@ bool STConfig::init(const char* schemadir)
     SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory);
 
     samlConf.getPlugMgr().regFactory(MEMORY_SESSIONCACHE,&MemoryCacheFactory);
-    samlConf.getPlugMgr().regFactory(LEGACY_REQUESTMAP_PROVIDER,&XMLRequestMapFactory);
-    samlConf.getPlugMgr().regFactory(XML_REQUESTMAP_PROVIDER,&XMLRequestMapFactory);
-    samlConf.getPlugMgr().regFactory(NATIVE_REQUESTMAP_PROVIDER,&XMLRequestMapFactory);
     
     auto_ptr_char temp1(shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI);
     samlConf.getPlugMgr().regFactory(temp1.get(),&ShibSessionInitiatorFactory);
index 313b0b5..272dd4d 100644 (file)
@@ -30,7 +30,6 @@
 #include <saml/saml2/metadata/EndpointManager.h>
 #include <saml/util/CommonDomainCookie.h>
 #include <shibsp/SPConfig.h>
-#include <shibsp/SPConstants.h>
 
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
@@ -53,8 +52,8 @@ namespace {
   public:
     SessionInitiator(const DOMElement* e) {}
     ~SessionInitiator() {}
-    pair<bool,void*> run(ShibTarget* st, bool isHandler=true) const;
-    pair<bool,void*> ShibAuthnRequest(
+    pair<bool,long> run(ShibTarget* st, bool isHandler=true) const;
+    pair<bool,long> ShibAuthnRequest(
         ShibTarget* st,
         const IHandler* shire,
         const char* dest,
@@ -68,7 +67,7 @@ namespace {
   public:
     SAML1Consumer(const DOMElement* e);
     ~SAML1Consumer();
-    pair<bool,void*> run(ShibTarget* st, bool isHandler=true) const;
+    pair<bool,long> run(ShibTarget* st, bool isHandler=true) const;
     DDF receive(const DDF& in);
   private:
     string m_address;
@@ -82,7 +81,7 @@ namespace {
   public:
     ShibLogout(const DOMElement* e) {}
     ~ShibLogout() {}
-    pair<bool,void*> run(ShibTarget* st, bool isHandler=true) const;
+    pair<bool,long> run(ShibTarget* st, bool isHandler=true) const;
   };
 }
 
@@ -107,7 +106,7 @@ IPlugIn* ShibLogoutFactory(const DOMElement* e)
     return new ShibLogout(e);
 }
 
-pair<bool,void*> SessionInitiator::run(ShibTarget* st, bool isHandler) const
+pair<bool,long> SessionInitiator::run(ShibTarget* st, bool isHandler) const
 {
     string dupresource;
     const char* resource=NULL;
@@ -121,12 +120,12 @@ pair<bool,void*> SessionInitiator::run(ShibTarget* st, bool isHandler) const
          *  acsIndex    optional index of an ACS to use on the way back in
          *  providerId  optional direct invocation of a specific IdP
          */
-        const char* option=st->getRequestParameter("acsIndex");
+        const char* option=st->getParameter("acsIndex");
         if (option)
             ACS=app->getAssertionConsumerServiceByIndex(atoi(option));
-        option=st->getRequestParameter("providerId");
+        option=st->getParameter("providerId");
         
-        resource=st->getRequestParameter("target");
+        resource=st->getParameter("target");
         if (!resource || !*resource) {
             pair<bool,const char*> home=app->getString("homeURL");
             if (home.first)
@@ -191,8 +190,9 @@ pair<bool,void*> SessionInitiator::run(ShibTarget* st, bool isHandler) const
             throw ConfigurationException("E-Authn requests cannot include relay state, so localRelayState must be enabled.");
 
         // Here we store the state in a cookie.
-        pair<string,const char*> shib_cookie=st->getCookieNameProps("_shibstate_");
-        st->setCookie(shib_cookie.first,opensaml::SAMLConfig::getConfig().getURLEncoder()->encode(resource) + shib_cookie.second);
+        pair<string,const char*> shib_cookie=app->getCookieNameProps("_shibstate_");
+        string stateval = opensaml::SAMLConfig::getConfig().getURLEncoder()->encode(resource) + shib_cookie.second;
+            st->setCookie(shib_cookie.first.c_str(),stateval.c_str());
         return make_pair(true, st->sendRedirect(wayfURL.second));
     }
    
@@ -200,7 +200,7 @@ pair<bool,void*> SessionInitiator::run(ShibTarget* st, bool isHandler) const
 }
 
 // Handles Shib 1.x AuthnRequest profile.
-pair<bool,void*> SessionInitiator::ShibAuthnRequest(
+pair<bool,long> SessionInitiator::ShibAuthnRequest(
     ShibTarget* st,
     const IHandler* shire,
     const char* dest,
@@ -229,8 +229,9 @@ pair<bool,void*> SessionInitiator::ShibAuthnRequest(
     else {
         // Here we store the state in a cookie and send a fixed
         // value to the IdP so we can recognize it on the way back.
-        pair<string,const char*> shib_cookie=st->getCookieNameProps("_shibstate_");
-        st->setCookie(shib_cookie.first,urlenc->encode(target) + shib_cookie.second);
+        pair<string,const char*> shib_cookie=st->getApplication()->getCookieNameProps("_shibstate_");
+        string stateval = urlenc->encode(target) + shib_cookie.second;
+        st->setCookie(shib_cookie.first.c_str(),stateval.c_str());
         req+="&target=cookie";
     }
     
@@ -238,7 +239,7 @@ pair<bool,void*> SessionInitiator::ShibAuthnRequest(
     if (providerId)
         req+="&providerId=" + urlenc->encode(providerId);
 
-    return make_pair(true, st->sendRedirect(req));
+    return make_pair(true, st->sendRedirect(req.c_str()));
 }
 
 SAML1Consumer::SAML1Consumer(const DOMElement* e)
@@ -283,7 +284,7 @@ DDF SAML1Consumer::receive(const DDF& in)
 
     // Find application.
     const char* aid=in["application_id"].string();
-    const IApplication* app=aid ? ShibTargetConfig::getConfig().getINI()->getApplication(aid) : NULL;
+    const IApplication* app=aid ? dynamic_cast<const IApplication*>(ShibTargetConfig::getConfig().getINI()->getApplication(aid)) : NULL;
     if (!app) {
         // Something's horribly wrong.
         log.error("couldn't find application (%s) for new session", aid ? aid : "(missing)");
@@ -441,7 +442,7 @@ DDF SAML1Consumer::receive(const DDF& in)
     return out;
 }
 
-pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
+pair<bool,long> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
 {
     DDF in,out;
     DDFJanitor jin(in),jout(out);
@@ -449,26 +450,26 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
     pair<bool,const XMLCh*> binding=getProperties()->getXMLString("Binding");
     if (!binding.first || !XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_POST)) {
 #ifdef HAVE_STRCASECMP
-        if (strcasecmp(st->getRequestMethod(), "POST")) {
+        if (strcasecmp(st->getMethod(), "POST")) {
 #else
-        if (_stricmp(st->getRequestMethod(), "POST")) {
+        if (_stricmp(st->getMethod(), "POST")) {
 #endif
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/POST handler ignoring non-POST request");
-            return pair<bool,void*>(false,NULL);
+            st->log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring non-POST request");
+            return pair<bool,long>(false,NULL);
         }
 #ifdef HAVE_STRCASECMP
-        if (!st->getContentType() || strcasecmp(st->getContentType(),"application/x-www-form-urlencoded")) {
+        if (strcasecmp(st->getContentType().c_str(),"application/x-www-form-urlencoded")) {
 #else
-        if (!st->getContentType() || _stricmp(st->getContentType(),"application/x-www-form-urlencoded")) {
+        if (_stricmp(st->getContentType().c_str(),"application/x-www-form-urlencoded")) {
 #endif
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/POST handler ignoring submission with unknown content-type.");
-            return pair<bool,void*>(false,NULL);
+            st->log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring submission with unknown content-type.");
+            return pair<bool,long>(false,0);
         }
 
-        const char* samlResponse = st->getRequestParameter("SAMLResponse");
+        const char* samlResponse = st->getParameter("SAMLResponse");
         if (!samlResponse) {
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter.");
-            return pair<bool,void*>(false,NULL);
+            st->log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter.");
+            return pair<bool,long>(false,0);
         }
 
         in=DDF(m_address.c_str()).structure();
@@ -476,27 +477,25 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
     }
     else if (!XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_ARTIFACT)) {
 #ifdef HAVE_STRCASECMP
-        if (strcasecmp(st->getRequestMethod(), "GET")) {
+        if (strcasecmp(st->getMethod(), "GET")) {
 #else
-        if (_stricmp(st->getRequestMethod(), "GET")) {
+        if (_stricmp(st->getMethod(), "GET")) {
 #endif
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request");
-            return pair<bool,void*>(false,NULL);
+            st->log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request");
+            return pair<bool,long>(false,0);
         }
 
-        const char* SAMLart=st->getRequestParameter("SAMLart");
-        if (!SAMLart) {
-            st->log(ShibTarget::LogLevelInfo, "SAML 1.x Browser/Artifact handler ignoring request with no SAMLart parameter.");
-            return pair<bool,void*>(false,NULL);
+        vector<const char*> arts;
+        if (st->getParameters("SAMLart",arts)==0) {
+            st->log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring request with no SAMLart parameter.");
+            return pair<bool,long>(false,0);
         }
 
         in=DDF(m_address.c_str()).structure();
         DDF artlist=in.addmember("SAMLart").list();
 
-        while (SAMLart) {
-            artlist.add(DDF(NULL).string(SAMLart));
-            SAMLart=st->getRequestParameter("SAMLart",artlist.integer());
-        }
+        for (vector<const char*>::const_iterator a=arts.begin(); a!=arts.end(); ++a)
+            artlist.add(DDF(NULL).string(*a));
     }
     
     // Compute the endpoint location.
@@ -507,24 +506,24 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
 
     // Add remaining parameters.
     in.addmember("application_id").string(st->getApplication()->getId());
-    in.addmember("client_address").string(st->getRemoteAddr());
+    in.addmember("client_address").string(st->getRemoteAddr().c_str());
 
     out=st->getConfig()->getListenerService()->send(in);
     if (!out["key"].isstring())
         throw opensaml::FatalProfileException("Remote processing of SAML 1.x Browser profile did not return a usable session key.");
     string key=out["key"].string();
 
-    st->log(ShibTarget::LogLevelDebug, string("profile processing succeeded, new session created (") + key + ")");
+    st->log(SPRequest::SPDebug, string("profile processing succeeded, new session created (") + key + ")");
 
-    const char* target=st->getRequestParameter("TARGET");
+    const char* target=st->getParameter("TARGET");
     if (target && !strcmp(target,"default")) {
         pair<bool,const char*> homeURL=st->getApplication()->getString("homeURL");
         target=homeURL.first ? homeURL.second : "/";
     }
     else if (!target || !strcmp(target,"cookie")) {
         // Pull the target value from the "relay state" cookie.
-        pair<string,const char*> relay_cookie = st->getCookieNameProps("_shibstate_");
-        const char* relay_state = st->getCookie(relay_cookie.first);
+        pair<string,const char*> relay_cookie = st->getApplication()->getCookieNameProps("_shibstate_");
+        const char* relay_state = st->getCookie(relay_cookie.first.c_str());
         if (!relay_state || !*relay_state) {
             // No apparent relay state value to use, so fall back on the default.
             pair<bool,const char*> homeURL=st->getApplication()->getString("homeURL");
@@ -537,12 +536,13 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
             free(rscopy);
             target=hURL.c_str();
         }
-        st->setCookie(relay_cookie.first,relay_cookie.second);
+        st->setCookie(relay_cookie.first.c_str(),relay_cookie.second);
     }
 
     // We've got a good session, set the session cookie.
-    pair<string,const char*> shib_cookie=st->getCookieNameProps("_shibsession_");
-    st->setCookie(shib_cookie.first, key + shib_cookie.second);
+    pair<string,const char*> shib_cookie=st->getApplication()->getCookieNameProps("_shibsession_");
+    key += shib_cookie.second;
+    st->setCookie(shib_cookie.first.c_str(), key.c_str());
 
     const char* providerId=out["provider_id"].string();
     if (providerId) {
@@ -554,22 +554,22 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
 
             // Either leave in memory or set an expiration.
             pair<bool,unsigned int> days=sessionProps->getUnsignedInt("idpHistoryDays");
-                if (!days.first || days.second==0)
-                    st->setCookie(CommonDomainCookie::CDCName,string(cdc.set(providerId)) + shib_cookie.second);
-                else {
-                    time_t now=time(NULL) + (days.second * 24 * 60 * 60);
+            if (!days.first || days.second==0) {
+                key = string(cdc.set(providerId)) + shib_cookie.second;
+                st->setCookie(CommonDomainCookie::CDCName, key.c_str());
+            }
+            else {
+                time_t now=time(NULL) + (days.second * 24 * 60 * 60);
 #ifdef HAVE_GMTIME_R
-                    struct tm res;
-                    struct tm* ptime=gmtime_r(&now,&res);
+                struct tm res;
+                struct tm* ptime=gmtime_r(&now,&res);
 #else
-                    struct tm* ptime=gmtime(&now);
+                struct tm* ptime=gmtime(&now);
 #endif
-                    char timebuf[64];
-                    strftime(timebuf,64,"%a, %d %b %Y %H:%M:%S GMT",ptime);
-                    st->setCookie(
-                        CommonDomainCookie::CDCName,
-                        string(cdc.set(providerId)) + shib_cookie.second + "; expires=" + timebuf
-                        );
+                char timebuf[64];
+                strftime(timebuf,64,"%a, %d %b %Y %H:%M:%S GMT",ptime);
+                key = string(cdc.set(providerId)) + shib_cookie.second + "; expires=" + timebuf;
+                st->setCookie(CommonDomainCookie::CDCName, key.c_str());
             }
         }
     }
@@ -578,30 +578,30 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, bool isHandler) const
     return make_pair(true, st->sendRedirect(target));
 }
 
-pair<bool,void*> ShibLogout::run(ShibTarget* st, bool isHandler) const
+pair<bool,long> ShibLogout::run(ShibTarget* st, bool isHandler) const
 {
     // Recover the session key.
-    pair<string,const char*> shib_cookie = st->getCookieNameProps("_shibsession_");
-    const char* session_id = st->getCookie(shib_cookie.first);
+    pair<string,const char*> shib_cookie = st->getApplication()->getCookieNameProps("_shibsession_");
+    const char* session_id = st->getCookie(shib_cookie.first.c_str());
     
     // Logout is best effort.
     if (session_id && *session_id) {
         try {
-            st->getConfig()->getSessionCache()->remove(session_id,st->getApplication(),st->getRemoteAddr());
+            st->getConfig()->getSessionCache()->remove(session_id,st->getApplication(),st->getRemoteAddr().c_str());
         }
         catch (exception& e) {
-            st->log(ShibTarget::LogLevelError, string("logout processing failed with exception: ") + e.what());
+            st->log(SPRequest::SPError, string("logout processing failed with exception: ") + e.what());
         }
 #ifndef _DEBUG
         catch (...) {
-            st->log(ShibTarget::LogLevelError, "logout processing failed with unknown exception");
+            st->log(SPRequest::SPError, "logout processing failed with unknown exception");
         }
 #endif
         // We send the cookie property alone, which acts as an empty value.
-        st->setCookie(shib_cookie.first,shib_cookie.second);
+        st->setCookie(shib_cookie.first.c_str(),shib_cookie.second);
     }
     
-    const char* ret=st->getRequestParameter("return");
+    const char* ret=st->getParameter("return");
     if (!ret)
         ret=getProperties()->getString("ResponseLocation").second;
     if (!ret)
index de4c83a..5d76761 100644 (file)
 #include <sys/stat.h>
 #include <log4cpp/Category.hh>
 #include <log4cpp/PropertyConfigurator.hh>
-#include <shibsp/DOMPropertySet.h>
-#include <shibsp/PKIXTrustEngine.h>
+#include <shibsp/RequestMapper.h>
 #include <shibsp/SPConfig.h>
-#include <shibsp/SPConstants.h>
+#include <shibsp/security/PKIXTrustEngine.h>
+#include <shibsp/util/DOMPropertySet.h>
 #include <saml/SAMLConfig.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml2/metadata/ChainingMetadataProvider.h>
@@ -152,7 +152,7 @@ namespace {
         XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer);
         ~XMLConfigImpl();
         
-        IRequestMapper* m_requestMapper;
+        RequestMapper* m_requestMapper;
         map<string,IApplication*> m_appmap;
         map<string,CredentialResolver*> m_credResolverMap;
         vector<IAttributeFactory*> m_attrFactories;
@@ -212,7 +212,7 @@ namespace {
 
         ISessionCache* getSessionCache() const {return m_sessionCache;}
         IReplayCache* getReplayCache() const {return m_replayCache;}
-        IRequestMapper* getRequestMapper() const {return m_impl->m_requestMapper;}
+        RequestMapper* getRequestMapper() const {return m_impl->m_requestMapper;}
         const IApplication* getApplication(const char* applicationId) const {
             map<string,IApplication*>::const_iterator i=m_impl->m_appmap.find(applicationId);
             return (i!=m_impl->m_appmap.end()) ? i->second : NULL;
@@ -243,7 +243,7 @@ namespace {
 #endif
 
     static const XMLCh AAPProvider[] =          UNICODE_LITERAL_11(A,A,P,P,r,o,v,i,d,e,r);
-    static const XMLCh Application[] =          UNICODE_LITERAL_11(A,p,p,l,i,c,a,t,i,o,n);
+    static const XMLCh _Application[] =         UNICODE_LITERAL_11(A,p,p,l,i,c,a,t,i,o,n);
     static const XMLCh Applications[] =         UNICODE_LITERAL_12(A,p,p,l,i,c,a,t,i,o,n,s);
     static const XMLCh AttributeFactory[] =     UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,F,a,c,t,o,r,y);
     static const XMLCh Credentials[] =          UNICODE_LITERAL_11(C,r,e,d,e,n,t,i,a,l,s);
@@ -618,7 +618,7 @@ short XMLApplication::acceptNode(const DOMNode* node) const
     else if (XMLHelper::isNodeNamed(node,samlconstants::SAML1_NS,Audience::LOCAL_NAME))
         return FILTER_REJECT;
     const XMLCh* name=node->getLocalName();
-    if (XMLString::equals(name,Application) ||
+    if (XMLString::equals(name,_Application) ||
         XMLString::equals(name,AssertionConsumerService::LOCAL_NAME) ||
         XMLString::equals(name,SingleLogoutService::LOCAL_NAME) ||
         XMLString::equals(name,DiagnosticService) ||
@@ -1042,22 +1042,12 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
         } // end of first-time-only stuff
         
         // Back to the fully dynamic stuff...next up is the RequestMapper.
-        if (conf.isEnabled(SPConfig::RequestMapper)) {
+        if (conf.isEnabled(SPConfig::RequestMapping)) {
             child=XMLHelper::getFirstChildElement(SHIRE,RequestMapProvider);
             if (child) {
                 xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type));
                 log.info("building RequestMapper of type %s...",type.get());
-                plugin=shibConf.getPlugMgr().newPlugin(type.get(),child);
-                if (plugin) {
-                    IRequestMapper* reqmap=dynamic_cast<IRequestMapper*>(plugin);
-                    if (reqmap)
-                        m_requestMapper=reqmap;
-                    else {
-                        delete plugin;
-                        log.fatal("plugin was not a RequestMapper object");
-                        throw UnknownExtensionException("plugin was not a RequestMapper object");
-                    }
-                }
+                m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child);
             }
             else {
                 log.fatal("can't build RequestMapper, missing conf:RequestMapProvider element?");
@@ -1145,7 +1135,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
         m_appmap[defapp->getId()]=defapp;
         
         // Load any overrides.
-        child = XMLHelper::getFirstChildElement(child,Application);
+        child = XMLHelper::getFirstChildElement(child,_Application);
         while (child) {
             auto_ptr<XMLApplication> iapp(new XMLApplication(m_outer,child,defapp));
             if (m_appmap.find(iapp->getId())!=m_appmap.end())
@@ -1153,7 +1143,7 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* o
             else
                 m_appmap[iapp->getId()]=iapp.release();
 
-            child = XMLHelper::getNextSiblingElement(child,Application);
+            child = XMLHelper::getNextSiblingElement(child,_Application);
         }
     }
     catch (exception&) {
index ac959d7..4607862 100644 (file)
 # include <unistd.h>
 #endif
 
-#include <ctime>
-#include <sstream>
 #include <fstream>
-#include <stdexcept>
 
 #include <saml/SAMLConfig.h>
-#include <saml/binding/URLEncoder.h>
 #include <xercesc/util/Base64.hpp>
+#include <shibsp/AccessControl.h>
+#include <shibsp/RequestMapper.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/TemplateEngine.h>
 #include <xmltooling/util/XMLHelper.h>
@@ -59,22 +57,6 @@ using xmltooling::XMLToolingConfig;
 using xmltooling::XMLHelper;
 
 namespace shibtarget {
-    class CgiParse
-    {
-    public:
-        CgiParse(const ShibTarget* st);
-        ~CgiParse();
-
-        typedef multimap<string,char*>::const_iterator walker;
-        pair<walker,walker> get_values(const char* name) const;
-        
-    private:
-        char* fmakeword(char stop, unsigned int *cl, const char** ppch);
-        char* makeword(char *line, char stop);
-        void plustospace(char *str);
-
-        multimap<string,char*> kvp_map;
-    };
 
     class ExtTemplateParameters : public TemplateEngine::TemplateParameters
     {
@@ -113,23 +95,20 @@ namespace shibtarget {
 
         // Helper functions
         void get_application(ShibTarget* st, const string& protocol, const string& hostname, int port, const string& uri);
-        void* sendError(ShibTarget* st, const char* page, ExtTemplateParameters& tp, const XMLToolingException* ex=NULL);
+        long sendError(ShibTarget* st, const char* page, ExtTemplateParameters& tp, const XMLToolingException* ex=NULL);
         void clearHeaders(ShibTarget* st);
     
     private:
         friend class ShibTarget;
-        IRequestMapper::Settings m_settings;
+        RequestMapper::Settings m_settings;
         const IApplication *m_app;
-        mutable string m_handlerURL;
-        mutable map<string,string> m_cookieMap;
-        mutable CgiParse* m_cgiParser;
 
         ISessionCacheEntry* m_cacheEntry;
 
         ShibTargetConfig* m_Config;
 
         IConfig* m_conf;
-        IRequestMapper* m_mapper;
+        RequestMapper* m_mapper;
     };
 
     static const XMLCh SessionInitiator[] =     UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
@@ -154,7 +133,7 @@ ShibTarget::~ShibTarget(void)
 }
 
 void ShibTarget::init(
-    const char* protocol,
+    const char* scheme,
     const char* hostname,
     int port,
     const char* uri,
@@ -171,14 +150,15 @@ void ShibTarget::init(
         throw XMLToolingException("Request initialization occurred twice!");
 
     if (method) m_method = method;
-    if (protocol) m_protocol = protocol;
+    if (scheme) m_scheme = scheme;
     if (hostname) m_hostname = hostname;
     if (uri) m_uri = uri;
     if (content_type) m_content_type = content_type;
     if (remote_addr) m_remote_addr = remote_addr;
     m_port = port;
     m_priv->m_Config = &ShibTargetConfig::getConfig();
-    m_priv->get_application(this, protocol, hostname, port, uri);
+    m_priv->get_application(this, scheme, hostname, port, uri);
+    AbstractSPRequest::m_app = m_priv->m_app;
 }
 
 
@@ -186,7 +166,7 @@ void ShibTarget::init(
 // The web server modules implement a subclass and then call into 
 // these methods once they instantiate their request object.
 
-pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
+pair<bool,long> ShibTarget::doCheckAuthN(bool handler)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("doCheckAuthN");
@@ -201,17 +181,17 @@ pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
             throw ConfigurationException("System uninitialized, application did not supply request information.");
 
         // If not SSL, check to see if we should block or redirect it.
-        if (!strcmp("http",getProtocol())) {
+        if (!strcmp("http",getScheme())) {
             pair<bool,const char*> redirectToSSL = m_priv->m_settings.first->getString("redirectToSSL");
             if (redirectToSSL.first) {
-                if (!strcasecmp("GET",getRequestMethod()) || !strcasecmp("HEAD",getRequestMethod())) {
+                if (!strcasecmp("GET",getMethod()) || !strcasecmp("HEAD",getMethod())) {
                     // Compute the new target URL
                     string redirectURL = string("https://") + getHostname();
                     if (strcmp(redirectToSSL.second,"443")) {
                         redirectURL = redirectURL + ':' + redirectToSSL.second;
                     }
                     redirectURL += getRequestURI();
-                    return make_pair(true, sendRedirect(redirectURL));
+                    return make_pair(true, sendRedirect(redirectURL.c_str()));
                 }
                 else {
                     tp.m_map["requestURL"] = m_url.substr(0,m_url.find('?'));
@@ -253,8 +233,8 @@ pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
         // Fix for secadv 20050901
         m_priv->clearHeaders(this);
 
-        pair<string,const char*> shib_cookie = getCookieNameProps("_shibsession_");
-        const char* session_id = getCookie(shib_cookie.first);
+        pair<string,const char*> shib_cookie = m_priv->m_app->getCookieNameProps("_shibsession_");
+        const char* session_id = getCookie(shib_cookie.first.c_str());
         if (!session_id || !*session_id) {
             // No session.  Maybe that's acceptable?
             if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
@@ -292,7 +272,7 @@ pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
                 throw RetryableProfileException("Session no longer valid.");
         }
         catch (exception& e) {
-            log(LogLevelError, string("session processing failed: ") + e.what());
+            log(SPError, string("session processing failed: ") + e.what());
 
             // If no session is required, bail now.
             if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
@@ -329,8 +309,8 @@ pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
 
         // We're done.  Everything is okay.  Nothing to report.  Nothing to do..
         // Let the caller decide how to proceed.
-        log(LogLevelDebug, "doCheckAuthN succeeded");
-        return make_pair(false,(void*)NULL);
+        log(SPDebug, "doCheckAuthN succeeded");
+        return make_pair(false,0);
     }
     catch (XMLToolingException& e) {
         tp.m_map["errorType"] = procState;
@@ -350,7 +330,7 @@ pair<bool,void*> ShibTarget::doCheckAuthN(bool handler)
 #endif
 }
 
-pair<bool,void*> ShibTarget::doHandler(void)
+pair<bool,long> ShibTarget::doHandler(void)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("doHandler");
@@ -381,8 +361,8 @@ pair<bool,void*> ShibTarget::doHandler(void)
         pair<bool,bool> handlerSSL=sessionProps->getBool("handlerSSL");
       
         // Make sure this is SSL, if it should be
-        if ((!handlerSSL.first || handlerSSL.second) && m_protocol != "https")
-            throw opensaml::FatalProfileException("Blocked non-SSL access to Shibboleth handler.");
+        if ((!handlerSSL.first || handlerSSL.second) && m_scheme != "https")
+            throw FatalProfileException("Blocked non-SSL access to Shibboleth handler.");
 
         // We dispatch based on our path info. We know the request URL begins with or equals the handler URL,
         // so the path info is the next character (or null).
@@ -400,7 +380,7 @@ pair<bool,void*> ShibTarget::doHandler(void)
             procState = "Diagnostics Error";
         else
             procState = "Extension Service Error";
-        pair<bool,void*> hret=handler->run(this);
+        pair<bool,long> hret=handler->run(this);
 
         // Did the handler run successfully?
         if (hret.first)
@@ -441,7 +421,7 @@ pair<bool,void*> ShibTarget::doHandler(void)
 #endif
 }
 
-pair<bool,void*> ShibTarget::doCheckAuthZ(void)
+pair<bool,long> ShibTarget::doCheckAuthZ(void)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("doCheckAuthZ");
@@ -476,8 +456,8 @@ pair<bool,void*> ShibTarget::doCheckAuthZ(void)
                
                if (!m_priv->m_cacheEntry) {
                    // No data yet, so we may need to try and get the session.
-                       pair<string,const char*> shib_cookie=getCookieNameProps("_shibsession_");
-                       const char *session_id = getCookie(shib_cookie.first);
+                       pair<string,const char*> shib_cookie=m_priv->m_app->getCookieNameProps("_shibsession_");
+                const char *session_id = getCookie(shib_cookie.first.c_str());
                    try {
                                if (session_id && *session_id) {
                         m_priv->m_cacheEntry=m_priv->m_conf->getSessionCache()->find(
@@ -488,15 +468,16 @@ pair<bool,void*> ShibTarget::doCheckAuthZ(void)
                                }
                    }
                    catch (exception&) {
-                       log(LogLevelError, "doCheckAuthZ: unable to obtain session information to pass to access control provider");
+                       log(SPError, "doCheckAuthZ: unable to obtain session information to pass to access control provider");
                    }
                }
        
             xmltooling::Locker acllock(m_priv->m_settings.second);
+            /* TODO: port
             if (m_priv->m_settings.second->authorized(this,m_priv->m_cacheEntry)) {
                 // Let the caller decide how to proceed.
                 log(LogLevelDebug, "doCheckAuthZ: access control provider granted access");
-                return make_pair(false,(void*)NULL);
+                return make_pair(false,0);
             }
             else {
                 log(LogLevelWarn, "doCheckAuthZ: access control provider denied access");
@@ -504,6 +485,8 @@ pair<bool,void*> ShibTarget::doCheckAuthZ(void)
                     tp.m_map["requestURL"] = targetURL;
                 return make_pair(true,m_priv->sendError(this, "access", tp));
             }
+            */
+            return make_pair(false,0);
         }
         else
             return make_pair(true,returnDecline());
@@ -526,7 +509,7 @@ pair<bool,void*> ShibTarget::doCheckAuthZ(void)
 #endif
 }
 
-pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
+pair<bool,long> ShibTarget::doExportAssertions(bool requireSession)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("doExportAssertions");
@@ -543,8 +526,8 @@ pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
         if (!m_priv->m_cacheEntry) {
             // No data yet, so we need to get the session. This can only happen
             // if the call to doCheckAuthn doesn't happen in the same object lifetime.
-               pair<string,const char*> shib_cookie=getCookieNameProps("_shibsession_");
-               const char *session_id = getCookie(shib_cookie.first);
+               pair<string,const char*> shib_cookie=m_priv->m_app->getCookieNameProps("_shibsession_");
+            const char *session_id = getCookie(shib_cookie.first.c_str());
             try {
                        if (session_id && *session_id) {
                     m_priv->m_cacheEntry=m_priv->m_conf->getSessionCache()->find(
@@ -555,7 +538,7 @@ pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
                        }
             }
             catch (exception&) {
-               log(LogLevelError, "unable to obtain session information to export into request headers");
+               log(SPError, "unable to obtain session information to export into request headers");
                // If we have to have a session, then this is a fatal error.
                if (requireSession)
                        throw;
@@ -567,7 +550,7 @@ pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
                if (requireSession)
                        throw RetryableProfileException("Unable to obtain session information for request.");
                else
-                       return make_pair(false,(void*)NULL);    // just bail silently
+                       return make_pair(false,0);      // just bail silently
         }
         
         // Extract data from session.
@@ -641,10 +624,10 @@ pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
                     
                         Iterator<string> vals=attr->getSingleByteValues();
                         if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())
-                            setRemoteUser(vals.next());
+                            setRemoteUser(vals.next().c_str());
                         else {
                             int it=0;
-                            string header = getHeader(rule->getHeader());
+                            string header = getSecureHeader(rule->getHeader());
                             if (!header.empty())
                                 it++;
                             for (; vals.hasNext(); it++) {
@@ -659,14 +642,14 @@ pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
                                     header += ";";
                                 header += value;
                             }
-                            setHeader(rule->getHeader(), header);
+                            setHeader(rule->getHeader(), header.c_str());
                         }
                     }
                 }
             }
         }
     
-        return make_pair(false,(void*)NULL);
+        return make_pair(false,0);
     }
     catch (XMLToolingException& e) {
         tp.m_map["errorType"] = procState;
@@ -686,162 +669,6 @@ pair<bool,void*> ShibTarget::doExportAssertions(bool requireSession)
 #endif
 }
 
-const char* ShibTarget::getRequestParameter(const char* param, size_t index) const
-{
-    if (!m_priv->m_cgiParser)
-        m_priv->m_cgiParser=new CgiParse(this);
-    
-    pair<CgiParse::walker,CgiParse::walker> bounds=m_priv->m_cgiParser->get_values(param);
-    
-    // Advance to the right index.
-    while (index && bounds.first!=bounds.second) {
-        index--;
-        bounds.first++;
-    }
-
-    return (bounds.first==bounds.second) ? NULL : bounds.first->second;
-}
-
-const char* ShibTarget::getCookie(const string& name) const
-{
-    if (m_priv->m_cookieMap.empty()) {
-        string cookies=getCookies();
-
-        string::size_type pos=0,cname,namelen,val,vallen;
-        while (pos !=string::npos && pos < cookies.length()) {
-            while (isspace(cookies[pos])) pos++;
-            cname=pos;
-            pos=cookies.find_first_of("=",pos);
-            if (pos == string::npos)
-                break;
-            namelen=pos-cname;
-            pos++;
-            if (pos==cookies.length())
-                break;
-            val=pos;
-            pos=cookies.find_first_of(";",pos);
-            if (pos != string::npos) {
-                vallen=pos-val;
-                pos++;
-                m_priv->m_cookieMap.insert(make_pair(cookies.substr(cname,namelen),cookies.substr(val,vallen)));
-            }
-            else
-                m_priv->m_cookieMap.insert(make_pair(cookies.substr(cname,namelen),cookies.substr(val)));
-        }
-    }
-    map<string,string>::const_iterator lookup=m_priv->m_cookieMap.find(name);
-    return (lookup==m_priv->m_cookieMap.end()) ? NULL : lookup->second.c_str();
-}
-
-pair<string,const char*> ShibTarget::getCookieNameProps(const char* prefix) const
-{
-    static const char* defProps="; path=/";
-    
-    const PropertySet* props=m_priv->m_app ? m_priv->m_app->getPropertySet("Sessions") : NULL;
-    if (props) {
-        pair<bool,const char*> p=props->getString("cookieProps");
-        if (!p.first)
-            p.second=defProps;
-        pair<bool,const char*> p2=props->getString("cookieName");
-        if (p2.first)
-            return make_pair(string(prefix) + p2.second,p.second);
-        return make_pair(string(prefix) + m_priv->m_app->getHash(),p.second);
-    }
-    
-    // Shouldn't happen, but just in case..
-    return pair<string,const char*>(prefix,defProps);
-}
-
-string ShibTarget::getHandlerURL(const char* resource) const
-{
-    if (!m_priv->m_handlerURL.empty() && resource && !strcmp(getRequestURL(),resource))
-        return m_priv->m_handlerURL;
-        
-    if (!m_priv->m_app)
-        throw ConfigurationException("Internal error in ShibTargetPriv::getHandlerURL, missing application pointer.");
-
-    bool ssl_only=false;
-    const char* handler=NULL;
-    const PropertySet* props=m_priv->m_app->getPropertySet("Sessions");
-    if (props) {
-        pair<bool,bool> p=props->getBool("handlerSSL");
-        if (p.first)
-            ssl_only=p.second;
-        pair<bool,const char*> p2=props->getString("handlerURL");
-        if (p2.first)
-            handler=p2.second;
-    }
-    
-    // Should never happen...
-    if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
-        throw ConfigurationException(
-            "Invalid handlerURL property ($1) in Application ($2)",
-            xmltooling::params(2, handler ? handler : "null", m_priv->m_app->getId())
-            );
-
-    // The "handlerURL" property can be in one of three formats:
-    //
-    // 1) a full URI:       http://host/foo/bar
-    // 2) a hostless URI:   http:///foo/bar
-    // 3) a relative path:  /foo/bar
-    //
-    // #  Protocol  Host        Path
-    // 1  handler   handler     handler
-    // 2  handler   resource    handler
-    // 3  resource  resource    handler
-    //
-    // note: if ssl_only is true, make sure the protocol is https
-
-    const char* path = NULL;
-
-    // Decide whether to use the handler or the resource for the "protocol"
-    const char* prot;
-    if (*handler != '/') {
-        prot = handler;
-    }
-    else {
-        prot = resource;
-        path = handler;
-    }
-
-    // break apart the "protocol" string into protocol, host, and "the rest"
-    const char* colon=strchr(prot,':');
-    colon += 3;
-    const char* slash=strchr(colon,'/');
-    if (!path)
-        path = slash;
-
-    // Compute the actual protocol and store in member.
-    if (ssl_only)
-        m_priv->m_handlerURL.assign("https://");
-    else
-        m_priv->m_handlerURL.assign(prot, colon-prot);
-
-    // create the "host" from either the colon/slash or from the target string
-    // If prot == handler then we're in either #1 or #2, else #3.
-    // If slash == colon then we're in #2.
-    if (prot != handler || slash == colon) {
-        colon = strchr(resource, ':');
-        colon += 3;      // Get past the ://
-        slash = strchr(colon, '/');
-    }
-    string host(colon, (slash ? slash-colon : strlen(colon)));
-
-    // Build the handler URL
-    m_priv->m_handlerURL+=host + path;
-    return m_priv->m_handlerURL;
-}
-
-void ShibTarget::log(ShibLogLevel level, const string& msg)
-{
-    Category::getInstance("shibtarget.ShibTarget").log(
-        (level == LogLevelDebug ? Priority::DEBUG :
-        (level == LogLevelInfo ? Priority::INFO :
-        (level == LogLevelWarn ? Priority::WARN : Priority::ERROR))),
-        msg
-    );
-}
-
 const IApplication* ShibTarget::getApplication() const
 {
     return m_priv->m_app;
@@ -852,12 +679,12 @@ const IConfig* ShibTarget::getConfig() const
     return m_priv->m_conf;
 }
 
-void* ShibTarget::returnDecline(void)
+long ShibTarget::returnDecline(void)
 {
     return NULL;
 }
 
-void* ShibTarget::returnOK(void)
+long ShibTarget::returnOK(void)
 {
     return NULL;
 }
@@ -867,7 +694,7 @@ void* ShibTarget::returnOK(void)
  */
 
 ShibTargetPriv::ShibTargetPriv()
-    : m_app(NULL), m_mapper(NULL), m_conf(NULL), m_Config(NULL), m_cacheEntry(NULL), m_cgiParser(NULL) {}
+    : m_app(NULL), m_mapper(NULL), m_conf(NULL), m_Config(NULL), m_cacheEntry(NULL) {}
 
 ShibTargetPriv::~ShibTargetPriv()
 {
@@ -886,7 +713,6 @@ ShibTargetPriv::~ShibTargetPriv()
         m_conf = NULL;
     }
 
-    delete m_cgiParser;
     m_app = NULL;
     m_Config = NULL;
 }
@@ -908,11 +734,11 @@ void ShibTargetPriv::get_application(ShibTarget* st, const string& protocol, con
   m_mapper->lock();
 
   // Obtain the application settings from the parsed URL
-  m_settings = m_mapper->getSettings(st);
+  m_settings = m_mapper->getSettings(*st);
 
   // Now find the application from the URL settings
   pair<bool,const char*> application_id=m_settings.first->getString("applicationId");
-  m_app=m_conf->getApplication(application_id.second);
+  m_app=dynamic_cast<const IApplication*>(m_conf->getApplication(application_id.second));
   if (!m_app) {
     m_mapper->unlock();
     m_mapper = NULL;
@@ -931,15 +757,14 @@ void ShibTargetPriv::get_application(ShibTarget* st, const string& protocol, con
   st->m_url += uri;
 }
 
-void* ShibTargetPriv::sendError(
+long ShibTargetPriv::sendError(
     ShibTarget* st, const char* page, ExtTemplateParameters& tp, const XMLToolingException* ex
     )
 {
-    ShibTarget::header_t hdrs[] = {
-        ShibTarget::header_t("Expires","01-Jan-1997 12:00:00 GMT"),
-        ShibTarget::header_t("Cache-Control","private,no-store,no-cache")
-        };
-    
+    st->setContentType("text/html");
+    st->setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
+    st->setResponseHeader("Cache-Control","private,no-store,no-cache");
+
     TemplateEngine* engine = XMLToolingConfig::getConfig().getTemplateEngine();
     const PropertySet* props=m_app->getPropertySet("Errors");
     if (props) {
@@ -948,22 +773,23 @@ void* ShibTargetPriv::sendError(
             ifstream infile(p.second);
             if (infile) {
                 tp.setPropertySet(props);
-                ostringstream ostr;
-                engine->run(infile, ostr, tp, ex);
-                return st->sendPage(ostr.str().c_str(), 200, "text/html", ArrayIterator<ShibTarget::header_t>(hdrs,2));
+                stringstream str;
+                engine->run(infile, str, tp, ex);
+                return st->sendResponse(str);
             }
         }
-        else if (!strcmp(page,"access"))
-            return st->sendPage("Access Denied", 403, "text/html", ArrayIterator<ShibTarget::header_t>(hdrs,2));
+        else if (!strcmp(page,"access")) {
+            istringstream msg("Access Denied");
+            return static_cast<opensaml::GenericResponse*>(st)->sendResponse(msg, opensaml::HTTPResponse::SAML_HTTP_STATUS_FORBIDDEN);
+        }
     }
 
     string errstr = string("sendError could not process error template (") + page + ") for application (";
     errstr += m_app->getId();
     errstr += ")";
-    st->log(ShibTarget::LogLevelError, errstr);
-    return st->sendPage(
-        "Internal Server Error. Please contact the site administrator.", 500, "text/html", ArrayIterator<ShibTarget::header_t>(hdrs,2)
-        );
+    st->log(SPRequest::SPError, errstr);
+    istringstream msg("Internal Server Error. Please contact the site administrator.");
+    return st->sendError(msg);
 }
 
 void ShibTargetPriv::clearHeaders(ShibTarget* st)
@@ -989,99 +815,3 @@ void ShibTargetPriv::clearHeaders(ShibTarget* st)
         }
     }
 }
-
-/*************************************************************************
- * CGI Parser implementation
- */
-
-CgiParse::CgiParse(const ShibTarget* st)
-{
-    const char* pch=NULL;
-    if (!strcmp(st->getRequestMethod(),"POST"))
-        pch=st->getRequestBody();
-    else
-        pch=st->getQueryString();
-    size_t cl=pch ? strlen(pch) : 0;
-    
-        
-    while (cl && pch) {
-        char *name;
-        char *value;
-        value=fmakeword('&',&cl,&pch);
-        plustospace(value);
-        opensaml::SAMLConfig::getConfig().getURLEncoder()->decode(value);
-        name=makeword(value,'=');
-        kvp_map.insert(pair<string,char*>(name,value));
-        free(name);
-    }
-}
-
-CgiParse::~CgiParse()
-{
-    for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
-        free(i->second);
-}
-
-pair<CgiParse::walker,CgiParse::walker> CgiParse::get_values(const char* name) const
-{
-    return kvp_map.equal_range(name);
-}
-
-/* Parsing routines modified from NCSA source. */
-char* CgiParse::makeword(char *line, char stop)
-{
-    int x = 0,y;
-    char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
-
-    for(x=0;((line[x]) && (line[x] != stop));x++)
-        word[x] = line[x];
-
-    word[x] = '\0';
-    if(line[x])
-        ++x;
-    y=0;
-
-    while(line[x])
-      line[y++] = line[x++];
-    line[y] = '\0';
-    return word;
-}
-
-char* CgiParse::fmakeword(char stop, size_t *cl, const char** ppch)
-{
-    int wsize;
-    char *word;
-    int ll;
-
-    wsize = 1024;
-    ll=0;
-    word = (char *) malloc(sizeof(char) * (wsize + 1));
-
-    while(1)
-    {
-        word[ll] = *((*ppch)++);
-        if(ll==wsize-1)
-        {
-            word[ll+1] = '\0';
-            wsize+=1024;
-            word = (char *)realloc(word,sizeof(char)*(wsize+1));
-        }
-        --(*cl);
-        if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
-        {
-            if(word[ll] != stop)
-                ll++;
-            word[ll] = '\0';
-            return word;
-        }
-        ++ll;
-    }
-}
-
-void CgiParse::plustospace(char *str)
-{
-    register int x;
-
-    for(x=0;str[x];x++)
-        if(str[x] == '+') str[x] = ' ';
-}
index 321dd5e..4d10e9f 100644 (file)
 #define SHIB_TARGET_H
 
 // New headers
-#include <shibsp/ListenerService.h>
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/Application.h>
 #include <shibsp/ServiceProvider.h>
-#include <saml/saml2/metadata/MetadataProvider.h>
-#include <xmltooling/security/TrustEngine.h>
+#include <shibsp/remoting/ListenerService.h>
 
 // Old headers
 #include <saml/saml.h>
@@ -65,7 +65,7 @@ namespace shibtarget {
         virtual ~IHandler() {}
         virtual const shibsp::PropertySet* getProperties() const { return m_props; }
         virtual void setProperties(const shibsp::PropertySet* properties) { m_props=properties; }
-        virtual std::pair<bool,void*> run(ShibTarget* st, bool isHandler=true) const=0;
+        virtual std::pair<bool,long> run(ShibTarget* st, bool isHandler=true) const=0;
     private:
         const shibsp::PropertySet* m_props;
     };
@@ -81,18 +81,12 @@ namespace shibtarget {
      * Application. Implementations should always expose an application named "default"
      * as a last resort.
      */
-    struct SHIBTARGET_EXPORTS IApplication : public virtual shibsp::PropertySet,
+    struct SHIBTARGET_EXPORTS IApplication : public virtual shibsp::Application,
         public virtual shibboleth::ShibBrowserProfile::ITokenValidator
     {
-        virtual const char* getId() const=0;
-        virtual const char* getHash() const=0;
-        
         virtual saml::Iterator<saml::SAMLAttributeDesignator*> getAttributeDesignators() const=0;
         virtual saml::Iterator<shibboleth::IAAP*> getAAPProviders() const=0;
-        virtual opensaml::saml2md::MetadataProvider* getMetadataProvider() const=0;
-        virtual xmltooling::TrustEngine* getTrustEngine() const=0;
         virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
-        virtual const shibsp::PropertySet* getCredentialUse(const opensaml::saml2md::EntityDescriptor* provider) const=0;
 
         // caller is borrowing object, must use within scope of config lock
         virtual const saml::SAMLBrowserProfile* getBrowserProfile() const=0;
@@ -258,45 +252,10 @@ namespace shibtarget {
     #define ODBC_REPLAYCACHE    "edu.internet2.middleware.shibboleth.sp.provider.ODBCReplayCacheProvider"
 
 
-    /**
-     * Interface to an access control plugin
-     * 
-     * Access control plugins return authorization decisions based on the intersection
-     * of the resource request and the active session. They can be implemented through
-     * cross-platform or platform-specific mechanisms.
-     */
-    struct SHIBTARGET_EXPORTS IAccessControl : public virtual xmltooling::Lockable, public virtual saml::IPlugIn
-    {
-        virtual bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const=0;
-        virtual ~IAccessControl() {}
-    };
-
-    #define HTACCESS_ACCESSCONTROL  "edu.internet2.middleware.shibboleth.sp.apache.provider.htAccessControl"
-    #define XML_ACCESSCONTROL       "edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"
-
-    /**
-     * Interface to a request mapping plugin
-     * 
-     * Request mapping plugins return configuration settings that apply to resource requests.
-     * They can be implemented through cross-platform or platform-specific mechanisms.
-     */
-    struct SHIBTARGET_EXPORTS IRequestMapper : public virtual xmltooling::Lockable, public virtual saml::IPlugIn
-    {
-        typedef std::pair<const shibsp::PropertySet*,IAccessControl*> Settings;
-        virtual Settings getSettings(ShibTarget* st) const=0;
-        virtual ~IRequestMapper() {}
-    };
-
-    #define XML_REQUESTMAP_PROVIDER     "edu.internet2.middleware.shibboleth.sp.provider.XMLRequestMapProvider"
-    #define NATIVE_REQUESTMAP_PROVIDER  "edu.internet2.middleware.shibboleth.sp.provider.NativeRequestMapProvider"
-    #define LEGACY_REQUESTMAP_PROVIDER  "edu.internet2.middleware.shibboleth.target.provider.XMLRequestMap"
-
     struct SHIBTARGET_EXPORTS IConfig : public virtual shibsp::ServiceProvider
     {
         virtual ISessionCache* getSessionCache() const=0;
         virtual saml::IReplayCache* getReplayCache() const=0;
-        virtual IRequestMapper* getRequestMapper() const=0;
-        virtual const IApplication* getApplication(const char* applicationId) const=0;
         virtual ~IConfig() {}
     };
 
@@ -319,112 +278,18 @@ namespace shibtarget {
     };
 
     class ShibTargetPriv;
-    class SHIBTARGET_EXPORTS ShibTarget {
+    class SHIBTARGET_EXPORTS ShibTarget : public shibsp::AbstractSPRequest {
     public:
         ShibTarget(const IApplication* app);
         virtual ~ShibTarget(void);
 
-        // These are defined here so the subclass does not need to specifically
-        // depend on log4cpp.  We could use log4cpp::Priority::PriorityLevel
-        // but this is just as easy, IMHO.  It's just a case statement in the
-        // implementation to handle the event level.
-        enum ShibLogLevel {
-          LogLevelDebug,
-          LogLevelInfo,
-          LogLevelWarn,
-          LogLevelError
-        };
-
-        //
-        // Note: subclasses MUST implement ALL of these virtual methods
-        //
-        
-        // Send a message to the Webserver log
-        virtual void log(ShibLogLevel level, const std::string &msg)=0;
-
-        void log(ShibLogLevel level, const char* msg) {
-          std::string s = msg;
-          log(level, s);
-        }
-
-        // Get/Set a cookie for this request
-        virtual std::string getCookies() const=0;
-        virtual void setCookie(const std::string& name, const std::string& value)=0;
-        virtual const char* getCookie(const std::string& name) const;
-        void setCookie(const char* name, const char* value) {
-          std::string ns = name;
-          std::string vs = value;
-          setCookie(ns, vs);
-        }
-        void setCookie(const char* name, const std::string& value) {
-          std::string ns = name;
-          setCookie(ns, value);
-        }
-
-        // Get any URL-encoded arguments or the raw POST body from the server
-        virtual const char* getQueryString() const=0;
-        virtual const char* getRequestBody() const=0;
-        virtual const char* getRequestParameter(const char* param, size_t index=0) const;
-
-        // Clear a header, set a header
-        // These APIs are used for exporting the Assertions into the
-        // Headers.  It will clear some well-known headers first to make
-        // sure none remain.  Then it will process the set of assertions
-        // and export them via setHeader().
-        virtual void clearHeader(const std::string& name)=0;
-        virtual void setHeader(const std::string& name, const std::string& value)=0;
-        virtual std::string getHeader(const std::string& name)=0;
-        virtual void setRemoteUser(const std::string& user)=0;
-        virtual std::string getRemoteUser()=0;
-
-        void clearHeader(const char* n) {
-          std::string s = n;
-          clearHeader(s);
-        }
-        void setHeader(const char* n, const char* v) {
-          std::string ns = n;
-          std::string vs = v;
-          setHeader(ns, vs);
-        }
-        void setHeader(const std::string& n, const char* v) {
-          std::string vs = v;
-          setHeader(n, vs);
-        }
-        void setHeader(const char* n, const std::string& v) {
-          std::string ns = n;
-          setHeader(ns, v);
-        }
-        std::string getHeader(const char* n) {
-          std::string s = n;
-          return getHeader(s);
-        }
-        void setRemoteUser(const char* n) {
-          std::string s = n;
-          setRemoteUser(s);
-        }
-
-        // We're done.  Finish up.  Send specific result content or a redirect.
-        // If there are no headers supplied assume the content-type is text/html
-        typedef std::pair<std::string, std::string> header_t;
-        virtual void* sendPage(
-            const std::string& msg,
-            int code = 200,
-            const std::string& content_type = "text/html",
-            const saml::Iterator<header_t>& headers = EMPTY(header_t)
-            )=0;
-        void* sendPage(const char* msg) {
-          std::string m = msg;
-          return sendPage(m);
-        }
-        virtual void* sendRedirect(const std::string& url)=0;
-        
         // These next two APIs are used to obtain the module-specific "OK"
         // and "Decline" results.  OK means "we believe that this request
         // should be accepted".  Declined means "we believe that this is
         // not a shibbolized request so we have no comment".
 
-        virtual void* returnDecline();
-        virtual void* returnOK();
+        virtual long returnDecline();
+        virtual long returnOK();
 
         //
         // Note:  Subclasses need not implement anything below this line
@@ -448,44 +313,29 @@ namespace shibtarget {
         //   automatically call doHandlePOST() when it encounters a request for
         //   the ShireURL;  if false it will call returnOK() instead.
         //
-        std::pair<bool,void*> doCheckAuthN(bool handler = false);
-        std::pair<bool,void*> doHandler();
-        std::pair<bool,void*> doCheckAuthZ();
-        std::pair<bool,void*> doExportAssertions(bool requireSession = true);
+        std::pair<bool,long> doCheckAuthN(bool handler = false);
+        std::pair<bool,long> doHandler();
+        std::pair<bool,long> doCheckAuthZ();
+        std::pair<bool,long> doExportAssertions(bool requireSession = true);
 
         // Basic request access in case any plugins need the info
         virtual const IConfig* getConfig() const;
         virtual const IApplication* getApplication() const;
-        const char* getRequestMethod() const {return m_method.c_str();}
-        const char* getProtocol() const {return m_protocol.c_str();}
-        const char* getHostname() const {return m_hostname.c_str();}
-        int getPort() const {return m_port;}
-        const char* getRequestURI() const {return m_uri.c_str();}
-        const char* getContentType() const {return m_content_type.c_str();}
-        const char* getRemoteAddr() const {return m_remote_addr.c_str();}
         const char* getRequestURL() const {return m_url.c_str();}
         
-        // Advanced methods useful to profile handlers implemented outside core
-        
-        // Get per-application session and state cookie name and properties
-        virtual std::pair<std::string,const char*> getCookieNameProps(const char* prefix) const;
-        
-        // Determine the effective handler URL based on the resource URL
-        virtual std::string getHandlerURL(const char* resource) const;
-
     protected:
         ShibTarget();
 
         // Internal APIs
 
         // Initialize the request from the parsed URL
-        // protocol == http, https, etc
+        // scheme == http, https, etc
         // hostname == server name
         // port == server port
         // uri == resource path
         // method == GET, POST, etc.
         void init(
-            const char* protocol,
+            const char* scheme,
             const char* hostname,
             int port,
             const char* uri,
@@ -494,7 +344,7 @@ namespace shibtarget {
             const char* method
             );
 
-        std::string m_url, m_method, m_protocol, m_hostname, m_uri, m_content_type, m_remote_addr;
+        std::string m_url, m_method, m_scheme, m_hostname, m_uri, m_content_type, m_remote_addr;
         int m_port;
 
     private:
index d7de190..d5cd8d6 100644 (file)
                        RelativePath="ShibHTTPHook.cpp"
                        >
                </File>
-               <File
-                       RelativePath="XMLRequestMapper.cpp"
-                       >
-               </File>
        </Files>
        <Globals>
        </Globals>
diff --git a/shibsp/AbstractSPRequest.cpp b/shibsp/AbstractSPRequest.cpp
new file mode 100644 (file)
index 0000000..bfa6125
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * AbstractSPRequest.cpp
+ * 
+ * Abstract base for SPRequest implementations  
+ */
+
+#include "internal.h"
+#include "AbstractSPRequest.h"
+#include "Application.h"
+#include "util/CGIParser.h"
+
+#include <log4cpp/Category.hh>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+AbstractSPRequest::AbstractSPRequest(const Application* app)
+    : m_app(app), m_log(&Category::getInstance(SHIBSP_LOGCAT)), m_parser(NULL)
+{
+    if (m_app)
+        return;
+}
+
+AbstractSPRequest::~AbstractSPRequest()
+{
+    delete m_parser;
+}
+
+const char* AbstractSPRequest::getParameter(const char* name) const
+{
+    if (!m_parser)
+        m_parser=new CGIParser(*this);
+    
+    pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
+    return (bounds.first==bounds.second) ? NULL : bounds.first->second;
+}
+
+vector<const char*>::size_type AbstractSPRequest::getParameters(const char* name, vector<const char*>& values) const
+{
+    if (!m_parser)
+        m_parser=new CGIParser(*this);
+
+    pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
+    while (bounds.first!=bounds.second) {
+        values.push_back(bounds.first->second);
+        ++bounds.first;
+    }
+    return values.size();
+}
+
+const char* AbstractSPRequest::getCookie(const char* name) const
+{
+    if (m_cookieMap.empty()) {
+        string cookies=getHeader("Cookie");
+
+        string::size_type pos=0,cname,namelen,val,vallen;
+        while (pos !=string::npos && pos < cookies.length()) {
+            while (isspace(cookies[pos])) pos++;
+            cname=pos;
+            pos=cookies.find_first_of("=",pos);
+            if (pos == string::npos)
+                break;
+            namelen=pos-cname;
+            pos++;
+            if (pos==cookies.length())
+                break;
+            val=pos;
+            pos=cookies.find_first_of(";",pos);
+            if (pos != string::npos) {
+                vallen=pos-val;
+                pos++;
+                m_cookieMap.insert(make_pair(cookies.substr(cname,namelen),cookies.substr(val,vallen)));
+            }
+            else
+                m_cookieMap.insert(make_pair(cookies.substr(cname,namelen),cookies.substr(val)));
+        }
+    }
+    map<string,string>::const_iterator lookup=m_cookieMap.find(name);
+    return (lookup==m_cookieMap.end()) ? NULL : lookup->second.c_str();
+}
+
+const char* AbstractSPRequest::getHandlerURL(const char* resource) const
+{
+    if (!m_handlerURL.empty() && resource && !strcmp(getRequestURL(),resource))
+        return m_handlerURL.c_str();
+        
+#ifdef HAVE_STRCASECMP
+    if (!resource || (strncasecmp(resource,"http://",7) && strncasecmp(resource,"https://",8)))
+#else
+    if (!resource || (strnicmp(resource,"http://",7) && strnicmp(resource,"https://",8)))
+#endif
+        throw ConfigurationException("Target resource was not an absolute URL.");
+
+    bool ssl_only=false;
+    const char* handler=NULL;
+    const PropertySet* props=m_app->getPropertySet("Sessions");
+    if (props) {
+        pair<bool,bool> p=props->getBool("handlerSSL");
+        if (p.first)
+            ssl_only=p.second;
+        pair<bool,const char*> p2=props->getString("handlerURL");
+        if (p2.first)
+            handler=p2.second;
+    }
+    
+    // Should never happen...
+    if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
+        throw ConfigurationException(
+            "Invalid handlerURL property ($1) in Application ($2)",
+            params(2, handler ? handler : "null", m_app->getId())
+            );
+
+    // The "handlerURL" property can be in one of three formats:
+    //
+    // 1) a full URI:       http://host/foo/bar
+    // 2) a hostless URI:   http:///foo/bar
+    // 3) a relative path:  /foo/bar
+    //
+    // #  Protocol  Host        Path
+    // 1  handler   handler     handler
+    // 2  handler   resource    handler
+    // 3  resource  resource    handler
+    //
+    // note: if ssl_only is true, make sure the protocol is https
+
+    const char* path = NULL;
+
+    // Decide whether to use the handler or the resource for the "protocol"
+    const char* prot;
+    if (*handler != '/') {
+        prot = handler;
+    }
+    else {
+        prot = resource;
+        path = handler;
+    }
+
+    // break apart the "protocol" string into protocol, host, and "the rest"
+    const char* colon=strchr(prot,':');
+    colon += 3;
+    const char* slash=strchr(colon,'/');
+    if (!path)
+        path = slash;
+
+    // Compute the actual protocol and store in member.
+    if (ssl_only)
+        m_handlerURL.assign("https://");
+    else
+        m_handlerURL.assign(prot, colon-prot);
+
+    // create the "host" from either the colon/slash or from the target string
+    // If prot == handler then we're in either #1 or #2, else #3.
+    // If slash == colon then we're in #2.
+    if (prot != handler || slash == colon) {
+        colon = strchr(resource, ':');
+        colon += 3;      // Get past the ://
+        slash = strchr(colon, '/');
+    }
+    string host(colon, (slash ? slash-colon : strlen(colon)));
+
+    // Build the handler URL
+    m_handlerURL += host + path;
+    return m_handlerURL.c_str();
+}
+
+void AbstractSPRequest::log(SPLogLevel level, const std::string& msg) const
+{
+    reinterpret_cast<Category*>(m_log)->log(
+        (level == SPDebug ? log4cpp::Priority::DEBUG :
+        (level == SPInfo ? log4cpp::Priority::INFO :
+        (level == SPWarn ? log4cpp::Priority::WARN :
+        (level == SPError ? log4cpp::Priority::ERROR : log4cpp::Priority::CRIT)))),
+        msg
+        );
+}
+
+bool AbstractSPRequest::isPriorityEnabled(SPLogLevel level) const
+{
+    return reinterpret_cast<Category*>(m_log)->isPriorityEnabled(
+        (level == SPDebug ? log4cpp::Priority::DEBUG :
+        (level == SPInfo ? log4cpp::Priority::INFO :
+        (level == SPWarn ? log4cpp::Priority::WARN :
+        (level == SPError ? log4cpp::Priority::ERROR : log4cpp::Priority::CRIT))))
+        );
+}
diff --git a/shibsp/AbstractSPRequest.h b/shibsp/AbstractSPRequest.h
new file mode 100644 (file)
index 0000000..82849b3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/AbstractSPRequest.h
+ * 
+ * Abstract base for SPRequest implementations  
+ */
+
+#ifndef __shibsp_abstreq_h__
+#define __shibsp_abstreq_h__
+
+#include <shibsp/exceptions.h>
+#include <shibsp/SPRequest.h>
+
+namespace shibsp {
+
+    class SHIBSP_API CGIParser;
+    
+    /**
+     * Abstract base for SPRequest implementations
+     */
+    class SHIBSP_API AbstractSPRequest : public virtual SPRequest
+    {
+    protected:
+        /**
+         * Constructor
+         * 
+         * @param app   pointer to effective Application, if known
+         */
+        AbstractSPRequest(const Application* app=NULL);
+        
+    public:
+        virtual ~AbstractSPRequest();
+        
+        const Application& getSPApplication() const {
+            return *m_app;
+        }
+
+        const char* getParameter(const char* name) const;
+
+        std::vector<const char*>::size_type getParameters(const char* name, std::vector<const char*>& values) const;
+
+        const char* getCookie(const char* name) const;
+
+        const char* getHandlerURL(const char* resource=NULL) const;
+
+        void log(SPLogLevel level, const std::string& msg) const;
+
+        bool isPriorityEnabled(SPLogLevel level) const;
+
+    protected:
+        /** Holds effective Application. */
+        const Application* m_app;
+    
+    private:
+        void* m_log; // declared void* to avoid log4cpp header conflicts in Apache
+        mutable std::string m_handlerURL;
+        mutable std::map<std::string,std::string> m_cookieMap;
+        mutable CGIParser* m_parser;
+    };
+};
+
+#endif /* __shibsp_abstreq_h__ */
diff --git a/shibsp/AccessControl.h b/shibsp/AccessControl.h
new file mode 100644 (file)
index 0000000..de8d7fb
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/AccessControl.h
+ * 
+ * Interface to an access control plugin
+ */
+
+#ifndef __shibsp_acl_h__
+#define __shibsp_acl_h__
+
+#include <shibsp/base.h>
+#include <xmltooling/Lockable.h>
+
+namespace shibsp {
+
+    class SHIBSP_API Session;
+    class SHIBSP_API SPRequest;
+
+     /**
+     * Interface to an access control plugin
+     * 
+     * Access control plugins return authorization decisions based on the intersection
+     * of the resource request and the active session. They can be implemented through
+     * cross-platform or platform-specific mechanisms.
+     */
+    class SHIBSP_API AccessControl : public virtual xmltooling::Lockable
+    {
+        MAKE_NONCOPYABLE(AccessControl);
+    protected:
+        AccessControl() {}
+    public:
+        virtual ~AccessControl() {}
+
+        /**
+         * Perform an authorization check.
+         * 
+         * @param request   SP request information
+         * @param session   active user session, if any
+         * @return true iff access should be granted
+         */
+        virtual bool authorized(SPRequest& request, Session* session) const=0;
+    };
+
+    /**
+     * Registers AccessControl classes into the runtime.
+     */
+    void SHIBSP_API registerAccessControls();
+
+    /** AccessControl based on rudimentary XML syntax. */
+    #define XML_ACCESS_CONTROL  "edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"
+
+    /** Reserved for Apache-style .htaccess support. */
+    #define HT_ACCESS_CONTROL   "edu.internet2.middleware.shibboleth.sp.apache.provider.htAccessControl"
+};
+
+#endif /* __shibsp_acl_h__ */
diff --git a/shibsp/Application.cpp b/shibsp/Application.cpp
new file mode 100644 (file)
index 0000000..b6fe37a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Application.cpp
+ * 
+ * Interface to a Shibboleth Application instance.
+ */
+
+#include "internal.h"
+#include "Application.h"
+
+using namespace shibsp;
+using namespace std;
+
+pair<string,const char*> Application::getCookieNameProps(const char* prefix) const
+{
+    static const char* defProps="; path=/";
+    
+    const PropertySet* props=getPropertySet("Sessions");
+    if (props) {
+        pair<bool,const char*> p=props->getString("cookieProps");
+        if (!p.first)
+            p.second=defProps;
+        pair<bool,const char*> p2=props->getString("cookieName");
+        if (p2.first)
+            return make_pair(string(prefix) + p2.second,p.second);
+        return make_pair(string(prefix) + getHash(),p.second);
+    }
+    
+    // Shouldn't happen, but just in case..
+    return pair<string,const char*>(prefix,defProps);
+}
diff --git a/shibsp/Application.h b/shibsp/Application.h
new file mode 100644 (file)
index 0000000..fa10141
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/Application.h
+ * 
+ * Interface to a Shibboleth Application instance.
+ */
+
+#ifndef __shibsp_app_h__
+#define __shibsp_app_h__
+
+#include <shibsp/util/PropertySet.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/security/TrustEngine.h>
+
+namespace shibsp {
+
+    /**
+     * Interface to a Shibboleth Application instance.
+     * 
+     * <p>An Application is a logical set of resources that act as a unit
+     * of session management and policy.
+     */
+    class SHIBSP_API Application : public virtual PropertySet
+    {
+        MAKE_NONCOPYABLE(Application);
+    protected:
+        Application() {}
+    public:
+        virtual ~Application() {}
+
+        /**
+         * Returns the Application's ID.
+         * 
+         * @return  the ID
+         */        
+        virtual const char* getId() const=0;
+
+        /**
+         * Returns a unique hash for the Application.
+         * 
+         * @return a value resulting from a hash of the Application's ID  
+         */
+        virtual const char* getHash() const=0;
+
+        /**
+         * Returns the name and cookie properties to use for this Application.
+         * 
+         * @param prefix    a value to prepend to the base cookie name
+         * @return  a pair containing the cookie name and the string to append to the cookie value
+         */
+        virtual std::pair<std::string,const char*> getCookieNameProps(const char* prefix) const;
+
+        /**
+         * Returns a MetadataProvider for use with this Application.
+         * 
+         * @return  a MetadataProvider instance, or NULL
+         */
+        virtual opensaml::saml2md::MetadataProvider* getMetadataProvider() const=0;
+        
+        /**
+         * Returns a TrustEngine for use with this Application.
+         * 
+         * @return  a TrustEngine instance, or NULL
+         */
+        virtual xmltooling::TrustEngine* getTrustEngine() const=0;
+        
+        /**
+         * Returns configuration properties governing security interactions with a peer entity.
+         * 
+         * @param provider  a peer entity's metadata
+         * @return  the applicable PropertySet
+         */
+        virtual const shibsp::PropertySet* getCredentialUse(const opensaml::saml2md::EntityDescriptor* provider) const=0;
+    };
+};
+
+#endif /* __shibsp_app_h__ */
index fefe2bf..4950a62 100644 (file)
@@ -7,38 +7,64 @@ lib_LTLIBRARIES = libshibsp.la
 
 libshibspincludedir = $(includedir)/shibsp
 
+mdincludedir = $(includedir)/shibsp/metadata
+
+remincludedir = $(includedir)/shibsp/remoting
+
+secincludedir = $(includedir)/shibsp/security
+
+utilincludedir = $(includedir)/shibsp/util
+
 libshibspinclude_HEADERS = \
+       AbstractSPRequest.h \
+       AccessControl.h \
+       Application.h \
        base.h \
-       ddf.h \
-       DOMPropertySet.h \
        exceptions.h \
-       ListenerService.h \
-       MetadataExt.h \
        paths.h \
-       PKIXTrustEngine.h \
-       PropertySet.h \
-       version.h \
+       RequestMapper.h \
        ServiceProvider.h \
-       SocketListener.h \
+       SessionCache.h \
        SPConfig.h \
-       SPConstants.h
+       SPRequest.h \
+       version.h
+
+mdinclude_HEADERS = \
+       metadata/MetadataExt.h
+
+reminclude_HEADERS = \
+       ddf.h \
+       ListenerService.h
+       
+secinclude_HEADERS = \
+       security/PKIXTrustEngine.h
+
+utilinclude_HEADERS = \
+       util/DOMPropertySet.h \
+       util/PropertySet.h \
+       util/SPConstants.h
 
 noinst_HEADERS = \
-       internal.h
+       internal.h \
+       remoting/impl/SocketListener.h
 
 libshibsp_la_SOURCES = \
-       ddf.cpp \
-       DOMPropertySet.cpp \
-       ListenerService.cpp \
-       MetadataExtImpl.cpp \
-       MetadataExtSchemaValidators.cpp \
-       PKIXTrustEngine.cpp \
+       AbstractSPRequest.cpp \
+       Application.cpp \
        ServiceProvider.cpp \
        SPConfig.cpp \
-       SPConstants.cpp \ 
-       SocketListener.cpp \
-       TCPListener.cpp \
-       UnixListener.cpp
+       impl/XMLAccessControl.cpp \
+       impl/XMLRequestMapper.cpp \
+       metadata/MetadataExtImpl.cpp \
+       metadata/MetadataExtSchemaValidators.cpp \
+       remoting/impl/ddf.cpp \
+       remoting/impl/ListenerService.cpp \
+       remoting/impl/SocketListener.cpp \
+       remoting/impl/TCPListener.cpp \
+       remoting/impl/UnixListener.cpp \
+       security/PKIXTrustEngine.cpp \
+       util/DOMPropertySet.cpp \
+       util/SPConstants.cpp 
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
diff --git a/shibsp/RequestMapper.h b/shibsp/RequestMapper.h
new file mode 100644 (file)
index 0000000..0c9264d
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/RequestMapper.h
+ * 
+ * Interface to a request mapping plugin
+ */
+
+#ifndef __shibsp_reqmap_h__
+#define __shibsp_reqmap_h__
+
+#include <shibsp/base.h>
+#include <xmltooling/Lockable.h>
+
+namespace shibsp {
+
+    class SHIBSP_API AccessControl;
+    class SHIBSP_API PropertySet;
+    class SHIBSP_API SPRequest;
+
+    /**
+     * Interface to a request mapping plugin
+     * 
+     * Request mapping plugins return configuration settings that apply to resource requests.
+     * They can be implemented through cross-platform or platform-specific mechanisms.
+     */
+    class SHIBSP_API RequestMapper : public virtual xmltooling::Lockable
+    {
+        MAKE_NONCOPYABLE(RequestMapper);
+    protected:
+        RequestMapper() {}
+    public:
+        virtual ~RequestMapper() {}
+
+        /** Combination of configuration settings and effective access control. */
+        typedef std::pair<const PropertySet*,AccessControl*> Settings;
+
+        /**
+         * Map request to settings.
+         * 
+         * @param request   SP request
+         * @return configuration settings and effective AccessControl plugin, if any
+         */        
+        virtual Settings getSettings(const SPRequest& request) const=0;
+    };
+
+    /**
+     * Registers RequestMapper classes into the runtime.
+     */
+    void SHIBSP_API registerRequestMappers();
+
+    /** XML-based RequestMapper implementation. */
+    #define XML_REQUEST_MAPPER      "edu.internet2.middleware.shibboleth.sp.provider.XMLRequestMapProvider"
+
+    /** Hybrid of XML and platform-specific configuration. */
+    #define NATIVE_REQUEST_MAPPER   "edu.internet2.middleware.shibboleth.sp.provider.NativeRequestMapProvider"
+};
+
+#endif /* __shibsp_reqmap_h__ */
index 3e98e04..a2ebfb4 100644 (file)
 
 #include "internal.h"
 #include "exceptions.h"
-#include "ListenerService.h"
-#include "MetadataExt.h"
-#include "PKIXTrustEngine.h"
+#include "AccessControl.h"
+#include "RequestMapper.h"
 #include "ServiceProvider.h"
 #include "SPConfig.h"
+#include "metadata/MetadataExt.h"
+#include "remoting/ListenerService.h"
+#include "security/PKIXTrustEngine.h"
 
 #include <log4cpp/Category.hh>
 #include <saml/SAMLConfig.h>
@@ -94,7 +96,9 @@ bool SPInternalConfig::init(const char* catalog_path)
     
     registerMetadataExtClasses();
     registerPKIXTrustEngine();
+    registerAccessControls();
     registerListenerServices();
+    registerRequestMappers();
     registerServiceProviders();
 
     log.info("library initialization complete");
@@ -112,8 +116,10 @@ void SPInternalConfig::term()
     delete m_serviceProvider;
     m_serviceProvider = NULL;
     
-    ListenerServiceManager.deregisterFactories();
     ServiceProviderManager.deregisterFactories();
+    RequestMapperManager.deregisterFactories();
+    ListenerServiceManager.deregisterFactories();
+    AccessControlManager.deregisterFactories();
 
     SAMLConfig::getConfig().term();
     log.info("library shutdown complete");
index 9afcc5d..9e57b2b 100644 (file)
@@ -33,7 +33,9 @@
  */
 namespace shibsp {
 
+    class SHIBSP_API AccessControl;
     class SHIBSP_API ListenerService;
+    class SHIBSP_API RequestMapper;
     class SHIBSP_API ServiceProvider;
 
 #if defined (_MSC_VER)
@@ -67,7 +69,7 @@ namespace shibsp {
             Trust = 8,
             Credentials = 16,
             AAP = 32,
-            RequestMapper = 64,
+            RequestMapping = 64,
             OutOfProcess = 128,
             InProcess = 256,
             Logging = 512
@@ -130,11 +132,21 @@ namespace shibsp {
         }
 
         /**
+         * Manages factories for AccessControl plugins.
+         */
+        xmltooling::PluginManager<AccessControl,const xercesc::DOMElement*> AccessControlManager;
+
+        /**
          * Manages factories for ListenerService plugins.
          */
         xmltooling::PluginManager<ListenerService,const xercesc::DOMElement*> ListenerServiceManager;
 
         /**
+         * Manages factories for RequestMapper plugins.
+         */
+        xmltooling::PluginManager<RequestMapper,const xercesc::DOMElement*> RequestMapperManager;
+
+        /**
          * Manages factories for ServiceProvider plugins.
          */
         xmltooling::PluginManager<ServiceProvider,const xercesc::DOMElement*> ServiceProviderManager;
diff --git a/shibsp/SPRequest.h b/shibsp/SPRequest.h
new file mode 100644 (file)
index 0000000..b57e2b3
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/SPRequest.h
+ * 
+ * Interface to server request being processed  
+ */
+
+#ifndef __shibsp_req_h__
+#define __shibsp_req_h__
+
+#include <shibsp/base.h>
+#include <saml/binding/HTTPRequest.h>
+#include <saml/binding/HTTPResponse.h>
+
+namespace shibsp {
+    
+    class SHIBSP_API Application;
+    
+    /**
+     * Interface to server request being processed
+     * 
+     * <p>To supply information from the surrounding web server environment,
+     * a shim must be supplied in the form of this interface to adapt the
+     * library to different proprietary server APIs.
+     * 
+     * <p>This interface need not be threadsafe.
+     */
+    class SHIBSP_API SPRequest : public virtual opensaml::HTTPRequest, public virtual opensaml::HTTPResponse
+    {
+    protected:
+        SPRequest() {}
+    public:
+        virtual ~SPRequest() {}
+        
+        /**
+         * Returns the Application governing the request.
+         * 
+         * @return reference to Application
+         */
+        virtual const Application& getSPApplication() const=0;
+        
+        /**
+         * Returns the effective base Handler URL for a resource,
+         * or the current request URL.
+         * 
+         * @param resource  resource URL to compute handler for
+         * @return  base location of handler
+         */
+        virtual const char* getHandlerURL(const char* resource=NULL) const=0;
+
+        /**
+         * Get a cookie value supplied by the client.
+         * 
+         * @param name  name of cookie
+         * @return  cookie value or NULL
+         */
+        virtual const char* getCookie(const char* name) const=0;
+        
+        /**
+         * Returns a non-spoofable request header value, if possible.
+         * Platforms that support environment export can redirect header
+         * lookups by overriding this method.
+         * 
+         * @param name  the name of the secure header to return
+         * @return the header's value, or an empty string
+         */
+        virtual std::string getSecureHeader(const char* name) const {
+            return getHeader(name);
+        }
+
+        /**
+         * Ensures no value exists for a request header.
+         * 
+         * @param name  name of header to clear 
+         */
+        virtual void clearHeader(const char* name)=0;
+
+        /**
+         * Sets a value for a request header.
+         * 
+         * @param name  name of header to set
+         * @param value value to set
+         */
+        virtual void setHeader(const char* name, const char* value)=0;
+
+        /**
+         * Establish REMOTE_USER identity in request.
+         * 
+         * @param user  REMOTE_USER value to set or NULL to clear
+         */
+        virtual void setRemoteUser(const char* user)=0;
+        
+        /** Portable logging levels. */
+        enum SPLogLevel {
+          SPDebug,
+          SPInfo,
+          SPWarn,
+          SPError,
+          SPCrit
+        };
+
+        /**
+         * Log to native server environment.
+         * 
+         * @param level logging level
+         * @param msg   message to log
+         */
+        virtual void log(SPLogLevel level, const std::string& msg) const=0;
+
+        /**
+         * Test logging level.
+         * 
+         * @param level logging level
+         * @return true iff logging level is enabled
+         */
+        virtual bool isPriorityEnabled(SPLogLevel level) const=0;
+    };
+};
+
+#endif /* __shibsp_req_h__ */
index 34958bd..0744e35 100644 (file)
@@ -38,3 +38,23 @@ void SHIBSP_API shibsp::registerServiceProviders()
 {
     //SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory);
 }
+
+pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handler) const
+{
+    return make_pair(true,0);
+}
+
+pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
+{
+    return make_pair(true,0);
+}
+
+pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSession) const
+{
+    return make_pair(true,0);
+}
+
+pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
+{
+    return make_pair(true,0);
+}
index 3fc4228..565b43f 100644 (file)
 #ifndef __shibsp_sp_h__
 #define __shibsp_sp_h__
 
-#include <shibsp/PropertySet.h>
+#include <shibsp/util/PropertySet.h>
 #include <xmltooling/signature/CredentialResolver.h>
 
 namespace shibsp {
 
-    class ListenerService;
+    class SHIBSP_API Application;
+    class SHIBSP_API ListenerService;
+    class SHIBSP_API RequestMapper;
+    class SHIBSP_API SessionCache;
+    class SHIBSP_API SPRequest;
 
     /**
      * Interface to a Shibboleth ServiceProvider instance.
@@ -69,11 +73,68 @@ namespace shibsp {
          */
         virtual xmlsignature::CredentialResolver* getCredentialResolver(const char* id) const=0;
 
+        /**
+         * Returns a RequestMapper instance.
+         * 
+         * @param a RequestMapper if available, or NULL
+         */
+        virtual RequestMapper* getRequestMapper() const=0;
+        
         //virtual ISessionCache* getSessionCache() const=0;
         
-        //virtual IRequestMapper* getRequestMapper() const=0;
+        /**
+         * Returns an Application instance matching the specified ID.
+         * 
+         * @param applicationId the ID of the application
+         * @return  pointer to the application, or NULL
+         */
+        virtual const Application* getApplication(const char* applicationId) const=0;
+
+        /**
+         * Enforces requirements for an authenticated session.
+         * 
+         * <p>If the return value's first member is true, then request processing should terminate
+         * with the second member as a status value. If false, processing can continue. 
+         * 
+         * @param request   SP request interface
+         * @param handler   true iff a request to a registered Handler location can be directly executed
+         * @return a pair containing a "request completed" indicator and a server-specific response code
+         */
+        virtual std::pair<bool,long> doAuthentication(SPRequest& request, bool handler=false) const;
+        
+        /**
+         * Enforces authorization requirements based on the authenticated session.
+         * 
+         * <p>If the return value's first member is true, then request processing should terminate
+         * with the second member as a status value. If false, processing can continue. 
+         * 
+         * @param request   SP request interface
+         * @return a pair containing a "request completed" indicator and a server-specific response code
+         */
+        virtual std::pair<bool,long> doAuthorization(SPRequest& request) const;
         
-        //virtual const IApplication* getApplication(const char* applicationId) const=0;
+        /**
+         * Publishes session contents to the request in the form of headers or environment variables.
+         * 
+         * <p>If the return value's first member is true, then request processing should terminate
+         * with the second member as a status value. If false, processing can continue. 
+         * 
+         * @param request   SP request interface
+         * @param requireSession    set to true iff an error should result if no session exists 
+         * @return a pair containing a "request completed" indicator and a server-specific response code
+         */
+        virtual std::pair<bool,long> doExport(SPRequest& request, bool requireSession=true) const;
+
+        /**
+         * Services requests for registered Handler locations. 
+         * 
+         * <p>If the return value's first member is true, then request processing should terminate
+         * with the second member as a status value. If false, processing can continue. 
+         * 
+         * @param request   SP request interface
+         * @return a pair containing a "request completed" indicator and a server-specific response code
+         */
+        virtual std::pair<bool,long> doHandler(SPRequest& request) const;
     };
 
     /**
diff --git a/shibsp/SessionCache.h b/shibsp/SessionCache.h
new file mode 100644 (file)
index 0000000..19ed841
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/SessionCache.h
+ * 
+ * Caches and manages user sessions
+ */
+
+#ifndef __shibsp_sessioncache_h__
+#define __shibsp_sessioncache_h__
+
+#include <xmltooling/Lockable.h>
+#include <xercesc/dom/DOM.hpp>
+
+namespace shibsp {
+
+    class SHIBSP_API Session : public virtual xmltooling::Lockable
+    {
+        MAKE_NONCOPYABLE(Session);
+    protected:
+        Session() {}
+        virtual ~Session() {}
+    public:
+        /* TODO: design new interface, probably with version-specific subinterfaces
+        virtual const char* getClientAddress() const=0;
+        virtual const char* getProviderId() const=0;
+        virtual std::pair<const char*,const saml::SAMLSubject*> getSubject(bool xml=true, bool obj=false) const=0;
+        virtual const char* getAuthnContext() const=0;
+        virtual std::pair<const char*,const saml::SAMLResponse*> getTokens(bool xml=true, bool obj=false) const=0;
+        virtual std::pair<const char*,const saml::SAMLResponse*> getFilteredTokens(bool xml=true, bool obj=false) const=0;
+        */
+    };
+    
+    /**
+     * Creates and manages user sessions
+     * 
+     * The cache abstracts a persistent (meaning across requests) cache of
+     * instances of the Session interface. Creation of new entries and entry
+     * lookup are confined to this interface to enable the implementation to
+     * remote and/or optimize calls by implementing custom versions of the
+     * Session interface as required.
+     */
+    class SHIBSP_API SessionCache
+    {
+        MAKE_NONCOPYABLE(SessionCache);
+    public:
+        /**
+         * Constructor
+         */
+        SessionCache(const xercesc::DOMElement* e);
+
+        virtual ~SessionCache();
+
+    };
+};
+
+#endif /* __shibsp_sessioncache_h__ */
similarity index 75%
rename from xmlproviders/XMLAccessControl.cpp
rename to shibsp/impl/XMLAccessControl.cpp
index 9d1fbb0..6bdcb08 100644 (file)
-/*
- *  Copyright 2001-2005 Internet2
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* XMLAccessControl.cpp - an XML-based access control syntax
-
-   Scott Cantor
-   10/25/05
-*/
-
-#include "internal.h"
-
-#include <algorithm>
-
-#include <shib-target/shib-target.h>
-#include <xmltooling/util/ReloadableXMLFile.h>
-#include <xmltooling/util/XMLHelper.h>
-
-#ifndef HAVE_STRCASECMP
-# define strcasecmp _stricmp
-#endif
-
-using namespace shibsp;
-using namespace shibtarget;
-using namespace saml;
-using namespace shibboleth;
-using namespace xmltooling;
-using namespace std;
-
-namespace {
-    struct IAuthz {
-        virtual ~IAuthz() {}
-        virtual bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const=0;
-    };
-    
-    class Rule : public IAuthz
-    {
-    public:
-        Rule(const DOMElement* e);
-        ~Rule() {}
-        bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const;
-    
-    private:
-        string m_alias;
-        vector <string> m_vals;
-    };
-    
-    class Operator : public IAuthz
-    {
-    public:
-        Operator(const DOMElement* e);
-        ~Operator();
-        bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const;
-        
-    private:
-        enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
-        vector<IAuthz*> m_operands;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4250 )
-#endif
-
-    class XMLAccessControl : public IAccessControl, public ReloadableXMLFile
-    {
-    public:
-        XMLAccessControl(const DOMElement* e) : ReloadableXMLFile(e), m_rootAuthz(NULL) {
-            load(); // guarantees an exception or the policy is loaded
-        }
-        
-        ~XMLAccessControl() {
-            delete m_rootAuthz;
-        }
-
-        bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const;
-
-    protected:
-        pair<bool,DOMElement*> load();
-
-    private:
-        IAuthz* m_rootAuthz;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-    static const XMLCh AccessControl[] =    UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
-    static const XMLCh require[] =          UNICODE_LITERAL_7(r,e,q,u,i,r,e);
-    static const XMLCh NOT[] =              UNICODE_LITERAL_3(N,O,T);
-    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);
-    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);
-    static const XMLCh _Rule[] =            UNICODE_LITERAL_4(R,u,l,e);
-}
-
-IPlugIn* XMLAccessControlFactory(const DOMElement* e)
-{
-    return new XMLAccessControl(e);
-}
-
-Rule::Rule(const DOMElement* e)
-{
-    xmltooling::auto_ptr_char req(e->getAttributeNS(NULL,require));
-    if (!req.get() || !*req.get())
-        throw ConfigurationException("Access control rule missing require attribute");
-    m_alias=req.get();
-    
-    xmltooling::auto_ptr_char vals(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL);
-#ifdef HAVE_STRTOK_R
-    char* pos=NULL;
-    const char* token=strtok_r(const_cast<char*>(vals.get()),"/",&pos);
-#else
-    const char* token=strtok(const_cast<char*>(vals.get()),"/");
-#endif
-    while (token) {
-        m_vals.push_back(token);
-#ifdef HAVE_STRTOK_R
-        token=strtok_r(NULL,"/",&pos);
-#else
-        token=strtok(NULL,"/");
-#endif
-    }
-}
-
-bool Rule::authorized(ShibTarget* st, ISessionCacheEntry* entry) const
-{
-    // Map alias in rule to the attribute.
-    Iterator<IAAP*> provs=st->getApplication()->getAAPProviders();
-    AAP wrapper(provs,m_alias.c_str());
-    if (wrapper.fail()) {
-        st->log(ShibTarget::LogLevelWarn, string("AccessControl plugin didn't recognize rule (") + m_alias + "), check AAP for corresponding Alias");
-        return false;
-    }
-    else if (!entry) {
-        st->log(ShibTarget::LogLevelWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
-        return false;
-    }
-    
-    // Find the corresponding attribute. This isn't very efficient...
-    pair<const char*,const SAMLResponse*> filtered=entry->getFilteredTokens(false,true);
-    Iterator<SAMLAssertion*> a_iter(filtered.second ? filtered.second->getAssertions() : EMPTY(SAMLAssertion*));
-    while (a_iter.hasNext()) {
-        SAMLAssertion* assert=a_iter.next();
-        Iterator<SAMLStatement*> statements=assert->getStatements();
-        while (statements.hasNext()) {
-            SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());
-            if (!astate)
-                continue;
-            Iterator<SAMLAttribute*> attrs=astate->getAttributes();
-            while (attrs.hasNext()) {
-                SAMLAttribute* attr=attrs.next();
-                if (!XMLString::compareString(attr->getName(),wrapper->getName()) &&
-                    !XMLString::compareString(attr->getNamespace(),wrapper->getNamespace())) {
-                    // Now we have to intersect the attribute's values against the rule's list.
-                    Iterator<string> vals=attr->getSingleByteValues();
-                    if (!vals.hasNext())
-                        return false;
-                    for (vector<string>::const_iterator ival=m_vals.begin(); ival!=m_vals.end(); ival++) {
-                        vals.reset();
-                        while (vals.hasNext()) {
-                            const string& v=vals.next();
-                            if ((wrapper->getCaseSensitive() && v == *ival) || (!wrapper->getCaseSensitive() && !strcasecmp(v.c_str(),ival->c_str()))) {
-                                st->log(ShibTarget::LogLevelDebug, string("XMLAccessControl plugin expecting " + *ival + ", authz granted"));
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-    
-    return false;
-}
-
-Operator::Operator(const DOMElement* e)
-{
-    if (XMLString::equals(e->getLocalName(),NOT))
-        m_op=OP_NOT;
-    else if (XMLString::equals(e->getLocalName(),AND))
-        m_op=OP_AND;
-    else if (XMLString::equals(e->getLocalName(),OR))
-        m_op=OP_OR;
-    else
-        throw ConfigurationException("Unrecognized operator in access control rule");
-    
-    try {
-        e=XMLHelper::getFirstChildElement(e);
-        if (XMLString::equals(e->getLocalName(),_Rule))
-            m_operands.push_back(new Rule(e));
-        else
-            m_operands.push_back(new Operator(e));
-        
-        if (m_op==OP_NOT)
-            return;
-        
-        e=XMLHelper::getNextSiblingElement(e);
-        while (e) {
-            if (XMLString::equals(e->getLocalName(),_Rule))
-                m_operands.push_back(new Rule(e));
-            else
-                m_operands.push_back(new Operator(e));
-            e=XMLHelper::getNextSiblingElement(e);
-        }
-    }
-    catch (exception&) {
-        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<IAuthz>());
-        throw;
-    }
-}
-
-Operator::~Operator()
-{
-    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<IAuthz>());
-}
-
-bool Operator::authorized(ShibTarget* st, ISessionCacheEntry* entry) const
-{
-    switch (m_op) {
-        case OP_NOT:
-            return !m_operands[0]->authorized(st,entry);
-        
-        case OP_AND:
-        {
-            for (vector<IAuthz*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
-                if (!(*i)->authorized(st,entry))
-                    return false;
-            }
-            return true;
-        }
-        
-        case OP_OR:
-        {
-            for (vector<IAuthz*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
-                if ((*i)->authorized(st,entry))
-                    return true;
-            }
-            return false;
-        }
-    }
-    st->log(ShibTarget::LogLevelWarn,"Unknown operation in access control policy, denying access");
-    return false;
-}
-
-pair<bool,DOMElement*> XMLAccessControl::load()
-{
-    // Load from source using base class.
-    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-    
-    // If we own it, wrap it.
-    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
-
-    // Check for AccessControl wrapper and drop a level.
-    if (XMLString::equals(raw.second->getLocalName(),AccessControl))
-        raw.second = XMLHelper::getFirstChildElement(raw.second);
-    
-    IAuthz* authz;
-    if (XMLString::equals(raw.second->getLocalName(),_Rule))
-        authz=new Rule(raw.second);
-    else
-        authz=new Operator(raw.second);
-
-    delete m_rootAuthz;
-    m_rootAuthz = authz;
-    return make_pair(false,(DOMElement*)NULL);
-}
-
-bool XMLAccessControl::authorized(ShibTarget* st, ISessionCacheEntry* entry) const
-{
-    return m_rootAuthz ? m_rootAuthz->authorized(st,entry) : false;
-}
+/*\r
+ *  Copyright 2001-2005 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
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * XMLAccessControl.cpp\r
+ *\r
+ * XML-based access control syntax\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "AccessControl.h"\r
+#include "SessionCache.h"\r
+\r
+#include <xmltooling/util/ReloadableXMLFile.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+#ifndef HAVE_STRCASECMP\r
+# define strcasecmp _stricmp\r
+#endif\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace {\r
+    \r
+    class Rule : public AccessControl\r
+    {\r
+    public:\r
+        Rule(const DOMElement* e);\r
+        ~Rule() {}\r
+\r
+        Lockable* lock() {return this;}\r
+        void unlock() {}\r
+\r
+        bool authorized(SPRequest& request, Session* session) const;\r
+    \r
+    private:\r
+        string m_alias;\r
+        vector <string> m_vals;\r
+    };\r
+    \r
+    class Operator : public AccessControl\r
+    {\r
+    public:\r
+        Operator(const DOMElement* e);\r
+        ~Operator();\r
+\r
+        Lockable* lock() {return this;}\r
+        void unlock() {}\r
+\r
+        bool authorized(SPRequest& request, Session* session) const;\r
+        \r
+    private:\r
+        enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;\r
+        vector<AccessControl*> m_operands;\r
+    };\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( push )\r
+    #pragma warning( disable : 4250 )\r
+#endif\r
+\r
+    class XMLAccessControl : public AccessControl, public ReloadableXMLFile\r
+    {\r
+    public:\r
+        XMLAccessControl(const DOMElement* e) : ReloadableXMLFile(e), m_rootAuthz(NULL) {\r
+            load(); // guarantees an exception or the policy is loaded\r
+        }\r
+        \r
+        ~XMLAccessControl() {\r
+            delete m_rootAuthz;\r
+        }\r
+\r
+        bool authorized(SPRequest& request, Session* session) const;\r
+\r
+    protected:\r
+        pair<bool,DOMElement*> load();\r
+\r
+    private:\r
+        AccessControl* m_rootAuthz;\r
+    };\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( pop )\r
+#endif\r
+\r
+    AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)\r
+    {\r
+        return new XMLAccessControl(e);\r
+    }\r
+\r
+    static const XMLCh _AccessControl[] =    UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
+    static const XMLCh require[] =          UNICODE_LITERAL_7(r,e,q,u,i,r,e);\r
+    static const XMLCh NOT[] =              UNICODE_LITERAL_3(N,O,T);\r
+    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);\r
+    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);\r
+    static const XMLCh _Rule[] =            UNICODE_LITERAL_4(R,u,l,e);\r
+}\r
+\r
+void SHIBSP_API shibsp::registerAccessControls()\r
+{\r
+    SPConfig::getConfig().AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
+}\r
+\r
+Rule::Rule(const DOMElement* e)\r
+{\r
+    xmltooling::auto_ptr_char req(e->getAttributeNS(NULL,require));\r
+    if (!req.get() || !*req.get())\r
+        throw ConfigurationException("Access control rule missing require attribute");\r
+    m_alias=req.get();\r
+    \r
+    xmltooling::auto_ptr_char vals(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL);\r
+#ifdef HAVE_STRTOK_R\r
+    char* pos=NULL;\r
+    const char* token=strtok_r(const_cast<char*>(vals.get()),"/",&pos);\r
+#else\r
+    const char* token=strtok(const_cast<char*>(vals.get()),"/");\r
+#endif\r
+    while (token) {\r
+        m_vals.push_back(token);\r
+#ifdef HAVE_STRTOK_R\r
+        token=strtok_r(NULL,"/",&pos);\r
+#else\r
+        token=strtok(NULL,"/");\r
+#endif\r
+    }\r
+}\r
+\r
+bool Rule::authorized(SPRequest& request, Session* session) const\r
+{\r
+    /*\r
+    TODO: port...\r
+    // Map alias in rule to the attribute.\r
+    Iterator<IAAP*> provs=st->getApplication()->getAAPProviders();\r
+    AAP wrapper(provs,m_alias.c_str());\r
+    if (wrapper.fail()) {\r
+        st->log(ShibTarget::LogLevelWarn, string("AccessControl plugin didn't recognize rule (") + m_alias + "), check AAP for corresponding Alias");\r
+        return false;\r
+    }\r
+    else if (!entry) {\r
+        st->log(ShibTarget::LogLevelWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
+        return false;\r
+    }\r
+    \r
+    // Find the corresponding attribute. This isn't very efficient...\r
+    pair<const char*,const SAMLResponse*> filtered=entry->getFilteredTokens(false,true);\r
+    Iterator<SAMLAssertion*> a_iter(filtered.second ? filtered.second->getAssertions() : EMPTY(SAMLAssertion*));\r
+    while (a_iter.hasNext()) {\r
+        SAMLAssertion* assert=a_iter.next();\r
+        Iterator<SAMLStatement*> statements=assert->getStatements();\r
+        while (statements.hasNext()) {\r
+            SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());\r
+            if (!astate)\r
+                continue;\r
+            Iterator<SAMLAttribute*> attrs=astate->getAttributes();\r
+            while (attrs.hasNext()) {\r
+                SAMLAttribute* attr=attrs.next();\r
+                if (!XMLString::compareString(attr->getName(),wrapper->getName()) &&\r
+                    !XMLString::compareString(attr->getNamespace(),wrapper->getNamespace())) {\r
+                    // Now we have to intersect the attribute's values against the rule's list.\r
+                    Iterator<string> vals=attr->getSingleByteValues();\r
+                    if (!vals.hasNext())\r
+                        return false;\r
+                    for (vector<string>::const_iterator ival=m_vals.begin(); ival!=m_vals.end(); ival++) {\r
+                        vals.reset();\r
+                        while (vals.hasNext()) {\r
+                            const string& v=vals.next();\r
+                            if ((wrapper->getCaseSensitive() && v == *ival) || (!wrapper->getCaseSensitive() && !strcasecmp(v.c_str(),ival->c_str()))) {\r
+                                st->log(ShibTarget::LogLevelDebug, string("XMLAccessControl plugin expecting " + *ival + ", authz granted"));\r
+                                return true;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    */\r
+    return true;\r
+}\r
+\r
+Operator::Operator(const DOMElement* e)\r
+{\r
+    if (XMLString::equals(e->getLocalName(),NOT))\r
+        m_op=OP_NOT;\r
+    else if (XMLString::equals(e->getLocalName(),AND))\r
+        m_op=OP_AND;\r
+    else if (XMLString::equals(e->getLocalName(),OR))\r
+        m_op=OP_OR;\r
+    else\r
+        throw ConfigurationException("Unrecognized operator in access control rule");\r
+    \r
+    try {\r
+        e=XMLHelper::getFirstChildElement(e);\r
+        if (XMLString::equals(e->getLocalName(),_Rule))\r
+            m_operands.push_back(new Rule(e));\r
+        else\r
+            m_operands.push_back(new Operator(e));\r
+        \r
+        if (m_op==OP_NOT)\r
+            return;\r
+        \r
+        e=XMLHelper::getNextSiblingElement(e);\r
+        while (e) {\r
+            if (XMLString::equals(e->getLocalName(),_Rule))\r
+                m_operands.push_back(new Rule(e));\r
+            else\r
+                m_operands.push_back(new Operator(e));\r
+            e=XMLHelper::getNextSiblingElement(e);\r
+        }\r
+    }\r
+    catch (exception&) {\r
+        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
+        throw;\r
+    }\r
+}\r
+\r
+Operator::~Operator()\r
+{\r
+    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
+}\r
+\r
+bool Operator::authorized(SPRequest& request, Session* session) const\r
+{\r
+    switch (m_op) {\r
+        case OP_NOT:\r
+            return !m_operands[0]->authorized(request,session);\r
+        \r
+        case OP_AND:\r
+        {\r
+            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
+                if (!(*i)->authorized(request,session))\r
+                    return false;\r
+            }\r
+            return true;\r
+        }\r
+        \r
+        case OP_OR:\r
+        {\r
+            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
+                if ((*i)->authorized(request,session))\r
+                    return true;\r
+            }\r
+            return false;\r
+        }\r
+    }\r
+    //st->log(ShibTarget::LogLevelWarn,"Unknown operation in access control policy, denying access");\r
+    return false;\r
+}\r
+\r
+pair<bool,DOMElement*> XMLAccessControl::load()\r
+{\r
+    // Load from source using base class.\r
+    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
+    \r
+    // If we own it, wrap it.\r
+    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
+\r
+    // Check for AccessControl wrapper and drop a level.\r
+    if (XMLString::equals(raw.second->getLocalName(),_AccessControl))\r
+        raw.second = XMLHelper::getFirstChildElement(raw.second);\r
+    \r
+    AccessControl* authz;\r
+    if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
+        authz=new Rule(raw.second);\r
+    else\r
+        authz=new Operator(raw.second);\r
+\r
+    delete m_rootAuthz;\r
+    m_rootAuthz = authz;\r
+    return make_pair(false,(DOMElement*)NULL);\r
+}\r
+\r
+bool XMLAccessControl::authorized(SPRequest& request, Session* session) const\r
+{\r
+    return m_rootAuthz ? m_rootAuthz->authorized(request,session) : false;\r
+}\r
similarity index 85%
rename from shib-target/XMLRequestMapper.cpp
rename to shibsp/impl/XMLRequestMapper.cpp
index 621feab..05521c0 100644 (file)
-/*
- *  Copyright 2001-2005 Internet2
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* XMLRequestMapper.cpp - an XML-based map of URLs to application names and settings
-
-   Scott Cantor
-   1/6/04
-
-   $History:$
-*/
-
-#include "internal.h"
-
-#include <algorithm>
-#include <shibsp/DOMPropertySet.h>
-#include <xmltooling/util/ReloadableXMLFile.h>
-#include <xmltooling/util/XMLHelper.h>
-
-using namespace shibsp;
-using namespace shibtarget;
-using namespace xmltooling;
-using namespace log4cpp;
-using namespace std;
-
-namespace shibtarget {
-
-    // Blocks access when an ACL plugin fails to load. 
-    class AccessControlDummy : public IAccessControl
-    {
-    public:
-        Lockable* lock() {
-            return this;
-        }
-        
-        void unlock() {}
-    
-        bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const {
-            return false;
-        }
-    };
-
-    class Override : public DOMPropertySet, public DOMNodeFilter
-    {
-    public:
-        Override() : m_base(NULL), m_acl(NULL) {}
-        Override(const DOMElement* e, Category& log, const Override* base=NULL);
-        ~Override();
-
-        // PropertySet
-        pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;
-        pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;
-        pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const;
-        pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const;
-        pair<bool,int> getInt(const char* name, const char* ns=NULL) const;
-        const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const;
-        
-        // Provides filter to exclude special config elements.
-        short acceptNode(const DOMNode* node) const;
-
-        const Override* locate(const char* path) const;
-        IAccessControl* getAC() const { return (m_acl ? m_acl : (m_base ? m_base->getAC() : NULL)); }
-        
-    protected:
-        void loadACL(const DOMElement* e, Category& log);
-        
-        map<string,Override*> m_map;
-    
-    private:
-        const Override* m_base;
-        IAccessControl* m_acl;
-    };
-
-    class XMLRequestMapperImpl : public Override
-    {
-    public:
-        XMLRequestMapperImpl(const DOMElement* e, Category& log);
-
-        ~XMLRequestMapperImpl() {
-            if (m_document)
-                m_document->release();
-        }
-
-        void setDocument(DOMDocument* doc) {
-            m_document = doc;
-        }
-    
-        const Override* findOverride(const char* vhost, const char* path) const;
-
-    private:    
-        map<string,Override*> m_extras;
-        DOMDocument* m_document;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4250 )
-#endif
-
-    class XMLRequestMapper : public IRequestMapper, public ReloadableXMLFile
-    {
-    public:
-        XMLRequestMapper(const DOMElement* e)
-                : ReloadableXMLFile(e), m_impl(NULL), m_log(Category::getInstance(SHIBT_LOGCAT".RequestMapper")) {
-            load();
-        }
-
-        ~XMLRequestMapper() {
-            delete m_impl;
-        }
-
-        virtual Settings getSettings(ShibTarget* st) const;
-
-    protected:
-        pair<bool,DOMElement*> load();
-
-    private:
-        XMLRequestMapperImpl* m_impl;
-        Category& m_log;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-    static const XMLCh AccessControl[] =            UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
-    static const XMLCh AccessControlProvider[] =    UNICODE_LITERAL_21(A,c,c,e,s,s,C,o,n,t,r,o,l,P,r,o,v,i,d,e,r);
-    static const XMLCh htaccess[] =                 UNICODE_LITERAL_8(h,t,a,c,c,e,s,s);
-    static const XMLCh Host[] =                     UNICODE_LITERAL_4(H,o,s,t);
-    static const XMLCh Path[] =                     UNICODE_LITERAL_4(P,a,t,h);
-    static const XMLCh name[] =                     UNICODE_LITERAL_4(n,a,m,e);
-    static const XMLCh type[] =                     UNICODE_LITERAL_4(t,y,p,e);
-}
-
-saml::IPlugIn* XMLRequestMapFactory(const DOMElement* e)
-{
-    return new XMLRequestMapper(e);
-}
-
-short Override::acceptNode(const DOMNode* node) const
-{
-    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB1SPCONFIG_NS))
-        return FILTER_ACCEPT;
-    const XMLCh* name=node->getLocalName();
-    if (XMLString::equals(name,Host) ||
-        XMLString::equals(name,Path) ||
-        XMLString::equals(name,AccessControl) ||
-        XMLString::equals(name,htaccess) ||
-        XMLString::equals(name,AccessControlProvider))
-        return FILTER_REJECT;
-
-    return FILTER_ACCEPT;
-}
-
-void Override::loadACL(const DOMElement* e, Category& log)
-{
-    try {
-        saml::IPlugIn* plugin=NULL;
-        const DOMElement* acl=XMLHelper::getFirstChildElement(e,htaccess);
-        if (acl) {
-            log.info("building Apache htaccess provider...");
-            plugin=saml::SAMLConfig::getConfig().getPlugMgr().newPlugin(HTACCESS_ACCESSCONTROL,acl);
-        }
-        else {
-            acl=XMLHelper::getFirstChildElement(e,AccessControl);
-            if (acl) {
-                log.info("building XML-based Access Control provider...");
-                plugin=saml::SAMLConfig::getConfig().getPlugMgr().newPlugin(XML_ACCESSCONTROL,acl);
-            }
-            else {
-                acl=XMLHelper::getFirstChildElement(e,AccessControlProvider);
-                if (acl) {
-                    xmltooling::auto_ptr_char type(acl->getAttributeNS(NULL,type));
-                    log.info("building Access Control provider of type %s...",type.get());
-                    plugin=saml::SAMLConfig::getConfig().getPlugMgr().newPlugin(type.get(),acl);
-                }
-            }
-        }
-        if (plugin) {
-            IAccessControl* acl=dynamic_cast<IAccessControl*>(plugin);
-            if (acl)
-                m_acl=acl;
-            else {
-                delete plugin;
-                throw UnknownExtensionException("plugin was not an Access Control provider");
-            }
-        }
-    }
-    catch (exception& ex) {
-        log.crit("exception building AccessControl provider: %s", ex.what());
-        m_acl = new AccessControlDummy();
-    }
-}
-
-Override::Override(const DOMElement* e, Category& log, const Override* base) : m_base(base), m_acl(NULL)
-{
-    try {
-        // Load the property set.
-        load(e,log,this);
-        
-        // Load any AccessControl provider.
-        loadACL(e,log);
-    
-        // Handle nested Paths.
-        DOMElement* path = XMLHelper::getFirstChildElement(e,Path);
-        for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Path)) {
-            const XMLCh* n=path->getAttributeNS(NULL,name);
-            
-            // Skip any leading slashes.
-            while (n && *n==chForwardSlash)
-                n++;
-            
-            // Check for empty name.
-            if (!n || !*n) {
-                log.warn("skipping Path element (%d) with empty name attribute", i);
-                continue;
-            }
-
-            // Check for an embedded slash.
-            int slash=XMLString::indexOf(n,chForwardSlash);
-            if (slash>0) {
-                // Copy the first path segment.
-                XMLCh* namebuf=new XMLCh[slash + 1];
-                for (int pos=0; pos < slash; pos++)
-                    namebuf[pos]=n[pos];
-                namebuf[slash]=chNull;
-                
-                // Move past the slash in the original pathname.
-                n=n+slash+1;
-                
-                // Skip any leading slashes again.
-                while (*n==chForwardSlash)
-                    n++;
-                
-                if (*n) {
-                    // Create a placeholder Path element for the first path segment and replant under it.
-                    DOMElement* newpath=path->getOwnerDocument()->createElementNS(shibspconstants::SHIB1SPCONFIG_NS,Path);
-                    newpath->setAttributeNS(NULL,name,namebuf);
-                    path->setAttributeNS(NULL,name,n);
-                    path->getParentNode()->replaceChild(newpath,path);
-                    newpath->appendChild(path);
-                    
-                    // Repoint our locals at the new parent.
-                    path=newpath;
-                    n=path->getAttributeNS(NULL,name);
-                }
-                else {
-                    // All we had was a pathname with trailing slash(es), so just reset it without them.
-                    path->setAttributeNS(NULL,name,namebuf);
-                    n=path->getAttributeNS(NULL,name);
-                }
-                delete[] namebuf;
-            }
-            
-            Override* o=new Override(path,log,this);
-            pair<bool,const char*> name=o->getString("name");
-            char* dup=strdup(name.second);
-            for (char* pch=dup; *pch; pch++)
-                *pch=tolower(*pch);
-            if (m_map.count(dup)) {
-                log.warn("Skipping duplicate Path element (%s)",dup);
-                free(dup);
-                delete o;
-                continue;
-            }
-            m_map[dup]=o;
-            free(dup);
-        }
-    }
-    catch (exception&) {
-        delete m_acl;
-        for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());
-        throw;
-    }
-}
-
-Override::~Override()
-{
-    delete m_acl;
-    for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());
-}
-
-pair<bool,bool> Override::getBool(const char* name, const char* ns) const
-{
-    pair<bool,bool> ret=DOMPropertySet::getBool(name,ns);
-    if (ret.first)
-        return ret;
-    return m_base ? m_base->getBool(name,ns) : ret;
-}
-
-pair<bool,const char*> Override::getString(const char* name, const char* ns) const
-{
-    pair<bool,const char*> ret=DOMPropertySet::getString(name,ns);
-    if (ret.first)
-        return ret;
-    return m_base ? m_base->getString(name,ns) : ret;
-}
-
-pair<bool,const XMLCh*> Override::getXMLString(const char* name, const char* ns) const
-{
-    pair<bool,const XMLCh*> ret=DOMPropertySet::getXMLString(name,ns);
-    if (ret.first)
-        return ret;
-    return m_base ? m_base->getXMLString(name,ns) : ret;
-}
-
-pair<bool,unsigned int> Override::getUnsignedInt(const char* name, const char* ns) const
-{
-    pair<bool,unsigned int> ret=DOMPropertySet::getUnsignedInt(name,ns);
-    if (ret.first)
-        return ret;
-    return m_base ? m_base->getUnsignedInt(name,ns) : ret;
-}
-
-pair<bool,int> Override::getInt(const char* name, const char* ns) const
-{
-    pair<bool,int> ret=DOMPropertySet::getInt(name,ns);
-    if (ret.first)
-        return ret;
-    return m_base ? m_base->getInt(name,ns) : ret;
-}
-
-const PropertySet* Override::getPropertySet(const char* name, const char* ns) const
-{
-    const PropertySet* ret=DOMPropertySet::getPropertySet(name,ns);
-    if (ret || !m_base)
-        return ret;
-    return m_base->getPropertySet(name,ns);
-}
-
-const Override* Override::locate(const char* path) const
-{
-    char* dup=strdup(path);
-    char* sep=strchr(dup,'?');
-    if (sep)
-        *sep=0;
-    for (char* pch=dup; *pch; pch++)
-        *pch=tolower(*pch);
-        
-    const Override* o=this;
-    
-#ifdef HAVE_STRTOK_R
-    char* pos=NULL;
-    const char* token=strtok_r(dup,"/",&pos);
-#else
-    const char* token=strtok(dup,"/");
-#endif
-    while (token)
-    {
-        map<string,Override*>::const_iterator i=o->m_map.find(token);
-        if (i==o->m_map.end())
-            break;
-        o=i->second;
-#ifdef HAVE_STRTOK_R
-        token=strtok_r(NULL,"/",&pos);
-#else
-        token=strtok(NULL,"/");
-#endif
-    }
-
-    free(dup);
-    return o;
-}
-
-XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) : m_document(NULL)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("XMLRequestMapperImpl");
-#endif
-
-    // Load the property set.
-    load(e,log,this);
-    
-    // Load any AccessControl provider.
-    loadACL(e,log);
-
-    // Loop over the Host elements.
-    const DOMElement* host = XMLHelper::getFirstChildElement(e,Host);
-    for (int i=1; host; ++i, host=XMLHelper::getNextSiblingElement(host,Host)) {
-        const XMLCh* n=host->getAttributeNS(NULL,name);
-        if (!n || !*n) {
-            log.warn("Skipping Host element (%d) with empty name attribute",i);
-            continue;
-        }
-        
-        Override* o=new Override(host,log,this);
-        pair<bool,const char*> name=o->getString("name");
-        pair<bool,const char*> scheme=o->getString("scheme");
-        pair<bool,const char*> port=o->getString("port");
-        
-        char* dup=strdup(name.second);
-        for (char* pch=dup; *pch; pch++)
-            *pch=tolower(*pch);
-        auto_ptr<char> dupwrap(dup);
-
-        if (!scheme.first && port.first) {
-            // No scheme, but a port, so assume http.
-            scheme = pair<bool,const char*>(true,"http");
-        }
-        else if (scheme.first && !port.first) {
-            // Scheme, no port, so default it.
-            // XXX Use getservbyname instead?
-            port.first = true;
-            if (!strcmp(scheme.second,"http"))
-                port.second = "80";
-            else if (!strcmp(scheme.second,"https"))
-                port.second = "443";
-            else if (!strcmp(scheme.second,"ftp"))
-                port.second = "21";
-            else if (!strcmp(scheme.second,"ldap"))
-                port.second = "389";
-            else if (!strcmp(scheme.second,"ldaps"))
-                port.second = "636";
-        }
-
-        if (scheme.first) {
-            string url(scheme.second);
-            url=url + "://" + dup;
-            
-            // Is this the default port?
-            if ((!strcmp(scheme.second,"http") && !strcmp(port.second,"80")) ||
-                (!strcmp(scheme.second,"https") && !strcmp(port.second,"443")) ||
-                (!strcmp(scheme.second,"ftp") && !strcmp(port.second,"21")) ||
-                (!strcmp(scheme.second,"ldap") && !strcmp(port.second,"389")) ||
-                (!strcmp(scheme.second,"ldaps") && !strcmp(port.second,"636"))) {
-                // First store a port-less version.
-                if (m_map.count(url) || m_extras.count(url)) {
-                    log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                    delete o;
-                    continue;
-                }
-                m_map[url]=o;
-                log.debug("Added <Host> mapping for %s",url.c_str());
-                
-                // Now append the port. We use the extras vector, to avoid double freeing the object later.
-                url=url + ':' + port.second;
-                m_extras[url]=o;
-                log.debug("Added <Host> mapping for %s",url.c_str());
-            }
-            else {
-                url=url + ':' + port.second;
-                if (m_map.count(url) || m_extras.count(url)) {
-                    log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                    delete o;
-                    continue;
-                }
-                m_map[url]=o;
-                log.debug("Added <Host> mapping for %s",url.c_str());
-            }
-        }
-        else {
-            // No scheme or port, so we enter dual hosts on http:80 and https:443
-            string url("http://");
-            url = url + dup;
-            if (m_map.count(url) || m_extras.count(url)) {
-                log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                delete o;
-                continue;
-            }
-            m_map[url]=o;
-            log.debug("Added <Host> mapping for %s",url.c_str());
-            
-            url = url + ":80";
-            if (m_map.count(url) || m_extras.count(url)) {
-                log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                continue;
-            }
-            m_extras[url]=o;
-            log.debug("Added <Host> mapping for %s",url.c_str());
-            
-            url = "https://";
-            url = url + dup;
-            if (m_map.count(url) || m_extras.count(url)) {
-                log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                continue;
-            }
-            m_extras[url]=o;
-            log.debug("Added <Host> mapping for %s",url.c_str());
-            
-            url = url + ":443";
-            if (m_map.count(url) || m_extras.count(url)) {
-                log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                continue;
-            }
-            m_extras[url]=o;
-            log.debug("Added <Host> mapping for %s",url.c_str());
-        }
-    }
-}
-
-const Override* XMLRequestMapperImpl::findOverride(const char* vhost, const char* path) const
-{
-    const Override* o=NULL;
-    map<string,Override*>::const_iterator i=m_map.find(vhost);
-    if (i!=m_map.end())
-        o=i->second;
-    else {
-        i=m_extras.find(vhost);
-        if (i!=m_extras.end())
-            o=i->second;
-    }
-    
-    return o ? o->locate(path) : this;
-}
-
-pair<bool,DOMElement*> XMLRequestMapper::load()
-{
-    // Load from source using base class.
-    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-    
-    // If we own it, wrap it.
-    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
-
-    XMLRequestMapperImpl* impl = new XMLRequestMapperImpl(raw.second,m_log);
-    
-    // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
-    impl->setDocument(docjanitor.release());
-
-    delete m_impl;
-    m_impl = impl;
-
-    return make_pair(false,(DOMElement*)NULL);
-}
-
-IRequestMapper::Settings XMLRequestMapper::getSettings(ShibTarget* st) const
-{
-    ostringstream vhost;
-    vhost << st->getProtocol() << "://" << st->getHostname() << ':' << st->getPort();
-
-    const Override* o=m_impl->findOverride(vhost.str().c_str(), st->getRequestURI());
-
-    if (m_log.isDebugEnabled()) {
-#ifdef _DEBUG
-        xmltooling::NDC ndc("getSettings");
-#endif
-        pair<bool,const char*> ret=o->getString("applicationId");
-        m_log.debug("mapped %s%s to %s", vhost.str().c_str(), st->getRequestURI() ? st->getRequestURI() : "", ret.second);
-    }
-
-    return Settings(o,o->getAC());
-}
+/*\r
+ *  Copyright 2001-2005 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
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/** XMLRequestMapper.cpp\r
+ * \r
+ * XML-based RequestMapper implementation\r
+ */\r
+\r
+#include "internal.h"\r
+#include "AccessControl.h"\r
+#include "RequestMapper.h"\r
+#include "SPRequest.h"\r
+#include "util/DOMPropertySet.h"\r
+#include "util/SPConstants.h"\r
+\r
+#include <xmltooling/util/NDC.h>\r
+#include <xmltooling/util/ReloadableXMLFile.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+\r
+    // Blocks access when an ACL plugin fails to load. \r
+    class AccessControlDummy : public AccessControl\r
+    {\r
+    public:\r
+        Lockable* lock() {\r
+            return this;\r
+        }\r
+        \r
+        void unlock() {}\r
+    \r
+        bool authorized(SPRequest& request, Session* session) const {\r
+            return false;\r
+        }\r
+    };\r
+\r
+    class Override : public DOMPropertySet, public DOMNodeFilter\r
+    {\r
+    public:\r
+        Override() : m_base(NULL), m_acl(NULL) {}\r
+        Override(const DOMElement* e, Category& log, const Override* base=NULL);\r
+        ~Override();\r
+\r
+        // PropertySet\r
+        pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;\r
+        pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;\r
+        pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const;\r
+        pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const;\r
+        pair<bool,int> getInt(const char* name, const char* ns=NULL) const;\r
+        const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const;\r
+        \r
+        // Provides filter to exclude special config elements.\r
+        short acceptNode(const DOMNode* node) const;\r
+\r
+        const Override* locate(const char* path) const;\r
+        AccessControl* getAC() const { return (m_acl ? m_acl : (m_base ? m_base->getAC() : NULL)); }\r
+        \r
+    protected:\r
+        void loadACL(const DOMElement* e, Category& log);\r
+        \r
+        map<string,Override*> m_map;\r
+    \r
+    private:\r
+        const Override* m_base;\r
+        AccessControl* m_acl;\r
+    };\r
+\r
+    class XMLRequestMapperImpl : public Override\r
+    {\r
+    public:\r
+        XMLRequestMapperImpl(const DOMElement* e, Category& log);\r
+\r
+        ~XMLRequestMapperImpl() {\r
+            if (m_document)\r
+                m_document->release();\r
+        }\r
+\r
+        void setDocument(DOMDocument* doc) {\r
+            m_document = doc;\r
+        }\r
+    \r
+        const Override* findOverride(const char* vhost, const char* path) const;\r
+\r
+    private:    \r
+        map<string,Override*> m_extras;\r
+        DOMDocument* m_document;\r
+    };\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( push )\r
+    #pragma warning( disable : 4250 )\r
+#endif\r
+\r
+    class XMLRequestMapper : public RequestMapper, public ReloadableXMLFile\r
+    {\r
+    public:\r
+        XMLRequestMapper(const DOMElement* e)\r
+                : ReloadableXMLFile(e), m_impl(NULL), m_log(Category::getInstance(SHIBSP_LOGCAT".RequestMapper")) {\r
+            load();\r
+        }\r
+\r
+        ~XMLRequestMapper() {\r
+            delete m_impl;\r
+        }\r
+\r
+        Settings getSettings(const SPRequest& request) const;\r
+\r
+    protected:\r
+        pair<bool,DOMElement*> load();\r
+\r
+    private:\r
+        XMLRequestMapperImpl* m_impl;\r
+        Category& m_log;\r
+    };\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( pop )\r
+#endif\r
+\r
+    RequestMapper* SHIBSP_DLLLOCAL XMLRequestMapperFactory(const DOMElement* const & e)\r
+    {\r
+        return new XMLRequestMapper(e);\r
+    }\r
+\r
+    static const XMLCh _AccessControl[] =            UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
+    static const XMLCh AccessControlProvider[] =    UNICODE_LITERAL_21(A,c,c,e,s,s,C,o,n,t,r,o,l,P,r,o,v,i,d,e,r);\r
+    static const XMLCh htaccess[] =                 UNICODE_LITERAL_8(h,t,a,c,c,e,s,s);\r
+    static const XMLCh Host[] =                     UNICODE_LITERAL_4(H,o,s,t);\r
+    static const XMLCh Path[] =                     UNICODE_LITERAL_4(P,a,t,h);\r
+    static const XMLCh name[] =                     UNICODE_LITERAL_4(n,a,m,e);\r
+    static const XMLCh type[] =                     UNICODE_LITERAL_4(t,y,p,e);\r
+}\r
+\r
+void SHIBSP_API shibsp::registerRequestMappers()\r
+{\r
+    SPConfig& conf=SPConfig::getConfig();\r
+    conf.RequestMapperManager.registerFactory(XML_REQUEST_MAPPER, XMLRequestMapperFactory);\r
+    conf.RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER, XMLRequestMapperFactory);\r
+}\r
+\r
+short Override::acceptNode(const DOMNode* node) const\r
+{\r
+    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB1SPCONFIG_NS))\r
+        return FILTER_ACCEPT;\r
+    const XMLCh* name=node->getLocalName();\r
+    if (XMLString::equals(name,Host) ||\r
+        XMLString::equals(name,Path) ||\r
+        XMLString::equals(name,_AccessControl) ||\r
+        XMLString::equals(name,htaccess) ||\r
+        XMLString::equals(name,AccessControlProvider))\r
+        return FILTER_REJECT;\r
+\r
+    return FILTER_ACCEPT;\r
+}\r
+\r
+void Override::loadACL(const DOMElement* e, Category& log)\r
+{\r
+    try {\r
+        const DOMElement* acl=XMLHelper::getFirstChildElement(e,htaccess);\r
+        if (acl) {\r
+            log.info("building Apache htaccess AccessControl provider...");\r
+            m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(HT_ACCESS_CONTROL,acl);\r
+        }\r
+        else {\r
+            acl=XMLHelper::getFirstChildElement(e,_AccessControl);\r
+            if (acl) {\r
+                log.info("building XML-based AccessControl provider...");\r
+                m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(XML_ACCESS_CONTROL,acl);\r
+            }\r
+            else {\r
+                acl=XMLHelper::getFirstChildElement(e,AccessControlProvider);\r
+                if (acl) {\r
+                    xmltooling::auto_ptr_char type(acl->getAttributeNS(NULL,type));\r
+                    log.info("building AccessControl provider of type %s...",type.get());\r
+                    m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(type.get(),acl);\r
+                }\r
+            }\r
+        }\r
+    }\r
+    catch (exception& ex) {\r
+        log.crit("exception building AccessControl provider: %s", ex.what());\r
+        m_acl = new AccessControlDummy();\r
+    }\r
+}\r
+\r
+Override::Override(const DOMElement* e, Category& log, const Override* base) : m_base(base), m_acl(NULL)\r
+{\r
+    try {\r
+        // Load the property set.\r
+        load(e,log,this);\r
+        \r
+        // Load any AccessControl provider.\r
+        loadACL(e,log);\r
+    \r
+        // Handle nested Paths.\r
+        DOMElement* path = XMLHelper::getFirstChildElement(e,Path);\r
+        for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Path)) {\r
+            const XMLCh* n=path->getAttributeNS(NULL,name);\r
+            \r
+            // Skip any leading slashes.\r
+            while (n && *n==chForwardSlash)\r
+                n++;\r
+            \r
+            // Check for empty name.\r
+            if (!n || !*n) {\r
+                log.warn("skipping Path element (%d) with empty name attribute", i);\r
+                continue;\r
+            }\r
+\r
+            // Check for an embedded slash.\r
+            int slash=XMLString::indexOf(n,chForwardSlash);\r
+            if (slash>0) {\r
+                // Copy the first path segment.\r
+                XMLCh* namebuf=new XMLCh[slash + 1];\r
+                for (int pos=0; pos < slash; pos++)\r
+                    namebuf[pos]=n[pos];\r
+                namebuf[slash]=chNull;\r
+                \r
+                // Move past the slash in the original pathname.\r
+                n=n+slash+1;\r
+                \r
+                // Skip any leading slashes again.\r
+                while (*n==chForwardSlash)\r
+                    n++;\r
+                \r
+                if (*n) {\r
+                    // Create a placeholder Path element for the first path segment and replant under it.\r
+                    DOMElement* newpath=path->getOwnerDocument()->createElementNS(shibspconstants::SHIB1SPCONFIG_NS,Path);\r
+                    newpath->setAttributeNS(NULL,name,namebuf);\r
+                    path->setAttributeNS(NULL,name,n);\r
+                    path->getParentNode()->replaceChild(newpath,path);\r
+                    newpath->appendChild(path);\r
+                    \r
+                    // Repoint our locals at the new parent.\r
+                    path=newpath;\r
+                    n=path->getAttributeNS(NULL,name);\r
+                }\r
+                else {\r
+                    // All we had was a pathname with trailing slash(es), so just reset it without them.\r
+                    path->setAttributeNS(NULL,name,namebuf);\r
+                    n=path->getAttributeNS(NULL,name);\r
+                }\r
+                delete[] namebuf;\r
+            }\r
+            \r
+            Override* o=new Override(path,log,this);\r
+            pair<bool,const char*> name=o->getString("name");\r
+            char* dup=strdup(name.second);\r
+            for (char* pch=dup; *pch; pch++)\r
+                *pch=tolower(*pch);\r
+            if (m_map.count(dup)) {\r
+                log.warn("Skipping duplicate Path element (%s)",dup);\r
+                free(dup);\r
+                delete o;\r
+                continue;\r
+            }\r
+            m_map[dup]=o;\r
+            free(dup);\r
+        }\r
+    }\r
+    catch (exception&) {\r
+        delete m_acl;\r
+        for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());\r
+        throw;\r
+    }\r
+}\r
+\r
+Override::~Override()\r
+{\r
+    delete m_acl;\r
+    for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());\r
+}\r
+\r
+pair<bool,bool> Override::getBool(const char* name, const char* ns) const\r
+{\r
+    pair<bool,bool> ret=DOMPropertySet::getBool(name,ns);\r
+    if (ret.first)\r
+        return ret;\r
+    return m_base ? m_base->getBool(name,ns) : ret;\r
+}\r
+\r
+pair<bool,const char*> Override::getString(const char* name, const char* ns) const\r
+{\r
+    pair<bool,const char*> ret=DOMPropertySet::getString(name,ns);\r
+    if (ret.first)\r
+        return ret;\r
+    return m_base ? m_base->getString(name,ns) : ret;\r
+}\r
+\r
+pair<bool,const XMLCh*> Override::getXMLString(const char* name, const char* ns) const\r
+{\r
+    pair<bool,const XMLCh*> ret=DOMPropertySet::getXMLString(name,ns);\r
+    if (ret.first)\r
+        return ret;\r
+    return m_base ? m_base->getXMLString(name,ns) : ret;\r
+}\r
+\r
+pair<bool,unsigned int> Override::getUnsignedInt(const char* name, const char* ns) const\r
+{\r
+    pair<bool,unsigned int> ret=DOMPropertySet::getUnsignedInt(name,ns);\r
+    if (ret.first)\r
+        return ret;\r
+    return m_base ? m_base->getUnsignedInt(name,ns) : ret;\r
+}\r
+\r
+pair<bool,int> Override::getInt(const char* name, const char* ns) const\r
+{\r
+    pair<bool,int> ret=DOMPropertySet::getInt(name,ns);\r
+    if (ret.first)\r
+        return ret;\r
+    return m_base ? m_base->getInt(name,ns) : ret;\r
+}\r
+\r
+const PropertySet* Override::getPropertySet(const char* name, const char* ns) const\r
+{\r
+    const PropertySet* ret=DOMPropertySet::getPropertySet(name,ns);\r
+    if (ret || !m_base)\r
+        return ret;\r
+    return m_base->getPropertySet(name,ns);\r
+}\r
+\r
+const Override* Override::locate(const char* path) const\r
+{\r
+    char* dup=strdup(path);\r
+    char* sep=strchr(dup,'?');\r
+    if (sep)\r
+        *sep=0;\r
+    for (char* pch=dup; *pch; pch++)\r
+        *pch=tolower(*pch);\r
+        \r
+    const Override* o=this;\r
+    \r
+#ifdef HAVE_STRTOK_R\r
+    char* pos=NULL;\r
+    const char* token=strtok_r(dup,"/",&pos);\r
+#else\r
+    const char* token=strtok(dup,"/");\r
+#endif\r
+    while (token)\r
+    {\r
+        map<string,Override*>::const_iterator i=o->m_map.find(token);\r
+        if (i==o->m_map.end())\r
+            break;\r
+        o=i->second;\r
+#ifdef HAVE_STRTOK_R\r
+        token=strtok_r(NULL,"/",&pos);\r
+#else\r
+        token=strtok(NULL,"/");\r
+#endif\r
+    }\r
+\r
+    free(dup);\r
+    return o;\r
+}\r
+\r
+XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) : m_document(NULL)\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("XMLRequestMapperImpl");\r
+#endif\r
+\r
+    // Load the property set.\r
+    load(e,log,this);\r
+    \r
+    // Load any AccessControl provider.\r
+    loadACL(e,log);\r
+\r
+    // Loop over the Host elements.\r
+    const DOMElement* host = XMLHelper::getFirstChildElement(e,Host);\r
+    for (int i=1; host; ++i, host=XMLHelper::getNextSiblingElement(host,Host)) {\r
+        const XMLCh* n=host->getAttributeNS(NULL,name);\r
+        if (!n || !*n) {\r
+            log.warn("Skipping Host element (%d) with empty name attribute",i);\r
+            continue;\r
+        }\r
+        \r
+        Override* o=new Override(host,log,this);\r
+        pair<bool,const char*> name=o->getString("name");\r
+        pair<bool,const char*> scheme=o->getString("scheme");\r
+        pair<bool,const char*> port=o->getString("port");\r
+        \r
+        char* dup=strdup(name.second);\r
+        for (char* pch=dup; *pch; pch++)\r
+            *pch=tolower(*pch);\r
+        auto_ptr<char> dupwrap(dup);\r
+\r
+        if (!scheme.first && port.first) {\r
+            // No scheme, but a port, so assume http.\r
+            scheme = pair<bool,const char*>(true,"http");\r
+        }\r
+        else if (scheme.first && !port.first) {\r
+            // Scheme, no port, so default it.\r
+            // XXX Use getservbyname instead?\r
+            port.first = true;\r
+            if (!strcmp(scheme.second,"http"))\r
+                port.second = "80";\r
+            else if (!strcmp(scheme.second,"https"))\r
+                port.second = "443";\r
+            else if (!strcmp(scheme.second,"ftp"))\r
+                port.second = "21";\r
+            else if (!strcmp(scheme.second,"ldap"))\r
+                port.second = "389";\r
+            else if (!strcmp(scheme.second,"ldaps"))\r
+                port.second = "636";\r
+        }\r
+\r
+        if (scheme.first) {\r
+            string url(scheme.second);\r
+            url=url + "://" + dup;\r
+            \r
+            // Is this the default port?\r
+            if ((!strcmp(scheme.second,"http") && !strcmp(port.second,"80")) ||\r
+                (!strcmp(scheme.second,"https") && !strcmp(port.second,"443")) ||\r
+                (!strcmp(scheme.second,"ftp") && !strcmp(port.second,"21")) ||\r
+                (!strcmp(scheme.second,"ldap") && !strcmp(port.second,"389")) ||\r
+                (!strcmp(scheme.second,"ldaps") && !strcmp(port.second,"636"))) {\r
+                // First store a port-less version.\r
+                if (m_map.count(url) || m_extras.count(url)) {\r
+                    log.warn("Skipping duplicate Host element (%s)",url.c_str());\r
+                    delete o;\r
+                    continue;\r
+                }\r
+                m_map[url]=o;\r
+                log.debug("Added <Host> mapping for %s",url.c_str());\r
+                \r
+                // Now append the port. We use the extras vector, to avoid double freeing the object later.\r
+                url=url + ':' + port.second;\r
+                m_extras[url]=o;\r
+                log.debug("Added <Host> mapping for %s",url.c_str());\r
+            }\r
+            else {\r
+                url=url + ':' + port.second;\r
+                if (m_map.count(url) || m_extras.count(url)) {\r
+                    log.warn("Skipping duplicate Host element (%s)",url.c_str());\r
+                    delete o;\r
+                    continue;\r
+                }\r
+                m_map[url]=o;\r
+                log.debug("Added <Host> mapping for %s",url.c_str());\r
+            }\r
+        }\r
+        else {\r
+            // No scheme or port, so we enter dual hosts on http:80 and https:443\r
+            string url("http://");\r
+            url = url + dup;\r
+            if (m_map.count(url) || m_extras.count(url)) {\r
+                log.warn("Skipping duplicate Host element (%s)",url.c_str());\r
+                delete o;\r
+                continue;\r
+            }\r
+            m_map[url]=o;\r
+            log.debug("Added <Host> mapping for %s",url.c_str());\r
+            \r
+            url = url + ":80";\r
+            if (m_map.count(url) || m_extras.count(url)) {\r
+                log.warn("Skipping duplicate Host element (%s)",url.c_str());\r
+                continue;\r
+            }\r
+            m_extras[url]=o;\r
+            log.debug("Added <Host> mapping for %s",url.c_str());\r
+            \r
+            url = "https://";\r
+            url = url + dup;\r
+            if (m_map.count(url) || m_extras.count(url)) {\r
+                log.warn("Skipping duplicate Host element (%s)",url.c_str());\r
+                continue;\r
+            }\r
+            m_extras[url]=o;\r
+            log.debug("Added <Host> mapping for %s",url.c_str());\r
+            \r
+            url = url + ":443";\r
+            if (m_map.count(url) || m_extras.count(url)) {\r
+                log.warn("Skipping duplicate Host element (%s)",url.c_str());\r
+                continue;\r
+            }\r
+            m_extras[url]=o;\r
+            log.debug("Added <Host> mapping for %s",url.c_str());\r
+        }\r
+    }\r
+}\r
+\r
+const Override* XMLRequestMapperImpl::findOverride(const char* vhost, const char* path) const\r
+{\r
+    const Override* o=NULL;\r
+    map<string,Override*>::const_iterator i=m_map.find(vhost);\r
+    if (i!=m_map.end())\r
+        o=i->second;\r
+    else {\r
+        i=m_extras.find(vhost);\r
+        if (i!=m_extras.end())\r
+            o=i->second;\r
+    }\r
+    \r
+    return o ? o->locate(path) : this;\r
+}\r
+\r
+pair<bool,DOMElement*> XMLRequestMapper::load()\r
+{\r
+    // Load from source using base class.\r
+    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
+    \r
+    // If we own it, wrap it.\r
+    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
+\r
+    XMLRequestMapperImpl* impl = new XMLRequestMapperImpl(raw.second,m_log);\r
+    \r
+    // If we held the document, transfer it to the impl. If we didn't, it's a no-op.\r
+    impl->setDocument(docjanitor.release());\r
+\r
+    delete m_impl;\r
+    m_impl = impl;\r
+\r
+    return make_pair(false,(DOMElement*)NULL);\r
+}\r
+\r
+RequestMapper::Settings XMLRequestMapper::getSettings(const SPRequest& request) const\r
+{\r
+    ostringstream vhost;\r
+    vhost << request.getScheme() << "://" << request.getHostname() << ':' << request.getPort();\r
+\r
+    const Override* o=m_impl->findOverride(vhost.str().c_str(), request.getRequestURI());\r
+\r
+    if (m_log.isDebugEnabled()) {\r
+#ifdef _DEBUG\r
+        xmltooling::NDC ndc("getSettings");\r
+#endif\r
+        pair<bool,const char*> ret=o->getString("applicationId");\r
+        m_log.debug("mapped %s%s to %s", vhost.str().c_str(), request.getRequestURI() ? request.getRequestURI() : "", ret.second);\r
+    }\r
+\r
+    return Settings(o,o->getAC());\r
+}\r
similarity index 95%
rename from shibsp/MetadataExt.h
rename to shibsp/metadata/MetadataExt.h
index f620150..dcc8c3c 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/MetadataExt.h
+ * @file shibsp/metadata/MetadataExt.h
  * 
  * XMLObjects representing Shibboleth metadata extensions
  */
@@ -23,7 +23,7 @@
 #ifndef __shibsp_metaext_h__
 #define __shibsp_metaext_h__
 
-#include <shibsp/SPConstants.h>
+#include <shibsp/util/SPConstants.h>
 #include <xmltooling/XMLObjectBuilder.h>
 #include <xmltooling/signature/KeyInfo.h>
 #include <xercesc/util/XMLUniDefs.hpp>
similarity index 99%
rename from shibsp/MetadataExtImpl.cpp
rename to shibsp/metadata/MetadataExtImpl.cpp
index 614217b..13062e3 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "MetadataExt.h"
+#include "metadata/MetadataExt.h"
 
 #include <xmltooling/AbstractComplexElement.h>
 #include <xmltooling/AbstractSimpleElement.h>
similarity index 97%
rename from shibsp/MetadataExtSchemaValidators.cpp
rename to shibsp/metadata/MetadataExtSchemaValidators.cpp
index 4ce8cec..f68f4f5 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "MetadataExt.h"
+#include "metadata/MetadataExt.h"
 
 #include <xmltooling/validation/ValidatorSuite.h>
 
similarity index 98%
rename from shibsp/ListenerService.h
rename to shibsp/remoting/ListenerService.h
index fa6dbd5..fe88d53 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/ListenerService.h
+ * @file shibsp/remoting/ListenerService.h
  * 
  * Interprocess remoting engine.
  */
@@ -23,7 +23,7 @@
 #ifndef __shibsp_listener_h__
 #define __shibsp_listener_h__
 
-#include <shibsp/ddf.h>
+#include <shibsp/remoting/ddf.h>
 #include <map>
 
 namespace shibsp {
similarity index 99%
rename from shibsp/ddf.h
rename to shibsp/remoting/ddf.h
index 11700ad..43c0442 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/ddf.h
+ * @file shibsp/remoting/ddf.h
  * 
  * C++ DDF abstraction for interpretive RPC
  */
similarity index 98%
rename from shibsp/ListenerService.cpp
rename to shibsp/remoting/impl/ListenerService.cpp
index 1caecd4..c33086c 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "ListenerService.h"
+#include "remoting/ListenerService.h"
 
 #include <log4cpp/Category.hh>
 #include <xercesc/dom/DOM.hpp>
similarity index 99%
rename from shibsp/SocketListener.cpp
rename to shibsp/remoting/impl/SocketListener.cpp
index cdec2ce..f32fc45 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "SocketListener.h"
+#include "remoting/impl/SocketListener.h"
 
 #include <errno.h>
 #include <stack>
similarity index 97%
rename from shibsp/SocketListener.h
rename to shibsp/remoting/impl/SocketListener.h
index 0dbcf9f..42edc97 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/SocketListener.h
+ * SocketListener.h
  * 
  * Berkeley Socket-based ListenerService implementation
  */
@@ -27,7 +27,7 @@
 # define FD_SETSIZE 1024
 #endif
 
-#include <shibsp/ListenerService.h>
+#include <shibsp/remoting/ListenerService.h>
 
 #include <log4cpp/Category.hh>
 #include <xercesc/dom/DOM.hpp>
similarity index 99%
rename from shibsp/TCPListener.cpp
rename to shibsp/remoting/impl/TCPListener.cpp
index 20c39a6..b605ec8 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 #include "internal.h"
-#include "SocketListener.h"
+#include "remoting/impl/SocketListener.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/unicode.h>
similarity index 95%
rename from shibsp/UnixListener.cpp
rename to shibsp/remoting/impl/UnixListener.cpp
index dd45509..834e204 100644 (file)
@@ -21,7 +21,7 @@
  */\r
 \r
 #include "internal.h"\r
-#include "SocketListener.h"\r
+#include "remoting/impl/SocketListener.h"\r
 \r
 #include <xercesc/util/XMLUniDefs.hpp>\r
 #include <xmltooling/unicode.h>\r
similarity index 99%
rename from shibsp/ddf.cpp
rename to shibsp/remoting/impl/ddf.cpp
index 3716203..d3c17c9 100644 (file)
  */
 
 #include "internal.h"
+#include "remoting/ddf.h"
 
 #ifdef WIN32
 # define snprintf _snprintf
 #endif
 
-#include <shibsp/ddf.h>
-
 #include <stdexcept>
 #include <xercesc/dom/DOM.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
similarity index 98%
rename from shibsp/PKIXTrustEngine.cpp
rename to shibsp/security/PKIXTrustEngine.cpp
index e5cc444..8f8bed0 100644 (file)
@@ -21,8 +21,8 @@
  */
 
 #include "internal.h"
-#include "MetadataExt.h"
-#include "PKIXTrustEngine.h"
+#include "metadata/MetadataExt.h"
+#include "security/PKIXTrustEngine.h"
 
 #include <saml/saml2/metadata/Metadata.h>
 #include <xmltooling/XMLToolingConfig.h>
similarity index 96%
rename from shibsp/PKIXTrustEngine.h
rename to shibsp/security/PKIXTrustEngine.h
index 49cd2c0..5e440fd 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/PKIXTrustEngine.h
+ * @file shibsp/security/PKIXTrustEngine.h
  * 
  * Shibboleth-specific PKIX-validation TrustEngine 
  */
index 5614e43..a567849 100644 (file)
                        UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
                        >\r
                        <File\r
-                               RelativePath=".\ddf.cpp"\r
+                               RelativePath=".\AbstractSPRequest.cpp"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\DOMPropertySet.cpp"\r
+                               RelativePath=".\Application.cpp"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\ListenerService.cpp"\r
+                               RelativePath=".\ServiceProvider.cpp"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\MetadataExtImpl.cpp"\r
+                               RelativePath=".\SPConfig.cpp"\r
                                >\r
                        </File>\r
-                       <File\r
-                               RelativePath=".\MetadataExtSchemaValidators.cpp"\r
+                       <Filter\r
+                               Name="util"\r
                                >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\PKIXTrustEngine.cpp"\r
-                               >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\ServiceProvider.cpp"\r
+                               <File\r
+                                       RelativePath=".\util\CGIParser.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\util\DOMPropertySet.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\util\SPConstants.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="security"\r
                                >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\SocketListener.cpp"\r
+                               <File\r
+                                       RelativePath=".\security\PKIXTrustEngine.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="metadata"\r
                                >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\SPConfig.cpp"\r
+                               <File\r
+                                       RelativePath=".\metadata\MetadataExtImpl.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\metadata\MetadataExtSchemaValidators.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="remoting"\r
                                >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\SPConstants.cpp"\r
+                               <Filter\r
+                                       Name="impl"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\remoting\impl\ddf.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\remoting\impl\ListenerService.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\remoting\impl\SocketListener.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\remoting\impl\SocketListener.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\remoting\impl\TCPListener.cpp"\r
+                                               >\r
+                                       </File>\r
+                               </Filter>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="impl"\r
                                >\r
-                       </File>\r
+                               <File\r
+                                       RelativePath=".\impl\XMLAccessControl.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\impl\XMLRequestMapper.cpp"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                        UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
                        >\r
                        <File\r
-                               RelativePath=".\base.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\ddf.h"\r
+                               RelativePath=".\AbstractSPRequest.h"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\DOMPropertySet.h"\r
+                               RelativePath=".\AccessControl.h"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\exceptions.h"\r
+                               RelativePath=".\Application.h"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\internal.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\ListenerService.h"\r
+                               RelativePath=".\base.h"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\MetadataExt.h"\r
+                               RelativePath=".\exceptions.h"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\PKIXTrustEngine.h"\r
+                               RelativePath=".\internal.h"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\PropertySet.h"\r
+                               RelativePath=".\RequestMapper.h"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\SocketListener.h"\r
+                               RelativePath=".\SessionCache.h"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\SPConstants.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
-                               RelativePath=".\TCPListener.cpp"\r
+                               RelativePath=".\SPRequest.h"\r
                                >\r
                        </File>\r
                        <File\r
                                RelativePath=".\version.h"\r
                                >\r
                        </File>\r
+                       <Filter\r
+                               Name="util"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\util\CGIParser.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\util\DOMPropertySet.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\util\PropertySet.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\util\SPConstants.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="security"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\security\PKIXTrustEngine.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="metadata"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\metadata\MetadataExt.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
+                       <Filter\r
+                               Name="remoting"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\remoting\ddf.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\remoting\ListenerService.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r
diff --git a/shibsp/util/CGIParser.cpp b/shibsp/util/CGIParser.cpp
new file mode 100644 (file)
index 0000000..91e10df
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * CGIParser.cpp
+ * 
+ * CGI GET/POST parameter parsing
+ */
+
+#include "internal.h"
+#include "util/CGIParser.h"
+
+#include <saml/SAMLConfig.h>
+#include <saml/binding/URLEncoder.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace std;
+
+
+CGIParser::CGIParser(const SPRequest& request)
+{
+    const char* pch=NULL;
+    if (!strcmp(request.getMethod(),"POST"))
+        pch=request.getRequestBody();
+    else
+        pch=request.getQueryString();
+    size_t cl=pch ? strlen(pch) : 0;
+    
+        
+    while (cl && pch) {
+        char *name;
+        char *value;
+        value=fmakeword('&',&cl,&pch);
+        plustospace(value);
+        SAMLConfig::getConfig().getURLEncoder()->decode(value);
+        name=makeword(value,'=');
+        kvp_map.insert(pair<string,char*>(name,value));
+        free(name);
+    }
+}
+
+CGIParser::~CGIParser()
+{
+    for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
+        free(i->second);
+}
+
+pair<CGIParser::walker,CGIParser::walker> CGIParser::getParameters(const char* name) const
+{
+    return kvp_map.equal_range(name);
+}
+
+/* Parsing routines modified from NCSA source. */
+char* CGIParser::makeword(char *line, char stop)
+{
+    int x = 0,y;
+    char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
+
+    for(x=0;((line[x]) && (line[x] != stop));x++)
+        word[x] = line[x];
+
+    word[x] = '\0';
+    if(line[x])
+        ++x;
+    y=0;
+
+    while(line[x])
+      line[y++] = line[x++];
+    line[y] = '\0';
+    return word;
+}
+
+char* CGIParser::fmakeword(char stop, size_t *cl, const char** ppch)
+{
+    int wsize;
+    char *word;
+    int ll;
+
+    wsize = 1024;
+    ll=0;
+    word = (char *) malloc(sizeof(char) * (wsize + 1));
+
+    while(1)
+    {
+        word[ll] = *((*ppch)++);
+        if(ll==wsize-1)
+        {
+            word[ll+1] = '\0';
+            wsize+=1024;
+            word = (char *)realloc(word,sizeof(char)*(wsize+1));
+        }
+        --(*cl);
+        if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
+        {
+            if(word[ll] != stop)
+                ll++;
+            word[ll] = '\0';
+            return word;
+        }
+        ++ll;
+    }
+}
+
+void CGIParser::plustospace(char *str)
+{
+    register int x;
+
+    for(x=0;str[x];x++)
+        if(str[x] == '+') str[x] = ' ';
+}
diff --git a/shibsp/util/CGIParser.h b/shibsp/util/CGIParser.h
new file mode 100644 (file)
index 0000000..3b0624f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/util/CGIParser.h
+ * 
+ * CGI GET/POST parameter parsing
+ */
+
+#ifndef __shibsp_cgi_h__
+#define __shibsp_cgi_h__
+
+#include <shibsp/SPRequest.h>
+
+namespace shibsp {
+
+    /**
+     * CGI GET/POST parameter parsing
+     */
+    class SHIBSP_API CGIParser
+    {
+        MAKE_NONCOPYABLE(CGIParser);
+    public:
+        /**
+         * Constructor
+         * 
+         * @param request   SP request
+         */
+        CGIParser(const SPRequest& request);
+
+        ~CGIParser();
+
+        typedef std::multimap<std::string,char*>::const_iterator walker;
+        
+        /**
+         * Returns a pair of bounded iterators around the values of a parameter.
+         * 
+         * @param name  name of parameter
+         * @return  a pair of multimap iterators surrounding the matching value(s)
+         */
+        std::pair<walker,walker> getParameters(const char* name) const;
+        
+    private:
+        char* fmakeword(char stop, unsigned int *cl, const char** ppch);
+        char* makeword(char *line, char stop);
+        void plustospace(char *str);
+
+        std::multimap<std::string,char*> kvp_map;
+    };
+};
+
+#endif /* __shibsp_cgi_h__ */
similarity index 99%
rename from shibsp/DOMPropertySet.cpp
rename to shibsp/util/DOMPropertySet.cpp
index 892fdfc..5df582e 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 #include "internal.h"
-#include "DOMPropertySet.h"
+#include "util/DOMPropertySet.h"
 
 #include <algorithm>
 #include <xmltooling/util/NDC.h>
similarity index 97%
rename from shibsp/DOMPropertySet.h
rename to shibsp/util/DOMPropertySet.h
index e061071..d46d288 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/DOMPropertySet.h
+ * @file shibsp/util/DOMPropertySet.h
  * 
  * DOM-based property set implementation.
  */
@@ -23,7 +23,7 @@
 #ifndef __shibsp_dompropset_h__
 #define __shibsp_dompropset_h__
 
-#include <shibsp/PropertySet.h>
+#include <shibsp/util/PropertySet.h>
 #include <log4cpp/Category.hh>
 
 namespace shibsp {
similarity index 99%
rename from shibsp/PropertySet.h
rename to shibsp/util/PropertySet.h
index 260f932..5cd25d4 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/PropertySet.h
+ * @file shibsp/util/PropertySet.h
  * 
  * Interface to a generic set of typed properties or a DOM container of additional data.
  */
similarity index 97%
rename from shibsp/SPConstants.cpp
rename to shibsp/util/SPConstants.cpp
index b381763..7bee69d 100644 (file)
@@ -21,7 +21,7 @@
  */\r
 \r
 #include "internal.h"\r
-#include "SPConstants.h"\r
+#include "util/SPConstants.h"\r
 #include <xercesc/util/XMLUniDefs.hpp>\r
 \r
 using namespace shibspconstants;\r
similarity index 98%
rename from shibsp/SPConstants.h
rename to shibsp/util/SPConstants.h
index e2f12a3..4f178f8 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /**
- * @file shibsp/SPConstants.h
+ * @file shibsp/util/SPConstants.h
  * 
  * Shibboleth SP XML constants. 
  */
index deab14a..354b2b9 100644 (file)
@@ -93,7 +93,7 @@ int main(int argc,char* argv[])
         IConfig* ini=ShibTargetConfig::getConfig().getINI();
         xmltooling::Locker locker(ini);
 
-        const IApplication* app=ini->getApplication(a_param);
+        const IApplication* app=dynamic_cast<const IApplication*>(ini->getApplication(a_param));
         if (!app) {
             throw ConfigurationException("Unable to locate application for new session, deleted?");
         }
index 17692d8..faa3f98 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <shib-target/shib-target.h>
 #include <shibsp/SPConfig.h>
-#include <shibsp/SPConstants.h>
+#include <shibsp/util/SPConstants.h>
 
 using namespace shibsp;
 using namespace shibtarget;
@@ -85,7 +85,7 @@ int main(int argc,char* argv[])
     xmltooling::Locker locker(ini);
 
     try {
-        const IApplication* app=ini->getApplication(a_param);
+        const IApplication* app=dynamic_cast<const IApplication*>(ini->getApplication(a_param));
         if (!app)
             throw SAMLException("specified <Application> section not found in configuration");
 
index c994f77..d5ec8f2 100644 (file)
@@ -14,7 +14,6 @@ xmlproviders_la_LIBADD = \
 xmlproviders_la_SOURCES = \
        TargetedID.cpp \
        XMLAAP.cpp \
-       XMLAccessControl.cpp \
        XMLProviders.cpp
 
 
index 5c4b9e4..71830a5 100644 (file)
@@ -25,8 +25,8 @@
 #include "internal.h"
 #include <algorithm>
 #include <log4cpp/Category.hh>
-#include <shibsp/MetadataExt.h>
-#include <shibsp/SPConstants.h>
+#include <shibsp/metadata/MetadataExt.h>
+#include <shibsp/util/SPConstants.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 #include <xmltooling/util/XMLHelper.h>
 
@@ -122,7 +122,9 @@ namespace {
     class XMLAAP : public IAAP, public ReloadableXMLFile
     {
     public:
-        XMLAAP(const DOMElement* e) : ReloadableXMLFile(e), m_impl(NULL) {}
+        XMLAAP(const DOMElement* e) : ReloadableXMLFile(e), m_impl(NULL) {
+            load();
+        }
         ~XMLAAP() {
             delete m_impl;
         }
index d3b5b49..987bd43 100644 (file)
@@ -40,7 +40,6 @@ using namespace std;
 
 PlugManager::Factory TargetedIDFactory;
 PlugManager::Factory XMLAAPFactory;
-PlugManager::Factory XMLAccessControlFactory;
 
 extern "C" int XML_EXPORTS saml_extension_init(void*)
 {
@@ -49,7 +48,6 @@ extern "C" int XML_EXPORTS saml_extension_init(void*)
     conf.getPlugMgr().regFactory("edu.internet2.middleware.shibboleth.common.provider.TargetedIDFactory",&TargetedIDFactory);
     conf.getPlugMgr().regFactory("edu.internet2.middleware.shibboleth.aap.provider.XMLAAP",&XMLAAPFactory);
     conf.getPlugMgr().regFactory("edu.internet2.middleware.shibboleth.target.provider.XMLAAP",&XMLAAPFactory);
-    conf.getPlugMgr().regFactory(XML_ACCESSCONTROL,&XMLAccessControlFactory);
 
     return 0;
 }
@@ -61,5 +59,4 @@ extern "C" void XML_EXPORTS saml_extension_term()
     conf.getPlugMgr().unregFactory("edu.internet2.middleware.shibboleth.common.provider.TargetedIDFactory");
     conf.getPlugMgr().unregFactory("edu.internet2.middleware.shibboleth.aap.provider.XMLAAP");
     conf.getPlugMgr().unregFactory("edu.internet2.middleware.shibboleth.target.provider.XMLAAP");
-    conf.getPlugMgr().unregFactory(XML_ACCESSCONTROL);
 }
index dda9ad4..65a7383 100644 (file)
                        >
                </File>
                <File
-                       RelativePath=".\XMLAccessControl.cpp"
-                       >
-               </File>
-               <File
                        RelativePath="XMLProviders.cpp"
                        >
                </File>