HTGroupTableApache(request_rec* r, const char *user, char *grpfile) {
groups = groups_for_user(r, user, grpfile);
if (!groups)
- throw ShibTargetException(SHIBRPC_OK, "EEP");
+ throw ResourceAccessException("Unable to access group file ($1) for user ($2)",params(2,grpfile,user));
}
~HTGroupTableApache() {}
bool lookup(const char *entry) { return (ap_table_get(groups, entry)!=NULL); }
virtual string getPostData(void) {
// Read the posted data
if (ap_setup_client_block(m_req, REQUEST_CHUNKED_ERROR))
- throw ShibTargetException(SHIBRPC_OK, "CGI setup_client_block failed");
+ throw FatalProfileException("Apache function (setup_client_block) failed while reading profile submission.");
if (!ap_should_client_block(m_req))
- throw ShibTargetException(SHIBRPC_OK, "CGI should_client_block failed");
+ throw FatalProfileException("Apache function (should_client_block) failed while reading profile submission.");
if (m_req->remaining > 1024*1024)
- throw ShibTargetException (SHIBRPC_OK, "CGI length too long...");
-
+ throw FatalProfileException("Blocked too-large a submission to profile endpoint.");
string cgistr;
char buff[HUGE_STRING_LEN];
ap_hard_timeout("[mod_shib] getPostData", m_req);
}
virtual string getPostData(void) {
if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
- throw ShibTargetException(SHIBRPC_OK,
- "blocked too-large a post to SHIRE POST processor");
+ throw FatalProfileException("Blocked too-large a submission to profile endpoint.");
else if (m_lpECB->cbTotalBytes != m_lpECB->cbAvailable) {
string cgistr;
char buf[8192];
DWORD buflen=8192;
BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
if (!ret || !buflen)
- throw ShibTargetException(SHIBRPC_OK,
- "error reading POST data from browser");
+ throw FatalProfileException("Error reading profile submission from browser.");
cgistr.append(buf, buflen);
datalen-=buflen;
}
throw MetadataException("ArtifactMapper::map() metadata lookup failed, unable to determine artifact issuer");
}
- if (log.isInfoEnabled()) {
- auto_ptr_char issuer(entity->getId());
- log.info("lookup succeeded, artifact issued by (%s)", issuer.get());
- }
-
SAMLBrowserProfile::ArtifactMapper::ArtifactMapperResponse amr;
-
+ auto_ptr_char issuer(entity->getId());
+ log.info("lookup succeeded, artifact issued by (%s)", issuer.get());
+ amr.source=issuer.get();
+
const IPropertySet* credUse=m_app->getCredentialUse(entity);
// Depends on type of artifact.
}
log.error("unable to locate acceptable binding endpoint to resolve artifact");
- throw MetadataException("ArtifactMapper::map() unable to locate acceptable binding endpoint to resolve artifact");
+ MetadataException ex("Unable to locate acceptable binding endpoint to resolve artifact.");
+ annotateException(ex,entity,false);
+ throw ex;
}
endif
libshib_targetdir = $(includedir)/shib-target
-libshib_target_HEADERS = shib-target.h shibrpc.h shib-paths.h
+libshib_target_HEADERS = shib-target.h shibrpc.h shib-paths.h hresult.h
noinst_HEADERS = internal.h
libshib_target_la_SOURCES = \
--- /dev/null
+/*
+ * 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.
+ */
+
+/*
+ * hresult.h - Code definitions
+= */
+
+#ifndef __shibtargethresult_h__
+#define __shibtargethresult_h__
+
+#include <shib/hresult.h>
+
+/* Codes from 0xA000 - 0xAFFF in FACILITY_ITF are reserved for the Shibboleth SP */
+
+#define SHIBSP_E_FIRST MAKE_HRESULT(SEVERITY_ERROR,FACILITY_ITF,SHIB_E_LAST + 0x0001)
+#define SHIBSP_E_LAST MAKE_HRESULT(SEVERITY_ERROR,FACILITY_ITF,SHIB_E_LAST + 0x1000)
+
+#define SHIBSP_S_FIRST MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_ITF,SHIB_S_LAST + 0x0001)
+#define SHIBSP_S_LAST MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_ITF,SHIB_S_LAST + 0x1000
+
+/* Specific code definitions */
+
+#define SHIBSP_E_UNSPECIFIED (SHIBSP_E_FIRST + 0L)
+
+#define SESSION_E_ADDRESSMISMATCH (SHIBSP_E_FIRST + 1L)
+#define SESSION_E_EXPIRED (SHIBSP_E_FIRST + 2L)
+
+#endif
#endif
#include "shib-target.h"
+#include "hresult.h"
#include <log4cpp/Category.hh>
#include <log4cpp/FixedContextCategory.hh>
RPC();
~RPC() {delete m_handle;}
RPCHandle* operator->() {return m_handle;}
- void pool() {m_pool.put(m_handle); m_handle=NULL;}
+ void pool() {if (m_handle) m_pool.put(m_handle); m_handle=NULL;}
private:
RPCHandlePool& m_pool;
catch (...) {
if (m_cache->m_propagateErrors)
throw;
- log->warn("suppressed exception caught while trying to fetch attributes");
+ log->warn("suppressed unknown exception caught while trying to fetch attributes");
}
}
const IApplication* application=conf->getApplication(m_application_id.c_str());
if (!application) {
log->crit("unable to locate application for session, deleted?");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate application for session, deleted?");
+ throw SAMLException("Unable to locate application for session, deleted?");
}
pair<bool,const XMLCh*> providerID=application->getXMLString("providerId");
if (!providerID.first) {
log->crit("unable to determine ProviderID for application, not set?");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to determine ProviderID for application, not set?");
+ throw SAMLException("Unable to determine ProviderID for application, not set?");
}
// Try this request.
const IEntityDescriptor* site=m.lookup(m_provider_id.c_str());
if (!site) {
log->error("unable to locate identity provider's metadata during attribute query");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate identity provider's metadata during attribute query.");
+ throw MetadataException("Unable to locate identity provider's metadata during attribute query.");
}
// Try to locate an AA role.
const IAttributeAuthorityDescriptor* AA=site->getAttributeAuthorityDescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
if (!AA) {
log->error("unable to locate metadata for identity provider's Attribute Authority");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate metadata for identity provider's Attribute Authority.",site);
+ MetadataException ex("Unable to locate metadata for identity provider's Attribute Authority.");
+ annotateException(ex,site);
}
// Get protocol signing policy.
}
catch (SAMLException& e) {
log->error("caught SAML exception during query to AA: %s", e.what());
- if (typeid(e)==typeid(InvalidHandleException))
- throw;
- ostringstream os;
- os << e;
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), AA);
+ annotateException(e,AA);
}
log->error("no response obtained");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's identity provider.",AA);
+ SAMLException ex("Unable to obtain attributes from user's identity provider.");
+ annotateException(ex,AA,false);
+ throw ex;
}
SAMLResponse* InternalCCacheEntry::filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source)
PlugManager::Factory XMLRequestMapFactory;
//PlugManager::Factory htaccessFactory;
+SAML_EXCEPTION_FACTORY(ListenerException);
+
ShibTargetConfig& ShibTargetConfig::getConfig()
{
return g_Config;
try {
// Register plugin types.
+ REGISTER_EXCEPTION_FACTORY(ListenerException);
#ifndef WIN32
samlConf.getPlugMgr().regFactory(shibtarget::XML::UnixListenerType,&UnixListenerFactory);
#endif
return run(str,props,output);
}
-void ShibMLP::insert (RPCError& e)
+void ShibMLP::insert(SAMLException& e)
{
- insert ("errorType", e.getType() ? e.getType() : "Unknown Type");
- insert ("errorText", e.getText() ? e.getText() : "No Message");
- insert ("errorDesc", e.getDesc() ? e.getDesc() : "No Description");
- insert ("originErrorURL", e.getErrorURL() ? e.getErrorURL() : "No Error URL");
- insert ("originContactName", e.getContactName() ? e.getContactName() : "No Contact Name");
- insert ("originContactEmail", e.getContactEmail() ? e.getContactEmail() : "No Contact Email");
+ insert("errorType", e.classname());
+ if (typeid(e)==typeid(ContentTypeException))
+ insert("errorText", "A problem was detected with your identity provider's software configuration.");
+ else
+ insert("errorText", e.getMessage() ? e.getMessage() : "No Message");
+ insert("originErrorURL", e.getProperty("errorURL") ? e.getProperty("errorURL") : "No Error URL");
+ insert("originContactName", e.getProperty("contactName") ? e.getProperty("contactName") : "No Contact Name");
+ insert("originContactEmail", e.getProperty("contactEmail") ? e.getProperty("contactEmail") : "No Contact Email");
}
void ShibMLP::insert (const std::string& key, const std::string& value)
+++ /dev/null
-/*
- * 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.
- */
-
-/*
- * shib-rpcerror.cpp -- RPC Error class
- *
- * Created by: Derek Atkins <derek@ihtfp.com>
- *
- * $Id$
- */
-
-#include "internal.h"
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include <stdexcept>
-#include <sstream>
-#include <typeinfo>
-#include <log4cpp/Category.hh>
-
-using namespace std;
-using namespace log4cpp;
-using namespace saml;
-using namespace shibboleth;
-using namespace shibtarget;
-
-ShibTargetException::ShibTargetException(ShibRpcStatus code, const char* msg, const IEntityDescriptor* provider) : m_code(code)
-{
- if (msg) m_msg=msg;
- if (provider) {
- auto_ptr_char id(provider->getId());
- m_providerId=id.get();
- Iterator<const IRoleDescriptor*> roles=provider->getRoleDescriptors();
- while (roles.hasNext()) {
- const IRoleDescriptor* role=roles.next();
- if (role->isValid()) {
- const char* temp=role->getErrorURL();
- if (temp) {
- m_errorURL=temp;
- break;
- }
- }
- }
-
- Iterator<const IContactPerson*> i=provider->getContactPersons();
- while (i.hasNext()) {
- const IContactPerson* c=i.next();
- if ((c->getType()==IContactPerson::technical || c->getType()==IContactPerson::support)) {
- const char* fname=c->getGivenName();
- const char* lname=c->getSurName();
- if (fname && lname)
- m_contact=string(fname) + ' ' + lname;
- else if (fname)
- m_contact=fname;
- else if (lname)
- m_contact=lname;
- Iterator<string> emails=c->getEmailAddresses();
- if (emails.hasNext())
- m_email=emails.next();
- return;
- }
- }
- }
-}
-
-ShibTargetException::ShibTargetException(ShibRpcStatus code, const char* msg, const IRoleDescriptor* role) : m_code(code)
-{
- if (msg) m_msg=msg;
- if (role) {
- auto_ptr_char id(role->getEntityDescriptor()->getId());
- m_providerId=id.get();
-
- const char* temp=role->getErrorURL();
- if (temp)
- m_errorURL=temp;
-
- Iterator<const IContactPerson*> i=role->getContactPersons();
- while (i.hasNext()) {
- const IContactPerson* c=i.next();
- if ((c->getType()==IContactPerson::technical || c->getType()==IContactPerson::support)) {
- const char* fname=c->getGivenName();
- const char* lname=c->getSurName();
- if (fname && lname)
- m_contact=string(fname) + ' ' + lname;
- else if (fname)
- m_contact=fname;
- else if (lname)
- m_contact=lname;
- Iterator<string> emails=c->getEmailAddresses();
- if (emails.hasNext())
- m_email=emails.next();
- return;
- }
- }
- }
-}
-
-class shibtarget::RPCErrorPriv {
-public:
- RPCErrorPriv(
- int stat=0,
- const char* msg=NULL,
- const char* provider=NULL,
- const char* url=NULL,
- const char* contact=NULL,
- const char* email=NULL
- );
- ~RPCErrorPriv();
-
- int status;
- string error_msg,m_provider,m_url,m_contact,m_email;
- SAMLException* except;
-};
-
-RPCErrorPriv::RPCErrorPriv(
- int stat, const char* msg, const char* provider, const char* url, const char* contact, const char* email
- ) : status(stat), except(NULL)
-{
- log4cpp::Category& log = log4cpp::Category::getInstance("shibtarget.RPCErrorPriv");
-
- if (provider)
- m_provider=provider;
- if (url)
- m_url=url;
- if (contact)
- m_contact=contact;
- if (email)
- m_email=email;
-
- if (status == SHIBRPC_SAML_EXCEPTION) {
- istringstream estr(msg);
- try {
- except = NULL;
- except = SAMLException::getInstance(estr);
- }
- catch (SAMLException& e) {
- log.error("Caught SAML Exception while building the SAMLException: %s", e.what());
- log.error("XML: %s", msg);
- }
- catch (XMLException& e) {
- log.error("Caught XML Exception building SAMLException: %s", e.getMessage());
- log.error("XML: %s", msg);
- }
- catch (...) {
- log.error("Caught exception building SAMLException!");
- log.error("XML: %s", msg);
- }
- if (dynamic_cast<ContentTypeException*>(except))
- error_msg =
- "We were unable to contact your identity provider and cannot grant "
- "access at this time. Please contact your provider's help desk or "
- "administrator so that the appropriate steps can be taken. "
- "Be sure to describe what you're trying to access and useful "
- "context like the current time.";
- else if (except)
- error_msg = except->what();
- else if (msg)
- error_msg = msg;
- }
- else if (msg)
- error_msg = msg;
-}
-
-RPCErrorPriv::~RPCErrorPriv()
-{
- if (except)
- delete except;
-}
-
-RPCError::RPCError() : m_priv(new RPCErrorPriv()) {}
-
-RPCError::RPCError(ShibRpcError* e)
-{
- if (!e || !e->status)
- m_priv=new RPCErrorPriv();
- m_priv=new RPCErrorPriv(
- e->status,
- e->ShibRpcError_u.e.error,
- e->ShibRpcError_u.e.provider,
- e->ShibRpcError_u.e.url,
- e->ShibRpcError_u.e.contact,
- e->ShibRpcError_u.e.email
- );
-}
-
-RPCError::RPCError(int s, const char* st) : m_priv(new RPCErrorPriv(s,st)) {}
-
-RPCError::RPCError(ShibTargetException& exc)
- : m_priv(new RPCErrorPriv(exc.which(),exc.what(),exc.syswho(),exc.where(),exc.who(),exc.how())) {}
-
-RPCError::~RPCError()
-{
- delete m_priv;
-}
-
-bool RPCError::isError() { return (m_priv->status != 0); }
-
-bool RPCError::isRetryable()
-{
- switch (m_priv->status) {
- case SHIBRPC_NO_SESSION:
- case SHIBRPC_SESSION_EXPIRED:
- return true;
-
- case SHIBRPC_SAML_EXCEPTION:
- if (m_priv->except && dynamic_cast<RetryableProfileException*>(m_priv->except))
- return true;
-
- // FALLTHROUGH
- default:
- return false;
- }
-}
-
-const char* RPCError::getType()
-{
- switch (m_priv->status) {
- case SHIBRPC_OK: return "No Error";
- case SHIBRPC_UNKNOWN_ERROR: return "Unknown error";
- case SHIBRPC_INTERNAL_ERROR: return "Internal Error";
- case SHIBRPC_XML_EXCEPTION: return "Xerces XML Exception";
- case SHIBRPC_SAX_EXCEPTION: return "Xerces SAX Exception";
- case SHIBRPC_SAML_EXCEPTION: return m_priv->except->classname();
-
- case SHIBRPC_NO_SESSION: return "No Session";
- case SHIBRPC_SESSION_EXPIRED: return "Session Expired";
- case SHIBRPC_IPADDR_MISMATCH: return "IP Address Mismatch";
-
- case SHIBRPC_IPADDR_MISSING: return "IP Address Missing";
- case SHIBRPC_RESPONSE_MISSING: return "SAML Response Missing";
- case SHIBRPC_ASSERTION_REPLAYED: return "SAML Assertion Replayed";
- default: return "Unknown Shibboleth RPC error";
- }
-}
-
-const char* RPCError::getText()
-{
- return m_priv->error_msg.c_str();
-}
-
-const char* RPCError::getDesc()
-{
- if (m_priv->except) {
- Iterator<saml::QName> i=m_priv->except->getCodes();
- if (i.hasNext() && XMLString::compareString(L(Responder),i.next().getLocalName()))
- return "An error occurred within the target system while processing your request";
- else
- return "An error occurred at your identity provider while processing your request";
- }
- else
- return "An error occurred while processing your request";
-}
-
-int RPCError::getCode() { return m_priv->status; }
-
-const char* RPCError::getProviderId() { return m_priv->m_provider.c_str(); }
-
-const char* RPCError::getErrorURL() { return m_priv->m_url.c_str(); }
-
-const char* RPCError::getContactName() { return m_priv->m_contact.c_str(); }
-
-const char* RPCError::getContactEmail() { return m_priv->m_email.c_str(); }
CLIENT* RPCHandle::connect()
{
+#ifdef _DEBUG
saml::NDC ndc("connect");
-
+#endif
if (m_clnt) {
- log->debug ("returning existing connection: %p -> %p", this, m_clnt);
+ log->debug("returning existing connection: %p -> %p", this, m_clnt);
return m_clnt;
}
- log->debug("trying to connect to SHAR");
+ log->debug("trying to connect to listener");
IListener::ShibSocket sock;
IConfig* conf=ShibTargetConfig::getConfig().getINI();
const IListener* listener=conf->getListener();
if (!listener->create(sock)) {
log->error("cannot create socket");
- throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR, "Cannot create socket");
+ throw ListenerException("Cannot create socket");
}
bool connected = false;
break;
}
- log->warn ("cannot connect %p to SHAR... %s", this, (i > 0 ? "retrying" : ""));
+ log->warn("cannot connect %p to listener...%s", this, (i > 0 ? "retrying" : ""));
- if (i)
+ if (i) {
#ifdef WIN32
Sleep(2000*(num_tries-i));
#else
sleep(2*(num_tries-i));
#endif
+ }
}
if (!connected) {
- log->crit("SHAR Unavailable.. Failing.");
+ log->crit("listener unavailable, failing");
listener->close(sock);
- throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR, "Cannot connect to SHAR process, target site adminstrator should be notified");
+ throw ListenerException("Cannot connect to listener process, a site adminstrator should be notified.");
}
CLIENT *clnt = listener->getClientHandle(sock, SHIBRPC_PROG, SHIBRPC_VERS_2);
const char* rpcerror = clnt_spcreateerror("RPCHandle::connect");
log->crit("RPC failed for %p: %s", this, rpcerror);
listener->close(sock);
- throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR, rpcerror);
+ throw ListenerException(rpcerror);
}
// Set the RPC timeout to a fairly high value...
if (m_priv) delete m_priv;
}
-void ShibTarget::init(ShibTargetConfig *config,
- string protocol, string hostname, int port,
- string uri, string content_type, string remote_host,
- string method)
+void ShibTarget::init(
+ ShibTargetConfig *config,
+ string protocol,
+ string hostname,
+ int port,
+ string uri,
+ string content_type,
+ string remote_host,
+ string method
+ )
{
#ifdef _DEBUG
saml::NDC ndc("ShibTarget::init");
ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handleProfile)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doCheckAuthN");
+ saml::NDC ndc("ShibTarget::doCheckAuthN");
#endif
- const char *targetURL = NULL;
- const char *procState = "Process Initialization Error";
- ShibMLP mlp;
+ const char *targetURL = NULL;
+ const char *procState = "Request Setup Error";
+ ShibMLP mlp;
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
-
- targetURL = m_priv->m_url.c_str();
- const char *shireURL = getShireURL(targetURL);
- if (! shireURL)
- throw ShibTargetException(SHIBRPC_OK, "Cannot map target URL to Shire URL. Check configuration");
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
+
+ targetURL = m_priv->m_url.c_str();
+ const char *shireURL = getShireURL(targetURL);
+ if (!shireURL)
+ throw SAMLException("Cannot determine assertion consumer service from resource URL, check configuration.");
+
+ if (strstr(targetURL,shireURL)) {
+ if (handleProfile)
+ return doHandleProfile();
+ else
+ return pair<bool,void*>(true, returnOK());
+ }
- if (strstr(targetURL,shireURL)) {
- if (handleProfile)
- return doHandleProfile();
- else
- return pair<bool,void*>(true, returnOK());
- }
+ string auth_type = getAuthType();
+ if (strcasecmp(auth_type.c_str(),"shibboleth"))
+ return pair<bool,void*>(true,returnDecline());
- string auth_type = getAuthType();
- if (strcasecmp(auth_type.c_str(),"shibboleth"))
- return pair<bool,void*>(true,returnDecline());
+ pair<bool,bool> requireSession = m_priv->m_settings.first->getBool("requireSession");
+ if (!requireSession.first || !requireSession.second) {
+ // Web server might override.
+ if (requireSessionFlag)
+ requireSession.second=true;
+ }
- pair<bool,bool> requireSession =
- m_priv->m_settings.first->getBool("requireSession");
- if (!requireSession.first || !requireSession.second)
- if (requireSessionFlag)
- requireSession.second=true;
+ const char* session_id = m_priv->getSessionId(this);
+ if (!session_id || !*session_id) {
+ // No session. Maybe that's acceptable?
+ if (!requireSession.second)
+ return pair<bool,void*>(true,returnOK());
- const char* session_id = m_priv->getSessionId(this);
- if (!session_id || !*session_id) {
- // No session. Maybe that's acceptable?
+ // No cookie, but we require a session. Generate an AuthnRequest.
+ return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ }
- if (!requireSession.second)
- return pair<bool,void*>(true,returnOK());
+ procState = "Session Processing Error";
+ try {
+ // Localized exception throw if the session isn't valid.
+ sessionGet(
+ session_id,
+ m_priv->m_remote_addr.c_str(),
+ m_priv->m_sso_profile,
+ m_priv->m_provider_id,
+ &m_priv->m_sso_statement,
+ &m_priv->m_pre_response,
+ &m_priv->m_post_response
+ );
+ }
+ catch (SAMLException& e) {
+ // If no session is required, bail now.
+ if (!requireSession.second)
+ // Has to be OK because DECLINED will just cause Apache
+ // to fail when it can't locate anything to process the
+ // AuthType. No session plus requireSession false means
+ // do not authenticate the user at this time.
+ return pair<bool,void*>(true, returnOK());
+
+ // TODO: need to test this...may need an actual reference cast
+ if (typeid(e)==typeid(RetryableProfileException)) {
+ // Session is invalid but we can retry -- generate an AuthnRequest
+ return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ }
+ throw; // send it to the outer handler
+ }
- // No cookie, but we require a session. Generate an AuthnRequest.
- return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ // We're done. Everything is okay. Nothing to report. Nothing to do..
+ // Let the caller decide how to proceed.
+ log(LogLevelInfo, "doCheckAuthN succeeded");
+ return pair<bool,void*>(false,NULL);
}
-
- procState = "Session Processing Error";
- auto_ptr<RPCError> status(
- sessionGet(
- session_id,
- m_priv->m_remote_addr.c_str(),
- m_priv->m_sso_profile,
- m_priv->m_provider_id,
- &m_priv->m_sso_statement,
- &m_priv->m_pre_response,
- &m_priv->m_post_response
- )
- );
-
- if (status->isError()) {
-
- // If no session is required, bail now.
- if (!requireSession.second)
- return pair<bool,void*>(true, returnOK());
- // XXX: Or should this be DECLINED?
- // Has to be OK because DECLINED will just cause Apache
- // to fail when it can't locate anything to process the
- // AuthType. No session plus requireSession false means
- // do not authenticate the user at this time.
- else if (status->isRetryable()) {
- // Session is invalid but we can retry the auth -- generate an AuthnRequest
- return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
-
- } else {
- string er = "Unretryable error: " ;
- er += status->getText();
- log(LogLevelError, er);
- mlp.insert(*status);
- goto out;
- }
+ catch (SAMLException& e) {
+ mlp.insert(e);
}
-
- // We're done. Everything is okay. Nothing to report. Nothing to do..
- // Let the caller decide how to proceed.
- log(LogLevelInfo, "doCheckAuthN Succeeded\n");
- return pair<bool,void*>(false,NULL);
-
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
-
- return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
}
pair<bool,void*>
ShibTarget::doHandleProfile(void)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doHandleProfile");
+ saml::NDC ndc("ShibTarget::doHandleProfile");
#endif
- const char *targetURL = NULL;
- const char *procState = "Session Creation Service Error";
- ShibMLP mlp;
-
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
+ const char *targetURL = NULL;
+ const char *procState = "Session Creation Service Error";
+ ShibMLP mlp;
- targetURL = m_priv->m_url.c_str();
- const char *shireURL = getShireURL(targetURL);
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
- if (!shireURL)
- throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to a proper shireURL setting. Check Configuration.");
+ targetURL = m_priv->m_url.c_str();
+ const char* shireURL = getShireURL(targetURL);
+ if (!shireURL)
+ throw SAMLException("Cannot determine assertion consumer service, check configuration.");
- // Make sure we only process the SHIRE requests.
- if (!strstr(targetURL, shireURL))
- return pair<bool,void*>(true, returnDecline());
+ // Make sure we only process the SHIRE requests.
+ if (!strstr(targetURL, shireURL))
+ return pair<bool,void*>(true, returnDecline());
- const IPropertySet* sessionProps=m_priv->m_app->getPropertySet("Sessions");
- if (!sessionProps)
- throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to application session settings. Check configuration");
+ const IPropertySet* sessionProps=m_priv->m_app->getPropertySet("Sessions");
+ if (!sessionProps)
+ throw SAMLException("Unable to map request to application session settings, check configuration.");
- // Process SHIRE request
+ // Process incoming request.
+ pair<bool,bool> shireSSL=sessionProps->getBool("shireSSL");
- pair<bool,bool> shireSSL=sessionProps->getBool("shireSSL");
-
- // Make sure this is SSL, if it should be
- if ((!shireSSL.first || shireSSL.second) && m_priv->m_protocol == "https")
- throw ShibTargetException(SHIBRPC_OK, "blocked non-SSL access to session creation service");
-
- // If this is a GET, we see if it's a lazy session request, otherwise
- // assume it's a profile response and process it.
- string cgistr;
- if (!strcasecmp(m_priv->m_method.c_str(), "GET")) {
- cgistr = getArgs();
- string areq;
- if (!cgistr.empty())
- areq=getLazyAuthnRequest(cgistr.c_str());
- if (!areq.empty())
- return pair<bool,void*>(true, sendRedirect(areq));
- }
- else if (!strcasecmp(m_priv->m_method.c_str(), "POST")) {
- if (m_priv->m_content_type.empty() || strcasecmp(m_priv->m_content_type.c_str(),"application/x-www-form-urlencoded")) {
- string er = string("blocked invalid POST content-type to session creation service: ") + m_priv->m_content_type;
- throw ShibTargetException(SHIBRPC_OK, er.c_str());
+ // Make sure this is SSL, if it should be
+ if ((!shireSSL.first || shireSSL.second) && m_priv->m_protocol != "https")
+ throw FatalProfileException("Blocked non-SSL access to session creation service.");
+
+ // If this is a GET, we see if it's a lazy session request, otherwise
+ // assume it's a profile response and process it.
+ string cgistr;
+ if (!strcasecmp(m_priv->m_method.c_str(), "GET")) {
+ cgistr = getArgs();
+ string areq;
+ if (!cgistr.empty())
+ areq=getLazyAuthnRequest(cgistr.c_str());
+ if (!areq.empty())
+ return pair<bool,void*>(true, sendRedirect(areq));
+ }
+ else if (!strcasecmp(m_priv->m_method.c_str(), "POST")) {
+ if (m_priv->m_content_type.empty() || strcasecmp(m_priv->m_content_type.c_str(),"application/x-www-form-urlencoded")) {
+ throw FatalProfileException(
+ "Blocked invalid POST content-type ($1) to session creation service.",
+ params(1,m_priv->m_content_type)
+ );
+ }
+ // Read the POST Data
+ cgistr = getPostData();
}
- // Read the POST Data
- cgistr = getPostData();
- }
- // process the submission
- string cookie,target;
- auto_ptr<RPCError> status(
- sessionNew(
- SAML_11_POST | SAML_11_ARTIFACT,
- cgistr.c_str(),
- m_priv->m_remote_addr.c_str(),
- cookie,
- target
- )
- );
-
- if (status->isError()) {
- char buf[25];
- sprintf(buf, "(%d): ", status->getCode());
- string er = string("doHandleProfile() profile processing failed ") + buf + status->getText();
- log(LogLevelError, er);
-
- if (status->isRetryable()) {
- return pair<bool,void*>(true, sendRedirect(getAuthnRequest(target.c_str())));
- }
-
- // return this error to the user.
- mlp.insert(*status);
- goto out;
- }
+ // Process the submission
+ string cookie,target;
+ try {
+ sessionNew(
+ SAML11_POST | SAML11_ARTIFACT,
+ cgistr.c_str(),
+ m_priv->m_remote_addr.c_str(),
+ cookie,
+ target
+ );
+ }
+ catch (SAMLException& e) {
+ log(LogLevelError, string("profile processing failed: ") + e.what());
+
+ // TODO: need to test this...may need an actual reference cast
+ if (typeid(e)==typeid(RetryableProfileException)) {
+ return pair<bool,void*>(true, sendRedirect(getAuthnRequest(target.c_str())));
+ }
+ throw; // send it to the outer handler
+ }
- log(LogLevelDebug, string("doHandleProfile() profile processing succeeded, new session(") + cookie + ")");
+ log(LogLevelDebug, string("profile processing succeeded, new session created (") + cookie + ")");
- if (target=="default") {
- pair<bool,const char*> homeURL=m_priv->m_app->getString("homeURL");
- target=homeURL.first ? homeURL.second : "/";
- }
- else if (target=="42") {
- // Pull the target value from the "relay state" cookie.
- const char* relay_state = m_priv->getRelayState(this);
- if (!relay_state || !*relay_state) {
- // No apparent relay state value to use, so fall back on the default.
+ if (target=="default") {
pair<bool,const char*> homeURL=m_priv->m_app->getString("homeURL");
target=homeURL.first ? homeURL.second : "/";
}
- else {
- CgiParse::url_decode((char*)relay_state);
- target=relay_state;
+ else if (target=="cookie") {
+ // Pull the target value from the "relay state" cookie.
+ const char* relay_state = m_priv->getRelayState(this);
+ if (!relay_state || !*relay_state) {
+ // No apparent relay state value to use, so fall back on the default.
+ pair<bool,const char*> homeURL=m_priv->m_app->getString("homeURL");
+ target=homeURL.first ? homeURL.second : "/";
+ }
+ else {
+ CgiParse::url_decode((char*)relay_state);
+ target=relay_state;
+ }
}
+
+ // We've got a good session, set the cookie...
+ pair<string,const char*> shib_cookie=getCookieNameProps("_shibsession_");
+ cookie += shib_cookie.second;
+ setCookie(shib_cookie.first, cookie);
+
+ // ... and redirect to the target
+ return pair<bool,void*>(true, sendRedirect(target));
+ }
+ catch (SAMLException& e) {
+ mlp.insert(e);
}
-
- // We've got a good session, set the cookie...
- pair<string,const char*> shib_cookie=getCookieNameProps("_shibsession_");
- cookie += shib_cookie.second;
- setCookie(shib_cookie.first, cookie);
-
- // ... and redirect to the target
- return pair<bool,void*>(true, sendRedirect(target));
-
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, "session", mlp));
}
pair<bool,void*>
ShibTarget::doCheckAuthZ(void)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doCheckAuthZ");
+ saml::NDC ndc("ShibTarget::doCheckAuthZ");
#endif
- ShibMLP mlp;
- const char *procState = "Authorization Processing Error";
- const char *targetURL = NULL;
- HTAccessInfo *ht = NULL;
- HTGroupTable* grpstatus = NULL;
-
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
-
- targetURL = m_priv->m_url.c_str();
- const char *session_id = m_priv->getSessionId(this);
-
- // Do we have an access control plugin?
- if (m_priv->m_settings.second) {
- Locker acllock(m_priv->m_settings.second);
- if (!m_priv->m_settings.second->authorized(*m_priv->m_sso_statement,
- m_priv->m_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*))) {
- log(LogLevelError, "doCheckAuthZ: access control provider denied access");
- goto out;
- }
- }
+ ShibMLP mlp;
+ const char *procState = "Authorization Processing Error";
+ const char *targetURL = NULL;
+ HTAccessInfo *ht = NULL;
+ HTGroupTable* grpstatus = NULL;
- // Perform HTAccess Checks
- ht = getAccessInfo();
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
+
+ targetURL = m_priv->m_url.c_str();
+ const char *session_id = m_priv->getSessionId(this);
+
+ // Do we have an access control plugin?
+ if (m_priv->m_settings.second) {
+ Locker acllock(m_priv->m_settings.second);
+ if (!m_priv->m_settings.second->authorized(*m_priv->m_sso_statement,
+ m_priv->m_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*))) {
+ log(LogLevelError, "doCheckAuthZ() access control provider denied access");
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
+ // TODO: check setting and return 403
+ return pair<bool,void*>(true,m_priv->sendError(this, "access", mlp));
+ }
+ }
- // No Info means OK. Just return
- if (!ht)
- return pair<bool,void*>(false, NULL);
+ // Perform HTAccess Checks
+ ht = getAccessInfo();
- vector<bool> auth_OK(ht->elements.size(), false);
- bool method_restricted=false;
- string remote_user = getRemoteUser();
+ // No Info means OK. Just return
+ if (!ht)
+ return pair<bool,void*>(false, NULL);
+
+ vector<bool> auth_OK(ht->elements.size(), false);
+ bool method_restricted=false;
+ string remote_user = getRemoteUser();
#define CHECK_OK do { \
if (ht->requireAll) { \
continue; \
} while (0)
- for (int x = 0; x < ht->elements.size(); x++) {
- auth_OK[x] = false;
- HTAccessInfo::RequireLine *line = ht->elements[x];
- if (! line->use_line)
- continue;
- method_restricted = true;
-
- const char *w = line->tokens[0].c_str();
-
- if (!strcasecmp(w,"Shibboleth")) {
- // This is a dummy rule needed because Apache conflates authn and authz.
- // Without some require rule, AuthType is ignored and no check_user hooks run.
- CHECK_OK;
- }
- else if (!strcmp(w,"valid-user")) {
- log(LogLevelDebug, "doCheckAuthZ accepting valid-user");
- CHECK_OK;
- }
- else if (!strcmp(w,"user") && !remote_user.empty()) {
- bool regexp=false;
- for (int i = 1; i < line->tokens.size(); i++) {
- w = line->tokens[i].c_str();
- if (*w == '~') {
- regexp = true;
- continue;
- }
-
- if (regexp) {
- try {
- // To do regex matching, we have to convert from UTF-8.
- auto_ptr<XMLCh> trans(fromUTF8(w));
- RegularExpression re(trans.get());
- auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
- if (re.matches(trans2.get())) {
- log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
- CHECK_OK;
- }
- }
- catch (XMLException& ex) {
- auto_ptr_char tmp(ex.getMessage());
- log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
- + w + "): " + tmp.get());
- }
- }
- else if (!strcmp(remote_user.c_str(), w)) {
- log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
- CHECK_OK;
- }
- }
- }
- else if (!strcmp(w,"group")) {
- grpstatus = getGroupTable(remote_user);
+ for (int x = 0; x < ht->elements.size(); x++) {
+ auth_OK[x] = false;
+ HTAccessInfo::RequireLine *line = ht->elements[x];
+ if (! line->use_line)
+ continue;
+ method_restricted = true;
- if (!grpstatus) {
- delete ht;
- return pair<bool,void*>(true, returnDecline());
- }
-
- for (int i = 1; i < line->tokens.size(); i++) {
- w = line->tokens[i].c_str();
- if (grpstatus->lookup(w)) {
- log(LogLevelDebug, string("doCheckAuthZ accepting group: ") + w);
- CHECK_OK;
- }
- }
- delete grpstatus;
- grpstatus = NULL;
- }
- else {
- Iterator<IAAP*> provs = m_priv->m_app->getAAPProviders();
- AAP wrapper(provs, w);
- if (wrapper.fail()) {
- log(LogLevelWarn, string("doCheckAuthZ didn't recognize require rule: ") + w);
- continue;
- }
+ const char *w = line->tokens[0].c_str();
- bool regexp = false;
- string vals = getHeader(wrapper->getHeader());
- for (int i = 1; i < line->tokens.size() && !vals.empty(); i++) {
- w = line->tokens[i].c_str();
- if (*w == '~') {
- regexp = true;
- continue;
- }
-
- try {
- auto_ptr<RegularExpression> re;
- if (regexp) {
- delete re.release();
- auto_ptr<XMLCh> trans(fromUTF8(w));
- auto_ptr<RegularExpression> temp(new RegularExpression(trans.get()));
- re=temp;
+ if (!strcasecmp(w,"Shibboleth")) {
+ // This is a dummy rule needed because Apache conflates authn and authz.
+ // Without some require rule, AuthType is ignored and no check_user hooks run.
+ CHECK_OK;
}
-
- string vals_str(vals);
- int j = 0;
- for (int i = 0; i < vals_str.length(); i++) {
- if (vals_str.at(i) == ';') {
- if (i == 0) {
- log(LogLevelError, string("doCheckAuthZ invalid header encoding") +
- vals + ": starts with a semicolon");
- goto out;
- }
-
- if (vals_str.at(i-1) == '\\') {
- vals_str.erase(i-1, 1);
- i--;
- continue;
- }
-
- string val = vals_str.substr(j, i-j);
- j = i+1;
- if (regexp) {
- auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
- if (re->matches(trans.get())) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted");
- CHECK_OK;
- }
- }
- else if ((wrapper->getCaseSensitive() && val==w) ||
- (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted.");
- CHECK_OK;
- }
- else {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authoritzation not granted.");
+ else if (!strcmp(w,"valid-user")) {
+ log(LogLevelDebug, "doCheckAuthZ accepting valid-user");
+ CHECK_OK;
+ }
+ else if (!strcmp(w,"user") && !remote_user.empty()) {
+ bool regexp=false;
+ for (int i = 1; i < line->tokens.size(); i++) {
+ w = line->tokens[i].c_str();
+ if (*w == '~') {
+ regexp = true;
+ continue;
+ }
+
+ if (regexp) {
+ try {
+ // To do regex matching, we have to convert from UTF-8.
+ auto_ptr<XMLCh> trans(fromUTF8(w));
+ RegularExpression re(trans.get());
+ auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
+ if (re.matches(trans2.get())) {
+ log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
+ CHECK_OK;
+ }
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
+ + w + "): " + tmp.get());
+ }
+ }
+ else if (!strcmp(remote_user.c_str(), w)) {
+ log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
+ CHECK_OK;
+ }
}
- }
}
+ else if (!strcmp(w,"group")) {
+ grpstatus = getGroupTable(remote_user);
+ if (!grpstatus) {
+ delete ht;
+ return pair<bool,void*>(true, returnDecline());
+ }
- string val = vals_str.substr(j, vals_str.length()-j);
- if (regexp) {
- auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
- if (re->matches(trans.get())) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted.");
- CHECK_OK;
- }
- }
- else if ((wrapper->getCaseSensitive() && val==w) ||
- (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization granted");
- CHECK_OK;
+ for (int i = 1; i < line->tokens.size(); i++) {
+ w = line->tokens[i].c_str();
+ if (grpstatus->lookup(w)) {
+ log(LogLevelDebug, string("doCheckAuthZ accepting group: ") + w);
+ CHECK_OK;
+ }
+ }
+ delete grpstatus;
+ grpstatus = NULL;
}
else {
- log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
- ", got " + val + ": authorization not granted");
- }
- }
- catch (XMLException& ex) {
- auto_ptr_char tmp(ex.getMessage());
- log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
- + w + "): " + tmp.get());
- }
- }
- }
- } // for x
+ Iterator<IAAP*> provs = m_priv->m_app->getAAPProviders();
+ AAP wrapper(provs, w);
+ if (wrapper.fail()) {
+ log(LogLevelWarn, string("doCheckAuthZ didn't recognize require rule: ") + w);
+ continue;
+ }
+ bool regexp = false;
+ string vals = getHeader(wrapper->getHeader());
+ for (int i = 1; i < line->tokens.size() && !vals.empty(); i++) {
+ w = line->tokens[i].c_str();
+ if (*w == '~') {
+ regexp = true;
+ continue;
+ }
+
+ try {
+ auto_ptr<RegularExpression> re;
+ if (regexp) {
+ delete re.release();
+ auto_ptr<XMLCh> trans(fromUTF8(w));
+ auto_ptr<RegularExpression> temp(new RegularExpression(trans.get()));
+ re=temp;
+ }
+
+ string vals_str(vals);
+ int j = 0;
+ for (int i = 0; i < vals_str.length(); i++) {
+ if (vals_str.at(i) == ';') {
+ if (i == 0) {
+ log(LogLevelError, string("doCheckAuthZ invalid header encoding") +
+ vals + ": starts with a semicolon");
+ throw SAMLException("Invalid information supplied to authorization module.");
+ }
+
+ if (vals_str.at(i-1) == '\\') {
+ vals_str.erase(i-1, 1);
+ i--;
+ continue;
+ }
+
+ string val = vals_str.substr(j, i-j);
+ j = i+1;
+ if (regexp) {
+ auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
+ if (re->matches(trans.get())) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted");
+ CHECK_OK;
+ }
+ }
+ else if ((wrapper->getCaseSensitive() && val==w) ||
+ (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted.");
+ CHECK_OK;
+ }
+ else {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authoritzation not granted.");
+ }
+ }
+ }
+
+ string val = vals_str.substr(j, vals_str.length()-j);
+ if (regexp) {
+ auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
+ if (re->matches(trans.get())) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted.");
+ CHECK_OK;
+ }
+ }
+ else if ((wrapper->getCaseSensitive() && val==w) ||
+ (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization granted");
+ CHECK_OK;
+ }
+ else {
+ log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+ ", got " + val + ": authorization not granted");
+ }
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
+ + w + "): " + tmp.get());
+ }
+ }
+ }
+ } // for x
- // check if all require directives are true
- bool auth_all_OK = true;
- for (int i = 0; i < ht->elements.size(); i++) {
- auth_all_OK &= auth_OK[i];
- }
- delete ht;
- if (grpstatus) delete grpstatus;
- if (auth_all_OK || !method_restricted)
- return pair<bool,void*>(false, NULL);
+ // check if all require directives are true
+ bool auth_all_OK = true;
+ for (int i = 0; i < ht->elements.size(); i++) {
+ auth_all_OK &= auth_OK[i];
+ }
- // If we get here there's an access error, so just fall through
+ delete ht;
+ if (grpstatus) delete grpstatus;
+ if (auth_all_OK || !method_restricted)
+ return pair<bool,void*>(false, NULL);
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
+ // If we get here there's an access error, so just fall through
+ }
+ catch (SAMLException& e) {
+ mlp.insert(e);
+ }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- if (ht)
delete ht;
- return pair<bool,void*>(true,m_priv->sendError(this, "access", mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, "access", mlp));
}
pair<bool,void*>
ShibTarget::doExportAssertions(bool exportAssertion)
{
#ifdef _DEBUG
- saml::NDC ndc("ShibTarget::doExportAssertions");
+ saml::NDC ndc("ShibTarget::doExportAssertions");
#endif
- ShibMLP mlp;
- const char *procState = "Attribute Processing Error";
- const char *targetURL = NULL;
- char *page = "rm";
-
- try {
- if (! m_priv->m_app)
- throw ShibTargetException(SHIBRPC_OK, "ShibTarget Uninitialized. Application did not supply request information.");
-
- targetURL = m_priv->m_url.c_str();
- const char *session_id = m_priv->getSessionId(this);
-
- if (!m_priv->m_sso_statement) {
- // No data yet, so we need to get the session. This can only happen
- // if the call to doCheckAuthn doesn't happen in the same object lifetime.
- RPCError* status = sessionGet(
- session_id,
- m_priv->m_remote_addr.c_str(),
- m_priv->m_sso_profile,
- m_priv->m_provider_id,
- &m_priv->m_sso_statement,
- &m_priv->m_pre_response,
- &m_priv->m_post_response
- );
- if (status->isError()) {
- string er = "sessionGet failed: ";
- er += status->getText();
- log(ShibTarget::LogLevelError, er);
- mlp.insert(*status);
- delete status;
- goto out;
+ ShibMLP mlp;
+ const char *procState = "Attribute Processing Error";
+ const char *targetURL = NULL;
+ char *page = "rm";
+
+ try {
+ if (!m_priv->m_app)
+ throw SAMLException("System uninitialized, application did not supply request information.");
+
+ targetURL = m_priv->m_url.c_str();
+ const char *session_id = m_priv->getSessionId(this);
+
+ if (!m_priv->m_sso_statement) {
+ // No data yet, so we need to get the session. This can only happen
+ // if the call to doCheckAuthn doesn't happen in the same object lifetime.
+ sessionGet(
+ session_id,
+ m_priv->m_remote_addr.c_str(),
+ m_priv->m_sso_profile,
+ m_priv->m_provider_id,
+ &m_priv->m_sso_statement,
+ &m_priv->m_pre_response,
+ &m_priv->m_post_response
+ );
}
- delete status;
- }
- // Get the AAP providers, which contain the attribute policy info.
- Iterator<IAAP*> provs=m_priv->m_app->getAAPProviders();
-
- // Clear out the list of mapped attributes
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- Locker locker(aap);
- Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
- while (rules.hasNext()) {
- const char* header=rules.next()->getHeader();
- if (header)
- clearHeader(header);
- }
- }
-
- // Maybe export the first assertion.
- clearHeader("Shib-Attributes");
- pair<bool,bool> exp=m_priv->m_settings.first->getBool("exportAssertion");
- if (!exp.first || !exp.second)
- if (exportAssertion)
- exp.second=true;
- if (exp.second && m_priv->m_pre_response) {
- ostringstream os;
- os << *(m_priv->m_pre_response);
- unsigned int outlen;
- char* resp = (char*)os.str().c_str();
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(resp), os.str().length(), &outlen);
- setHeader("Shib-Attributes", reinterpret_cast<char*>(serialized));
- XMLString::release(&serialized);
- }
+ // Get the AAP providers, which contain the attribute policy info.
+ Iterator<IAAP*> provs=m_priv->m_app->getAAPProviders();
- // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
- clearHeader("Shib-Origin-Site");
- clearHeader("Shib-Identity-Provider");
- clearHeader("Shib-Authentication-Method");
- clearHeader("Shib-NameIdentifier-Format");
- setHeader("Shib-Origin-Site", m_priv->m_provider_id.c_str());
- setHeader("Shib-Identity-Provider", m_priv->m_provider_id.c_str());
- auto_ptr_char am(m_priv->m_sso_statement->getAuthMethod());
- setHeader("Shib-Authentication-Method", am.get());
-
- // Export NameID?
- provs.reset();
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- Locker locker(aap);
- const IAttributeRule* rule=aap->lookup(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
- if (rule && rule->getHeader()) {
- auto_ptr_char form(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
- auto_ptr_char nameid(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getName());
- setHeader("Shib-NameIdentifier-Format", form.get());
- if (!strcmp(rule->getHeader(),"REMOTE_USER"))
- setRemoteUser(nameid.get());
- else
- setHeader(rule->getHeader(), nameid.get());
+ // Clear out the list of mapped attributes
+ while (provs.hasNext()) {
+ IAAP* aap=provs.next();
+ Locker locker(aap);
+ Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
+ while (rules.hasNext()) {
+ const char* header=rules.next()->getHeader();
+ if (header)
+ clearHeader(header);
+ }
+ }
+
+ // Maybe export the first assertion.
+ clearHeader("Shib-Attributes");
+ pair<bool,bool> exp=m_priv->m_settings.first->getBool("exportAssertion");
+ if (!exp.first || !exp.second)
+ if (exportAssertion)
+ exp.second=true;
+ if (exp.second && m_priv->m_pre_response) {
+ ostringstream os;
+ os << *(m_priv->m_pre_response);
+ unsigned int outlen;
+ char* resp = (char*)os.str().c_str();
+ XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(resp), os.str().length(), &outlen);
+ // TODO: strip linefeeds
+ setHeader("Shib-Attributes", reinterpret_cast<char*>(serialized));
+ XMLString::release(&serialized);
}
- }
- clearHeader("Shib-Application-ID");
- setHeader("Shib-Application-ID", m_priv->m_app->getId());
-
- // Export the attributes.
- Iterator<SAMLAssertion*> a_iter(m_priv->m_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*));
- while (a_iter.hasNext()) {
- SAMLAssertion* assert=a_iter.next();
- Iterator<SAMLStatement*> statements=assert->getStatements();
- while (statements.hasNext()) {
- SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());
- if (!astate)
- continue;
- Iterator<SAMLAttribute*> attrs=astate->getAttributes();
- while (attrs.hasNext()) {
- SAMLAttribute* attr=attrs.next();
+ // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
+ clearHeader("Shib-Origin-Site");
+ clearHeader("Shib-Identity-Provider");
+ clearHeader("Shib-Authentication-Method");
+ clearHeader("Shib-NameIdentifier-Format");
+ setHeader("Shib-Origin-Site", m_priv->m_provider_id.c_str());
+ setHeader("Shib-Identity-Provider", m_priv->m_provider_id.c_str());
+ auto_ptr_char am(m_priv->m_sso_statement->getAuthMethod());
+ setHeader("Shib-Authentication-Method", am.get());
- // Are we supposed to export it?
- provs.reset();
- while (provs.hasNext()) {
+ // Export NameID?
+ provs.reset();
+ while (provs.hasNext()) {
IAAP* aap=provs.next();
Locker locker(aap);
- const IAttributeRule* rule=aap->lookup(attr->getName(),attr->getNamespace());
- if (!rule || !rule->getHeader()) {
- continue;
+ const IAttributeRule* rule=aap->lookup(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
+ if (rule && rule->getHeader()) {
+ auto_ptr_char form(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getFormat());
+ auto_ptr_char nameid(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getName());
+ setHeader("Shib-NameIdentifier-Format", form.get());
+ if (!strcmp(rule->getHeader(),"REMOTE_USER"))
+ setRemoteUser(nameid.get());
+ else
+ setHeader(rule->getHeader(), nameid.get());
}
-
- Iterator<string> vals=attr->getSingleByteValues();
- if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())
- setRemoteUser(vals.next());
- else {
- int it=0;
- string header = getHeader(rule->getHeader());
- if (!header.empty())
- it++;
- for (; vals.hasNext(); it++) {
- string value = vals.next();
- for (string::size_type pos = value.find_first_of(";", string::size_type(0));
- pos != string::npos;
- pos = value.find_first_of(";", pos)) {
- value.insert(pos, "\\");
- pos += 2;
- }
- if (it)
- header += ";";
- header += value;
+ }
+
+ clearHeader("Shib-Application-ID");
+ setHeader("Shib-Application-ID", m_priv->m_app->getId());
+
+ // Export the attributes.
+ Iterator<SAMLAssertion*> a_iter(m_priv->m_post_response ? m_priv->m_post_response->getAssertions() : EMPTY(SAMLAssertion*));
+ while (a_iter.hasNext()) {
+ SAMLAssertion* assert=a_iter.next();
+ Iterator<SAMLStatement*> statements=assert->getStatements();
+ while (statements.hasNext()) {
+ SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());
+ if (!astate)
+ continue;
+ Iterator<SAMLAttribute*> attrs=astate->getAttributes();
+ while (attrs.hasNext()) {
+ SAMLAttribute* attr=attrs.next();
+
+ // Are we supposed to export it?
+ provs.reset();
+ while (provs.hasNext()) {
+ IAAP* aap=provs.next();
+ Locker locker(aap);
+ const IAttributeRule* rule=aap->lookup(attr->getName(),attr->getNamespace());
+ if (!rule || !rule->getHeader())
+ continue;
+
+ Iterator<string> vals=attr->getSingleByteValues();
+ if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())
+ setRemoteUser(vals.next());
+ else {
+ int it=0;
+ string header = getHeader(rule->getHeader());
+ if (!header.empty())
+ it++;
+ for (; vals.hasNext(); it++) {
+ string value = vals.next();
+ for (string::size_type pos = value.find_first_of(";", string::size_type(0));
+ pos != string::npos;
+ pos = value.find_first_of(";", pos)) {
+ value.insert(pos, "\\");
+ pos += 2;
+ }
+ if (it)
+ header += ";";
+ header += value;
+ }
+ setHeader(rule->getHeader(), header);
+ }
+ }
}
- setHeader(rule->getHeader(), header);
}
- }
}
- }
+
+ return pair<bool,void*>(false,NULL);
+ }
+ catch (SAMLException& e) {
+ mlp.insert(e);
}
-
- return pair<bool,void*>(false,NULL);
- }
- catch (ShibTargetException &e) {
- mlp.insert("errorText", e.what());
- }
#ifndef _DEBUG
- catch (...) {
- mlp.insert("errorText", "Unexpected Exception");
- }
+ catch (...) {
+ mlp.insert("errorText", "Caught an unknown exception.");
+ }
#endif
- // If we get here then we've got an error.
- mlp.insert("errorType", procState);
- mlp.insert("errorDesc", "An error occurred while processing your request.");
+ // If we get here then we've got an error.
+ mlp.insert("errorType", procState);
- out:
- if (targetURL)
- mlp.insert("requestURL", targetURL);
+ if (targetURL)
+ mlp.insert("requestURL", targetURL);
- return pair<bool,void*>(true,m_priv->sendError(this, page, mlp));
+ return pair<bool,void*>(true,m_priv->sendError(this, page, mlp));
}
-// SHIRE APIs
+// Low level APIs
// Get the session cookie name and properties for the application
pair<string,const char*> ShibTarget::getCookieNameProps(const char* prefix) const
// value to the IdP so we can recognize it on the way back.
pair<string,const char*> shib_cookie=getCookieNameProps("_shibstate_");
setCookie(shib_cookie.first,m_priv->url_encode(resource) + shib_cookie.second);
- req += "&target=42";
+ req += "&target=cookie";
}
pair<bool,bool> old=m_priv->m_app->getBool("oldAuthnRequest");
return getAuthnRequest(target);
}
-RPCError* ShibTarget::sessionNew(
+void ShibTarget::sessionNew(
int supported_profiles,
const char* packet,
const char* ip,
) const
{
#ifdef _DEBUG
- saml::NDC ndc("sessionNew");
+ saml::NDC ndc("sessionNew");
#endif
- Category& log = Category::getInstance("shibtarget.ShibTarget");
+ Category& log = Category::getInstance("shibtarget.ShibTarget");
- if (!packet || !*packet) {
- log.error("Empty profile content");
- return new RPCError(SHIBRPC_RESPONSE_MISSING, "Empty profile content");
- }
+ if (!packet || !*packet) {
+ log.error("missing profile response");
+ throw FatalProfileException("Profile response missing.");
+ }
- if (!ip || !*ip) {
- log.error("Invalid IP address");
- return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP address");
- }
+ if (!ip || !*ip) {
+ log.error("missing client address");
+ throw FatalProfileException("Invalid client address.");
+ }
- if (supported_profiles <= 0) {
- log.error("No profile support indicated");
- return new RPCError(SHIBRPC_INTERNAL_ERROR, "No profile support indicated");
- }
+ if (supported_profiles <= 0) {
+ log.error("no profile support indicated");
+ throw FatalProfileException("No profile support indicated.");
+ }
- shibrpc_new_session_args_2 arg;
- arg.recipient = (char*) m_priv->m_shireURL.c_str();
- arg.application_id = (char*) m_priv->m_app->getId();
- arg.packet = (char*)packet;
- arg.client_addr = (char*)ip;
- arg.supported_profiles = supported_profiles;
-
- log.info("create session for user at (%s) for application (%s)", ip, arg.application_id);
-
- shibrpc_new_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_new_session_2 (&arg, &ret, clnt);
- if (status != RPC_SUCCESS) {
- // FAILED. Release, disconnect, and retry
- log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_2"));
- rpc->disconnect();
- if (retry)
- retry--;
- else
- return new RPCError(-1, "RPC Failure");
+ shibrpc_new_session_args_2 arg;
+ arg.recipient = (char*) m_priv->m_shireURL.c_str();
+ arg.application_id = (char*) m_priv->m_app->getId();
+ arg.packet = (char*)packet;
+ arg.client_addr = (char*)ip;
+ arg.supported_profiles = supported_profiles;
+
+ log.info("create session for user at (%s) for application (%s)", ip, arg.application_id);
+
+ shibrpc_new_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_new_session_2 (&arg, &ret, clnt);
+ if (status != RPC_SUCCESS) {
+ // FAILED. Release, disconnect, and retry
+ log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_2"));
+ rpc->disconnect();
+ if (retry)
+ retry--;
+ else
+ throw ListenerException("Failure passing session setup information to listener.");
+ }
+ else {
+ // SUCCESS. Pool and continue
+ 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_new_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw FatalProfileException("An unrecoverable error occurred while creating your session.");
+ }
+#ifndef _DEBUG
+ catch (...) {
+ log.error("caught unknown exception building SAMLException");
+ log.error("XML was: %s", ret.status);
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
+ }
+#endif
}
else {
- // SUCCESS. Pool and continue
- retry = -1;
+ log.debug("new session cookie: %s", ret.cookie);
+ cookie = ret.cookie;
+ if (ret.target)
+ target = ret.target;
}
- } while (retry>=0);
-
- log.debug("RPC completed with status %d (%p)", ret.status.status, this);
-
- RPCError* retval;
- if (ret.status.status)
- retval = new RPCError(&ret.status);
- else {
- log.debug ("new session cookie: %s", ret.cookie);
- cookie = ret.cookie;
- if (ret.target)
- target = ret.target;
- retval = new RPCError();
- }
-
- clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
- rpc.pool();
- return retval;
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ if (except) {
+ auto_ptr<SAMLException> wrapper(except);
+ throw *wrapper;
+ }
}
-RPCError* ShibTarget::sessionGet(
+void ShibTarget::sessionGet(
const char* cookie,
const char* ip,
ShibProfile& profile,
) const
{
#ifdef _DEBUG
- saml::NDC ndc("sessionGet");
+ saml::NDC ndc("sessionGet");
#endif
- Category& log = Category::getInstance("shibtarget.ShibTarget");
-
- if (!cookie || !*cookie) {
- log.error("No cookie value was provided");
- return new RPCError(SHIBRPC_NO_SESSION, "No cookie value was provided");
- }
- else if (strchr(cookie,'=')) {
- log.error("The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
- return new RPCError(SHIBRPC_INTERNAL_ERROR, "The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
- }
-
- if (!ip || !*ip) {
- log.error("Invalid IP Address");
- return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP Address");
- }
+ Category& log = Category::getInstance("shibtarget.ShibTarget");
- log.info("getting session for client at (%s)", ip);
- log.debug("session cookie (%s)", cookie);
-
- shibrpc_get_session_args_2 arg;
-
- arg.cookie = (char*)cookie;
- arg.client_addr = (char*)ip;
- arg.application_id = (char*)m_priv->m_app->getId();
-
- shibrpc_get_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_get_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_get_session_2"));
- rpc->disconnect();
- if (retry)
- retry--;
- else
- return new RPCError(-1, "RPC Failure");
+ if (!cookie || !*cookie) {
+ log.error("no session key provided");
+ throw InvalidSessionException("No session key was provided.");
}
- else {
- // SUCCESS
- retry = -1;
+ 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.");
}
- } while (retry>=0);
- log.debug("RPC completed with status %d, %p", ret.status.status, this);
+ if (!ip || !*ip) {
+ log.error("invalid client Address");
+ throw FatalProfileException("Invalid client address.");
+ }
- RPCError* retval = NULL;
- if (ret.status.status)
- retval = new RPCError(&ret.status);
- else {
- try {
- try {
- profile = ret.profile;
- provider_id = ret.provider_id;
-
- // return the Authentication Statement
- if (auth_statement) {
- istringstream authstream(ret.auth_statement);
-
- log.debugStream() << "Trying to decode authentication statement: "
- << ret.auth_statement << CategoryStream::ENDLINE;
- *auth_statement = new SAMLAuthenticationStatement(authstream);
+ log.info("getting session for client at (%s)", ip);
+ log.debug("session cookie (%s)", cookie);
+
+ shibrpc_get_session_args_2 arg;
+ arg.cookie = (char*)cookie;
+ arg.client_addr = (char*)ip;
+ arg.application_id = (char*)m_priv->m_app->getId();
+
+ shibrpc_get_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_get_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_get_session_2"));
+ rpc->disconnect();
+ if (retry)
+ retry--;
+ else
+ throw ListenerException("Failure requesting session information from listener.");
}
-
- // return the unfiltered Response
- if (attr_response_pre) {
- istringstream prestream(ret.attr_response_pre);
-
- log.debugStream() << "Trying to decode unfiltered attribute response: "
- << ret.attr_response_pre << CategoryStream::ENDLINE;
- *attr_response_pre = new SAMLResponse(prestream);
+ else {
+ // SUCCESS
+ retry = -1;
}
+ } while (retry>=0);
- // return the filtered Response
- if (attr_response_post) {
- istringstream poststream(ret.attr_response_post);
-
- log.debugStream() << "Trying to decode filtered attribute response: "
- << ret.attr_response_post << CategoryStream::ENDLINE;
- *attr_response_post = new SAMLResponse(poststream);
+ 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_get_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_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
}
- }
- catch (SAMLException& e) {
- log.error ("SAML Exception: %s", e.what());
- ostringstream os;
- os << e;
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str());
- }
- catch (XMLException& e) {
- log.error ("XML Exception: %s", e.getMessage());
- auto_ptr_char msg(e.getMessage());
- throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get());
- }
}
- catch (ShibTargetException &e) {
- retval = new RPCError(e);
+ else {
+ try {
+ profile = ret.profile;
+ provider_id = ret.provider_id;
+
+ // return the Authentication Statement
+ if (auth_statement) {
+ istringstream authstream(ret.auth_statement);
+ log.debugStream() << "trying to decode authentication statement: "
+ << ret.auth_statement << CategoryStream::ENDLINE;
+ *auth_statement = new SAMLAuthenticationStatement(authstream);
+ }
+
+ // return the unfiltered Response
+ if (attr_response_pre) {
+ istringstream prestream(ret.attr_response_pre);
+ log.debugStream() << "trying to decode unfiltered attribute response: "
+ << ret.attr_response_pre << CategoryStream::ENDLINE;
+ *attr_response_pre = new SAMLResponse(prestream);
+ }
+
+ // return the filtered Response
+ if (attr_response_post) {
+ istringstream poststream(ret.attr_response_post);
+ log.debugStream() << "trying to decode filtered attribute response: "
+ << ret.attr_response_post << CategoryStream::ENDLINE;
+ *attr_response_post = new SAMLResponse(poststream);
+ }
+ }
+ catch (SAMLException& e) {
+ log.error("caught SAML exception while reconstituting session objects: %s", e.what());
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
+ }
+#ifndef _DEBUG
+ catch (...) {
+ log.error("caught unknown exception while reconstituting session objects");
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ throw;
+ }
+#endif
}
- if (!retval)
- retval = new RPCError();
- }
-
- clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
- rpc.pool();
-
- return retval;
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
+ rpc.pool();
+ if (except) {
+ auto_ptr<SAMLException> wrapper(except);
+ throw *wrapper;
+ }
}
/*************************************************************************
m_mapper = NULL;
m_conf->unlock();
m_conf = NULL;
- throw ShibTargetException(SHIBRPC_OK, "unable to map request to application settings. Check configuration");
+ throw SAMLException("Unable to map request to application settings, check configuration.");
}
// Store the application for later use
void*
ShibTargetPriv::sendError(ShibTarget* st, string page, ShibMLP &mlp)
{
- const IPropertySet* props=m_app->getPropertySet("Errors");
- if (props) {
- pair<bool,const char*> p=props->getString(page.c_str());
- if (p.first) {
- ifstream infile(p.second);
- if (!infile.fail()) {
- const char* res = mlp.run(infile,props);
- if (res)
- return st->sendPage(res);
- }
+ const IPropertySet* props=m_app->getPropertySet("Errors");
+ if (props) {
+ pair<bool,const char*> p=props->getString(page.c_str());
+ if (p.first) {
+ ifstream infile(p.second);
+ if (!infile.fail()) {
+ const char* res = mlp.run(infile,props);
+ if (res)
+ return st->sendPage(res);
+ }
+ }
}
- }
- string errstr = "sendError could not process the error template for application ";
- errstr += m_app->getId();
- st->log(ShibTarget::LogLevelError, errstr);
- return st->sendPage("Internal Server Error. Please contact the server administrator.");
+ string errstr = "sendError could not process the error template for application (";
+ errstr += m_app->getId();
+ errstr += ")";
+ st->log(ShibTarget::LogLevelError, errstr);
+ return st->sendPage("Internal Server Error. Please contact the site administrator.");
}
const char* ShibTargetPriv::getSessionId(ShibTarget* st)
namespace shibtarget {
- //******************************************************************************
- // You probably don't care about much below this line
- // unless you are using the lower-layer APIs provided by
- // the shib target library. Go to the end of the file to
- // find the ShibTarget class -- you probably wnat to use that.
- //
-
- class SHIBTARGET_EXPORTS ShibTargetException : public std::exception
- {
- public:
- explicit ShibTargetException() : m_code(SHIBRPC_OK) {}
- explicit ShibTargetException(ShibRpcStatus code, const char* msg, const shibboleth::IEntityDescriptor* provider);
- explicit ShibTargetException(ShibRpcStatus code, const char* msg, const shibboleth::IRoleDescriptor* role=NULL);
-
- virtual ~ShibTargetException() throw () {}
- virtual ShibRpcStatus which() const throw () { return m_code; }
- virtual const char* what() const throw () { return m_msg.c_str(); }
- virtual const char* syswho() const throw() { return m_providerId.c_str(); }
- virtual const char* where() const throw () { return m_errorURL.c_str(); }
- virtual const char* who() const throw () { return m_contact.c_str(); }
- virtual const char* how() const throw () { return m_email.c_str(); }
-
- private:
- ShibRpcStatus m_code;
- std::string m_msg;
- std::string m_providerId;
- std::string m_errorURL;
- std::string m_contact;
- std::string m_email;
- };
-
- class RPCErrorPriv;
- class SHIBTARGET_EXPORTS RPCError
- {
- public:
- RPCError();
- RPCError(ShibRpcError* e);
- RPCError(int s, const char* st);
- RPCError(ShibTargetException &exp);
- ~RPCError();
-
- bool isError();
- bool isRetryable();
-
- // Return a set of strings that correspond to the error properties
- const char* getType();
- const char* getText();
- const char* getDesc();
- const char* getProviderId();
- const char* getErrorURL();
- const char* getContactName();
- const char* getContactEmail();
- int getCode();
-
- private:
- RPCErrorPriv* m_priv;
- };
+ DECLARE_SAML_EXCEPTION(SHIBTARGET_EXPORTS,ListenerException,SAMLException);
// Abstract APIs for access to configuration information
std::string k = key, v = value;
insert(k,v);
}
- void insert (RPCError& e);
+ void insert (saml::SAMLException& e);
void clear () { m_map.clear(); }
std::string m_generated;
};
- //******************************************************************************
- //
- // This is the interface you're looking for.
- //
-
class HTAccessInfo {
public:
class RequireLine {
ShibTarget();
// Currently wraps remoted interface.
- // TODO: Move this functionality behind ISessionCache
- RPCError* sessionNew(
+ // TODO: Move this functionality behind IListener
+ void sessionNew(
int supported_profiles,
const char* packet,
const char* ip,
std::string& target
) const;
- RPCError* sessionGet(
+ void sessionGet(
const char* cookie,
const char* ip,
ShibProfile& profile,
return TRUE;
}
-// Functions to map errors into IDL-defined status structure
-
-void set_rpc_status(ShibRpcError *error, ShibRpcStatus status, const char* msg=NULL)
-{
- error->status = status;
- if (status) {
- error->ShibRpcError_u.e.error = strdup(msg ? msg : "");
- error->ShibRpcError_u.e.provider = strdup("");
- error->ShibRpcError_u.e.url = strdup("");
- error->ShibRpcError_u.e.contact = strdup("");
- error->ShibRpcError_u.e.email = strdup("");
- }
-}
-
-void set_rpc_status(ShibRpcError *error, ShibTargetException& exc)
-{
- error->status = exc.which();
- if (error->status) {
- error->ShibRpcError_u.e.error = strdup(exc.what() ? exc.what() : "");
- error->ShibRpcError_u.e.provider = strdup(exc.syswho() ? exc.syswho() : "");
- error->ShibRpcError_u.e.url = strdup(exc.where() ? exc.where() : "");
- error->ShibRpcError_u.e.contact = strdup(exc.who() ? exc.who() : "");
- error->ShibRpcError_u.e.email = strdup(exc.how() ? exc.how() : "");
- }
-}
-
extern "C" bool_t
shibrpc_get_session_2_svc(
shibrpc_get_session_args_2 *argp,
struct svc_req *rqstp
)
{
- Category& log = get_category();
- string ctx = get_threadid("get_session");
- saml::NDC ndc(ctx);
+ Category& log = get_category();
+ string ctx = get_threadid("get_session");
+ saml::NDC ndc(ctx);
- if (!argp || !result) {
- log.error ("RPC Argument Error");
- return FALSE;
- }
+ 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("");
+ memset (result, 0, sizeof (*result));
+ result->provider_id = strdup("");
+ result->auth_statement = strdup("");
+ result->attr_response_pre = strdup("");
+ result->attr_response_post = strdup("");
- log.debug ("checking: %s@%s", argp->cookie, argp->client_addr);
+ log.debug ("checking: %s@%s", argp->cookie, argp->client_addr);
- // See if the session exists...
+ // See if the session exists...
- IConfig* conf=ShibTargetConfig::getConfig().getINI();
- Locker locker(conf);
- log.debug ("application: %s", argp->application_id);
- const IApplication* app=conf->getApplication(argp->application_id);
- if (!app) {
- // Something's horribly wrong.
- log.error("couldn't find application for session");
- set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "Unable to locate application for session, deleted?");
- return TRUE;
- }
-
- bool checkIPAddress=true;
- int lifetime=0,timeout=0;
- const IPropertySet* props=app->getPropertySet("Sessions");
- if (props) {
- pair<bool,unsigned int> p=props->getUnsignedInt("lifetime");
- if (p.first)
- lifetime = p.second;
- p=props->getUnsignedInt("timeout");
- if (p.first)
- timeout = p.second;
- pair<bool,bool> pcheck=props->getBool("checkAddress");
- if (pcheck.first)
- checkIPAddress = pcheck.second;
- }
-
- ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie,app);
-
- // If not, leave now..
- if (!entry) {
- log.debug ("Not found");
- set_rpc_status(&result->status, SHIBRPC_NO_SESSION, "No session exists for this key value");
- return TRUE;
- }
-
- // TEST the session...
- try {
- // Verify the address is the same
- if (checkIPAddress) {
- log.debug("Checking address against %s", entry->getClientAddress());
- if (strcmp(argp->client_addr, entry->getClientAddress())) {
- log.debug ("IP Address mismatch");
- Metadata m(app->getMetadataProviders());
- throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
- "Your IP address does not match the address recorded at the time the session was established.",
- m.lookup(entry->getProviderId()));
- }
+ IConfig* conf=ShibTargetConfig::getConfig().getINI();
+ Locker locker(conf);
+ log.debug ("application: %s", argp->application_id);
+ const IApplication* app=conf->getApplication(argp->application_id);
+ if (!app) {
+ // Something's horribly wrong.
+ 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;
}
- // and that the session is still valid...
- if (!entry->isValid(lifetime,timeout)) {
- log.debug ("Session expired");
- Metadata m(app->getMetadataProviders());
- throw ShibTargetException(SHIBRPC_SESSION_EXPIRED,
- "Your session has expired, and you must re-authenticate.",
- m.lookup(entry->getProviderId()));
+ bool checkIPAddress=true;
+ int lifetime=0,timeout=0;
+ const IPropertySet* props=app->getPropertySet("Sessions");
+ if (props) {
+ pair<bool,unsigned int> p=props->getUnsignedInt("lifetime");
+ if (p.first)
+ lifetime = p.second;
+ p=props->getUnsignedInt("timeout");
+ if (p.first)
+ timeout = p.second;
+ pair<bool,bool> pcheck=props->getBool("checkAddress");
+ if (pcheck.first)
+ checkIPAddress = pcheck.second;
+ }
+
+ ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie,app);
+
+ // If not, leave now..
+ if (!entry) {
+ log.debug("session not found");
+ InvalidSessionException ex("No session exists for key value ($session_id)",namedparams(1,"session_id",argp->cookie));
+ ostringstream os;
+ os << ex;
+ result->status=strdup(os.str().c_str());
+ return TRUE;
}
+ // TEST the session...
try {
- // Set profile and provider
- result->profile = entry->getProfile();
- free(result->provider_id);
- result->provider_id = strdup(entry->getProviderId());
+ // Verify the address is the same
+ if (checkIPAddress) {
+ log.debug("Checking address against %s", entry->getClientAddress());
+ if (strcmp(argp->client_addr, entry->getClientAddress())) {
+ log.debug("client address mismatch");
+ InvalidSessionException ex(
+ SESSION_E_ADDRESSMISMATCH,
+ "Your IP address (%1) does not match the address recorded at the time the session was established.",
+ params(1,argp->client_addr)
+ );
+ Metadata m(app->getMetadataProviders());
+ annotateException(ex,m.lookup(entry->getProviderId())); // throws it
+ }
+ }
+
+ // and that the session is still valid...
+ if (!entry->isValid(lifetime,timeout)) {
+ log.debug("session expired");
+ InvalidSessionException ex(SESSION_E_EXPIRED, "Your session has expired, and you must re-authenticate.");
+ Metadata m(app->getMetadataProviders());
+ annotateException(ex,m.lookup(entry->getProviderId())); // throws it
+ }
+
+ // 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());
+ // 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());
- }
+ 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());
+ }
}
catch (SAMLException &e) {
- log.error ("caught SAML exception: %s", e.what());
- ostringstream os;
- os << e;
- Metadata m(app->getMetadataProviders());
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), m.lookup(entry->getProviderId()));
+ entry->unlock();
+ log.error("caught SAML exception: %s", e.what());
+ conf->getSessionCache()->remove(argp->cookie);
+ ostringstream os;
+ os << e;
+ result->status = strdup(os.str().c_str());
+
+ // Transaction Logging
+ STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
+ stc.getTransactionLog().infoStream() <<
+ "Destroyed invalid session (ID: " <<
+ argp->cookie <<
+ ") with (applicationId: " <<
+ argp->application_id <<
+ "), request was from (ClientAddress: " <<
+ argp->client_addr <<
+ ")";
+ stc.releaseTransactionLog();
+ return TRUE;
}
- }
- catch (ShibTargetException &e) {
- entry->unlock();
- log.error ("FAILED: %s", e.what());
- conf->getSessionCache()->remove(argp->cookie);
- set_rpc_status(&result->status, e);
- // Transaction Logging
- STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
- stc.getTransactionLog().infoStream() <<
- "Destroyed invalid session (ID: " <<
- argp->cookie <<
- ") with (applicationId: " <<
- argp->application_id <<
- "), request was from (ClientAddress: " <<
- argp->client_addr <<
- ")";
- stc.releaseTransactionLog();
- return TRUE;
- }
#ifndef _DEBUG
- catch (...) {
- entry->unlock();
- log.error ("Unknown exception");
- conf->getSessionCache()->remove(argp->cookie);
- set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "An unknown exception occurred");
- // Transaction Logging
- STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
- stc.getTransactionLog().infoStream() <<
- "Destroyed invalid session (ID: " <<
- argp->cookie <<
- ") with (applicationId: " <<
- argp->application_id <<
- "), request was from (ClientAddress: " <<
- argp->client_addr <<
- ")";
- stc.releaseTransactionLog();
- return TRUE;
- }
+ catch (...) {
+ log.error("caught unknown exception");
+ InvalidSessionException ex("An unexpected error occurred while validating your session, and you must re-authenticate.");
+ Metadata m(app->getMetadataProviders());
+ annotateException(ex,m.lookup(entry->getProviderId()),false);
+ entry->unlock();
+ conf->getSessionCache()->remove(argp->cookie);
+ ostringstream os;
+ os << ex;
+ result->status = strdup(os.str().c_str());
+
+ // Transaction Logging
+ STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
+ stc.getTransactionLog().infoStream() <<
+ "Destroyed invalid session (ID: " <<
+ argp->cookie <<
+ ") with (applicationId: " <<
+ argp->application_id <<
+ "), request was from (ClientAddress: " <<
+ argp->client_addr <<
+ ")";
+ stc.releaseTransactionLog();
+ return TRUE;
+ }
#endif
- // Ok, just release it.
- entry->unlock();
-
- // ok, we've succeeded..
- set_rpc_status(&result->status, SHIBRPC_OK);
- log.debug ("session ok");
- return TRUE;
+ // Ok, just release it.
+ entry->unlock();
+ log.debug ("session ok");
+ result->status=strdup("");
+ return TRUE;
}
extern "C" bool_t
struct svc_req *rqstp
)
{
- Category& log = get_category();
- string ctx=get_threadid("new_session");
- saml::NDC ndc(ctx);
-
- if (!argp || !result) {
- log.error ("Invalid RPC Arguments");
- return FALSE;
- }
+ Category& log = get_category();
+ string ctx=get_threadid("new_session");
+ saml::NDC ndc(ctx);
- // Initialize the result structure
- memset (result, 0, sizeof(*result));
- result->cookie = strdup ("");
- result->target = strdup ("");
+ if (!argp || !result) {
+ log.error ("Invalid RPC Arguments");
+ return FALSE;
+ }
- log.debug ("creating session for %s", argp->client_addr);
- log.debug ("recipient: %s", argp->recipient);
- log.debug ("application: %s", argp->application_id);
+ // Initialize the result structure
+ memset (result, 0, sizeof(*result));
+ result->cookie = strdup ("");
+ result->target = strdup ("");
+
+ log.debug ("creating session for %s", argp->client_addr);
+ log.debug ("recipient: %s", argp->recipient);
+ log.debug ("application: %s", argp->application_id);
+
+ auto_ptr_XMLCh recipient(argp->recipient);
+
+ // 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;
+ }
- auto_ptr_XMLCh recipient(argp->recipient);
+ bool checkIPAddress=true;
+ const IPropertySet* props=app->getPropertySet("Sessions");
+ if (props) {
+ pair<bool,bool> pcheck=props->getBool("checkAddress");
+ if (pcheck.first)
+ checkIPAddress = pcheck.second;
+ }
- SAMLResponse* r = NULL;
- const SAMLAuthenticationStatement* auth_st = NULL;
- XMLCh* origin = NULL;
+ pair<bool,bool> checkReplay=pair<bool,bool>(false,false);
+ props=app->getPropertySet("Sessions");
+ if (props)
+ checkReplay=props->getBool("checkReplay");
- // 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");
- set_rpc_status(&result->status, SHIBRPC_INTERNAL_ERROR, "Unable to locate application for session, deleted?");
- return TRUE;
- }
-
- bool checkIPAddress=true;
- const IPropertySet* props=app->getPropertySet("Sessions");
- if (props) {
- pair<bool,bool> pcheck=props->getBool("checkAddress");
- if (pcheck.first)
- checkIPAddress = pcheck.second;
- }
-
- pair<bool,bool> checkReplay=pair<bool,bool>(false,false);
- props=app->getPropertySet("Sessions");
- if (props)
- checkReplay=props->getBool("checkReplay");
-
- const IRoleDescriptor* role=NULL;
- Metadata m(app->getMetadataProviders());
- SAMLBrowserProfile::BrowserProfileResponse bpr;
- try
- {
- if (!app)
- // Something's horribly wrong.
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate application configuration, deleted?");
-
- try
- {
- auto_ptr<SAMLBrowserProfile::ArtifactMapper> artifactMapper(app->getArtifactMapper());
+ const IRoleDescriptor* role=NULL;
+ Metadata m(app->getMetadataProviders());
+ SAMLBrowserProfile::BrowserProfileResponse bpr;
+ try {
+ auto_ptr<SAMLBrowserProfile::ArtifactMapper> artifactMapper(app->getArtifactMapper());
- // Try and run the profile.
- log.debug ("Executing browser profile...");
- bpr=app->getBrowserProfile()->receive(
- &origin,
- argp->packet,
- recipient.get(),
- SAMLBrowserProfile::Post | SAMLBrowserProfile::Artifact,
- (!checkReplay.first || checkReplay.second) ? conf->getReplayCache() : NULL,
- artifactMapper.get()
- );
-
- // Blow it away to clear any locks that might be held.
- delete artifactMapper.release();
-
- // Try and map to metadata for support purposes.
- const IEntityDescriptor* provider=m.lookup(origin);
- if (provider) {
- const IIDPSSODescriptor* IDP=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
- role=IDP;
- }
- // This can't really happen, since the profile must have found a role.
- if (!role)
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,
- "Unable to locate role-specific metadata for identity provider", provider);
+ // Try and run the profile.
+ log.debug("executing browser profile...");
+ int allowed = 0;
+ if (argp->supported_profiles & SAML11_POST)
+ allowed |= SAMLBrowserProfile::Post;
+ if (argp->supported_profiles & SAML11_ARTIFACT)
+ allowed |= SAMLBrowserProfile::Artifact;
+ bpr=app->getBrowserProfile()->receive(
+ argp->packet,
+ recipient.get(),
+ allowed,
+ (!checkReplay.first || checkReplay.second) ? conf->getReplayCache() : NULL,
+ artifactMapper.get()
+ );
+
+ // Blow it away to clear any locks that might be held.
+ delete artifactMapper.release();
+
+ // Try and map to metadata (again).
+ // Once the metadata layer is in the SAML core, the repetition should be fixed.
+ const IEntityDescriptor* provider=m.lookup(bpr.assertion->getIssuer());
+ if (!provider && bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier())
+ provider=m.lookup(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+ if (provider) {
+ const IIDPSSODescriptor* IDP=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
+ role=IDP;
+ }
+
+ // This isn't likely, since the profile must have found a role.
+ if (!role) {
+ MetadataException ex("Unable to locate role-specific metadata for identity provider.");
+ annotateException(ex,provider); // throws it
+ }
- // Maybe verify the origin address....
- if (checkIPAddress) {
- log.debug ("verify client address");
-
- // Verify the client address exists
- const XMLCh* ip = bpr.authnStatement->getSubjectIP();
- if (ip && *ip) {
- // Verify the client address matches authentication
- auto_ptr_char this_ip(ip);
- if (strcmp(argp->client_addr, this_ip.get()))
- throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
- "Your client's current IP address differs from the one used when you authenticated "
- "to your identity provider. To correct this problem, you may need to bypass a proxy server. "
- "Please contact your local support staff or help desk for assistance.",
- role);
+ // Maybe verify the origin address....
+ if (checkIPAddress) {
+ log.debug("verify client address");
+ // Verify the client address exists
+ const XMLCh* ip = bpr.authnStatement->getSubjectIP();
+ if (ip && *ip) {
+ // Verify the client address matches authentication
+ auto_ptr_char this_ip(ip);
+ if (strcmp(argp->client_addr, this_ip.get())) {
+ FatalProfileException ex(
+ SESSION_E_ADDRESSMISMATCH,
+ "Your client's current address ($1) differs from the one used when you authenticated "
+ "to your identity provider. To correct this problem, you may need to bypass a proxy server. "
+ "Please contact your local support staff or help desk for assistance.",
+ params(1,argp->client_addr)
+ );
+ annotateException(ex,role); // throws it
+ }
+ }
}
- }
- // Verify condition(s) on authentication assertion.
- // Attribute assertions get filtered later, essentially just like an AAP.
- Iterator<SAMLCondition*> conditions=bpr.assertion->getConditions();
- while (conditions.hasNext()) {
- SAMLCondition* cond=conditions.next();
- const SAMLAudienceRestrictionCondition* ac=dynamic_cast<const SAMLAudienceRestrictionCondition*>(cond);
- if (!ac) {
- ostringstream os;
- os << *cond;
- log.error("Unrecognized Condition in authentication assertion (%s), tossing it.",os.str().c_str());
- throw FatalProfileException("Unable to start session due to unrecognized condition in authentication assertion.");
+ // Verify condition(s) on authentication assertion.
+ // Attribute assertions get filtered later, essentially just like an AAP.
+ Iterator<SAMLCondition*> conditions=bpr.assertion->getConditions();
+ while (conditions.hasNext()) {
+ SAMLCondition* cond=conditions.next();
+ const SAMLAudienceRestrictionCondition* ac=dynamic_cast<const SAMLAudienceRestrictionCondition*>(cond);
+ if (!ac) {
+ ostringstream os;
+ os << *cond;
+ log.error("Unrecognized Condition in authentication assertion (%s), tossing it.",os.str().c_str());
+ FatalProfileException ex("Unable to create session due to unrecognized condition in authentication assertion.");
+ annotateException(ex,role); // throws it
+ }
+ else if (!ac->eval(app->getAudiences())) {
+ ostringstream os;
+ os << *ac;
+ log.error("Unacceptable AudienceRestrictionCondition in authentication assertion (%s), tossing it.",os.str().c_str());
+ FatalProfileException ex("Unable to create session due to unacceptable AudienceRestrictionCondition in authentication assertion.");
+ annotateException(ex,role); // throws it
+ }
}
- else if (!ac->eval(app->getAudiences())) {
- ostringstream os;
- os << *ac;
- log.error("Unacceptable AudienceRestrictionCondition in authentication assertion (%s), tossing it.",os.str().c_str());
- throw FatalProfileException("Unable to start session due to unacceptable AudienceRestrictionCondition in authentication assertion.");
- }
- }
- }
- catch (ReplayedAssertionException& e) {
- // Specific case where we have an error code.
- if (!role && origin) {
- // Try and map to metadata for support purposes.
- const IEntityDescriptor* provider=m.lookup(origin);
- if (provider) {
- const IIDPSSODescriptor* IDP=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
- role=IDP;
- }
- }
- throw ShibTargetException(SHIBRPC_ASSERTION_REPLAYED, e.what(), role);
}
catch (SAMLException& e) {
- log.error ("caught SAML exception: %s", e.what());
- ostringstream os;
- os << e;
- if (!role && origin) {
- // Try and map to metadata for support purposes.
- const IEntityDescriptor* provider=m.lookup(origin);
- if (provider) {
- const IIDPSSODescriptor* IDP=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
- role=IDP;
- }
- }
- throw ShibTargetException (SHIBRPC_SAML_EXCEPTION, os.str().c_str(), role);
+ bpr.clear();
+ log.error("caught SAML exception: %s", e.what());
+ ostringstream os;
+ os << e;
+ result->status = strdup(os.str().c_str());
+ return TRUE;
}
- }
- catch (ShibTargetException& e) {
- log.error ("FAILED: %s", e.what());
- bpr.clear();
- if (origin) XMLString::release(&origin);
- set_rpc_status(&result->status, e);
- return TRUE;
- }
#ifndef _DEBUG
- catch (...) {
- log.error ("Unknown error");
- bpr.clear();
- if (origin) XMLString::release(&origin);
- set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "An unknown exception occurred");
- return TRUE;
- }
+ catch (...) {
+ log.error("unknown error");
+ bpr.clear();
+ SAMLException e("An unexpected error occurred while creating your session.");
+ annotateException(e,role,false);
+ ostringstream os;
+ os << e;
+ result->status = strdup(os.str().c_str());
+ return TRUE;
+ }
#endif
- // It passes all our tests -- create a new session.
- log.info ("Creating new session");
-
- // Create a new session key.
- string cookie = conf->getSessionCache()->generateKey();
-
- // Are attributes present?
- bool attributesPushed=false;
- Iterator<SAMLAssertion*> assertions=bpr.response->getAssertions();
- while (!attributesPushed && assertions.hasNext()) {
- Iterator<SAMLStatement*> statements=assertions.next()->getStatements();
- while (!attributesPushed && statements.hasNext()) {
- if (dynamic_cast<SAMLAttributeStatement*>(statements.next()))
- attributesPushed=true;
- }
- }
-
- // Insertion into cache might fail.
- auto_ptr_char oname(origin);
- SAMLAuthenticationStatement* as=NULL;
- try {
- as=static_cast<SAMLAuthenticationStatement*>(bpr.authnStatement->clone());
- // TODO: we need to extract the Issuer and propagate that around as the origin site along
- // with the statement and attribute assertions.
- conf->getSessionCache()->insert(
- cookie.c_str(),
- app,
- argp->client_addr,
- SAML_11_POST, // TODO: need to vary this
- oname.get(),
- as,
- (attributesPushed ? bpr.response : NULL),
- role
- );
- }
- catch (SAMLException& e) {
- log.error ("caught SAML exception during cache insertion: %s", e.what());
- delete as;
- ostringstream os;
- os << e;
- bpr.clear();
- if (origin) XMLString::release(&origin);
- ShibTargetException ex(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), role);
- set_rpc_status(&result->status, ex);
- return TRUE;
- }
+ // It passes all our tests -- create a new session.
+ log.info("creating new session");
+
+ // Create a new session key.
+ string cookie = conf->getSessionCache()->generateKey();
+
+ // Are attributes present?
+ bool attributesPushed=false;
+ Iterator<SAMLAssertion*> assertions=bpr.response->getAssertions();
+ while (!attributesPushed && assertions.hasNext()) {
+ Iterator<SAMLStatement*> statements=assertions.next()->getStatements();
+ while (!attributesPushed && statements.hasNext()) {
+ if (dynamic_cast<SAMLAttributeStatement*>(statements.next()))
+ attributesPushed=true;
+ }
+ }
+
+ auto_ptr_char oname(role->getEntityDescriptor()->getId());
+ auto_ptr_char hname(bpr.authnStatement->getSubject()->getNameIdentifier()->getName());
+
+ try {
+ // Insert into cache.
+ auto_ptr<SAMLAuthenticationStatement> as(static_cast<SAMLAuthenticationStatement*>(bpr.authnStatement->clone()));
+ conf->getSessionCache()->insert(
+ cookie.c_str(),
+ app,
+ argp->client_addr,
+ (bpr.profile==SAMLBrowserProfile::Post) ? SAML11_POST : SAML11_ARTIFACT,
+ oname.get(),
+ as.get(),
+ (attributesPushed ? bpr.response : NULL),
+ role
+ );
+ as.release(); // owned by cache now
+ }
+ catch (SAMLException& e) {
+ bpr.clear();
+ log.error("caught SAML exception: %s", e.what());
+ ostringstream os;
+ os << e;
+ result->status = strdup(os.str().c_str());
+ return TRUE;
+ }
#ifndef _DEBUG
- catch (...) {
- log.error ("caught unknown exception during cache insertion");
- delete as;
- bpr.clear();
- if (origin) XMLString::release(&origin);
- set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "An unknown exception occurred");
- return TRUE;
- }
+ catch (...) {
+ log.error("unknown error");
+ bpr.clear();
+ SAMLException e("An unexpected error occurred while creating your session.");
+ annotateException(e,role,false);
+ ostringstream os;
+ os << e;
+ result->status = strdup(os.str().c_str());
+ return TRUE;
+ }
#endif
-
- // And let the user know.
- if (result->cookie) free(result->cookie);
- if (result->target) free(result->target);
- result->cookie = strdup(cookie.c_str());
- result->target = strdup(bpr.TARGET.c_str());
- set_rpc_status(&result->status, SHIBRPC_OK);
-
- // Maybe delete the response...
- if (!attributesPushed)
- bpr.clear();
-
- log.debug("new session id: %s", cookie.c_str());
-
- // Transaction Logging
- STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
- auto_ptr_char hname(as->getSubject()->getNameIdentifier()->getName());
- stc.getTransactionLog().infoStream() <<
- "New session (ID: " <<
- result->cookie <<
- ") with (applicationId: " <<
- argp->application_id <<
- ") for principal from (IdP: " <<
- oname.get() <<
- ") at (ClientAddress: " <<
- argp->client_addr <<
- ") with (NameIdentifier: " <<
- hname.get() <<
- ")";
-
- stc.releaseTransactionLog();
-
- // Delete the origin...
- if (origin) XMLString::release(&origin);
- return TRUE;
+ // And let the user know.
+ if (result->cookie) free(result->cookie);
+ if (result->target) free(result->target);
+ result->cookie = strdup(cookie.c_str());
+ result->target = strdup(bpr.TARGET.c_str());
+ result->status = strdup("");
+
+ // Maybe delete the response...
+ if (!attributesPushed)
+ bpr.clear();
+
+ log.debug("new session id: %s", cookie.c_str());
+
+ // Transaction Logging
+ STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
+ stc.getTransactionLog().infoStream() <<
+ "New session (ID: " <<
+ result->cookie <<
+ ") with (applicationId: " <<
+ argp->application_id <<
+ ") for principal from (IdP: " <<
+ oname.get() <<
+ ") at (ClientAddress: " <<
+ argp->client_addr <<
+ ") with (NameIdentifier: " <<
+ hname.get() <<
+ ")";
+
+ stc.releaseTransactionLog();
+ return TRUE;
}
extern "C" int
bool_t
-xdr_ShibRpcStatus (XDR *xdrs, ShibRpcStatus *objp)
-{
- register int32_t *buf;
-
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_ShibRpcErr (XDR *xdrs, ShibRpcErr *objp)
-{
- register int32_t *buf;
-
- if (!xdr_string (xdrs, &objp->error, ~0))
- return FALSE;
- if (!xdr_string (xdrs, &objp->provider, ~0))
- return FALSE;
- if (!xdr_string (xdrs, &objp->url, ~0))
- return FALSE;
- if (!xdr_string (xdrs, &objp->contact, ~0))
- return FALSE;
- if (!xdr_string (xdrs, &objp->email, ~0))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_ShibRpcError (XDR *xdrs, ShibRpcError *objp)
-{
- register int32_t *buf;
-
- if (!xdr_ShibRpcStatus (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case SHIBRPC_OK:
- break;
- default:
- if (!xdr_ShibRpcErr (xdrs, &objp->ShibRpcError_u.e))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
xdr_ShibProfile (XDR *xdrs, ShibProfile *objp)
{
register int32_t *buf;
{
register int32_t *buf;
- if (!xdr_ShibRpcError (xdrs, &objp->status))
+ if (!xdr_string (xdrs, &objp->status, ~0))
return FALSE;
if (!xdr_string (xdrs, &objp->target, ~0))
return FALSE;
{
register int32_t *buf;
- if (!xdr_ShibRpcError (xdrs, &objp->status))
+ if (!xdr_string (xdrs, &objp->status, ~0))
return FALSE;
if (!xdr_ShibProfile (xdrs, &objp->profile))
return FALSE;
#endif
-enum ShibRpcStatus {
- SHIBRPC_OK = 0,
- SHIBRPC_UNKNOWN_ERROR = 1,
- SHIBRPC_INTERNAL_ERROR = 2,
- SHIBRPC_XML_EXCEPTION = 3,
- SHIBRPC_SAX_EXCEPTION = 4,
- SHIBRPC_SAML_EXCEPTION = 5,
- SHIBRPC_NO_SESSION = 10,
- SHIBRPC_SESSION_EXPIRED = 11,
- SHIBRPC_IPADDR_MISMATCH = 12,
- SHIBRPC_IPADDR_MISSING = 20,
- SHIBRPC_RESPONSE_MISSING = 21,
- SHIBRPC_ASSERTION_REPLAYED = 22,
-};
-typedef enum ShibRpcStatus ShibRpcStatus;
-
-struct ShibRpcErr {
- char *error;
- char *provider;
- char *url;
- char *contact;
- char *email;
-};
-typedef struct ShibRpcErr ShibRpcErr;
-
-struct ShibRpcError {
- ShibRpcStatus status;
- union {
- ShibRpcErr e;
- } ShibRpcError_u;
-};
-typedef struct ShibRpcError ShibRpcError;
-
enum ShibProfile {
PROFILE_UNSPECIFIED = 0,
- SAML_10_POST = 1,
- SAML_10_ARTIFACT = 2,
- SAML_11_POST = 4,
- SAML_11_ARTIFACT = 8,
- SAML_20_SSO = 16,
+ SAML10_POST = 1,
+ SAML10_ARTIFACT = 2,
+ SAML11_POST = 4,
+ SAML11_ARTIFACT = 8,
+ SAML20_SSO = 16,
};
typedef enum ShibProfile ShibProfile;
typedef struct shibrpc_new_session_args_2 shibrpc_new_session_args_2;
struct shibrpc_new_session_ret_2 {
- ShibRpcError status;
+ char *status;
char *target;
char *cookie;
};
typedef struct shibrpc_get_session_args_2 shibrpc_get_session_args_2;
struct shibrpc_get_session_ret_2 {
- ShibRpcError status;
+ char *status;
ShibProfile profile;
char *provider_id;
char *auth_statement;
/* the xdr functions */
#if defined(__STDC__) || defined(__cplusplus)
-extern bool_t xdr_ShibRpcStatus (XDR *, ShibRpcStatus*);
-extern bool_t xdr_ShibRpcErr (XDR *, ShibRpcErr*);
-extern bool_t xdr_ShibRpcError (XDR *, ShibRpcError*);
extern bool_t xdr_ShibProfile (XDR *, ShibProfile*);
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_ret_2 (XDR *, shibrpc_get_session_ret_2*);
#else /* K&R C */
-extern bool_t xdr_ShibRpcStatus ();
-extern bool_t xdr_ShibRpcErr ();
-extern bool_t xdr_ShibRpcError ();
extern bool_t xdr_ShibProfile ();
extern bool_t xdr_shibrpc_new_session_args_2 ();
extern bool_t xdr_shibrpc_new_session_ret_2 ();
%
#endif
-enum ShibRpcStatus {
- SHIBRPC_OK = 0,
- SHIBRPC_UNKNOWN_ERROR = 1,
- SHIBRPC_INTERNAL_ERROR = 2,
- SHIBRPC_XML_EXCEPTION = 3,
- SHIBRPC_SAX_EXCEPTION = 4,
- SHIBRPC_SAML_EXCEPTION = 5,
-
- /* session_is_valid errors */
- SHIBRPC_NO_SESSION = 10,
- SHIBRPC_SESSION_EXPIRED = 11,
- SHIBRPC_IPADDR_MISMATCH = 12,
-
- /* new_session errors */
- SHIBRPC_IPADDR_MISSING = 20,
- SHIBRPC_RESPONSE_MISSING = 21,
- SHIBRPC_ASSERTION_REPLAYED = 22
-
- /* get_attrs errors */
-};
-
-/* Hold an error, providerId, and support data */
-struct ShibRpcErr {
- string error<>;
- string provider<>;
- string url<>;
- string contact<>;
- string email<>;
-};
-
-/* A type for RPC Errors */
-union ShibRpcError switch(ShibRpcStatus status) {
- case SHIBRPC_OK:
- void;
- default:
- ShibRpcErr e;
-};
-
/* enumerate profiles/bindings to support */
enum ShibProfile {
PROFILE_UNSPECIFIED = 0,
- SAML_10_POST = 1,
- SAML_10_ARTIFACT = 2,
- SAML_11_POST = 4,
- SAML_11_ARTIFACT = 8,
- SAML_20_SSO = 16
+ SAML10_POST = 1,
+ SAML10_ARTIFACT = 2,
+ SAML11_POST = 4,
+ SAML11_ARTIFACT = 8,
+ SAML20_SSO = 16
};
/* function argument and response structures */
};
struct shibrpc_new_session_ret_2 {
- ShibRpcError status;
+ string status<>; /* empty string or a SAMLException */
string target<>; /* profile-specific state token from client */
string cookie<>; /* session key manufactured for client */
};
};
struct shibrpc_get_session_ret_2 {
- ShibRpcError status;
+ string status<>; /* empty string or a SAMLException */
ShibProfile profile; /* profile used in creating session */
string provider_id<>; /* authenticating IdP */
string auth_statement<>; /* SAML authn statement */
# End Source File
# Begin Source File
+SOURCE=.\hresult.h
+# End Source File
+# Begin Source File
+
SOURCE=.\internal.h
# End Source File
# Begin Source File
# End Source File
# Begin Source File
-SOURCE=".\shib-rpcerror.cpp"
-# End Source File
-# Begin Source File
-
SOURCE=".\shib-rpchandle.cpp"
# End Source File
# Begin Source File