- Update to Xerces-2.1 support
authorDerek Atkins <derek@ihtfp.com>
Sat, 21 Sep 2002 02:44:42 +0000 (02:44 +0000)
committerDerek Atkins <derek@ihtfp.com>
Sat, 21 Sep 2002 02:44:42 +0000 (02:44 +0000)
- add rmError, wayfError, and rmError HTML response files
- add more configuration ability
- move initialization to new ShibTargetConfig class
- better error handling
- update configuration and error handling in both shire and rm modules

20 files changed:
Makefile.gcc
configs/accessError.html [new file with mode: 0644]
configs/rmError.html [new file with mode: 0644]
configs/shibboleth.ini
configs/wayfError.html [new file with mode: 0644]
include/shib-target.h
mod_shibrm/Makefile.gcc
mod_shibrm/mod_shibrm.cpp
mod_shire/Makefile.gcc
mod_shire/mod_shire.cpp
shib-target/shib-config.cpp [new file with mode: 0644]
shib-target/shib-ini.cpp
shib-target/shib-mlp.cpp
shib-target/shib-rm.cpp
shib-target/shib-rpcerror.cpp
shib-target/shib-shire.cpp
shib-target/shib-target.cpp
shib-target/shibrpc-server.cpp
shib-target/testinit.c
shib-target/testlog.cpp

index e6782d0..4eea66e 100644 (file)
@@ -4,14 +4,15 @@ INCDIR                = include
 CP             = cp -p
 CC             = gcc3
 CXX            = g++3
-XERCES          = ../../xerces-c-src1_7_0
+XERCES          = ../../xerces-c-src2_1_0
 LOG4CPP                = ../../..
-CFLAGS         = -g -fpic -Iinclude -I../../opensaml/c/include \
+DEBUG          = -g
+CFLAGS         = $(DEBUG) -fpic -Iinclude -I../../opensaml/c/include \
                   -I/usr/local/include -I$(XERCES)/include -I$(LOG4CPP)/include
 CCFLAGS                = $(CFLAGS)
 CXXFLAGS       = $(CFLAGS)
 LDFLAGS                = -L/usr/local/lib -L$(OUTDIR) -L../../opensaml/c/lib \
-                  -L$(XERCES)/lib -luuid -lcurl -lxerces-c1_7_0 -lsaml \
+                  -L$(XERCES)/lib -luuid -lcurl -lxerces-c -lsaml \
                  -L$(LOG4CPP)/lib -llog4cpp
 SHIB_OBJS      = \
         shib/ClubShibPOSTProfile.o \
@@ -46,7 +47,8 @@ SHIBTARGET_OBJS = \
        shib-target/shib-shire.o \
        shib-target/shib-rm.o \
        shib-target/shib-ini.o \
-       shib-target/shib-mlp.o
+       shib-target/shib-mlp.o \
+       shib-target/shib-config.o
 
 INC_TARGETS = $(INCDIR)/shibrpc.h
 
diff --git a/configs/accessError.html b/configs/accessError.html
new file mode 100644 (file)
index 0000000..ae9181c
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+       PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "DTD/xhtml1-strict.dtd">
+       
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" type="text/css" href="main.css" />
+       <title>Authorization Failed</title>
+</head>
+
+<body>
+<div class="head">
+<img src="<shibmlp logoLocation />" alt="Logo" />
+<h1>Authorization Failed</h1>
+</div>
+
+Based on the information provided to this server about you, you are
+not authorized to access "<shibmlp requestURL />"<br>
+
+Please contact the administrator of this service or application if you
+believe this to be an error.<br>
+
+</body>
+</html>
diff --git a/configs/rmError.html b/configs/rmError.html
new file mode 100644 (file)
index 0000000..45d69e1
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+       PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "DTD/xhtml1-strict.dtd">
+       
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" type="text/css" href="main.css" />
+       <title>Access System Failure</title>
+</head>
+
+<body>
+<div class="head">
+<img src="<shibmlp logoLocation />" alt="Logo" />
+<h1>Inter-institutional Access System Failure</h1>
+</div>
+
+<p>The inter-institutional access system experienced a technical failure.</p>
+
+<p>Please email <a href="mailto:<shibmlp supportContact />"><shibmlp supportContact /></a> and include the following error message:</p>
+
+<p class="error">Resource Manager failure at (<shibmlp requestURL />)</p>
+
+<p><shibmlp errorText /></p>
+
+
+</body>
+</html>
index 719929c..2b5a28b 100644 (file)
@@ -1,9 +1,24 @@
 [general]
 logger=/mit/shibboleth/src/shibboleth/c/shibboleth.logger
+schemadir=/mit/shibboleth/src/shibboleth/c/schemas/
+
+[http]
+# These items must live in [http]
+shire=/shibboleth/SHIRE
+wayfLocation=https://shibprod0.internet2.edu/shibboleth/WAYF
+cookie=shib-cookie
+
+# these can live anywhere
+supportContact=warlord@MIT.EDU
+logoLocation=/icons/index.gifw
+
+# These must live in [http] as well
+ayfError=/mit/shibboleth/src/shibboleth/c/configs/wayfError.html
+rmError=/mit/shibboleth/src/shibboleth/c/configs/rmError.html
+accessError=/mit/shibboleth/src/shibboleth/c/configs/accessError.html
 
 [shar]
 logger=/mit/shibboleth/src/shibboleth/c/shibboleth.logger-scott
-schemadir=/mit/shibboleth/src/shibboleth/c/schemas/
 #certfile=
 #keyfile=
 #keypass=
diff --git a/configs/wayfError.html b/configs/wayfError.html
new file mode 100644 (file)
index 0000000..bc562b2
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+       PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "DTD/xhtml1-strict.dtd">
+       
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" type="text/css" href="main.css" />
+       <title>Access System Failure</title>
+</head>
+
+<body>
+<div class="head">
+<img src="<shibmlp logoLocation />" alt="Logo" />
+<h1>Inter-institutional Access System Failure</h1>
+</div>
+
+<p>The inter-institutional access system experienced a technical failure.</p>
+
+<p>Please email <a href="mailto:<shibmlp supportContact />"><shibmlp supportContact /></a> and include the following error message:</p>
+
+<p class="error">WAYF failure at (<shibmlp requestURL />)</p>
+
+<p><shibmlp errorText /></p>
+
+
+</body>
+</html>
index 861340d..f437e6b 100644 (file)
@@ -74,6 +74,9 @@ int shib_sock_connect (ShibSocket s, ShibSockName name);
 #define SHIBTARGET_SHIRE       "shire"
 #define SHIBTARGET_RM          "rm"
 
+/* configuration headers */
+#define SHIBTARGET_HTTP                "http"
+
 /* configuration tags */
 #define SHIBTARGET_TAG_LOGGER  "logger"
 #define SHIBTARGET_TAG_SCHEMAS "schemadir"
@@ -189,7 +192,10 @@ namespace shibtarget {
     ~RPCError();
 
     bool       isError() { return (status != 0); }
-    std::string        getHTML();
+    bool       isRetryable();
+
+    // Return a string that corresponds to the "status"
+    const char* toString();
 
     int                status;
     std::string        error_msg;
@@ -215,9 +221,9 @@ namespace shibtarget {
     SHIRE(RPCHandle *rpc, SHIREConfig config, std::string shire_url);
     ~SHIRE();
 
-    RPCError sessionIsValid(const char* cookie, const char* ip);
-    RPCError sessionCreate(const char* post, const char* ip,
-                     std::string &cookie);
+    RPCError* sessionIsValid(const char* cookie, const char* ip);
+    RPCError* sessionCreate(const char* post, const char* ip,
+                            std::string &cookie);
   private:
     SHIREPriv *m_priv;
   };
@@ -235,11 +241,11 @@ namespace shibtarget {
     RM(RPCHandle *rpc, RMConfig config);
     ~RM();
 
-    RPCError getAttributes(const char* cookie, const char* ip,
-                          Resource *resource,
-                          std::vector<saml::QName*> attr_requests,
-                          std::vector<saml::SAMLAttribute*> &attr_replies,
-                          std::string &assertion);
+    RPCError* getAttributes(const char* cookie, const char* ip,
+                           Resource *resource,
+                           std::vector<saml::QName*> attr_requests,
+                           std::vector<saml::SAMLAttribute*> &attr_replies,
+                           std::string &assertion);
   private:
     RMPriv *m_priv;
   };
@@ -282,6 +288,24 @@ namespace shibtarget {
       return exists(h,t);
     }
 
+    // Special method to look for a tag in one header and maybe in the
+    // 'SHIBTARGET_GENERAL' header
+    bool get_tag(std::string& header, std::string& tag, bool try_general,
+                std::string* result) const;
+
+    bool get_tag(std::string& header, const char* tag, bool try_general,
+                std::string* result) const {
+      std::string t = tag;
+      return get_tag (header,t,try_general,result);
+    }
+
+    bool get_tag(const char* header, const char* tag, bool try_general,
+                std::string* result) const {
+      std::string h = header, t = tag;
+      return get_tag (h,t,try_general,result);
+    }
+
+    // Dump out the inifile to the output stream
     void dump(std::ostream& os) const;
 
     // Iterators
@@ -329,6 +353,7 @@ namespace shibtarget {
       std::string k = key, v = value;
       insert(k,v);
     }
+    void insert (RPCError& e);
 
     void clear () { m_map.clear(); }
 
@@ -344,12 +369,15 @@ namespace shibtarget {
     std::map<std::string,std::string> m_map;
   };
 
+  class ShibTargetConfig
+  {
+  public:
+    static ShibTargetConfig& init(const char* app_name, const char* inifile);
+    virtual void shutdown() = 0;
+    virtual ShibINI& getINI() = 0;
+  };
+
 } // namespace
 #endif
 
 #endif /* SHIB_COMMON_H */
-#if 0
-log2cpp::Category& shibtarget::g_log = log4cpp::Category::getRoot();
-g_log.addAppender(appender);
-g_log.setPriority(log3cpp::Priority::NOTSET);
-#endif
index daa9d85..92ac231 100644 (file)
@@ -6,12 +6,12 @@
 #   the used tools
 CC=g++3
 SAMLRT=../../../opensaml/c
-XERCES=../../../xerces-c-src1_7_0
+XERCES=../../../xerces-c-src2_1_0
 APXS=/usr/sbin/apxs
 APACHECTL=/usr/sbin/apachectl
 SHIB_CFLAGS=-g -I$(SAMLRT)/include -I$(XERCES)/include -I../include
 SHIB_LDFLAGS=-L$(SAMLRT)/lib -L$(XERCES)/lib -L../lib 
-SHIB_LIBS=-lsaml -lshib -lshib-target -lxerces-c1_7_0
+SHIB_LIBS=-lsaml -lshib -lshib-target -lxerces-c
 
 
 # Get all of apxs's internal values.
@@ -45,7 +45,7 @@ mod_shibrm.so: mod_shibrm.o
 
 # install the shared object file into Apache 
 install: all
-       $(APXS) -i -n 'shire_module' mod_shibrm.so
+       $(APXS) -i -n 'shibrm_module' mod_shibrm.so
 
 # display the apxs variables
 check_apxs_vars:
index ac89d74..8484bda 100644 (file)
@@ -23,6 +23,7 @@
 #include <shib.h>
 #include <shib-target.h>
 
+#include <fstream>
 #include <strstream>
 #include <stdexcept>
 
@@ -32,6 +33,7 @@ using namespace shibboleth;
 using namespace shibtarget;
 
 static RPCHandle *rpc_handle = NULL;
+static ShibTargetConfig* g_szConfig = NULL;
 
 map<string,string> g_mapAttribNameToHeader;
 map<string,string> g_mapAttribRuleToHeader;
@@ -146,9 +148,11 @@ typedef const char* (*config_fn_t)(void);
 static command_rec shibrm_cmds[] = {
   {"ShibMapAttribute", (config_fn_t)ap_set_attribute_mapping, NULL,
    RSRC_CONF, TAKE23, "Define request header name and 'require' alias for an attribute."},
+#if 0
   {"ShibCookieName", (config_fn_t)ap_set_server_string_slot,
    (void *) XtOffsetOf (shibrm_server_config, szCookieName),
    RSRC_CONF, TAKE1, "Name of cookie to use as session token."},
+#endif
   {"ShibNormalizeRequest", (config_fn_t)set_normalize, NULL,
    RSRC_CONF, TAKE1, "Normalize/convert browser requests using server name when redirecting."},
 
@@ -173,7 +177,22 @@ static command_rec shibrm_cmds[] = {
  */
 extern "C" void shibrm_child_init(server_rec* s, pool* p)
 {
-    // XXX: Runtime components are initialized in SHIRE module...
+    if (g_szConfig) {
+      ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,s,
+                  "shibrm_child_init(): already initialized!");
+      exit (1);
+    }
+
+    try {
+      // Assume that we've been initialized from the SHIRE module!
+      g_szConfig = &(ShibTargetConfig::init(SHIBTARGET_RM, "NOOP"));
+    } catch (runtime_error& e) {
+      ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,
+                  "shibrm_child_init() failed to initialize SHIB Target");
+      exit (1);
+    }
+  
+    saml::NDC ndc("shibrm_child_init");
 
     // Create the RPC Handle..  Note: this should be per _thread_
     // if there is some way to do that reasonably..
@@ -187,7 +206,7 @@ extern "C" void shibrm_child_init(server_rec* s, pool* p)
        g_mapAttribNames[temp.get()]=i->first;
     }
 
-    ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shibrm_child_exit() done");
+    ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shibrm_child_init() done");
 }
 
 
@@ -198,50 +217,11 @@ extern "C" void shibrm_child_init(server_rec* s, pool* p)
 extern "C" void shibrm_child_exit(server_rec* s, pool* p)
 {
     delete rpc_handle;
+    g_szConfig->shutdown();
+    g_szConfig = NULL;
     ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shibrm_child_exit() done");
 }
 
-inline char hexchar(unsigned short s)
-{
-    return (s<=9) ? ('0' + s) : ('A' + s - 10);
-}
-
-static char* url_encode(request_rec* r, const char* s)
-{
-    static char badchars[]="\"\\+<>#%{}|^~[]`;/?:@=&";
-    char* ret=(char*)ap_palloc(r->pool,sizeof(char)*3*strlen(s)+1);
-
-    unsigned long count=0;
-    for (; *s; s++)
-    {
-        if (strchr(badchars,*s)!=NULL || *s<=0x1F || *s>=0x7F)
-        {
-           ret[count++]='%';
-           ret[count++]=hexchar(*s >> 4);
-           ret[count++]=hexchar(*s & 0x0F);
-       }
-       else
-           ret[count++]=*s;
-    }
-    ret[count++]=*s;
-    return ret;
-}
-
-static const char* get_target(request_rec* r, const char* target)
-{
-    shibrm_server_config* sc=
-        (shibrm_server_config*)ap_get_module_config(r->server->module_config,&shibrm_module);
-    if (sc->bNormalizeRequest)
-    {
-        const char* colon=strchr(target,':');
-        const char* slash=strchr(colon+3,'/');
-        const char* second_colon=strchr(colon+3,':');
-        return ap_pstrcat(r->pool,ap_pstrndup(r->pool,target,colon+3-target),ap_get_server_name(r),
-                         (second_colon && second_colon < slash) ? second_colon : slash,NULL);
-    }
-    return target;
-}
-
 static table* groups_for_user(request_rec* r, const char* user, char* grpfile)
 {
     configfile_t* f;
@@ -282,14 +262,37 @@ static table* groups_for_user(request_rec* r, const char* user, char* grpfile)
     return grps;
 }
 
+static int shibrm_error_page(request_rec* r, const char* filename, ShibMLP& mlp)
+{
+  ifstream infile (filename);
+  if (!infile) {
+      ap_log_rerror(APLOG_MARK,APLOG_ERR,r,
+                   "shibrm_error_page() cannot open %s", filename);
+      return SERVER_ERROR;
+  }
+
+  string res = mlp.run(infile);
+  r->content_type = ap_psprintf(r->pool, "text/html");
+  ap_send_http_header(r);
+  ap_rprintf(r, res.c_str());
+  return DONE;
+}
+
 extern "C" int shibrm_check_auth(request_rec* r)
 {
+    ostrstream threadid;
+    threadid << "[" << getpid() << "] shibrm" << '\0';
+    saml::NDC ndc(threadid.str());
+
+    ShibINI& ini = g_szConfig->getINI();
+
     shibrm_server_config* sc=
         (shibrm_server_config*)ap_get_module_config(r->server->module_config,&shibrm_module);
     shibrm_dir_config* dc=
         (shibrm_dir_config*)ap_get_module_config(r->per_dir_config,&shibrm_module);
 
-    ap_log_rerror(APLOG_MARK,APLOG_DEBUG,r,"shibrm_check_auth() executing");
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
+                 "shibrm_check_auth() executing");
 
     char* targeturl=ap_construct_url(r->pool,r->unparsed_uri,r);
 
@@ -300,18 +303,29 @@ extern "C" int shibrm_check_auth(request_rec* r)
 
     // Ok, this is a SHIB target; grab the cookie
 
+    ShibMLP markupProcessor;
+    string tag;
+    bool has_tag = ini.get_tag (SHIBTARGET_HTTP, "supportContact", true, &tag);
+    markupProcessor.insert ("supportContact", has_tag ? tag : "");
+    has_tag = ini.get_tag (SHIBTARGET_HTTP, "logoLocation", true, &tag);
+    markupProcessor.insert ("logoLocation", has_tag ? tag : "");
+    markupProcessor.insert ("requestURL", targeturl);
+
+    const string& shib_cookie = ini.get (SHIBTARGET_HTTP, "cookie");
+
     const char* session_id=NULL;
     const char* cookies=ap_table_get(r->headers_in,"Cookie");
-    if (!cookies || !(session_id=strstr(cookies,sc->szCookieName)))
+    if (!cookies || !(session_id=strstr(cookies,shib_cookie.c_str())))
     {
       // No cookie???  Must be a server error!
-      ap_log_rerror(APLOG_MARK,APLOG_ERR,r,"shibrm_check_auth() no cookie found");
+      ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
+                   "shibrm_check_auth() no cookie found");
 
       return SERVER_ERROR;
     }
 
     // Yep, we found a cookie -- pull it out (our session_id)
-    session_id+=strlen(sc->szCookieName) + 1;  /* Skip over the '=' */
+    session_id+=strlen(shib_cookie.c_str()) + 1;       /* Skip over the '=' */
     char* cookiebuf = ap_pstrdup(r->pool,session_id);
     char* cookieend = strchr(cookiebuf,';');
     if (cookieend)
@@ -327,19 +341,21 @@ extern "C" int shibrm_check_auth(request_rec* r)
     vector<SAMLAttribute*> response;
     string assertion;
 
-    RPCError status = rm.getAttributes(session_id, r->connection->remote_ip,
+    RPCError* status = rm.getAttributes(session_id, r->connection->remote_ip,
                                       &resource, request, response, assertion);
 
 
-    if (status.isError()) {
-      // XXX: return an error page
-
-      ap_log_rerror(APLOG_MARK,APLOG_ERR,r,
-                   "shibrm_check_auth() getAttributed failed: %s",
-                   status.error_msg.c_str());
+    if (status->isError()) {
+      ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
+                   "shibrm_check_auth() getAttributes failed: %s",
+                   status->error_msg.c_str());
 
-      return SERVER_ERROR;
+      const string& rmError = ini.get (SHIBTARGET_HTTP, "rmError");
+      markupProcessor.insert (*status);
+      delete status;
+      return shibrm_error_page (r, rmError.c_str(), markupProcessor);
     }
+    delete status;
 
     // Clear out the list of mapped attributes
     for (map<string,string>::const_iterator i=g_mapAttribNameToHeader.begin();
@@ -464,19 +480,8 @@ extern "C" int shibrm_check_auth(request_rec* r)
     if (!method_restricted)
         return OK;
 
-    r->content_type = ap_psprintf(r->pool, "text/html");
-    ap_send_http_header(r);
-    ap_rprintf(r, "<html>\n");
-    ap_rprintf(r, "<head>\n");
-    ap_rprintf(r, "<title>Authorization Failed</title>\n");
-    ap_rprintf(r, "<h1>Authorization Failed</h1>\n");
-    ap_rprintf(r, "Based on the information provided to this server about you, you are not authorized to access '%s'<br>", targeturl);
-    ap_rprintf(r, "Please contact the administrator of this service or application if you believe this to be an error.<br>");
-    ap_rprintf(r, "</head>\n");
-    ap_rprintf(r, "</html>\n");
-    ap_rflush(r);
-
-    return DONE;
+    const string& rmError = ini.get (SHIBTARGET_HTTP, "accessError");
+    return shibrm_error_page (r, rmError.c_str(), markupProcessor);
 }
 
 extern "C"{
index 2de9d71..f93262e 100644 (file)
@@ -6,14 +6,14 @@
 #   the used tools
 CC=g++3
 SAMLRT=../../../opensaml/c
-XERCES=../../../xerces-c-src1_7_0
+XERCES=../../../xerces-c-src2_1_0
 LIBAPREQ=../../../libapreq-1.0
 APXS=/usr/sbin/apxs
 APACHECTL=/usr/sbin/apachectl
 SHIB_CFLAGS=-g -I$(SAMLRT)/include -I$(XERCES)/include -I../include \
        -I$(LIBAPREQ)/include
 SHIB_LDFLAGS=-L$(SAMLRT)/lib -L$(XERCES)/lib -L../lib -L$(LIBAPREQ)/lib
-SHIB_LIBS=-lsaml -lshib -lshib-target -lxerces-c1_7_0 -lapreq
+SHIB_LIBS=-lsaml -lshib -lshib-target -lxerces-c -lapreq
 
 
 # Get all of apxs's internal values.
index 6b2f9e3..c6279be 100644 (file)
@@ -26,6 +26,7 @@
 #include <shib.h>
 #include <shib-target.h>
 
+#include <fstream>
 #include <strstream>
 #include <stdexcept>
 
@@ -34,10 +35,11 @@ using namespace saml;
 using namespace shibboleth;
 using namespace shibtarget;
 
-static RPCHandle *rpc_handle = NULL;
-
 extern "C" module MODULE_VAR_EXPORT shire_module;
-char* g_szSHIREConfig = NULL;
+
+static char* g_szSHIREConfig = NULL;
+static RPCHandle *rpc_handle = NULL;
+static ShibTargetConfig * g_szConfig = NULL;
 
 // per-server configuration structure
 struct shire_server_config
@@ -53,9 +55,6 @@ struct shire_server_config
 extern "C" void* create_shire_server_config (pool * p, server_rec * s)
 {
     shire_server_config* sc=(shire_server_config*)ap_pcalloc(p,sizeof(shire_server_config));
-    sc->szCookieName = NULL;
-    sc->szWAYFLocation = NULL;
-    sc->szSHIRELocation = NULL;
     sc->bSSLOnly = -1;
     sc->bNormalizeRequest = -1;
     return sc;
@@ -176,6 +175,7 @@ static command_rec shire_cmds[] = {
   {"SHIREConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIREConfig,
    RSRC_CONF, TAKE1, "Path to SHIRE ini file."},
 
+#if 0
   {"SHIRELocation", (config_fn_t)ap_set_server_string_slot,
    (void *) XtOffsetOf (shire_server_config, szSHIRELocation),
    RSRC_CONF, TAKE1, "URL of SHIRE handle acceptance point."},
@@ -190,6 +190,7 @@ static command_rec shire_cmds[] = {
    RSRC_CONF, TAKE1, "Name of cookie to use as session token."},
   {"ShibNormalizeRequest", (config_fn_t)set_normalize, NULL,
    RSRC_CONF, TAKE1, "Normalize/convert browser requests using server name when redirecting."},
+#endif
 
   {"ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
    (void *) XtOffsetOf (shire_dir_config, bBasicHijack),
@@ -218,7 +219,15 @@ extern "C" void shire_child_init(server_rec* s, pool* p)
 {
     // Initialize runtime components.
 
-    if (shib_target_initialize (SHIBTARGET_SHIRE, g_szSHIREConfig)) {
+    if (g_szConfig) {
+      ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,s,
+                  "shire_child_init(): already initialized!");
+      exit (1);
+    }
+
+    try {
+      g_szConfig = &(ShibTargetConfig::init(SHIBTARGET_SHIRE, g_szSHIREConfig));
+    } catch (runtime_error& e) {
       ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,
                   "shire_child_init() failed to initialize SHIB Target");
       exit (1);
@@ -239,7 +248,8 @@ extern "C" void shire_child_init(server_rec* s, pool* p)
 extern "C" void shire_child_exit(server_rec* s, pool* p)
 {
     delete rpc_handle;
-    shib_target_finalize();
+    g_szConfig->shutdown();
+    g_szConfig = NULL;
     ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_exit() done");
 }
 
@@ -286,36 +296,63 @@ static const char* get_target(request_rec* r, const char* target)
 
 static const char* get_shire_location(request_rec* r, const char* target, bool encode)
 {
-    shire_server_config* sc=
-        (shire_server_config*)ap_get_module_config(r->server->module_config,&shire_module);
-    if (*(sc->szSHIRELocation)!='/') {
-      if (encode)
-        return url_encode(r,sc->szSHIRELocation);
-      else
-       return sc->szSHIRELocation;
+  ShibINI& ini = g_szConfig->getINI();
+  const string& shire_location = ini.get (SHIBTARGET_HTTP, "shire");
+
+  const char* shire = shire_location.c_str();
+
+  if (*shire != '/') {
+    if (encode)
+      return url_encode(r,shire);
+    else
+      return ap_pstrdup(r->pool,shire);
     }    
     const char* colon=strchr(target,':');
     const char* slash=strchr(colon+3,'/');
     if (encode)
-      return url_encode(r,ap_pstrcat(r->pool,ap_pstrndup(r->pool,target,slash-target),
-                                    sc->szSHIRELocation,NULL));
+      return url_encode(r,ap_pstrcat(r->pool,
+                                    ap_pstrndup(r->pool,target,slash-target),
+                                    shire,NULL));
     else
-      return ap_pstrcat(r->pool,ap_pstrndup(r->pool,target,slash-target),
-                       sc->szSHIRELocation,NULL);
+      return ap_pstrcat(r->pool, ap_pstrndup(r->pool,target,slash-target),
+                       shire, NULL);
 }
 
-static bool is_shire_location(const char* target, const char* shire)
+static bool is_shire_location(request_rec* r, const char* target)
 {
+  const char* shire = get_shire_location(r, target, false);
+
   if (!strstr(target, shire))
     return false;
 
-  const char* colon=strchr(target,':');
-  const char* slash=strchr(colon+3,'/');
-  return (!strcmp(slash,shire));
+  return (!strcmp(target,shire));
+}
+
+static int shire_error_page(request_rec* r, const char* filename, ShibMLP& mlp)
+{
+  ifstream infile (filename);
+  if (!infile) {
+      ap_log_rerror(APLOG_MARK,APLOG_ERR,r,
+                   "shire_error_page() cannot open %s", filename);
+      return SERVER_ERROR;
+  }
+
+  string res = mlp.run(infile);
+  r->content_type = ap_psprintf(r->pool, "text/html");
+  ap_send_http_header(r);
+  ap_rprintf(r, res.c_str());
+  return DONE;
 }
 
 extern "C" int shire_check_user(request_rec* r)
 {
+    ostrstream threadid;
+    threadid << "[" << getpid() << "] shire" << '\0';
+    saml::NDC ndc(threadid.str());
+
+    ShibINI& ini = g_szConfig->getINI();
+    ShibMLP markupProcessor;
+
     ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
                  "shire_check_user: ENTER");
 
@@ -331,146 +368,195 @@ extern "C" int shire_check_user(request_rec* r)
     dc->config.checkIPAddress = (dc->checkIPAddress == 1 ? true : false);
     SHIRE shire(rpc_handle, dc->config, shire_url);
 
-    if (is_shire_location (targeturl, sc->szSHIRELocation)) {
+    const string& shib_cookie = ini.get (SHIBTARGET_HTTP, "cookie");
+    const string& wayfLocation = ini.get (SHIBTARGET_HTTP, "wayfLocation");
+    const string& wayfError = ini.get (SHIBTARGET_HTTP, "wayfError");
+
+    string tag;
+    bool has_tag = ini.get_tag (SHIBTARGET_HTTP, "supportContact", true, &tag);
+    markupProcessor.insert ("supportContact", has_tag ? tag : "");
+    has_tag = ini.get_tag (SHIBTARGET_HTTP, "logoLocation", true, &tag);
+    markupProcessor.insert ("logoLocation", has_tag ? tag : "");
+    markupProcessor.insert ("requestURL", targeturl);
+
+    if (is_shire_location (r, targeturl)) {
       // Process SHIRE POST
 
       ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
                    "shire_check_user() Beginning SHIRE POST processing");
       
 
-      // Make sure this is SSL, if it should be
-      if (sc->bSSLOnly==1 && strcmp(ap_http_method(r),"https"))
-      {
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-             "shire_check_user() blocked non-SSL access to SHIRE POST processor");
-        return SERVER_ERROR;
-      }
-
-      // Make sure this is a POST
-      if (strcasecmp (r->method, "POST")) {
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-             "shire_check_user() blocked non-POST to SHIRE POST processor");
-       return SERVER_ERROR;
-      }
-
-      // Sure sure this POST is an appropriate content type
-      const char *ct = ap_table_get (r->headers_in, "Content-type");
-      if (strcasecmp (ct, "application/x-www-form-urlencoded")) {
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-             "shire_check_user() blocked bad content-type to SHIRE POST processor");
-
-       return SERVER_ERROR;
-      }
-
-      // Make sure the "bytes sent" is a reasonable number
-      if (r->bytes_sent > 1024*1024) { // 1MB?
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-             "shire_check_user() blocked too-large a post to SHIRE POST processor");
+      try {
+
+       // Make sure this is SSL, if it should be
+       if (sc->bSSLOnly==1 && strcmp(ap_http_method(r),"https"))
+         throw ShibTargetException (SHIBRPC_OK,
+                                    "blocked non-SSL access to SHIRE POST processor");
+
+       // Make sure this is a POST
+       if (strcasecmp (r->method, "POST"))
+         throw ShibTargetException (SHIBRPC_OK,
+                                    "blocked non-POST to SHIRE POST processor");
+
+       // Sure sure this POST is an appropriate content type
+       const char *ct = ap_table_get (r->headers_in, "Content-type");
+       if (strcasecmp (ct, "application/x-www-form-urlencoded"))
+         throw ShibTargetException (SHIBRPC_OK,
+                                    ap_psprintf(r->pool,
+                                    "blocked bad content-type to SHIRE POST processor: %s",
+                                                ct));
        
-       return SERVER_ERROR;
-      }
-
-      // Read the posted data
-      ApacheRequest *ap_req = ApacheRequest_new(r);
-      int err = ApacheRequest_parse(ap_req);
-      if (err != OK) {
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-             "shire_check_user() ApacheRequest_parse() failed with %d.", err);
-
-       return SERVER_ERROR;
-      }
-
-      // Make sure the target parameter exists
-      const char *target = ApacheRequest_param(ap_req, "TARGET");
-      if (!target || *target == '\0') {
-       // invalid post
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-                     "shire_check_user() SHIRE POST failed to find TARGET");
-
-       return SERVER_ERROR;
-      }
-
-      // Make sure the SAML Response parameter exists
-      const char *post = ApacheRequest_param(ap_req, "SAMLResponse");
-      if (!post || *post == '\0') {
-       // invalid post
-        ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-                     "shire_check_user() SHIRE POST failed to find SAMLResponse");
-
-       return SERVER_ERROR;
-      }
-
-      ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
-           "shire_check_user() Processing POST for target: %s", target);
-
-      post = 
-       "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
-       "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
-       "c3VlSW5zdGFudD0iMjAwMi0wOS0xN1QwNDowMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
-       "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
-       "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
-       "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
-       "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
-       "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
-       "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTE3VDA0OjAwOjAwWiIgSXNzdWVy"
-       "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
-       "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
-       "dE9uT3JBZnRlcj0iMjAwMi0wOS0xN1QwNDowMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
-       "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
-       "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
-       "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
-       "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0xN1QwNDowMDowMFoiIEF1dGhl"
-       "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
-       "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
-       "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
-       "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
-       "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
-       "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
-       "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
-       "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
-       "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
-       "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
-       "c3NlcnRpb24+PC9SZXNwb25zZT4K";
-
-      // process the post
-      string cookie;
-      RPCError status = shire.sessionCreate(post, r->connection->remote_ip, cookie);
-
-      if (status.isError()) {
-       ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
-                     "shire_check_user() POST processes failed (%d): %s",
-                     status.status, status.error_msg.c_str());
-
-       // XXX: respond to the user here?
-       return SERVER_ERROR;
-      }
-
-      ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
-                   "shire_check_user() POST process succeeded.  New cookie: %s",
-                   cookie.c_str());
-
-      // We've got a good session, set the cookie...
-      char * domain = NULL;
-      char * new_cookie = ap_psprintf(r->pool, "%s=%s; path=/%s%s",
-                                     sc->szCookieName,
-                                     cookie.c_str(),
-                                     (domain ? "; domain=" : ""),
-                                     (domain ? domain : ""));
-
-      ap_table_setn(r->err_headers_out, "Set-Cookie", new_cookie);
-      ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
-                   "shire_check_user() Set cookie: %s", new_cookie);
+       // Make sure the "bytes sent" is a reasonable number
+       if (r->bytes_sent > 1024*1024) // 1MB?
+         throw ShibTargetException (SHIBRPC_OK,
+                                    "blocked too-large a post to SHIRE POST processor");
+
+       // Read the posted data
+       ApacheRequest *ap_req = ApacheRequest_new(r);
+       int err = ApacheRequest_parse(ap_req);
+       if (err != OK)
+         throw ShibTargetException (SHIBRPC_OK,
+                                    ap_psprintf(r->pool,
+                                    "ApacheRequest_parse() failed with %d.", err));
+
+
+       // Make sure the target parameter exists
+       const char *target = ApacheRequest_param(ap_req, "TARGET");
+       if (!target || *target == '\0')
+         // invalid post
+         throw ShibTargetException (SHIBRPC_OK,
+                                    "SHIRE POST failed to find TARGET");
+
+       // Make sure the SAML Response parameter exists
+       const char *post = ApacheRequest_param(ap_req, "SAMLResponse");
+       if (!post || *post == '\0')
+         // invalid post
+         throw ShibTargetException (SHIBRPC_OK,
+                                    "SHIRE POST failed to find SAMLResponse");
+
+       ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
+             "shire_check_user() Processing POST for target: %s", target);
+
+#if 0 // 2002-09-19
+       post = 
+         "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
+         "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
+         "c3VlSW5zdGFudD0iMjAwMi0wOS0xOVQwNTozMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
+         "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
+         "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
+         "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
+         "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
+         "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
+         "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTE5VDA1OjMwOjAwWiIgSXNzdWVy"
+         "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
+         "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
+         "dE9uT3JBZnRlcj0iMjAxMC0wOS0xOVQwNjozMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
+         "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
+         "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
+         "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
+         "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0xOVQwNTozMDowMFoiIEF1dGhl"
+         "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
+         "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
+         "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
+         "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
+         "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
+         "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
+         "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
+         "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
+         "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
+         "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
+         "c3NlcnRpb24+PC9SZXNwb25zZT4K";
+#endif
+#if 0 // 2002-09-20
+       post = 
+         "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
+         "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
+         "c3VlSW5zdGFudD0iMjAwMi0wOS0yMFQyMzowMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
+         "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
+         "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
+         "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
+         "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
+         "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
+         "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTIwVDIzOjAwOjAwWiIgSXNzdWVy"
+         "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
+         "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
+         "dE9uT3JBZnRlcj0iMjAxMC0wOS0xOVQwNjozMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
+         "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
+         "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
+         "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
+         "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0yMFQyMzowMDowMFoiIEF1dGhl"
+         "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
+         "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
+         "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
+         "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
+         "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
+         "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
+         "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
+         "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
+         "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
+         "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
+         "c3NlcnRpb24+PC9SZXNwb25zZT4K";
+#endif
+       
+       // process the post
+       string cookie;
+       RPCError* status = shire.sessionCreate(post, r->connection->remote_ip, cookie);
+
+       if (status->isError()) {
+         ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
+                       "shire_check_user() POST process failed (%d): %s",
+                       status->status, status->error_msg.c_str());
+
+         if (status->isRetryable()) {
+           ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
+                         "shire_check_user() Retrying POST by redirecting to WAYF");
+
+           char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
+                                 "?shire=",shire_location,
+                                 "&target=",url_encode(r,target),NULL);
+           ap_table_setn(r->headers_out,"Location",wayf);
+           delete status;
+           return REDIRECT;
+         }
+
+         // return this error to the user.
+         markupProcessor.insert (*status);
+         delete status;
+         return shire_error_page (r, wayfError.c_str(), markupProcessor);
+       }
+       delete status;
+
+       ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
+                     "shire_check_user() POST process succeeded.  New cookie: %s",
+                     cookie.c_str());
+
+       // We've got a good session, set the cookie...
+       char * domain = NULL;
+       char * new_cookie = ap_psprintf(r->pool, "%s=%s; path=/%s%s",
+                                       shib_cookie.c_str(),
+                                       cookie.c_str(),
+                                       (domain ? "; domain=" : ""),
+                                       (domain ? domain : ""));
+
+       ap_table_setn(r->err_headers_out, "Set-Cookie", new_cookie);
+       ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
+                     "shire_check_user() Set cookie: %s", new_cookie);
                    
+       // ... and redirect to the target
+       char* redir=ap_pstrcat(r->pool,url_encode(r,target),NULL);
+       ap_table_setn(r->headers_out, "Location", target);
+       return REDIRECT;
 
-      const char* stored_cookie = ap_table_get(r->err_headers_out, "Set-Cookie");
-      ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
-                   "shire_check_user() Stored cookie: %s", stored_cookie);
-      
+      } catch (ShibTargetException &e) {
+       ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
+                     "shire_check_user(): %s", e.what());
+       
+       markupProcessor.insert ("errorType", "SHIRE Processing Error");
+       markupProcessor.insert ("errorText", e.what());
+       return shire_error_page (r, wayfError.c_str(), markupProcessor);
+      }
 
-      // ... and redirect to the target
-      char* redir=ap_pstrcat(r->pool,url_encode(r,target),NULL);
-      ap_table_setn(r->headers_out, "Location", target);
-      return REDIRECT;
+      /**************************************************************************/
 
     } else {
       // Regular access to arbitrary resource...check AuthType
@@ -512,12 +598,12 @@ extern "C" int shire_check_user(request_rec* r)
                      "shire_check_user() cookies found: %s",
                      cookies);               
 
-      if (!cookies || !(session_id=strstr(cookies,sc->szCookieName)))
+      if (!cookies || !(session_id=strstr(cookies,shib_cookie.c_str())))
       {
         // No cookie.  Redirect to WAYF.
         ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
                      "shire_check_user() no cookie found -- redirecting to WAYF");
-        char* wayf=ap_pstrcat(r->pool,sc->szWAYFLocation,
+        char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
                              "?shire=",shire_location,
                              "&target=",url_encode(r,targeturl),NULL);
        ap_table_setn(r->headers_out,"Location",wayf);
@@ -525,7 +611,7 @@ extern "C" int shire_check_user(request_rec* r)
       }
 
       // Yep, we found a cookie -- pull it out (our session_id)
-      session_id+=strlen(sc->szCookieName) + 1;        /* Skip over the '=' */
+      session_id+=strlen(shib_cookie.c_str()) + 1;     /* Skip over the '=' */
       char* cookiebuf = ap_pstrdup(r->pool,session_id);
       char* cookieend = strchr(cookiebuf,';');
       if (cookieend)
@@ -533,23 +619,26 @@ extern "C" int shire_check_user(request_rec* r)
       session_id=cookiebuf;
 
       // Make sure this session is still valid
-      RPCError status = shire.sessionIsValid(session_id, r->connection->remote_ip);
+      RPCError* status = shire.sessionIsValid(session_id, r->connection->remote_ip);
 
       // Check the status
-      if (status.isError()) {
+      if (status->isError()) {
 
        ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
                      "shire_check_user() session invalid: %s",
-                     status.error_msg.c_str());
+                     status->error_msg.c_str());
 
         // Oops, session is invalid.  Redirect to WAYF.
-        char* wayf=ap_pstrcat(r->pool,sc->szWAYFLocation,
+        char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
                              "?shire=",shire_location,
                              "&target=",url_encode(r,targeturl),NULL);
        ap_table_setn(r->headers_out,"Location",wayf);
+
+       delete status;
        return REDIRECT;
 
       } else {
+       delete status;
         ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
                      "shire_check_user() success");
        return OK;
diff --git a/shib-target/shib-config.cpp b/shib-target/shib-config.cpp
new file mode 100644 (file)
index 0000000..a83d00b
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * shib-config.cpp -- ShibTarget initialization and finalization routines
+ *
+ * Created By: Derek Atkins <derek@ihtfp.com>
+ *
+ * $Id$
+ */
+
+#include "shib-target.h"
+
+#include <log4cpp/PropertyConfigurator.hh>
+#include <log4cpp/Category.hh>
+
+using namespace saml;
+using namespace shibboleth;
+using namespace shibtarget;
+using namespace std;
+
+#ifndef SHIBTARGET_INIFILE
+#define SHIBTARGET_INIFILE "/etc/shibboleth.ini"
+#endif
+
+class STConfig : public ShibTargetConfig
+{
+public:
+  STConfig(const char* app_name, const char* inifile);
+  ~STConfig();
+  void shutdown();
+  ShibINI& getINI() { return *ini; }
+
+  void ref();
+private:
+  SAMLConfig& samlConf;
+  ShibConfig& shibConf;
+  ShibINI* ini;
+  int refcount;
+};
+
+static STConfig * g_Config = NULL;
+CCache* shibtarget::g_shibTargetCCache = NULL;
+
+
+/****************************************************************************/
+// External Interface
+
+
+ShibTargetConfig& ShibTargetConfig::init(const char* app_name, const char* inifile)
+{
+  if (!app_name)
+    throw runtime_error ("No Application name");
+
+  if (g_Config) {
+    g_Config->ref();
+    return *g_Config;
+  }
+
+  g_Config = new STConfig(app_name, inifile);
+}
+
+
+
+/****************************************************************************/
+// Mapper
+
+class DummyMapper : public IOriginSiteMapper
+{
+public:
+    DummyMapper();
+    ~DummyMapper();
+    virtual Iterator<xstring> getHandleServiceNames(const XMLCh* originSite) { return Iterator<xstring>(m_hsnames); }
+    virtual Key* getHandleServiceKey(const XMLCh* handleService) { return NULL; }
+    virtual Iterator<xstring> getSecurityDomains(const XMLCh* originSite);
+    virtual Iterator<X509Certificate*> getTrustedRoots() { return Iterator<X509Certificate*>(); }
+
+private:
+    typedef map<xstring,vector<xstring>*> domains_t;
+    domains_t m_domains;
+    vector<xstring> m_hsnames;
+};
+
+DummyMapper::DummyMapper()
+{
+    auto_ptr<XMLCh> buf(XMLString::transcode("shibprod0.internet2.edu"));
+    m_hsnames.push_back(buf.get());
+}
+
+Iterator<xstring> DummyMapper::getSecurityDomains(const XMLCh* originSite)
+{
+    domains_t::iterator i=m_domains.find(originSite);
+    if (i==m_domains.end())
+    {
+        vector<xstring>* pv=new vector<xstring>();
+        pv->push_back(originSite);
+        pair<domains_t::iterator,bool> p=m_domains.insert(domains_t::value_type(originSite,pv));
+       i=p.first;
+    }
+    return Iterator<xstring>(*(i->second));
+}
+
+DummyMapper::~DummyMapper()
+{
+    for (domains_t::iterator i=m_domains.begin(); i!=m_domains.end(); i++)
+        delete i->second;
+}
+
+
+
+
+/****************************************************************************/
+// STConfig
+
+STConfig::STConfig(const char* app_name, const char* inifile)
+  :  samlConf(SAMLConfig::getConfig()), shibConf(ShibConfig::getConfig())
+{
+  ini = new ShibINI((inifile ? inifile : SHIBTARGET_INIFILE));
+
+  string app = app_name;
+  string tag;
+
+  // Initialize Log4cpp
+  if (ini->get_tag (app, SHIBTARGET_TAG_LOGGER, true, &tag)) {
+    cerr << "Trying to load logger configuration: " << tag << "\n";
+    try {
+      log4cpp::PropertyConfigurator::configure(tag);
+    } catch (log4cpp::ConfigureFailure& e) {
+      cerr << "Error reading configuration: " << e.what() << "\n";
+    }
+  } else {
+    log4cpp::Category& category = log4cpp::Category::getRoot();
+    category.setPriority(log4cpp::Priority::DEBUG);
+    cerr << "No logger configuration found\n";
+  }
+
+  log4cpp::Category& log = log4cpp::Category::getInstance("shibtarget.STConfig");
+
+  // Init SAML
+  if (ini->get_tag (app, SHIBTARGET_TAG_SCHEMAS, true, &tag))
+    samlConf.schema_dir = tag;
+  if (ini->get_tag (app, SHIBTARGET_TAG_CERTFILE, true, &tag))
+    samlConf.ssl_certfile = tag;
+  if (ini->get_tag (app, SHIBTARGET_TAG_KEYFILE, true, &tag))
+    samlConf.ssl_keyfile = tag;
+  if (ini->get_tag (app, SHIBTARGET_TAG_KEYPASS, true, &tag))
+    samlConf.ssl_keypass = tag;
+  if (ini->get_tag (app, SHIBTARGET_TAG_CALIST, true, &tag))
+    samlConf.ssl_calist = tag;
+
+  if (!samlConf.init()) {
+    log.error ("Failed to initialize SAML Library");
+    throw runtime_error ("Failed to initialize SAML Library");
+  } else
+    log.debug ("SAML Initialized");
+
+  // Init Shib
+  shibConf.origin_mapper = new DummyMapper();
+  
+  if (!shibConf.init()) {
+    log.error ("Failed to initialize Shib library");
+    throw runtime_error ("Failed to initialize Shib Library");
+  } else
+    log.debug ("Shib Initialized");
+
+  // Initialize the SHAR Cache
+  if (!strcmp (app_name, SHIBTARGET_SHAR))
+    g_shibTargetCCache = CCache::getInstance();  
+
+  // Load any extensions
+  string ext = "extensions";
+  if (ini->exists(ext)) {
+    saml::NDC ndc("load extensions");
+    ShibINI::Iterator* iter = ini->tag_iterator(ext);
+
+    for (const string* str = iter->begin(); str; str = iter->next()) {
+      string file = ini->get(ext, *str);
+      try
+      {
+       samlConf.saml_register_extension(file.c_str());
+       log.debug("%s: loading %s", str->c_str(), file.c_str());
+      }
+      catch (SAMLException& e)
+      {
+       log.error("%s: %s", str->c_str(), e.what());
+      }
+    }
+    delete iter;
+  }
+
+  ref();
+  log.debug("finished");
+}
+
+STConfig::~STConfig()
+{
+  if (ini) delete ini;
+  
+  if (g_shibTargetCCache)
+    delete g_shibTargetCCache;
+
+  delete shibConf.origin_mapper;
+  shibConf.term();
+  samlConf.term();
+}
+
+void STConfig::ref()
+{
+  refcount++;
+}
+
+void STConfig::shutdown()
+{
+  refcount--;
+  if (!refcount) {
+    delete g_Config;
+    g_Config = NULL;
+  }
+}
index b4df525..b238a46 100644 (file)
@@ -231,6 +231,22 @@ bool ShibINI::exists(const std::string& header, const std::string& tag) const
   return (m_priv->table[h].find(t) != m_priv->table[h].end());
 }
 
+bool ShibINI::get_tag (string& header, string& tag, bool try_general, string* result) const
+{
+  if (!result) return false;
+
+  if (exists (header, tag)) {
+    *result = get (header, tag);
+    return true;
+  }
+  if (try_general && exists (SHIBTARGET_GENERAL, tag)) {
+    *result = get (SHIBTARGET_GENERAL, tag);
+    return true;
+  }
+  return false;
+}
+
+
 void ShibINI::dump (ostream& os) const
 {
   os << "File: " << m_priv->file << "\n";
index 7908bdc..36482fa 100644 (file)
@@ -123,3 +123,9 @@ string ShibMLP::run (istream& is) const
 
   return run(str);
 }
+
+void ShibMLP::insert (RPCError& e)
+{
+  insert ("errorType", e.toString());
+  insert ("errorText", (e.m_except ? e.m_except->what() : e.error_msg));
+}
index 9c043aa..fb4656a 100644 (file)
@@ -52,7 +52,7 @@ RM::~RM()
   delete m_priv;
 }
 
-RPCError RM::getAttributes(const char* cookie, const char* ip,
+RPCError* RM::getAttributes(const char* cookie, const char* ip,
                           Resource *resource,
                           vector<saml::QName*> attr_requests,
                           vector<SAMLAttribute*> &attr_replies,
@@ -63,17 +63,17 @@ RPCError RM::getAttributes(const char* cookie, const char* ip,
 
   if (!cookie || *cookie == '\0') {
     m_priv->log->error ("no cookie");
-    return RPCError(-1, "No such cookie");
+    return new RPCError(-1, "No such cookie");
   }
 
   if (!ip) {
     m_priv->log->error ("no ip address");
-    return RPCError(-1, "No IP Address");
+    return new RPCError(-1, "No IP Address");
   }
 
   if (!resource) {
     m_priv->log->error ("no resource");
-    return RPCError(-1, "Invalid Resource");
+    return new RPCError(-1, "Invalid Resource");
   }
 
   m_priv->log->info ("request from %s for \"%s\"", ip, resource->getResource());
@@ -101,7 +101,7 @@ RPCError RM::getAttributes(const char* cookie, const char* ip,
        retry--;
       else {
        m_priv->log->error ("RPC Failure");
-       return RPCError(-1, "RPC Failure");
+       return new RPCError(-1, "RPC Failure");
       }
     } else
       retry = -1;
@@ -109,19 +109,29 @@ RPCError RM::getAttributes(const char* cookie, const char* ip,
 
   m_priv->log->debug ("RPC completed with status %d", ret.status);
 
-  RPCError retval;
+  RPCError* retval = NULL;
   if (ret.status)
-    retval = RPCError(ret.status, ret.error_msg);
+    retval = new RPCError(ret.status, ret.error_msg);
   else {
-    retval = RPCError();
     for (u_int i = 0; i < ret.attr_reps.attr_reps_len; i++) {
       istrstream attrstream(ret.attr_reps.attr_reps_val[i].rep);
-      SAMLAttribute *attr = new SAMLAttribute(attrstream);
+      SAMLAttribute *attr = NULL;
+      try {
+       m_priv->log->debug("Trying to decode attribute %d: %s", i,
+                          ret.attr_reps.attr_reps_val[i].rep);
+       attr = new SAMLAttribute(attrstream);
+      } catch (XMLException& e) {
+       m_priv->log->error ("XML Exception: %s", e.getMessage());
+       throw;
+      }
 
       if (attr)
        attr_replies.push_back(attr);
     }
-    assertion = ret.assertion;
+    if (!retval) {
+      retval = new RPCError();
+      assertion = ret.assertion;
+    }
   }
 
   clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_attrs_ret_1, (caddr_t)&ret);
index 84868ed..fa2de7d 100644 (file)
@@ -35,11 +35,6 @@ void RPCError::init(int stat, char const* msg)
       log.error ("Caught SAML Exception while building the SAMLException: %s",
                 e.what());
       log.error ("XML: %s", msg);
-    } catch (SAXException& e) {
-      ostrstream os;
-      xmlout(os, e.getMessage());
-      log.error ("Caught SAX Exception building SAMLException: %s", os.str());
-      log.error ("XML: %s", msg);
     } catch (XMLException& e) {
       log.error ("Caught XML Exception building SAMLException: %s",
                 e.getMessage());
@@ -48,7 +43,7 @@ void RPCError::init(int stat, char const* msg)
       log.error ("Caught exception building SAMLException!");
       log.error ("XML: %s", msg);
     }
-    error_msg = "";
+    error_msg = (m_except ? m_except->what() : msg);
   } else {
     error_msg = msg;
     m_except = NULL;
@@ -61,96 +56,43 @@ RPCError::~RPCError()
     delete m_except;
 }
 
-string RPCError::getHTML()
+const char* RPCError::toString()
 {
-  string retval;
-
   switch (status) {
-  case SHIBRPC_OK:
-    break;
-
-  case SHIBRPC_UNKNOWN_ERROR:
-    retval = "Unknown error: ";
-    break;
-
-  case SHIBRPC_IPADDR_MISMATCH:
-    retval =
-      "IP Address Mismatch: "
-      "Your IP Address does not match the your authentication token.";
-    break;
+  case SHIBRPC_OK:             return "No Error";
+  case SHIBRPC_UNKNOWN_ERROR:  return "Unknown error";
+  case SHIBRPC_IPADDR_MISMATCH:        return "IP Address Mismatch";
+  case SHIBRPC_NO_SESSION:     return "No Session";
+  case SHIBRPC_XML_EXCEPTION:  return "Xerces XML Exception";
+  case SHIBRPC_SAML_EXCEPTION: return "Unknown OpenSAML Exception";
+  case SHIBRPC_INTERNAL_ERROR: return "Internal Error";
+  case SHIBRPC_SAX_EXCEPTION:  return "Xerces SAX Exception";
+  case SHIBRPC_SESSION_EXPIRED:        return "Session Expired";
+  case SHIBRPC_AUTHSTATEMENT_MISSING:  return "Authentication Statement Missing";
+  case SHIBRPC_IPADDR_MISSING: return "IP Address Missing";
+  case SHIBRPC_RESPONSE_MISSING:       return "SAML Response Missing";
+  case SHIBRPC_ASSERTION_MISSING:      return "SAML Assertion Missing";
+  case SHIBRPC_ASSERTION_REPLAYED:     return "SAML Assertion Replayed";
+  default:                     return "Unknown Shibboleth RPC error";
+  }
+}
 
+bool RPCError::isRetryable()
+{
+  switch (status) {
   case SHIBRPC_NO_SESSION:
-    retval =
-      "No Session: "
-      "This server could not find a session for you.  This should not happen.<p>\n"
-      "The only information about this error is:";
-    break;
-
-  case SHIBRPC_XML_EXCEPTION:
-    retval = "Xerces XML Exception: ";
-    break;
-
-  case SHIBRPC_SAML_EXCEPTION:
-    retval = "Unknown OpenSAML Exception: ";
-    break;
-
-  case SHIBRPC_INTERNAL_ERROR:
-    retval = "Internal Error: ";
-    break;
-
-  case SHIBRPC_SAX_EXCEPTION:
-    retval = "Xerces SAX Exception: ";
-    break;
-
   case SHIBRPC_SESSION_EXPIRED:
-    retval =
-      "Session Expired: "
-      "Your Shibboleth Session has expired.  Please log in again.";
-    break;
-
-  case SHIBRPC_AUTHSTATEMENT_MISSING:
-    retval =
-      "Authentication Statement Missing: "
-      "The assertion of your Shibboleth identity was missing or incompatible "
-      "with the policies of this site.";
-    break;
-
-  case SHIBRPC_IPADDR_MISSING:
-    retval =
-      "IP Address Missing: "
-      "This site requires your Shibboleth to provide your IP Address in your "
-      "identity assertion.";
-    break;
-
-  case SHIBRPC_RESPONSE_MISSING:
-    retval =
-      "SAML Response Missing: "
-      "The assertion of your Shibboleth Identity was missing in the response "
-      "or incompatible with the policies of this site.";
-    break;
-
-  case SHIBRPC_ASSERTION_MISSING:
-    retval =
-      "SAML Assertion Missing: "
-      "Could not find the SSO assertion while processing your SAML Response.";
-    break;
+    return true;
 
-  case SHIBRPC_ASSERTION_REPLAYED:
-    retval =
-      "SAML Assertion Replayed: "
-      "This SAML Response has already been seen.  Either you double-clicked "
-      "while submitting the response or someone is trying to attack this server.";
-    break;
+  case SHIBRPC_SAML_EXCEPTION:
+  {
+    const char* msg = (m_except ? m_except->what() : "");
+    if (!strcmp(msg, "SAMLPOSTProfile::accept() detected expired response"))
+      return true;
+  }
 
   default:
-    retval =
-      "An unknown Shibboleth error occurred at this server.\n"
-      "Contact the server adminstrator for more information.\n";
-    break;
+    return false;
   }
-
-  retval.append ("<p>\n");
-  retval.append (error_msg);
-
-  return retval;
 }
+
index 9f5e675..175ce24 100644 (file)
@@ -56,18 +56,18 @@ SHIRE::~SHIRE()
 }
 
 
-RPCError SHIRE::sessionIsValid(const char* cookie, const char* ip)
+RPCError* SHIRE::sessionIsValid(const char* cookie, const char* ip)
 {
   saml::NDC ndc("sessionIsValid");
 
   if (!cookie || *cookie == '\0') {
     m_priv->log->error ("No cookie");
-    return RPCError(-1, "No such cookie");
+    return new RPCError(-1, "No such cookie");
   }
 
   if (!ip) {
     m_priv->log->error ("No IP");
-    return RPCError(-1, "Invalid IP Address");
+    return new RPCError(-1, "Invalid IP Address");
   }
 
   m_priv->log->info ("is session valid: %s", ip);
@@ -95,7 +95,7 @@ RPCError SHIRE::sessionIsValid(const char* cookie, const char* ip)
        retry--;
       else {
        m_priv->log->error ("RPC Failure");
-       return RPCError(-1, "RPC Failure");
+       return new RPCError(-1, "RPC Failure");
       }
     } else
       retry = -1;
@@ -103,11 +103,11 @@ RPCError SHIRE::sessionIsValid(const char* cookie, const char* ip)
 
   m_priv->log->debug ("RPC completed with status %d", ret.status);
 
-  RPCError retval;
+  RPCError* retval;
   if (ret.status)
-    retval = RPCError(ret.status, ret.error_msg);
+    retval = new RPCError(ret.status, ret.error_msg);
   else
-    retval = RPCError();
+    retval = new RPCError();
 
   clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_session_is_valid_ret_1, (caddr_t)&ret);
 
@@ -115,18 +115,18 @@ RPCError SHIRE::sessionIsValid(const char* cookie, const char* ip)
   return retval;
 }
 
-RPCError SHIRE::sessionCreate(const char* post, const char* ip, string& cookie)
+RPCError* SHIRE::sessionCreate(const char* post, const char* ip, string& cookie)
 {
   saml::NDC ndc("sessionCreate");
 
   if (!post || *post == '\0') {
     m_priv->log->error ("No POST");
-    return RPCError(-1,  "Invalid POST string");
+    return new RPCError(-1,  "Invalid POST string");
   }
 
   if (!ip) {
     m_priv->log->error ("No IP");
-    return RPCError(-1, "Invalid IP Address");
+    return new RPCError(-1, "Invalid IP Address");
   }
 
   m_priv->log->info ("create session for user at %s", ip);
@@ -151,7 +151,7 @@ RPCError SHIRE::sessionCreate(const char* post, const char* ip, string& cookie)
        retry--;
       else {
        m_priv->log->error ("RPC Failure");
-       return RPCError(-1, "RPC Failure");
+       return new RPCError(-1, "RPC Failure");
       }
     } else
       retry = -1;
@@ -159,13 +159,13 @@ RPCError SHIRE::sessionCreate(const char* post, const char* ip, string& cookie)
 
   m_priv->log->debug ("RPC completed with status %d", ret.status);
 
-  RPCError retval;
+  RPCError* retval;
   if (ret.status)
-    retval = RPCError(ret.status, ret.error_msg);
+    retval = new RPCError(ret.status, ret.error_msg);
   else {
     m_priv->log->debug ("new cookie: %s", ret.cookie);
     cookie = ret.cookie;
-    retval = RPCError();
+    retval = new RPCError();
   }
 
   clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_1, (caddr_t)&ret);
index 66bd6c9..c3f23f8 100644 (file)
@@ -8,7 +8,6 @@
 
 #include "shib-target.h"
 
-#include <log4cpp/PropertyConfigurator.hh>
 #include <log4cpp/Category.hh>
 
 using namespace saml;
@@ -16,77 +15,9 @@ using namespace shibboleth;
 using namespace shibtarget;
 using namespace std;
 
-CCache* shibtarget::g_shibTargetCCache = NULL;
-
 /* shib-target.cpp */
 
-#ifndef SHIBTARGET_INIFILE
-#define SHIBTARGET_INIFILE "/etc/shibboleth.ini"
-#endif
-
-static bool get_tag (ShibINI& ini, string& header, string& tag, bool try_general,
-                    string* result)
-{
-  if (!result) return false;
-
-  if (ini.exists (header, tag)) {
-    *result = ini.get(header, tag);
-    return true;
-  }
-  if (try_general && ini.exists (SHIBTARGET_GENERAL, tag)) {
-    *result = ini.get(SHIBTARGET_GENERAL, tag);
-    return true;
-  }
-  return false;
-}
-
-static bool get_tag (ShibINI& ini, string& header, const char* tag,
-                    bool try_general, string* result)
-{
-  string tag_s = tag;
-  return get_tag (ini, header, tag_s, try_general, result);
-}
-
-class DummyMapper : public IOriginSiteMapper
-{
-public:
-    DummyMapper();
-    ~DummyMapper();
-    virtual Iterator<xstring> getHandleServiceNames(const XMLCh* originSite) { return Iterator<xstring>(m_hsnames); }
-    virtual Key* getHandleServiceKey(const XMLCh* handleService) { return NULL; }
-    virtual Iterator<xstring> getSecurityDomains(const XMLCh* originSite);
-    virtual Iterator<X509Certificate*> getTrustedRoots() { return Iterator<X509Certificate*>(); }
-
-private:
-    typedef map<xstring,vector<xstring>*> domains_t;
-    domains_t m_domains;
-    vector<xstring> m_hsnames;
-};
-
-DummyMapper::DummyMapper()
-{
-    auto_ptr<XMLCh> buf(XMLString::transcode("shibprod0.internet2.edu"));
-    m_hsnames.push_back(buf.get());
-}
-
-Iterator<xstring> DummyMapper::getSecurityDomains(const XMLCh* originSite)
-{
-    domains_t::iterator i=m_domains.find(originSite);
-    if (i==m_domains.end())
-    {
-        vector<xstring>* pv=new vector<xstring>();
-        pv->push_back(originSite);
-        pair<domains_t::iterator,bool> p=m_domains.insert(domains_t::value_type(originSite,pv));
-       i=p.first;
-    }
-    return Iterator<xstring>(*(i->second));
-}
-
-DummyMapper::~DummyMapper()
-{
-    for (domains_t::iterator i=m_domains.begin(); i!=m_domains.end(); i++)
-        delete i->second;
-}
+static ShibTargetConfig* g_Config = NULL;
 
 /* initialize and finalize the target library: return 0 on success, 1 on failure */
 extern "C" int shib_target_initialize (const char* app_name, const char* inifile)
@@ -96,96 +27,26 @@ extern "C" int shib_target_initialize (const char* app_name, const char* inifile
     return 1;
   }
 
-  // Open the inifile
-  ShibINI ini((inifile ? inifile : SHIBTARGET_INIFILE));
-
-  string app = app_name;
-  string tag;
-
-  // Initialize Log4cpp
-  if (get_tag (ini, app, SHIBTARGET_TAG_LOGGER, true, &tag)) {
-    cerr << "Trying to load logger configuration: " << tag << "\n";
-    try {
-      log4cpp::PropertyConfigurator::configure(tag);
-    } catch (log4cpp::ConfigureFailure& e) {
-      cerr << "Error reading configuration: " << e.what() << "\n";
-    }
-  } else {
-    log4cpp::Category& category = log4cpp::Category::getRoot();
-    category.setPriority(log4cpp::Priority::DEBUG);
-    cerr << "No logger configuration found\n";
-  }
-
-  log4cpp::Category& log = log4cpp::Category::getInstance("shibtarget.initialize");
-
-  // Initialize SAML and Shib libraries
-  SAMLConfig& samlConf = SAMLConfig::getConfig();
-  ShibConfig& shibConf = ShibConfig::getConfig();
-
-  // Init SAML
-  if (get_tag (ini, app, SHIBTARGET_TAG_SCHEMAS, true, &tag))
-    samlConf.schema_dir = tag;
-  if (get_tag (ini, app, SHIBTARGET_TAG_CERTFILE, true, &tag))
-    samlConf.ssl_certfile = tag;
-  if (get_tag (ini, app, SHIBTARGET_TAG_KEYFILE, true, &tag))
-    samlConf.ssl_keyfile = tag;
-  if (get_tag (ini, app, SHIBTARGET_TAG_KEYPASS, true, &tag))
-    samlConf.ssl_keypass = tag;
-  if (get_tag (ini, app, SHIBTARGET_TAG_CALIST, true, &tag))
-    samlConf.ssl_calist = tag;
-
-  if (!samlConf.init()) {
-    log.error ("Failed to initialize SAML Library");
+  if (g_Config) {
+    log4cpp::Category& log = log4cpp::Category::getInstance("shibtarget.init");
+    log.error("shib_target_initialize: Already initialized");
     return 1;
-  } else
-    log.debug ("SAML Initialized");
+  }
 
-  // Init Shib
-  shibConf.origin_mapper = new DummyMapper();
-  
-  if (!shibConf.init()) {
-    log.error ("Failed to initialize SHIB library");
+  try {
+    g_Config = &(ShibTargetConfig::init(app_name, inifile));
+  } catch (runtime_error &e) {
     return 1;
-  } else
-    log.debug ("Shib Initialized");
-
-  // Initialize the SHAR Cache
-  if (!strcmp (app_name, SHIBTARGET_SHAR))
-    g_shibTargetCCache = CCache::getInstance();  
-
-  // Load any extensions
-  string ext = "extensions";
-  if (ini.exists(ext)) {
-    saml::NDC ndc("load extensions");
-    ShibINI::Iterator* iter = ini.tag_iterator(ext);
-
-    for (const string* str = iter->begin(); str; str = iter->next()) {
-      string file = ini.get(ext, *str);
-      try
-      {
-       samlConf.saml_register_extension(file.c_str());
-       log.debug("%s: loading %s", str->c_str(), file.c_str());
-      }
-      catch (SAMLException& e)
-      {
-       log.error("%s: %s", str->c_str(), e.what());
-      }
-    }
-    delete iter;
   }
 
-  log.debug("shib_target_initialize() finished");
   return 0;
 }
 
 extern "C" void shib_target_finalize (void)
 {
-  delete g_shibTargetCCache;
-
-  ShibConfig& shibConf = ShibConfig::getConfig();
-  delete shibConf.origin_mapper;
-  shibConf.term();
+  if (!g_Config)
+    return;
 
-  SAMLConfig& samlConf = SAMLConfig::getConfig();
-  samlConf.term();
+  g_Config->shutdown();
+  g_Config = NULL;
 }
index 759ee1d..a70065d 100644 (file)
@@ -199,7 +199,7 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
     catch (SAMLException &e)
     {
       log.error ("received SAML exception");
-      ostrstream os;
+      ostringstream os;
       os << e;
       throw ShibTargetException (SHIBRPC_SAML_EXCEPTION, os.str());
     }
@@ -209,12 +209,6 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
       auto_ptr<char> msg(XMLString::transcode(e.getMessage()));
       throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get());
     }
-    catch (SAXException &e)
-    {
-      log.error ("received SAX exception");
-      auto_ptr<char> msg(XMLString::transcode(e.getMessage()));
-      throw ShibTargetException (SHIBRPC_SAX_EXCEPTION, msg.get());
-    }
   }
   catch (ShibTargetException &e)
   {
@@ -320,9 +314,9 @@ shibrpc_get_attrs_1_svc(shibrpc_get_attrs_args_1 *argp,
     u_int i = 0;
     while (iter.hasNext()) {
       SAMLAttribute* attr = iter.next();
-      ostrstream os;
+      ostringstream os;
       os << *attr;
-      av[i++].rep = strdup(os.str());
+      av[i++].rep = strdup(os.str().c_str());
     }
   }
 
index e104916..bdc8a6d 100644 (file)
@@ -3,5 +3,6 @@
 main()
 {
   char* init = getenv("SHIBCONFIG");
-  shib_target_initialize("Test App", init);
+  char* app = getenv("SHIBTESTAPP");
+  shib_target_initialize((app ? app : "Test App"), init);
 }
index 9bdae51..74e016a 100644 (file)
@@ -1,5 +1,6 @@
 #include <log4cpp/Category.hh>
 #include <log4cpp/RemoteSyslogAppender.hh>
+#include <log4cpp/SyslogAppender.hh>
 
 #include <string>
 
@@ -17,4 +18,10 @@ main()
   log.setAppender(app);
 
   log.error("Test Log Entry");
+
+  Category& syslog = Category::getInstance("test");
+  SyslogAppender sapp(name, sysname);
+  syslog.setAppender(sapp);
+
+  syslog.error("test Syslog entry");
 }