}
}
+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");
}
// 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));
}
/*************************************************************************
saml::SAMLResponse** attr_response_post=NULL
) const;
+ void sessionEnd(const char* cookie) const;
+
protected:
ShibTarget();
(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));
+}
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)
{
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)
{
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;
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;
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;
+}
#include <rpc/rpc.h>
#ifdef HAVE_PTHREAD
-#include <pthread.h>
+# include <pthread.h>
#endif
#ifdef __cplusplus
};
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
#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 */
#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 */
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 ();
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 */
/* 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<>;
};
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 {
/* 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 */