Refactored remote API into IListener, moved ONC server marshallers to shibd
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 2 May 2005 13:44:28 +0000 (13:44 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 2 May 2005 13:44:28 +0000 (13:44 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@1578 cb58f699-b61c-0410-a6fe-9272a202ed29

shar/Makefile.am
shar/shar-utils.h
shar/shar.cpp
shar/shar.dsp
shar/shibrpc-server.cpp [new file with mode: 0644]
shar/test-client.cpp
shib/ShibBrowserProfile.cpp
shib/ShibConfig.cpp
shib/shib.h

index 747b9c8..4052682 100644 (file)
@@ -13,7 +13,7 @@ endif
 
 test_client_SOURCES = test-client.cpp
 
-shibd_SOURCES = shar.cpp shar-utils.cpp
+shibd_SOURCES = shar.cpp shar-utils.cpp shibrpc-server.cpp
 noinst_HEADERS = shar-utils.h
 
 test_client_LDADD = \
index 7804bff..a314b7f 100644 (file)
@@ -58,6 +58,8 @@
 #ifndef SHAR_UTILS_H
 #define SHAR_UTILS_H
 
+#include <saml/saml.h>
+#include <shib-target/shibrpc.h>
 #include <shib-target/shib-target.h>
 
 extern "C" {
index cf1d51d..3bdcf1f 100644 (file)
@@ -87,6 +87,9 @@ using namespace log4cpp;
 
 extern "C" void shibrpc_prog_2(struct svc_req* rqstp, register SVCXPRT* transp);
 
+// Declare a "MemoryListener" that our server methods will forward their work to.
+IListener* g_MemoryListener = NULL;
+
 int shar_run = 1;
 const char* shar_config = NULL;
 const char* shar_schemadir = NULL;
@@ -107,7 +110,7 @@ static bool new_connection(IListener::ShibSocket& listener, const Iterator<ShibR
     }
     catch (...) {
         saml::NDC ndc("new_connection");
-        Category& log=Category::getInstance("SHAR");
+        Category& log=Category::getInstance("shibd");
         log.crit("error starting new child thread to service request");
         return false;
     }
@@ -116,8 +119,10 @@ static bool new_connection(IListener::ShibSocket& listener, const Iterator<ShibR
 
 static void shar_svc_run(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
 {
+#ifdef _DEBUG
     saml::NDC ndc("shar_svc_run");
-    Category& log=Category::getInstance("SHAR");
+#endif
+    Category& log=Category::getInstance("shibd");
 
     while (shar_run) {
         fd_set readfds;
@@ -189,19 +194,31 @@ int real_main(int preinit)
             fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
             return 0;
         }
+        
+        // Build an internal "listener" to handle the work.
+        IPlugIn* plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemoryListenerType,NULL);
+        g_MemoryListener=dynamic_cast<IListener*>(plugin);
+        if (!g_MemoryListener) {
+            delete plugin;
+            fprintf(stderr, "MemoryListener plugin failed to load");
+            conf.shutdown();
+            return -3;
+        }
 
         const IListener* listener=conf.getINI()->getListener();
         
         // Create the SHAR listener socket
         if (!listener->create(sock)) {
+            delete g_MemoryListener;
             conf.shutdown();
-            return -3;
+            return -4;
         }
 
         // Bind to the proper port
         if (!listener->bind(sock)) {
+            delete g_MemoryListener;
             conf.shutdown();
-            return -4;
+            return -5;
         }
 
         // Initialize the SHAR Utilitites
@@ -218,6 +235,7 @@ int real_main(int preinit)
             conf.getINI()->getListener()->close(sock);
         }
 
+        delete g_MemoryListener;
         conf.shutdown();
         fprintf(stdout, "shibd shutdown complete\n");
     }
@@ -346,18 +364,31 @@ int main(int argc, char *argv[])
     if (shar_checkonly)
         fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
     else {
+
+        // Build an internal "listener" to handle the work.
+        IPlugIn* plugin=SAMLConfig::getConfig().newPlugin(shibtarget::XML::MemoryListenerType,NULL);
+        g_MemoryListener=dynamic_cast<IListener*>(plugin);
+        if (!g_MemoryListener) {
+            delete plugin;
+            fprintf(stderr, "MemoryListener plugin failed to load");
+            conf.shutdown();
+            return -3;
+        }
+
         const IListener* listener=conf.getINI()->getListener();
         
         // Create the SHAR listener socket
         if (!listener->create(sock)) {
+            delete g_MemoryListener;
             conf.shutdown();
-            return -3;
+            return -4;
         }
     
         // Bind to the proper port
         if (!listener->bind(sock, unlink_socket==1)) {
+            delete g_MemoryListener;
             conf.shutdown();
-            return -4;
+            return -5;
         }
     
         // Initialize the SHAR Utilitites
index a5428c4..d86cccc 100644 (file)
@@ -106,5 +106,17 @@ SOURCE=.\shar.rc
 
 SOURCE=.\shar_win32.cpp
 # End Source File
+# Begin Source File
+
+SOURCE=".\shibrpc-server.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE="..\shib-target\shibrpc-svc.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\shib-target\shibrpc-xdr.c"
+# End Source File
 # End Target
 # End Project
diff --git a/shar/shibrpc-server.cpp b/shar/shibrpc-server.cpp
new file mode 100644 (file)
index 0000000..9739708
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * shibrpc-server.cpp -- SHIBRPC Server implementation.  Originally created
+ *                       as shibrpc-server-stubs.c; make sure that the function
+ *                       prototypes here match those in shibrpc.x.
+ *
+ * Created by: Derek Atkins <derek@ihtfp.com>
+ *
+ * $Id$
+ */
+
+#include <saml/saml.h>
+#include <shib-target/shibrpc.h>
+
+// eventually we might be able to support autoconf via cygwin...
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#include <shib-target/shib-target.h>
+
+#ifdef HAVE_LIBDMALLOCXX
+#include <dmalloc.h>
+#endif
+
+#include <sstream>
+#include <log4cpp/Category.hh>
+
+using namespace std;
+using namespace log4cpp;
+using namespace saml;
+using namespace shibboleth;
+using namespace shibtarget;
+
+extern IListener* g_MemoryListener;
+
+static string get_threadid (const char* proc)
+{
+  static u_long counter = 0;
+  ostringstream buf;
+  buf << "[" << counter++ << "] " << proc;
+  return buf.str();
+}
+
+static Category& get_category (void)
+{
+  return Category::getInstance("shibd.Listener");
+}
+
+extern "C" bool_t shibrpc_ping_2_svc(int *argp, int *result, struct svc_req *rqstp)
+{
+    g_MemoryListener->ping(*argp);
+    *result=*argp;
+    return TRUE;
+}
+
+extern "C" bool_t shibrpc_get_session_2_svc(
+    shibrpc_get_session_args_2 *argp,
+    shibrpc_get_session_ret_2 *result,
+    struct svc_req *rqstp
+    )
+{
+    Category& log = get_category();
+    string ctx = get_threadid("sessionGet");
+    saml::NDC ndc(ctx);
+
+    if (!argp || !result) {
+        log.error("RPC Argument Error");
+        return FALSE;
+    }
+
+    memset(result, 0, sizeof (*result));
+    result->provider_id = strdup("");
+    result->auth_statement = strdup("");
+    result->attr_response_pre = strdup("");
+    result->attr_response_post = strdup("");
+
+    IConfig* conf=ShibTargetConfig::getConfig().getINI();
+    Locker locker(conf);
+    const IApplication* app=conf->getApplication(argp->application_id);
+    if (!app) {
+        // Something's horribly wrong.
+        log.error("couldn't find application (%s) for session", argp->application_id);
+        SAMLException ex("Unable to locate application for session, deleted?");
+        ostringstream os;
+        os << ex;
+        result->status=strdup(os.str().c_str());
+        return TRUE;
+    }
+    
+    ISessionCacheEntry* entry=NULL;
+    try {
+        // Delegate...
+        g_MemoryListener->sessionGet(app,argp->cookie,argp->client_addr,&entry);
+
+        // Set profile and provider
+        result->profile = entry->getProfile();
+        free(result->provider_id);
+        result->provider_id = strdup(entry->getProviderId());
+     
+        // Now grab the serialized authentication statement and responses
+        ostringstream os;
+        os << *(entry->getAuthnStatement());
+        free(result->auth_statement);
+        result->auth_statement = strdup(os.str().c_str());
+      
+        ISessionCacheEntry::CachedResponse responses=entry->getResponse();
+        if (!responses.empty()) {
+            os.str("");
+            os << *responses.unfiltered;
+            free(result->attr_response_pre);
+            result->attr_response_pre = strdup(os.str().c_str());
+
+            os.str("");
+            os << *responses.filtered;
+            free(result->attr_response_post);
+            result->attr_response_post = strdup(os.str().c_str());
+        }
+
+        // Ok, just release it.
+        entry->unlock();
+        entry=NULL;
+        result->status=strdup("");
+    }
+    catch (SAMLException &e) {
+        // If the entry is set, it happened after the call.
+        if (entry) {
+            entry->unlock();
+            conf->getSessionCache()->remove(argp->cookie);
+        }
+        ostringstream os;
+        os << e;
+        result->status = strdup(os.str().c_str());
+    }
+#ifndef _DEBUG
+    catch (...) {
+        // If the entry is set, it happened after the call.
+        if (entry) {
+            entry->unlock();
+            conf->getSessionCache()->remove(argp->cookie);
+        }
+        InvalidSessionException ex("An unexpected error occurred while validating your session, and you must re-authenticate.");
+        ostringstream os;
+        os << ex;
+        result->status = strdup(os.str().c_str());
+    }
+#endif
+
+    return TRUE;
+}
+
+extern "C" bool_t
+shibrpc_new_session_2_svc(
+    shibrpc_new_session_args_2 *argp,
+    shibrpc_new_session_ret_2 *result,
+    struct svc_req *rqstp
+    )
+{
+    Category& log = get_category();
+    string ctx=get_threadid("sessionNew");
+    saml::NDC ndc(ctx);
+
+    if (!argp || !result) {
+        log.error("Invalid RPC Arguments");
+        return FALSE;
+    }
+
+    // Initialize the result structure
+    memset (result, 0, sizeof(*result));
+    result->cookie = strdup ("");
+    result->target = strdup ("");
+    result->provider_id = strdup("");
+
+    // Access the application config.
+    IConfig* conf=ShibTargetConfig::getConfig().getINI();
+    Locker locker(conf);
+    const IApplication* app=conf->getApplication(argp->application_id);
+    if (!app) {
+        // Something's horribly wrong. Flush the session.
+        log.error("couldn't find application for session");
+        SAMLException ex("Unable to locate application for session, deleted?");
+        ostringstream os;
+        os << ex;
+        result->status=strdup(os.str().c_str());
+        return TRUE;
+    }
+
+    try {
+        // Delagate the work...
+        string target,cookie,provider_id;
+        g_MemoryListener->sessionNew(
+            app,
+            argp->supported_profiles,
+            argp->recipient,
+            argp->packet,
+            argp->client_addr,
+            target,
+            cookie,
+            provider_id
+            );
+
+        // And let the user know.
+        if (result->cookie) free(result->cookie);
+        if (result->target) free(result->target);
+        if (result->provider_id) free(result->provider_id);
+        result->cookie = strdup(cookie.c_str());
+        result->target = strdup(target.c_str());
+        result->provider_id = strdup(provider_id.c_str());
+        result->status = strdup("");
+    }
+    catch (SAMLException& e) {
+        ostringstream os;
+        os << e;
+        result->status = strdup(os.str().c_str());
+    }
+#ifndef _DEBUG
+    catch (...) {
+        SAMLException e("An unexpected error occurred while creating your session.");
+        ostringstream os;
+        os << e;
+        result->status = strdup(os.str().c_str());
+    }
+#endif
+
+    return TRUE;
+}
+
+extern "C" bool_t
+shibrpc_end_session_2_svc(
+    shibrpc_end_session_args_2 *argp,
+    shibrpc_end_session_ret_2 *result,
+    struct svc_req *rqstp
+    )
+{
+    Category& log = get_category();
+    string ctx = get_threadid("sessionEnd");
+    saml::NDC ndc(ctx);
+
+    if (!argp || !result) {
+        log.error("RPC Argument Error");
+        return FALSE;
+    }
+
+    memset(result, 0, sizeof (*result));
+
+    IConfig* conf=ShibTargetConfig::getConfig().getINI();
+    Locker locker(conf);
+    
+    try {
+        g_MemoryListener->sessionEnd(NULL,argp->cookie);
+        result->status=strdup("");
+    }
+    catch (SAMLException& e) {
+        ostringstream os;
+        os << e;
+        result->status = strdup(os.str().c_str());
+    }
+#ifndef _DEBUG
+    catch (...) {
+        SAMLException ex("An unexpected error occurred while ending your session.");
+        ostringstream os;
+        os << ex;
+        result->status = strdup(os.str().c_str());
+    }
+#endif
+  
+    return TRUE;
+}
+
+extern "C" int
+shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
+{
+       xdr_free (xdr_result, result);
+
+       /*
+        * Insert additional freeing code here, if needed
+        */
+
+       return 1;
+}
index 226f734..4ebe4bb 100644 (file)
@@ -2,13 +2,11 @@
 #include <iostream>
 
 using namespace std;
+using namespace saml;
 using namespace shibtarget;
 
 int main (int argc, char *argv[])
 {
-  int res,start;
-  enum clnt_stat clnt_stat;
-
   const char* config=getenv("SHIBCONFIG");
   if (!config)
     config=SHIB_CONFIG;
@@ -18,42 +16,18 @@ int main (int argc, char *argv[])
 
   ShibTargetConfig& conf=ShibTargetConfig::getConfig();
   conf.setFeatures(ShibTargetConfig::Listener);
-  if (!conf.init(schemadir) || conf.load(config))
+  if (!conf.init(schemadir) || !conf.load(config))
       return -10;
 
-  IListener::ShibSocket sock;
-  const IListener* listener=conf.getINI()->getListener();
-  if (!listener->create(sock))
-  {
-    cerr << "create failed\n";
-    return -1;
+  try {
+      int i=0;
+      conf.getINI()->getListener()->ping(i);
+      cerr << 0 << " -> " << i << "\n";
   }
-
-  if (!listener->connect(sock))
-  {
-    cerr << "connect failed\n";
-    return -2;
+  catch (SAMLException& e) {
+      cerr << "caught SAML exception: " << e.what() << "\n";
   }
-
-  CLIENT* clnt = listener->getClientHandle(sock,SHIBRPC_PROG, SHIBRPC_VERS_2);
-  if (!clnt) {
-    clnt_pcreateerror("shibrpc_client_create");
-    cerr << "shibrpc_client_create failed\n";
-    return -3;
-  }
-
-  res = start = 0;
-  clnt_stat = shibrpc_ping_2 (&start, &res, clnt);
-
-  if (clnt_stat != RPC_SUCCESS) {
-    clnt_perror (clnt, "rpc");
-    cerr << "RPC error:" << clnt_stat << ", " << res << "\n";
-    return -4;
-  }
-
-  cout << sock << " -> " << res << "\n";
-  clnt_destroy (clnt);
-
+  
   conf.shutdown();
   return 0;
 }
index d26e006..a8f72a1 100644 (file)
@@ -109,8 +109,8 @@ SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
             const IEntityDescriptor* provider=m.lookup(e.getProperty("issuer"),false);
             if (provider) {
                 const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
-                if (role) annotateException(e,role); // throws it
-                annotateException(e,provider);  // throws it
+                if (role) annotateException(&e,role); // throws it
+                annotateException(&e,provider);  // throws it
             }
         }
         throw;
@@ -141,7 +141,7 @@ SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
         if (provider) {
             bpr.clear();
             MetadataException ex("metadata lookup failed, unable to process assertion");
-            annotateException(ex,provider);  // throws it
+            annotateException(&ex,provider);  // throws it
         }
         bpr.clear();
         throw MetadataException("metadata lookup failed, unable to process assertion",namedparams(1,"issuer",issuer.get()));
@@ -158,7 +158,7 @@ SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
             if (!t.validate(*bpr.response,role)) {
                 bpr.clear();
                 TrustException ex("unable to verify signed profile response");
-                annotateException(ex,role); // throws it
+                annotateException(&ex,role); // throws it
             }
         }    
         // SSO assertion signed?
@@ -167,7 +167,7 @@ SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
             if (!t.validate(*bpr.assertion,role)) {
                 bpr.clear();
                 TrustException ex("unable to verify signed authentication assertion");
-                annotateException(ex,role); // throws it
+                annotateException(&ex,role); // throws it
             }
         }
         return bpr;
@@ -179,6 +179,6 @@ SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
         issuer.get(), (nq.get() ? nq.get() : "none"));
     bpr.clear();
     MetadataException ex("metadata lookup failed, issuer not registered as SAML 1.x identity provider");
-    annotateException(ex,provider,false);
+    annotateException(&ex,provider,false);
     throw ex;
 }
index 0db5b55..0744498 100644 (file)
@@ -217,18 +217,18 @@ ShibConfig& ShibConfig::getConfig()
     return g_config;
 }
 
-void shibboleth::annotateException(SAMLException& e, const IEntityDescriptor* entity, bool rethrow)
+void shibboleth::annotateException(SAMLException* e, const IEntityDescriptor* entity, bool rethrow)
 {
     if (entity) {
         auto_ptr_char id(entity->getId());
-        e.addProperty("providerId",id.get());
+        e->addProperty("providerId",id.get());
         Iterator<const IRoleDescriptor*> roles=entity->getRoleDescriptors();
         while (roles.hasNext()) {
             const IRoleDescriptor* role=roles.next();
             if (role->isValid()) {
                 const char* temp=role->getErrorURL();
                 if (temp) {
-                    e.addProperty("errorURL",temp);
+                    e->addProperty("errorURL",temp);
                     break;
                 }
             }
@@ -242,32 +242,32 @@ void shibboleth::annotateException(SAMLException& e, const IEntityDescriptor* en
                 const char* lname=c->getSurName();
                 if (fname && lname) {
                     string contact=string(fname) + ' ' + lname;
-                    e.addProperty("contactName",contact.c_str());
+                    e->addProperty("contactName",contact.c_str());
                 }
                 else if (fname)
-                    e.addProperty("contactName",fname);
+                    e->addProperty("contactName",fname);
                 else if (lname)
-                    e.addProperty("contactName",lname);
+                    e->addProperty("contactName",lname);
                 Iterator<string> emails=c->getEmailAddresses();
                 if (emails.hasNext())
-                    e.addProperty("contactEmail",emails.next().c_str());
+                    e->addProperty("contactEmail",emails.next().c_str());
                 break;
             }
         }
     }
     
     if (rethrow)
-        throw e;
+        e->raise();
 }
 
-void shibboleth::annotateException(saml::SAMLException& e, const IRoleDescriptor* role, bool rethrow)
+void shibboleth::annotateException(saml::SAMLException* e, const IRoleDescriptor* role, bool rethrow)
 {
     if (role) {
         auto_ptr_char id(role->getEntityDescriptor()->getId());
-        e.addProperty("providerId",id.get());
+        e->addProperty("providerId",id.get());
         const char* temp=role->getErrorURL();
         if (role->getErrorURL())
-            e.addProperty("errorURL",role->getErrorURL());
+            e->addProperty("errorURL",role->getErrorURL());
 
         Iterator<const IContactPerson*> i=role->getContactPersons();
         while (i.hasNext()) {
@@ -277,20 +277,20 @@ void shibboleth::annotateException(saml::SAMLException& e, const IRoleDescriptor
                 const char* lname=c->getSurName();
                 if (fname && lname) {
                     string contact=string(fname) + ' ' + lname;
-                    e.addProperty("contactName",contact.c_str());
+                    e->addProperty("contactName",contact.c_str());
                 }
                 else if (fname)
-                    e.addProperty("contactName",fname);
+                    e->addProperty("contactName",fname);
                 else if (lname)
-                    e.addProperty("contactName",lname);
+                    e->addProperty("contactName",lname);
                 Iterator<string> emails=c->getEmailAddresses();
                 if (emails.hasNext())
-                    e.addProperty("contactEmail",emails.next().c_str());
+                    e->addProperty("contactEmail",emails.next().c_str());
                 break;
             }
         }
     }
     
     if (rethrow)
-        throw e;
+        e->raise();
 }
index 19560c7..eceb96e 100644 (file)
@@ -607,8 +607,8 @@ namespace shibboleth
      *  contactName         A formatted support or technical contact name
      *  contactEmail        A contact email address
      */
-    SHIB_EXPORTS void annotateException(saml::SAMLException& e, const IEntityDescriptor* entity, bool rethrow=true);
-    SHIB_EXPORTS void annotateException(saml::SAMLException& e, const IRoleDescriptor* role, bool rethrow=true);
+    SHIB_EXPORTS void annotateException(saml::SAMLException* e, const IEntityDescriptor* entity, bool rethrow=true);
+    SHIB_EXPORTS void annotateException(saml::SAMLException* e, const IRoleDescriptor* role, bool rethrow=true);
 }
 
 #endif