Implemented simple logout handler.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Wed, 6 Apr 2005 03:52:30 +0000 (03:52 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Wed, 6 Apr 2005 03:52:30 +0000 (03:52 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@1505 cb58f699-b61c-0410-a6fe-9272a202ed29

shib-target/shib-target.cpp
shib-target/shib-target.h
shib-target/shibrpc-clnt.c
shib-target/shibrpc-server-stubs.c
shib-target/shibrpc-server.cpp
shib-target/shibrpc-svc.c
shib-target/shibrpc-xdr.c
shib-target/shibrpc.h
shib-target/shibrpc.x

index e6bd1b7..063941a 100644 (file)
@@ -1072,6 +1072,88 @@ void ShibTarget::sessionGet(
     }
 }
 
+void ShibTarget::sessionEnd(const char* cookie) const
+{
+#ifdef _DEBUG
+    saml::NDC ndc("sessionEnd");
+#endif
+    Category& log = Category::getInstance("shibtarget.ShibTarget");
+
+    if (!cookie || !*cookie) {
+        log.error("no session key provided");
+        throw InvalidSessionException("No session key was provided.");
+    }
+    else if (strchr(cookie,'=')) {
+        log.error("cookie value not extracted successfully, probably overlapping cookies across domains");
+        throw InvalidSessionException("The session key wasn't extracted successfully from the browser cookie.");
+    }
+
+    log.debug("ending session with cookie (%s)", cookie);
+
+    shibrpc_end_session_args_2 arg;
+    arg.cookie = (char*)cookie;
+
+    shibrpc_end_session_ret_2 ret;
+    memset (&ret, 0, sizeof(ret));
+
+    // Loop on the RPC in case we lost contact the first time through
+    int retry = 1;
+    CLIENT *clnt;
+    RPC rpc;
+    do {
+        clnt = rpc->connect();
+        clnt_stat status = shibrpc_end_session_2(&arg, &ret, clnt);
+        if (status != RPC_SUCCESS) {
+            // FAILED.  Release, disconnect, and try again...
+            log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_end_session_2"));
+            rpc->disconnect();
+            if (retry)
+                retry--;
+            else
+                throw ListenerException("Failure ending session through listener.");
+        }
+        else {
+            // SUCCESS
+            retry = -1;
+        }
+    } while (retry>=0);
+
+    if (ret.status && *ret.status)
+        log.debug("RPC completed with exception: %s", ret.status);
+    else
+        log.debug("RPC completed successfully");
+
+    SAMLException* except=NULL;
+    if (ret.status && *ret.status) {
+        // Reconstitute exception object.
+        try { 
+            istringstream estr(ret.status);
+            except=SAMLException::getInstance(estr);
+        }
+        catch (SAMLException& e) {
+            log.error("caught SAML Exception while building the SAMLException: %s", e.what());
+            log.error("XML was: %s", ret.status);
+            clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_end_session_ret_2, (caddr_t)&ret);
+            rpc.pool();
+            throw FatalProfileException("An unrecoverable error occurred while accessing your session.");
+        }
+        catch (...) {
+            log.error("caught unknown exception building SAMLException");
+            log.error("XML was: %s", ret.status);
+            clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_end_session_ret_2, (caddr_t)&ret);
+            rpc.pool();
+            throw;
+        }
+    }
+
+    clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_end_session_ret_2, (caddr_t)&ret);
+    rpc.pool();
+    if (except) {
+        auto_ptr<SAMLException> wrapper(except);
+        wrapper->raise();
+    }
+}
+
 void* ShibTarget::sendError(const char* page, ShibMLP &mlp)
 {
     const IPropertySet* props=m_priv->m_app->getPropertySet("Errors");
@@ -1536,12 +1618,49 @@ pair<bool,void*> ShibTargetPriv::doAssertionConsumer(ShibTarget* st, const IProp
     }
 
     // Now redirect to the target.
-    return pair<bool,void*>(true, st->sendRedirect(target));
+    return make_pair(true, st->sendRedirect(target));
 }
 
 pair<bool,void*> ShibTargetPriv::doLogout(ShibTarget* st, const IPropertySet* handler) const
 {
-    throw UnsupportedProfileException("Logout not yet supported.");
+    pair<bool,const XMLCh*> binding=handler->getXMLString("Binding");
+    if (!binding.first || XMLString::compareString(binding.second,Constants::SHIB_LOGOUT_PROFILE_URI)) {
+        if (!binding.first)
+            throw UnsupportedProfileException("Missing Logout binding.");
+        throw UnsupportedProfileException("Unsupported Logout binding ($1).", params(1,handler->getString("Binding").second));
+    }
+
+    // Recover the session key.
+    pair<string,const char*> shib_cookie = getCookieNameProps("_shibsession_");
+    const char* session_id = getCookie(st,shib_cookie.first);
+    
+    // Logout is best effort.
+    if (session_id && *session_id) {
+        try {
+            st->sessionEnd(session_id);
+        }
+        catch (SAMLException& e) {
+            st->log(ShibTarget::LogLevelError, string("logout processing failed with exception: ") + e.what());
+        }
+#ifndef _DEBUG
+        catch (...) {
+            st->log(ShibTarget::LogLevelError, "logout processing failed with unknown exception");
+        }
+#endif
+        st->setCookie(shib_cookie.first,"");
+    }
+    
+    string query=st->getArgs();
+    CgiParse parser(query.c_str(),query.length());
+
+    const char* ret=parser.get_value("return");
+    if (!ret)
+        ret=handler->getString("ResponseLocation").second;
+    else if (!ret)
+        ret=m_app->getString("homeURL").second;
+    else if (!ret)
+        ret="/";
+    return make_pair(true, st->sendRedirect(ret));
 }
 
 /*************************************************************************
index 4ff9e06..bd8b7a2 100644 (file)
@@ -487,6 +487,8 @@ namespace shibtarget {
         saml::SAMLResponse** attr_response_post=NULL
         ) const;
 
+    void sessionEnd(const char* cookie) const;
+
   protected:
     ShibTarget();
 
index 9b747de..466e07c 100644 (file)
@@ -35,3 +35,12 @@ shibrpc_get_session_2(shibrpc_get_session_args_2 *argp, shibrpc_get_session_ret_
                (xdrproc_t) xdr_shibrpc_get_session_ret_2, (caddr_t) clnt_res,
                TIMEOUT));
 }
+
+enum clnt_stat 
+shibrpc_end_session_2(shibrpc_end_session_args_2 *argp, shibrpc_end_session_ret_2 *clnt_res, CLIENT *clnt)
+{
+       return (clnt_call(clnt, shibrpc_end_session,
+               (xdrproc_t) xdr_shibrpc_end_session_args_2, (caddr_t) argp,
+               (xdrproc_t) xdr_shibrpc_end_session_ret_2, (caddr_t) clnt_res,
+               TIMEOUT));
+}
index b99cea2..b3c1659 100644 (file)
@@ -42,6 +42,18 @@ shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *argp, shibrpc_get_session_
        return retval;
 }
 
+bool_t
+shibrpc_end_session_2_svc(shibrpc_end_session_args_2 *argp, shibrpc_end_session_ret_2 *result, struct svc_req *rqstp)
+{
+       bool_t retval;
+
+       /*
+        * insert server code here
+        */
+
+       return retval;
+}
+
 int
 shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
 {
index d9534c3..7687544 100644 (file)
@@ -515,6 +515,39 @@ shibrpc_new_session_2_svc(
     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("end_session");
+    saml::NDC ndc(ctx);
+
+    if (!argp || !result) {
+        log.error("RPC Argument Error");
+        return FALSE;
+    }
+
+    memset (result, 0, sizeof (*result));
+
+    log.debug ("checking: %s", argp->cookie);
+
+    IConfig* conf=ShibTargetConfig::getConfig().getINI();
+    Locker locker(conf);
+    conf->getSessionCache()->remove(argp->cookie);
+  
+    // Transaction Logging
+    STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
+    stc.getTransactionLog().infoStream() << "Destroyed session (ID: " << argp->cookie << ")";
+    stc.releaseTransactionLog();
+
+    result->status=strdup("");
+    return TRUE;
+}
+
 extern "C" int
 shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
 {
index b136444..69949f7 100644 (file)
@@ -27,11 +27,13 @@ shibrpc_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)
                int shibrpc_ping_2_arg;
                shibrpc_new_session_args_2 shibrpc_new_session_2_arg;
                shibrpc_get_session_args_2 shibrpc_get_session_2_arg;
+               shibrpc_end_session_args_2 shibrpc_end_session_2_arg;
        } argument;
        union {
                int shibrpc_ping_2_res;
                shibrpc_new_session_ret_2 shibrpc_new_session_2_res;
                shibrpc_get_session_ret_2 shibrpc_get_session_2_res;
+               shibrpc_end_session_ret_2 shibrpc_end_session_2_res;
        } result;
        bool_t retval;
        xdrproc_t _xdr_argument, _xdr_result;
@@ -56,6 +58,12 @@ shibrpc_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)
                local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_get_session_2_svc;
                break;
 
+       case shibrpc_end_session:
+               _xdr_argument = (xdrproc_t) xdr_shibrpc_end_session_args_2;
+               _xdr_result = (xdrproc_t) xdr_shibrpc_end_session_ret_2;
+               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_end_session_2_svc;
+               break;
+
        default:
                svcerr_noproc (transp);
                return;
index 7f73512..385bd00 100644 (file)
@@ -88,3 +88,23 @@ xdr_shibrpc_get_session_ret_2 (XDR *xdrs, shibrpc_get_session_ret_2 *objp)
                 return FALSE;
        return TRUE;
 }
+
+bool_t
+xdr_shibrpc_end_session_args_2 (XDR *xdrs, shibrpc_end_session_args_2 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->cookie, ~0))
+                return FALSE;
+       return TRUE;
+}
+
+bool_t
+xdr_shibrpc_end_session_ret_2 (XDR *xdrs, shibrpc_end_session_ret_2 *objp)
+{
+       register int32_t *buf;
+
+        if (!xdr_string (xdrs, &objp->status, ~0))
+                return FALSE;
+       return TRUE;
+}
index 8f6f360..c6eb542 100644 (file)
@@ -9,7 +9,7 @@
 #include <rpc/rpc.h>
 
 #ifdef HAVE_PTHREAD
-#include <pthread.h>
+# include <pthread.h>
 #endif
 
 #ifdef __cplusplus
@@ -61,6 +61,16 @@ struct shibrpc_get_session_ret_2 {
 };
 typedef struct shibrpc_get_session_ret_2 shibrpc_get_session_ret_2;
 
+struct shibrpc_end_session_args_2 {
+       char *cookie;
+};
+typedef struct shibrpc_end_session_args_2 shibrpc_end_session_args_2;
+
+struct shibrpc_end_session_ret_2 {
+       char *status;
+};
+typedef struct shibrpc_end_session_ret_2 shibrpc_end_session_ret_2;
+
 #define SHIBRPC_PROG 123456
 #define SHIBRPC_VERS_2 2
 
@@ -74,6 +84,9 @@ extern  bool_t shibrpc_new_session_2_svc(shibrpc_new_session_args_2 *, shibrpc_n
 #define shibrpc_get_session 2
 extern  enum clnt_stat shibrpc_get_session_2(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, CLIENT *);
 extern  bool_t shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, struct svc_req *);
+#define shibrpc_end_session 3
+extern  enum clnt_stat shibrpc_end_session_2(shibrpc_end_session_args_2 *, shibrpc_end_session_ret_2 *, CLIENT *);
+extern  bool_t shibrpc_end_session_2_svc(shibrpc_end_session_args_2 *, shibrpc_end_session_ret_2 *, struct svc_req *);
 extern int shibrpc_prog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
 
 #else /* K&R C */
@@ -86,6 +99,9 @@ extern  bool_t shibrpc_new_session_2_svc();
 #define shibrpc_get_session 2
 extern  enum clnt_stat shibrpc_get_session_2();
 extern  bool_t shibrpc_get_session_2_svc();
+#define shibrpc_end_session 3
+extern  enum clnt_stat shibrpc_end_session_2();
+extern  bool_t shibrpc_end_session_2_svc();
 extern int shibrpc_prog_2_freeresult ();
 #endif /* K&R C */
 
@@ -97,6 +113,8 @@ extern  bool_t xdr_shibrpc_new_session_args_2 (XDR *, shibrpc_new_session_args_2
 extern  bool_t xdr_shibrpc_new_session_ret_2 (XDR *, shibrpc_new_session_ret_2*);
 extern  bool_t xdr_shibrpc_get_session_args_2 (XDR *, shibrpc_get_session_args_2*);
 extern  bool_t xdr_shibrpc_get_session_ret_2 (XDR *, shibrpc_get_session_ret_2*);
+extern  bool_t xdr_shibrpc_end_session_args_2 (XDR *, shibrpc_end_session_args_2*);
+extern  bool_t xdr_shibrpc_end_session_ret_2 (XDR *, shibrpc_end_session_ret_2*);
 
 #else /* K&R C */
 extern bool_t xdr_ShibProfile ();
@@ -104,6 +122,8 @@ extern bool_t xdr_shibrpc_new_session_args_2 ();
 extern bool_t xdr_shibrpc_new_session_ret_2 ();
 extern bool_t xdr_shibrpc_get_session_args_2 ();
 extern bool_t xdr_shibrpc_get_session_ret_2 ();
+extern bool_t xdr_shibrpc_end_session_args_2 ();
+extern bool_t xdr_shibrpc_end_session_ret_2 ();
 
 #endif /* K&R C */
 
index edd3047..64ff201 100644 (file)
@@ -28,23 +28,23 @@ enum ShibProfile {
 /* function argument and response structures */
 
 struct shibrpc_new_session_args_2 {
-  int          supported_profiles;             /* bitmask of supported profiles */
+  int          supported_profiles;                     /* bitmask of supported profiles */
   string       application_id<>;
-  string       packet<>;                               /* profile input packet from client */
-  string       recipient<>;                    /* endpoint that received packet */
+  string       packet<>;                                       /* profile input packet from client */
+  string       recipient<>;                            /* endpoint that received packet */
   string       client_addr<>;
 };
 
 struct shibrpc_new_session_ret_2 {
-  string       status<>;                               /* empty string or a SAMLException */
-  string       target<>;                               /* profile-specific state token from client */
-  string       cookie<>;                               /* session key manufactured for client */
-  string       provider_id<>;                  /* authenticating IdP */
+  string       status<>;                                       /* empty string or a SAMLException */
+  string       target<>;                                       /* profile-specific state token from client */
+  string       cookie<>;                                       /* session key manufactured for client */
+  string       provider_id<>;                          /* authenticating IdP */
 };
 
 struct shibrpc_get_session_args_2 {
   string               application_id<>;
-  string               cookie<>;                       /* session key provided by client */
+  string               cookie<>;                               /* session key provided by client */
   string               client_addr<>;
 };
 
@@ -57,6 +57,14 @@ struct shibrpc_get_session_ret_2 {
   string               attr_response_post<>;   /* SAML attr assertions post-filtering */
 };
 
+struct shibrpc_end_session_args_2 {
+  string               cookie<>;                               /* session key provided by client */
+};
+
+struct shibrpc_end_session_ret_2 {
+  string               status<>;                               /* empty string or a SAMLException */
+};
+
 
 /* Define the Shib Target RPC interface */
 program SHIBRPC_PROG {
@@ -72,6 +80,9 @@ program SHIBRPC_PROG {
 
     /* Validate and access data associated with existing session */
     shibrpc_get_session_ret_2 shibrpc_get_session (shibrpc_get_session_args_2) = 2;
+    
+    /* End a session */
+    shibrpc_end_session_ret_2 shibrpc_end_session (shibrpc_end_session_args_2) = 3;
 
   } = 2;
 } = 123456;                    /* Arbitrary RPC Program Number */