return NULL;
}
- virtual void* sendPage(const string &msg, const string content_type,
- const pair<string, string> headers[], int code) {
+ virtual void* sendPage(
+ const string &msg,
+ const string content_type,
+ const saml::Iterator<header_t>& headers=EMPTY(header_t),
+ int code=200
+ ) {
m_req->content_type = ap_psprintf(m_req->pool, content_type.c_str());
- // XXX: push headers and code into the response
+ while (headers.hasNext()) {
+ const header_t& h=headers.next();
+ ap_table_setn(m_req->headers_out, h.first.c_str(), h.second.c_str());
+ }
ap_send_http_header(m_req);
ap_rprintf(m_req, msg.c_str());
return (void*)DONE;
#endif
ShibTargetApache sta(r);
- pair<bool,void*> res = sta.doHandlePOST();
+ pair<bool,void*> res = sta.doHandleProfile();
if (res.first) return (int)res.second;
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r),
- "doHandlePOST() did not do anything.");
+ "doHandleProfile() did not do anything.");
return SERVER_ERROR;
#ifndef _DEBUG
class ShibTargetIsapiF : public ShibTarget
{
public:
- ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPRC_HEADERS pn,
+ ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn,
const site_t& site) {
// URL path always come from IIS.
~ShibTargetIsapiF() { }
virtual void log(ShibLogLevel level, const string &msg) {
- LogEvent(NULL, (level == LogLevelDebug : EVENTLOG_DEBUG_TYPE ?
- (level == LogLevelInfo : EVENTLOG_INFORMATION_TYPE ?
- (level == LogLevelWarn : EVENTLOG_WARNING_TYPE ?
- EVENTLOG_ERROR_TYPE))),
+ LogEvent(NULL, (level == LogLevelDebug ? EVENTLOG_INFORMATION_TYPE :
+ (level == LogLevelInfo ? EVENTLOG_INFORMATION_TYPE :
+ (level == LogLevelWarn ? EVENTLOG_WARNING_TYPE : EVENTLOG_ERROR_TYPE))),
2100, NULL, msg.c_str());
}
virtual string getCookies(void) {
dynabuf buf(128);
GetHeader(m_pn, m_pfc, "Cookie:", buf, 128, false);
+ return buf.empty() ? "" : buf;
}
- // XXX: the filter never processes the POST.
- //virtual void setCookie(const string &name, const string &value) { }
- //virtual string getArgs(void) { }
- //virtual string getPostData(void) { }
+
virtual void clearHeader(const string &name) {
string hdr = name + ":";
m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), "");
virtual string getHeader(const string &name) {
string hdr = name + ":";
dynabuf buf(1024);
- GetHeader(m_pn, m_pfc, hdr.c_str(), buf, 1024, false);
+ GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 1024, false);
return string(buf);
}
virtual void setRemoteUser(const string &user) {
return getHeader(string("remote-user"));
}
virtual void* sendPage(const string &msg, const string content_type,
- const pair<string, string> headers[], int code) {
+ const Iterator<header_t>& headers=EMPTY(header_t), int code=200) {
string hdr = string ("Connection: close\r\nContent-type: ") + content_type + "\r\n";
- for (int k = 0; k < headers.size(); k++) {
- hdr += headers[k].first + ": " + headers[k].second + "\r\n";
+ while (headers.hasNext()) {
+ const header_t& h=headers.next();
+ hdr += h.first + ": " + h.second + "\r\n";
}
hdr += "\r\n";
// XXX Need to handle "code"
- m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "200 OK",
- (dword)hdr.c_str(), 0);
+ m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "200 OK", (DWORD)hdr.c_str(), 0);
DWORD resplen = msg.size();
m_pfc->WriteClient(m_pfc, (LPVOID)msg.c_str(), &resplen, 0);
return (void*)SF_STATUS_REQ_FINISHED;
static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
DWORD resplen=40;
m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
- return SF_STATUS_REQ_FINISHED;
+ return reinterpret_cast<void*>(SF_STATUS_REQ_FINISHED);
}
// XXX: We might not ever hit the 'decline' status in this filter.
//virtual void* returnDecline(void) { }
virtual void* returnOK(void) { return (void*) SF_STATUS_REQ_NEXT_NOTIFICATION; }
+ // The filter never processes the POST, so stub these methods.
+ virtual void setCookie(const string &name, const string &value) { throw runtime_error("setCookie not implemented"); }
+ virtual string getArgs(void) { throw runtime_error("getArgs not implemented"); }
+ virtual string getPostData(void) { throw runtime_error("getPostData not implemented"); }
+
PHTTP_FILTER_CONTEXT m_pfc;
- PHTTP_FILTER_PREPRC_HEADERS m_pn
+ PHTTP_FILTER_PREPROC_HEADERS m_pn;
};
DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
ShibTargetIsapiF stf(pfc, pn, map_i->second);
// "false" because we don't override the Shib settings
- pair<bool,void*> res = ste.doCheckAuthN();
+ pair<bool,void*> res = stf.doCheckAuthN();
if (res.first) return (DWORD)res.second;
// "false" because we don't override the Shib settings
- res = ste.doExportAssertions();
+ res = stf.doExportAssertions();
if (res.first) return (DWORD)res.second;
- res = ste.doCheckAuthZ();
+ res = stf.doCheckAuthZ();
if (res.first) return (DWORD)res.second;
return SF_STATUS_REQ_NEXT_NOTIFICATION;
/****************************************************************************/
// ISAPI Extension
+DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
+{
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
+ static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+ lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
+ static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
+ DWORD resplen=strlen(xmsg);
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
+ resplen=strlen(msg);
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
+ static const char* xmsg2="</BODY></HTML>";
+ resplen=strlen(xmsg2);
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);
+ return HSE_STATUS_SUCCESS;
+}
+
+
class ShibTargetIsapiE : public ShibTarget
{
public:
~ShibTargetIsapiE() { }
virtual void log(ShibLogLevel level, const string &msg) {
- LogEvent(NULL, (level == LogLevelDebug : EVENTLOG_DEBUG_TYPE ?
- (level == LogLevelInfo : EVENTLOG_INFORMATION_TYPE ?
- (level == LogLevelWarn : EVENTLOG_WARNING_TYPE ?
- EVENTLOG_ERROR_TYPE))),
+ LogEvent(NULL, (level == LogLevelDebug ? EVENTLOG_INFORMATION_TYPE :
+ (level == LogLevelInfo ? EVENTLOG_INFORMATION_TYPE :
+ (level == LogLevelWarn ? EVENTLOG_WARNING_TYPE : EVENTLOG_ERROR_TYPE))),
2100, NULL, msg.c_str());
}
- // Not used in the extension.
- //virtual string getCookies(void) { }
virtual void setCookie(const string &name, const string &value) {
// Set the cookie for later. Use it during the redirect.
m_cookie += "Set-Cookie: " + name + "=" + value + "\r\n";
if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
throw ShibTargetException(SHIBRPC_OK,
"blocked too-large a post to SHIRE POST processor");
- else if (m_lpECB->cbTotalBytes != lpECB->cbAvailable) {
+ else if (m_lpECB->cbTotalBytes != m_lpECB->cbAvailable) {
string cgistr;
char buf[8192];
DWORD datalen=m_lpECB->cbTotalBytes;
else
return string(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
}
- // Not used in the Extension
- //virtual void clearHeader(const string &name) { }
- //virtual void setHeader(const string &name, const string &value) { }
- //virtual string getHeader(const string &name) { }
- //virtual void setRemoteUser(const string &user) { }
- //virtual string getRemoteUser(void) { }
virtual void* sendPage(const string &msg, const string content_type,
- const pair<string, string> headers[], int code) {
+ const Iterator<header_t>& headers=EMPTY(header_t), int code=200) {
string hdr = string ("Connection: close\r\nContent-type: ") + content_type + "\r\n";
for (int k = 0; k < headers.size(); k++) {
hdr += headers[k].first + ": " + headers[k].second + "\r\n";
hdr += "\r\n";
// XXX Need to handle "code"
m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
- "200 OK", (LPDWORD)hdr.c_str());
+ "200 OK", 0, (LPDWORD)hdr.c_str());
DWORD resplen = msg.size();
m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)msg.c_str(), &resplen, HSE_IO_SYNC);
return (void*)HSE_STATUS_SUCCESS;
}
virtual void* returnOK(void) { return (void*) HSE_STATUS_SUCCESS; }
+ // Not used in the extension.
+ virtual string getCookies(void) { throw runtime_error("getCookies not implemented"); }
+ virtual void clearHeader(const string &name) { throw runtime_error("clearHeader not implemented"); }
+ virtual void setHeader(const string &name, const string &value) { throw runtime_error("setHeader not implemented"); }
+ virtual string getHeader(const string &name) { throw runtime_error("getHeader not implemented"); }
+ virtual void setRemoteUser(const string &user) { throw runtime_error("setRemoteUser not implemented"); }
+ virtual string getRemoteUser(void) { throw runtime_error("getRemoteUser not implemented"); }
+
LPEXTENSION_CONTROL_BLOCK m_lpECB;
string m_cookie;
};
-DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
-{
- LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
- lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
- static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
- DWORD resplen=strlen(xmsg);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
- resplen=strlen(msg);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
- static const char* xmsg2="</BODY></HTML>";
- resplen=strlen(xmsg2);
- lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);
- return HSE_STATUS_SUCCESS;
-}
-
extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
{
string targeturl;
return WriteClientError(lpECB, "Shibboleth Extension not configured for this web site.");
ShibTargetIsapiE ste(lpECB, map_i->second);
- pair<bool,void*> res = ste.doHandlePOST();
+ pair<bool,void*> res = ste.doHandleProfile();
if (res.first) return (DWORD)res.second;
return WriteClientError(lpECB, "Shibboleth Extension failed to process POST");
# define FD_SETSIZE 1024
#endif
-extern "C" void shibrpc_prog_1(struct svc_req* rqstp, register SVCXPRT* transp);
+extern "C" void shibrpc_prog_2(struct svc_req* rqstp, register SVCXPRT* transp);
int shar_run = 1;
const char* shar_config = NULL;
{
static IListener::ShibSocket sock;
ShibRPCProtocols protos[1] = {
- { SHIBRPC_PROG, SHIBRPC_VERS_1, shibrpc_prog_1 }
+ { SHIBRPC_PROG, SHIBRPC_VERS_2, shibrpc_prog_2 }
};
ShibTargetConfig& conf=ShibTargetConfig::getConfig();
return -2;
}
- CLIENT* clnt = listener->getClientHandle(sock,SHIBRPC_PROG, SHIBRPC_VERS_1);
+ CLIENT* clnt = listener->getClientHandle(sock,SHIBRPC_PROG, SHIBRPC_VERS_2);
if (!clnt) {
clnt_pcreateerror("shibrpc_client_create");
cerr << "shibrpc_client_create failed\n";
}
res = start = 0;
- clnt_stat = shibrpc_ping_1 (&start, &res, clnt);
+ clnt_stat = shibrpc_ping_2 (&start, &res, clnt);
if (clnt_stat != RPC_SUCCESS) {
clnt_perror (clnt, "rpc");
# PROP BASE Output_Dir "testclient___Win32_Debug"\r
# PROP BASE Intermediate_Dir "testclient___Win32_Debug"\r
# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
+# PROP Use_MFC 2\r
# PROP Use_Debug_Libraries 1\r
# PROP Output_Dir "testclient___Win32_Debug"\r
# PROP Intermediate_Dir "testclient___Win32_Debug"\r
# PROP Ignore_Export_Lib 0\r
# PROP Target_Dir ""\r
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "../oncrpc" /I "..\..\..\opensaml\c" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "../oncrpc" /I "..\..\..\opensaml\c" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_AFXDLL" /FR /YX /FD /GZ /c\r
# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"\r
BSC32=bscmake.exe\r
# ADD BASE BSC32 /nologo\r
# ADD BSC32 /nologo\r
virtual void unlock() { m_cacheEntry->unlock(); delete this; }
virtual bool isValid(time_t lifetime, time_t timeout) const;
virtual const char* getClientAddress() const { return m_cacheEntry->getClientAddress(); }
- virtual const char* getSerializedStatement() const { return m_cacheEntry->getSerializedStatement(); }
- virtual const SAMLAuthenticationStatement* getStatement() const { return m_cacheEntry->getStatement(); }
+ virtual const SAMLAuthenticationStatement* getAuthnStatement() const { return m_cacheEntry->getAuthnStatement(); }
virtual Iterator<SAMLAssertion*> getAssertions() { return m_cacheEntry->getAssertions(); }
- virtual void preFetch(int prefetch_window) { m_cacheEntry->preFetch(prefetch_window); }
private:
bool touch() const;
shib-config.cpp \
shib-ini.cpp \
shib-mlp.cpp \
- shib-rm.cpp \
shib-rpcerror.cpp \
shib-rpchandle.cpp \
shib-sock.cpp \
bool isValid(time_t lifetime, time_t timeout) const;
const char* getClientAddress() const { return m_clientAddress.c_str(); }
- const char* getSerializedStatement() const { return m_statement.c_str(); }
- const SAMLAuthenticationStatement* getStatement() const { return p_auth; }
-
+ const SAMLAuthenticationStatement* getAuthnStatement() const { return p_auth; }
Iterator<SAMLAssertion*> getAssertions();
- void preFetch(int prefetch_window);
void setCache(InternalCCache *cache) { m_cache = cache; }
time_t lastAccess() const { return m_lastAccess; }
bool checkApplication(const IApplication* application) { return (m_application_id==application->getId()); }
private:
- bool responseValid(int slop);
- void populate(int slop);
- SAMLResponse* getNewResponse();
+ void populate(); // wraps process of checking cache, and repopulating if need be
+ bool responseValid(); // checks validity of existing response
+ SAMLResponse* getNewResponse(); // wraps an actual query
+
+ void filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source);
string m_id;
string m_application_id;
- string m_statement;
string m_originSite;
string m_clientAddress;
time_t m_sessionCreated;
/******************************************************************************/
InternalCCacheEntry::InternalCCacheEntry(
- const char* id, const IApplication* application, SAMLAuthenticationStatement *s, const char* client_addr, SAMLResponse* r, const IRoleDescriptor* source
+ const char* id,
+ const IApplication* application,
+ SAMLAuthenticationStatement *s,
+ const char* client_addr,
+ SAMLResponse* r,
+ const IRoleDescriptor* source
) : m_response(r), m_responseCreated(r ? time(NULL) : 0), m_lastRetry(0),
log(&Category::getInstance("shibtarget::InternalCCacheEntry"))
{
// Save for later.
p_auth = s;
- // Save the serialized version of the auth statement
- ostringstream os;
- os << *s;
- m_statement = os.str();
-
- if (r) {
- // Run pushed data through the AAP. Note that we could end up with an empty response!
- Iterator<SAMLAssertion*> assertions=r->getAssertions();
- for (unsigned long i=0; i < assertions.size();) {
- try {
- AAP::apply(application->getAAPProviders(),*(assertions[i]),source);
- i++;
- }
- catch (SAMLException&) {
- log->info("no statements remain, removing assertion");
- r->removeAssertion(i);
- }
- }
- }
+ // If pushing attributes, filter the response.
+ if (r)
+ filter(r, application, source);
m_lock = Mutex::create();
bool InternalCCacheEntry::isValid(time_t lifetime, time_t timeout) const
{
+#ifdef _DEBUG
saml::NDC ndc("isValid");
- log->debug("testing session (ID: %s) (lifetime=%ld, timeout=%ld)", m_id.c_str(), lifetime, timeout);
+#endif
+
+ log->debug("testing session (ID: %s) (lifetime=%ld, timeout=%ld)",
+ m_id.c_str(), lifetime, timeout);
+
time_t now=time(NULL);
if (lifetime > 0 && now > m_sessionCreated+lifetime) {
- log->debug("session beyond lifetime (ID: %s)", m_id.c_str());
+ log->info("session beyond lifetime (ID: %s)", m_id.c_str());
return false;
}
if (timeout > 0 && now-m_lastAccess >= timeout) {
- log->debug("session timed out (ID: %s)", m_id.c_str());
+ log->info("session timed out (ID: %s)", m_id.c_str());
return false;
}
m_lastAccess=now;
Iterator<SAMLAssertion*> InternalCCacheEntry::getAssertions()
{
+#ifdef _DEBUG
saml::NDC ndc("getAssertions");
- populate(0);
+#endif
+ populate();
return (m_response) ? m_response->getAssertions() : EMPTY(SAMLAssertion*);
}
-void InternalCCacheEntry::preFetch(int prefetch_window)
-{
- saml::NDC ndc("preFetch");
- populate(prefetch_window);
-}
-
-bool InternalCCacheEntry::responseValid(int slop)
+bool InternalCCacheEntry::responseValid()
{
+#ifdef _DEBUG
saml::NDC ndc("responseValid");
-
- log->debug("checking AA response validity");
+#endif
+ log->debug("checking attribute data validity");
+ time_t now=time(NULL) - SAMLConfig::getConfig().clock_skew_secs;
int count = 0;
Iterator<SAMLAssertion*> iter = m_response->getAssertions();
count++;
- if (time(NULL)+slop >= thistime->getEpoch()) {
+ if (now >= thistime->getEpoch()) {
log->debug("nope, not still valid");
return false;
}
// If we didn't find any assertions with times, then see if we're
// older than the default response lifetime.
if (!count) {
- if ((time(NULL)+slop - m_responseCreated) > m_cache->m_defaultLifetime) {
+ if ((now - m_responseCreated) > m_cache->m_defaultLifetime) {
log->debug("response is beyond default life, so it's invalid");
return false;
}
return true;
}
-void InternalCCacheEntry::populate(int slop)
+void InternalCCacheEntry::populate()
{
+#ifdef _DEBUG
saml::NDC ndc("populate");
+#endif
log->debug("populating attributes for session (ID: %s)", m_id.c_str());
// Do we have any data cached?
if (m_response) {
// Can we use what we have?
- if (responseValid(slop))
+ if (responseValid())
return;
// If we're being strict, dump what we have and reset timestamps.
}
}
- // Need to try and get a new response.
-
try {
-
// Transaction Logging
STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
stc.getTransactionLog().infoStream() <<
SAMLResponse* InternalCCacheEntry::getNewResponse()
{
+#ifdef _DEBUG
saml::NDC ndc("getNewResponse");
+#endif
// The retryInterval determines how often to poll an AA that might be down.
- if ((time(NULL) - m_lastRetry) < m_cache->m_retryInterval)
+ time_t now=time(NULL);
+ if ((now - m_lastRetry) < m_cache->m_retryInterval)
return NULL;
if (m_lastRetry)
log->debug("retry interval exceeded, so trying again");
- m_lastRetry=time(NULL);
+ m_lastRetry=now;
log->info("trying to get new attributes for session (ID=%s)", m_id.c_str());
throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to determine ProviderID for application, not set?");
}
- // Get signing policies.
+ // Get protocol signing policy.
pair<bool,bool> signRequest=application->getBool("signRequest");
pair<bool,bool> signedResponse=application->getBool("signedResponse");
- pair<bool,bool> signedAssertions=application->getBool("signedAssertions");
// Try this request. The binding wrapper class handles most of the details.
Metadata m(application->getMetadataProviders());
throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate metadata for identity provider's Attribute Authority.",site);
}
-
SAMLResponse* response = NULL;
try {
// Build a SAML Request....
bindconf.conn_timeout=m_cache->m_AAConnectTimeout;
ShibBinding binding(application->getRevocationProviders(),application->getTrustProviders(),conf->getCredentialsProviders());
response=binding.send(*req,AA,application->getTLSCred(site),application->getAudiences(),p_auth->getBindings(),bindconf);
+
+ if (signedResponse.first && signedResponse.second && !response->isSigned()) {
+ delete response;
+ response=NULL;
+ log->error("unsigned response obtained, but we were told it must be signed.");
+ }
+ else {
+ // Run it through the filter. Note that we could end up with an empty response.
+ filter(response,application,AA);
+ }
}
catch (SAMLException& e) {
log->error("caught SAML exception during query to AA: %s", e.what());
// See if we got a response.
if (!response) {
log->error("no response obtained");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's origin site.",AA);
- }
- else if (signedResponse.first && signedResponse.second && !response->isSigned()) {
- delete response;
- log->error("unsigned response obtained, but we were told it must be signed.");
- throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's origin site.",AA);
+ throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's identity provider.",AA);
}
+ return response;
+}
+
+void InternalCCacheEntry::filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source)
+{
+ Trust t(application->getTrustProviders());
+ pair<bool,bool> signedAssertions=application->getBool("signedAssertions");
- // Run it through the AAP. Note that we could end up with an empty response!
- Iterator<SAMLAssertion*> a=response->getAssertions();
- for (unsigned long i=0; i < a.size();) {
+ // Examine each new assertion...
+ Iterator<SAMLAssertion*> assertions=r->getAssertions();
+ for (unsigned long i=0; i < assertions.size();) {
try {
- if (signedAssertions.first && signedAssertions.second && !(a[i]->isSigned())) {
+ // Check signing policy.
+ if (signedAssertions.first && signedAssertions.second && !(assertions[i]->isSigned())) {
log->warn("removing unsigned assertion from response, in accordance with signedAssertions policy");
- response->removeAssertion(i);
+ r->removeAssertion(i);
continue;
}
- AAP::apply(application->getAAPProviders(),*(a[i]),AA);
+
+ // Check any conditions.
+ bool pruned=false;
+ Iterator<SAMLCondition*> conds=assertions[i]->getConditions();
+ while (conds.hasNext()) {
+ SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
+ if (!cond || !cond->eval(application->getAudiences())) {
+ log->warn("assertion condition invalid, removing it");
+ r->removeAssertion(i);
+ pruned=true;
+ break;
+ }
+ }
+ if (pruned)
+ continue;
+
+ // Check token signature.
+ if (assertions[i]->isSigned() && !t.validate(application->getRevocationProviders(),source,*(assertions[i]))) {
+ log->warn("signed assertion failed to validate, removing it");
+ r->removeAssertion(i);
+ continue;
+ }
+
+ // Finally, filter the content.
+ AAP::apply(application->getAAPProviders(),*(assertions[i]),source);
i++;
}
catch (SAMLException&) {
- log->info("no statements remain, removing assertion");
- response->removeAssertion(i);
+ log->info("no statements remain after AAP, removing assertion");
+ r->removeAssertion(i);
}
}
-
- return response;
}
return false;
}
+#ifndef _DEBUG
try {
+#endif
// Register plugin types.
#ifndef WIN32
samlConf.m_plugMgr.regFactory(shibtarget::XML::UnixListenerType,&UnixListenerFactory);
m_tranLogLock = Mutex::create();
m_rpcpool = new RPCHandlePool;
+#ifndef _DEBUG
}
catch (...) {
log.fatal("caught exception while loading/initializing configuration");
samlConf.term();
return false;
}
+#endif
log.info("finished initializing");
class XMLApplication : public virtual IApplication, public XMLPropertySet, public DOMNodeFilter
{
public:
- XMLApplication(const DOMElement* e, const XMLApplication* base=NULL);
+ XMLApplication(const IConfig*, const DOMElement* e, const XMLApplication* base=NULL);
~XMLApplication();
// IPropertySet
Iterator<const XMLCh*> getAudiences() const;
const char* getTLSCred(const IEntityDescriptor* provider) const {return getCredentialUse(provider).first.c_str();}
const char* getSigningCred(const IEntityDescriptor* provider) const {return getCredentialUse(provider).second.c_str();}
+ SAMLBrowserProfile* getBrowserProfile() const {return m_profile;}
// Provides filter to exclude special config elements.
short acceptNode(const DOMNode* node) const;
private:
+ const IConfig* m_ini; // this is ok because its locking scope includes us
const XMLApplication* m_base;
vector<SAMLAttributeDesignator*> m_designators;
vector<IAAP*> m_aaps;
vector<IRevocation*> m_revocations;
vector<const XMLCh*> m_audiences;
pair<string,string> m_credDefault;
+ ShibBrowserProfile* m_profile;
#ifdef HAVE_GOOD_STL
map<xstring,pair<string,string> > m_credMap;
#else
class XMLConfig : public IConfig, public ReloadableXMLFile
{
public:
- XMLConfig(const DOMElement* e) : ReloadableXMLFile(e), m_listener(NULL), m_cache(NULL) {}
- ~XMLConfig() {delete m_listener; delete m_cache;}
+ XMLConfig(const DOMElement* e) : ReloadableXMLFile(e), m_listener(NULL), m_sessionCache(NULL), m_replayCache(NULL) {}
+ ~XMLConfig() {delete m_listener; delete m_sessionCache; delete m_replayCache;}
// IPropertySet
pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return static_cast<XMLConfigImpl*>(m_impl)->getBool(name,ns);}
// IConfig
const IListener* getListener() const {return m_listener;}
- ISessionCache* getSessionCache() const {return m_cache;}
+ ISessionCache* getSessionCache() const {return m_sessionCache;}
+ IReplayCache* getReplayCache() const {return m_replayCache;}
IRequestMapper* getRequestMapper() const {return static_cast<XMLConfigImpl*>(m_impl)->m_requestMapper;}
const IApplication* getApplication(const char* applicationId) const
{
private:
friend class XMLConfigImpl;
mutable IListener* m_listener;
- mutable ISessionCache* m_cache;
+ mutable ISessionCache* m_sessionCache;
+ mutable IReplayCache* m_replayCache;
};
}
return (i!=m_nested.end()) ? i->second : NULL;
}
-XMLApplication::XMLApplication(const DOMElement* e, const XMLApplication* base) : m_base(base)
+XMLApplication::XMLApplication(const IConfig* ini, const DOMElement* e, const XMLApplication* base)
+ : m_ini(ini), m_base(base), m_profile(NULL)
{
NDC ndc("XMLApplication");
Category& log=Category::getInstance("shibtarget.XMLApplication");
cu=saml::XML::getNextSiblingElement(cu,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(RelyingParty));
}
}
+
+ if (conf.isEnabled(ShibTargetConfig::SessionCache)) {
+ // Really finally, build a local browser profile object.
+ m_profile=new ShibBrowserProfile(
+ getMetadataProviders(),
+ getRevocationProviders(),
+ getTrustProviders()
+ );
+ }
}
catch (...) {
this->~XMLApplication(); // does this work?
XMLApplication::~XMLApplication()
{
+ delete m_profile;
Iterator<SAMLAttributeDesignator*> i(m_designators);
while (i.hasNext())
delete i.next();
if (plugin) {
ISessionCache* cache=dynamic_cast<ISessionCache*>(plugin);
if (cache)
- m_outer->m_cache=cache;
+ m_outer->m_sessionCache=cache;
else {
delete plugin;
log.fatal("plugin was not a Session Cache object");
throw UnsupportedExtensionException("plugin was not a Session Cache object");
}
}
+
+ // For now, just default the replay cache.
+ // TODO: make it configurable/pluggable
+ m_outer->m_replayCache=IReplayCache::getInstance();
}
}
}
}
- // Load the default application. This actually has a fixed ID of "default". ;-)
- const DOMElement* app=saml::XML::getFirstChildElement(
- ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Applications)
- );
- if (!app) {
- log.fatal("can't build default Application object, missing conf:Applications element?");
- throw SAMLException("can't build default Application object, missing conf:Applications element?");
- }
- XMLApplication* defapp=new XMLApplication(app);
- m_appmap[defapp->getId()]=defapp;
-
- // Load any overrides.
- DOMNodeList* nlist=app->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Application));
- for (int i=0; nlist && i<nlist->getLength(); i++) {
- XMLApplication* iapp=new XMLApplication(static_cast<DOMElement*>(nlist->item(i)),defapp);
- if (m_appmap.find(iapp->getId())!=m_appmap.end()) {
- log.fatal("found conf:Application element with duplicate Id attribute");
- throw SAMLException("found conf:Application element with duplicate Id attribute");
- }
- m_appmap[iapp->getId()]=iapp;
- }
-
- // Finally we load any credentials providers.
+ // Now we load any credentials providers.
+ DOMNodeList* nlist;
if (conf.isEnabled(ShibTargetConfig::Credentials)) {
nlist=ReloadableXMLFileImpl::m_root->getElementsByTagNameNS(
ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(CredentialsProvider)
}
}
}
+
+ // Load the default application. This actually has a fixed ID of "default". ;-)
+ const DOMElement* app=saml::XML::getFirstChildElement(
+ ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Applications)
+ );
+ if (!app) {
+ log.fatal("can't build default Application object, missing conf:Applications element?");
+ throw SAMLException("can't build default Application object, missing conf:Applications element?");
+ }
+ XMLApplication* defapp=new XMLApplication(m_outer, app);
+ m_appmap[defapp->getId()]=defapp;
+
+ // Load any overrides.
+ nlist=app->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Application));
+ for (int i=0; nlist && i<nlist->getLength(); i++) {
+ XMLApplication* iapp=new XMLApplication(m_outer,static_cast<DOMElement*>(nlist->item(i)),defapp);
+ if (m_appmap.find(iapp->getId())!=m_appmap.end()) {
+ log.fatal("found conf:Application element with duplicate Id attribute");
+ throw SAMLException("found conf:Application element with duplicate Id attribute");
+ }
+ m_appmap[iapp->getId()]=iapp;
+ }
}
catch (SAMLException& e) {
log.errorStream() << "Error while loading target configuration: " << e.what() << CategoryStream::ENDLINE;
throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR, "Cannot connect to SHAR process, target site adminstrator should be notified");
}
- CLIENT *clnt = listener->getClientHandle(sock, SHIBRPC_PROG, SHIBRPC_VERS_1);
+ CLIENT *clnt = listener->getClientHandle(sock, SHIBRPC_PROG, SHIBRPC_VERS_2);
if (!clnt) {
const char* rpcerror = clnt_spcreateerror("RPCHandle::connect");
log->crit("RPC failed for %p: %s", this, rpcerror);
~ShibTargetPriv();
string url_encode(const char* s);
- void get_application(string protocol, string hostname, int port, string uri);
+ void get_application(const string& protocol, const string& hostname, int port, const string& uri);
void* sendError(ShibTarget* st, string page, ShibMLP &mlp);
const char *getSessionId(ShibTarget* st);
- bool get_assertions(ShibTarget *st, const char *session_id, ShibMLP &mlp);
IRequestMapper::Settings m_settings;
const IApplication *m_app;
string m_cookieName;
string m_shireURL;
string m_authnRequest;
- CgiParse* m_parser;
const char *session_id;
string m_cookies;
// The web server modules implement a subclass and then call into
// these methods once they instantiate their request object.
pair<bool,void*>
-ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handlePost)
+ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handleProfile)
{
+#ifdef _DEBUG
saml::NDC ndc("ShibTarget::doCheckAuthN");
+#endif
const char *targetURL = NULL;
const char *procState = "Process Initialization Error";
throw ShibTargetException(SHIBRPC_OK, "Cannot map target URL to Shire URL. Check configuration");
if (strstr(targetURL,shireURL)) {
- if (handlePost)
- return doHandlePOST();
+ if (handleProfile)
+ return doHandleProfile();
else
- return pair<bool,void*>(true, returnOK());
+ return pair<bool,void*>(true, returnOK());
}
string auth_type = getAuthType();
// No session. Maybe that's acceptable?
if (!requireSession.second)
- return pair<bool,void*>(true,returnOK());
+ return pair<bool,void*>(true,returnOK());
// No cookie, but we require a session. Generate an AuthnRequest.
return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
}
procState = "Session Processing Error";
- RPCError *status = sessionIsValid(session_id, m_priv->m_remote_addr.c_str());
+ RPCError *status = sessionGet(session_id, m_priv->m_remote_addr.c_str(), m_priv->m_assertions, &m_priv->m_sso_statement);
if (status->isError()) {
// If no session is required, bail now.
if (!requireSession.second)
- return pair<bool,void*>(true, returnOK());
+ 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
- delete status;
- return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+ // Session is invalid but we can retry the auth -- generate an AuthnRequest
+ delete status;
+ return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
} else {
-
- string er = "Unretryable error: " ;
- er += status->getText();
- log(LogLevelError, er);
- mlp.insert(*status);
- delete status;
- goto out;
+ string er = "Unretryable error: " ;
+ er += status->getText();
+ log(LogLevelError, er);
+ mlp.insert(*status);
+ delete status;
+ goto out;
}
delete status;
-
}
// We're done. Everything is okay. Nothing to report. Nothing to do..
}
pair<bool,void*>
-ShibTarget::doHandlePOST(void)
+ShibTarget::doHandleProfile(void)
{
- saml::NDC ndc("ShibTarget::doHandlePOST");
+#ifdef _DEBUG
+ saml::NDC ndc("ShibTarget::doHandleProfile");
+#endif
const char *targetURL = NULL;
const char *procState = "Session Creation Service Error";
const char *shireURL = getShireURL(targetURL);
if (!shireURL)
- throw ShibTargetException(SHIBRPC_OK, "doHandlePOST: unable to map request to a proper shireURL setting. Check Configuration.");
+ throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to a proper shireURL setting. Check Configuration.");
// Make sure we only process the SHIRE requests.
const IPropertySet* sessionProps=m_priv->m_app->getPropertySet("Sessions");
if (!sessionProps)
- throw ShibTargetException(SHIBRPC_OK, "doHandlePOST: unable to map request to application session settings. Check configuration");
+ throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to application session settings. Check configuration");
// this always returns something
pair<const char*,const char*> shib_cookie=getCookieNameProps();
string args = getArgs();
const char* areq=args.empty() ? NULL : getLazyAuthnRequest(args.c_str());
if (!areq)
- throw ShibTargetException(SHIBRPC_OK, "malformed GET arguments to request a new session");
+ throw ShibTargetException(SHIBRPC_OK, "malformed GET arguments to request a new session");
return pair<bool,void*>(true, sendRedirect(areq));
}
else if (strcasecmp(m_priv->m_method.c_str(), "POST")) {
// Make sure this POST is an appropriate content type
if (m_priv->m_content_type.empty() ||
- strcasecmp(m_priv->m_content_type.c_str(),
- "application/x-www-form-urlencoded")) {
+ strcasecmp(m_priv->m_content_type.c_str(),"application/x-www-form-urlencoded")) {
string er = string("blocked bad content-type to SHIRE POST processor: ") +
- m_priv->m_content_type;
+ m_priv->m_content_type;
throw ShibTargetException(SHIBRPC_OK, er.c_str());
}
// Read the POST Data
string cgistr = getPostData();
- // Parse the submission.
- pair<const char*,const char*> elements =
- getFormSubmission(cgistr.c_str(),cgistr.length());
-
- // Make sure the SAML Response parameter exists
- if (!elements.first || !*elements.first)
- throw ShibTargetException(SHIBRPC_OK, "SHIRE POST failed to find SAMLResponse form element");
-
- // Make sure the target parameter exists
- if (!elements.second || !*elements.second)
- throw ShibTargetException(SHIBRPC_OK, "SHIRE POST failed to find TARGET form element");
-
- // process the post
- string cookie;
- RPCError* status = sessionCreate(elements.first, m_priv->m_remote_addr.c_str(),
- cookie);
+ // process the submission
+ string cookie,target;
+ RPCError* status = sessionNew(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("doHandlePost() POST process failed ") + buf +
- status->getText();
+ string er = string("doHandleProfile() profile processing failed ") + buf + status->getText();
log(LogLevelError, er);
if (status->isRetryable()) {
- delete status;
-
- return pair<bool,void*>(true, sendRedirect(getAuthnRequest(elements.second)));
+ delete status;
+ return pair<bool,void*>(true, sendRedirect(getAuthnRequest(target.c_str())));
}
// return this error to the user.
}
delete status;
- log(LogLevelDebug,
- string("doHandlePost() POST process succeeded. New session: ") + cookie);
+ log(LogLevelDebug, string("doHandleProfile() profile processing succeeded, new session(") + cookie + ")");
// We've got a good session, set the cookie...
cookie += shib_cookie.second;
setCookie(shib_cookie.first, cookie);
// ... and redirect to the target
- return pair<bool,void*>(true, sendRedirect(elements.second));
+ return pair<bool,void*>(true, sendRedirect(target));
} catch (ShibTargetException &e) {
mlp.insert("errorText", e.what());
pair<bool,void*>
ShibTarget::doCheckAuthZ(void)
{
+#ifdef _DEBUG
saml::NDC ndc("ShibTarget::doCheckAuthZ");
+#endif
ShibMLP mlp;
const char *procState = "Authorization Processing Error";
targetURL = m_priv->m_url.c_str();
const char *session_id = m_priv->getSessionId(this);
- // XXX: need to make sure that export assertions was already called.
- //if (m_priv->get_assertions(this, session_id, mlp))
- //goto out;
-
// 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_assertions)) {
- log(LogLevelError, "doCheckAuthZ: access control provider denied access");
- goto out;
+ log(LogLevelError, "doCheckAuthZ: access control provider denied access");
+ goto out;
}
}
auth_OK[x] = false;
HTAccessInfo::RequireLine *line = ht->elements[x];
if (! line->use_line)
- continue;
+ 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;
+ // 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;
+ 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;
- }
+ 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;
- }
- }
+ 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);
+ grpstatus = getGroupTable(remote_user);
- if (!grpstatus) {
- delete ht;
- return pair<bool,void*>(true, returnDecline());
- }
+ 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;
+ 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;
- }
-
- 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;
- }
+ 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;
+ }
- 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;
- }
+ 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");
- 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.");
- }
- }
- }
+ 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.");
+ }
+ }
+ }
- 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());
- }
- }
+ 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
targetURL = m_priv->m_url.c_str();
const char *session_id = m_priv->getSessionId(this);
- if (m_priv->get_assertions(this, session_id, mlp))
- goto out;
+ 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_assertions, &m_priv->m_sso_statement);
+ if (status->isError()) {
+ string er = "getAssertions failed: ";
+ er += status->getText();
+ log(ShibTarget::LogLevelError, er);
+ mlp.insert(*status);
+ delete status;
+ goto out;
+ }
+ delete status;
+ }
// Get the AAP providers, which contain the attribute policy info.
Iterator<IAAP*> provs=m_priv->m_app->getAAPProviders();
IAAP* aap=provs.next();
aap->lock();
try {
- Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
- while (rules.hasNext()) {
- const char* header=rules.next()->getHeader();
- if (header)
- clearHeader(header);
- }
+ Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
+ while (rules.hasNext()) {
+ const char* header=rules.next()->getHeader();
+ if (header)
+ clearHeader(header);
+ }
}
catch(...) {
- aap->unlock();
- log(LogLevelError, "caught unexpected error while clearing headers");
- throw;
+ aap->unlock();
+ log(LogLevelError, "caught unexpected error while clearing headers");
+ throw;
}
aap->unlock();
}
pair<bool,bool> exp=m_priv->m_settings.first->getBool("exportAssertion");
if (!exp.first || !exp.second)
if (exportAssertion)
- exp.second=true;
+ exp.second=true;
if (exp.second && m_priv->m_assertions.size()) {
- string assertion;
- RM::serialize(*(m_priv->m_assertions[0]), assertion);
+ ostringstream os;
+ os << *(m_priv->m_assertions[0]);
+ unsigned int outlen;
+ char* assn = (char*)os.str().c_str();
+ XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(assn), os.str().length(), &outlen);
+ string assertion = (char*)serialized;
+ XMLString::release(&serialized);
setHeader("Shib-Attributes", assertion.c_str());
}
auto_ptr_char nameid(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getName());
setHeader("Shib-NameIdentifier-Format", form.get());
if (!strcmp(wrapper->getHeader(),"REMOTE_USER"))
- setRemoteUser(nameid.get());
+ setRemoteUser(nameid.get());
else
- setHeader(wrapper->getHeader(), nameid.get());
+ setHeader(wrapper->getHeader(), nameid.get());
}
clearHeader("Shib-Application-ID");
return getAuthnRequest(target);
}
-// Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
-std::pair<const char*,const char*>
-ShibTarget::getFormSubmission(const char* post, unsigned int len) const
-{
- m_priv->m_parser = new CgiParse(post,len);
- return pair<const char*,const char*>(m_priv->m_parser->get_value("SAMLResponse"),m_priv->m_parser->get_value("TARGET"));
-}
-
RPCError*
-ShibTarget::sessionCreate(const char* response, const char* ip, std::string &cookie)
+ShibTarget::sessionNew(const char* packet, const char* ip, string& cookie, string& target)
const
{
+#ifdef _DEBUG
saml::NDC ndc("sessionCreate");
- Category& log = Category::getInstance("shibtarget.SHIRE");
+#endif
+ Category& log = Category::getInstance("shibtarget.ShibTarget");
- if (!response || !*response) {
+ if (!packet || !*packet) {
log.error ("Empty SAML response content");
return new RPCError(-1, "Empty SAML response content");
}
return new RPCError(-1, "Invalid IP address");
}
- shibrpc_new_session_args_1 arg;
- arg.shire_location = (char*) m_priv->m_shireURL.c_str();
+ 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.saml_post = (char*)response;
+ arg.packet = (char*)packet;
arg.client_addr = (char*)ip;
arg.checkIPAddress = true;
arg.checkIPAddress = pcheck.second;
}
- shibrpc_new_session_ret_1 ret;
+ shibrpc_new_session_ret_2 ret;
memset (&ret, 0, sizeof(ret));
// Loop on the RPC in case we lost contact the first time through
RPC rpc;
do {
clnt = rpc->connect();
- clnt_stat status = shibrpc_new_session_1 (&arg, &ret, clnt);
+ 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_1"));
+ log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_2"));
rpc->disconnect();
if (retry)
retry--;
else {
log.debug ("new 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_1, (caddr_t)&ret);
+ clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
rpc.pool();
log.debug("returning");
}
RPCError*
-ShibTarget::sessionIsValid(const char* session_id, const char* ip) const
+ShibTarget::sessionGet(
+ const char* cookie,
+ const char* ip,
+ std::vector<saml::SAMLAssertion*>& assertions,
+ saml::SAMLAuthenticationStatement **statement
+ ) const
{
- saml::NDC ndc("sessionIsValid");
- Category& log = Category::getInstance("shibtarget.SHIRE");
+#ifdef _DEBUG
+ saml::NDC ndc("sessionGet");
+#endif
+ Category& log = Category::getInstance("shibtarget.ShibTarget");
- if (!session_id || !*session_id) {
+ if (!cookie || !*cookie) {
log.error ("No cookie value was provided");
return new RPCError(SHIBRPC_NO_SESSION, "No cookie value was provided");
}
- else if (strchr(session_id,'=')) {
+ 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.");
}
return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP Address");
}
- log.info ("is session valid: %s", ip);
- log.debug ("session cookie: %s", session_id);
+ log.info ("get session for client address (%s)", ip);
+ log.debug ("session cookie (%s)", cookie);
- shibrpc_session_is_valid_args_1 arg;
+ shibrpc_get_session_args_2 arg;
- arg.cookie.cookie = (char*)session_id;
- arg.cookie.client_addr = (char *)ip;
- arg.application_id = (char *)m_priv->m_app->getId();
+ arg.cookie = (char*)cookie;
+ arg.client_addr = (char*)ip;
+ arg.application_id = (char*)m_priv->m_app->getId();
// Get rest of input from the application Session properties.
arg.lifetime = 3600;
arg.checkIPAddress = pcheck.second;
}
- shibrpc_session_is_valid_ret_1 ret;
+ shibrpc_get_session_ret_2 ret;
memset (&ret, 0, sizeof(ret));
// Loop on the RPC in case we lost contact the first time through
RPC rpc;
do {
clnt = rpc->connect();
- clnt_stat status = shibrpc_session_is_valid_1(&arg, &ret, clnt);
+ 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_session_is_valid_1"));
+ log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_get_session_2"));
rpc->disconnect();
if (retry)
retry--;
log.debug("RPC completed with status %d, %p", ret.status.status, this);
- RPCError* retval;
- if (ret.status.status)
- retval = new RPCError(&ret.status);
- else
- retval = new RPCError();
-
- clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_session_is_valid_ret_1, (caddr_t)&ret);
- rpc.pool();
-
- log.debug("returning");
- return retval;
-}
-
-// RM APIS
-
-RPCError*
-ShibTarget::getAssertions(const char* cookie, const char* ip,
- std::vector<saml::SAMLAssertion*>& assertions,
- saml::SAMLAuthenticationStatement **statement
- ) const
-{
- saml::NDC ndc("getAssertions");
- Category& log=Category::getInstance("shibtarget.RM");
- log.info("get assertions...");
-
- if (!cookie || !*cookie) {
- log.error ("No cookie value provided.");
- return new RPCError(-1, "No cookie value provided.");
- }
-
- if (!ip || !*ip) {
- log.error ("Invalid ip address");
- return new RPCError(-1, "Invalid IP address");
- }
-
- log.debug("session cookie: %s", cookie);
-
- shibrpc_get_assertions_args_1 arg;
- arg.cookie.cookie = (char*)cookie;
- arg.cookie.client_addr = (char*)ip;
- arg.checkIPAddress = true;
- arg.application_id = (char *)m_priv->m_app->getId();
-
- log.info("request from %s for \"%s\"", ip, arg.application_id);
-
- const IPropertySet* props=m_priv->m_app->getPropertySet("Sessions");
- if (props) {
- pair<bool,bool> pcheck=props->getBool("checkAddress");
- if (pcheck.first)
- arg.checkIPAddress = pcheck.second;
- }
-
- shibrpc_get_assertions_ret_1 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_assertions_1(&arg, &ret, clnt);
- if (status != RPC_SUCCESS) {
- // FAILED. Release, disconnect, and try again.
- log.debug("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_get_assertions_1"));
- rpc->disconnect();
- if (retry)
- retry--;
- else
- return new RPCError(-1, "RPC Failure");
- }
- else {
- // SUCCESS. Release back into pool
- retry = -1;
- }
- } while (retry>=0);
-
- log.debug("RPC completed with status %d (%p)", ret.status.status, this);
-
RPCError* retval = NULL;
if (ret.status.status)
retval = new RPCError(&ret.status);
}
}
catch (SAMLException& e) {
- log.error ("SAML Exception: %s", e.what());
- ostringstream os;
- os << e;
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str());
+ 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());
+ 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();
}
- clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_get_assertions_ret_1, (caddr_t)&ret);
+ clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
rpc.pool();
- log.debug ("returning..");
+ log.debug("returning");
return retval;
}
-void
-ShibTarget::serialize(saml::SAMLAssertion &assertion, std::string &result)
-{
- saml::NDC ndc("serialize");
- Category& log=Category::getInstance("shibtarget.RM");
-
- ostringstream os;
- os << assertion;
- unsigned int outlen;
- char* assn = (char*) os.str().c_str();
- XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(assn), os.str().length(), &outlen);
- result = (char*) serialized;
- XMLString::release(&serialized);
-}
-
-
/*************************************************************************
* Shib Target Private implementation
*/
-ShibTargetPriv::ShibTargetPriv() : m_parser(NULL), m_app(NULL), m_mapper(NULL),
- m_conf(NULL), m_Config(NULL), m_assertions()
-{
- session_id = NULL;
- m_sso_statement = NULL;
-}
+ShibTargetPriv::ShibTargetPriv()
+ : m_app(NULL), m_mapper(NULL), m_conf(NULL), m_Config(NULL), session_id(NULL), m_sso_statement(NULL) {}
ShibTargetPriv::~ShibTargetPriv()
{
- if (m_sso_statement) {
- delete m_sso_statement;
- m_sso_statement = NULL;
- }
+ delete m_sso_statement;
+ m_sso_statement = NULL;
+
for (int k = 0; k < m_assertions.size(); k++)
delete m_assertions[k];
- m_assertions = vector<SAMLAssertion*>();
+ m_assertions.clear();
- if (m_parser) {
- delete m_parser;
- m_parser = NULL;
- }
if (m_mapper) {
m_mapper->unlock();
m_mapper = NULL;
}
void
-ShibTargetPriv::get_application(string protocol, string hostname, int port,
- string uri)
+ShibTargetPriv::get_application(const string& protocol, const string& hostname, int port, const string& uri)
{
if (m_app)
return;
// XXX: Do we need to keep conf and mapper locked while we hold m_app?
+ // TODO: No, should be able to hold the conf but release the mapper.
// We lock the configuration system for the duration.
m_conf=m_Config->getINI();
return session_id;
}
-bool
-ShibTargetPriv::get_assertions(ShibTarget* st, const char *session_id, ShibMLP &mlp)
-{
- if (m_sso_statement)
- return false;
-
- RPCError *status = NULL;
- status = st->getAssertions(session_id, m_remote_addr.c_str(),
- m_assertions, &m_sso_statement);
-
- if (status->isError()) {
- string er = "getAssertions failed: ";
- er += status->getText();
- st->log(ShibTarget::LogLevelError, er);
- mlp.insert(*status);
- delete status;
- return true;
- }
- delete status;
- return false;
-}
-
-
/*************************************************************************
* CGI Parser implementation
*/
virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
virtual const char* getTLSCred(const shibboleth::IEntityDescriptor* provider) const=0;
virtual const char* getSigningCred(const shibboleth::IEntityDescriptor* provider) const=0;
+ virtual saml::SAMLBrowserProfile* getBrowserProfile() const=0;
virtual ~IApplication() {}
};
- struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
+ struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
{
virtual bool isValid(time_t lifetime, time_t timeout) const=0;
virtual const char* getClientAddress() const=0;
- virtual const char* getSerializedStatement() const=0;
- virtual const saml::SAMLAuthenticationStatement* getStatement() const=0;
- virtual void preFetch(int prefetch_window)=0;
+ virtual const saml::SAMLAuthenticationStatement* getAuthnStatement() const=0;
virtual saml::Iterator<saml::SAMLAssertion*> getAssertions()=0;
virtual ~ISessionCacheEntry() {}
};
{
virtual const IListener* getListener() const=0;
virtual ISessionCache* getSessionCache() const=0;
+ virtual saml::IReplayCache* getReplayCache() const=0;
virtual IRequestMapper* getRequestMapper() const=0;
virtual const IApplication* getApplication(const char* applicationId) const=0;
virtual saml::Iterator<shibboleth::ICredentials*> getCredentialsProviders() const=0;
unsigned long m_features;
};
- class SHIBTARGET_EXPORTS RM
- {
- public:
- RM(const IApplication* app) : m_app(app) {}
- ~RM() {}
-
- RPCError* getAssertions(
- const char* cookie,
- const char* ip,
- std::vector<saml::SAMLAssertion*>& assertions,
- saml::SAMLAuthenticationStatement **statement = NULL
- );
- static void serialize(saml::SAMLAssertion &assertion, std::string &result);
-
- private:
- const IApplication* m_app;
- };
-
class ShibMLPPriv;
class SHIBTARGET_EXPORTS ShibMLP {
public:
// We're done. Finish up. Send either a result (error?) page or a redirect.
// If there are no headers supplied assume the content-type == text/html
+ typedef std::pair<std::string, std::string> header_t;
virtual void* sendPage(
const std::string &msg,
const std::string content_type = "text/html",
- const std::pair<std::string, std::string> headers[] = NULL,
+ const saml::Iterator<header_t>& headers = EMPTY(header_t),
int code = 200
)=0;
void* sendPage(const char *msg) {
// exportAssertion values passed in here are only used if the
// settings resource is negative.
//
- // The handlePost argument declares whether doCheckAuthN() should
+ // The handleProfile argument declares whether doCheckAuthN() should
// automatically call doHandlePOST() when it encounters a request for
// the ShireURL; if false it will call returnOK() instead.
//
- std::pair<bool,void*> doCheckAuthN(bool requireSession = false,
- bool handlePost = false);
- std::pair<bool,void*> doHandlePOST(void);
- std::pair<bool,void*> doCheckAuthZ(void);
+ std::pair<bool,void*> doCheckAuthN(bool requireSession = false, bool handleProfile = false);
+ std::pair<bool,void*> doHandleProfile();
+ std::pair<bool,void*> doCheckAuthZ();
std::pair<bool,void*> doExportAssertions(bool exportAssertion = false);
//**************************************************************************
// Process a lazy session setup request and turn it into an AuthnRequest
const char* getLazyAuthnRequest(const char* query_string) const;
- // Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
- std::pair<const char*,const char*>
- getFormSubmission(const char* post, unsigned int len) const;
-
- RPCError* sessionCreate(
- const char* response,
- const char* ip,
- std::string &cookie
- ) const;
- RPCError* sessionIsValid(const char* session_id, const char* ip) const;
-
- // RM APIS
-
- RPCError* getAssertions(
- const char* cookie,
- const char* ip,
- std::vector<saml::SAMLAssertion*>& assertions,
- saml::SAMLAuthenticationStatement **statement = NULL
- ) const;
- static void serialize(saml::SAMLAssertion &assertion, std::string &result);
-
-
protected:
- ShibTarget(void);
+ ShibTarget();
+
+ // Currently wraps remoted interface.
+ // TODO: Move this functionality behind ISessionCache
+ RPCError* sessionNew(
+ const char* packet,
+ const char* ip,
+ std::string& cookie,
+ std::string& target
+ ) const;
+
+ RPCError* sessionGet(
+ const char* cookie,
+ const char* ip,
+ std::vector<saml::SAMLAssertion*>& assertions,
+ saml::SAMLAuthenticationStatement **statement = NULL
+ ) const;
// Initialize the request from the parsed URL
// protocol == http, https, etc
private:
mutable ShibTargetPriv *m_priv;
};
-
- //******************************************************************************
- // You probably don't care about much below this line
- // unless you are using the lower-layer APIs provided by
- // the shib target library.
- /*
- class SHIBTARGET_EXPORTS SHIRE
- {
- public:
- SHIRE(const IApplication* app) { m_st = new ShibTarget(app); }
- ~SHIRE() { delete m_st; }
-
- // Get the session cookie name and properties for the application
- std::pair<const char*,const char*> getCookieNameProps() const
- { return m_st->getCookieNameProps(); }
-
- // Find the default assertion consumer service for the resource
- const char* getShireURL(const char* resource) const
- { return m_st->getShireURL(resource); }
-
- // Generate a Shib 1.x AuthnRequest redirect URL for the resource
- const char* getAuthnRequest(const char* resource) const
- { return m_st->getAuthnRequest(resource); }
-
- // Process a lazy session setup request and turn it into an AuthnRequest
- const char* getLazyAuthnRequest(const char* query_string) const
- { return m_st->getLazyAuthnRequest(query_string); }
-
- // Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
- std::pair<const char*,const char*> getFormSubmission(const char* post, unsigned int len) const
- { return m_st->getFormSubmission(post, len); }
-
- RPCError* sessionCreate(const char* response, const char* ip, std::string &cookie) const
- { return m_st->sessionCreate(response, ip, cookie); }
- RPCError* sessionIsValid(const char* session_id, const char* ip) const
- { return m_st->sessionIsValid(session_id, ip); }
-
- private:
- ShibTarget *m_st;
- //const IApplication* m_app;
- //mutable std::string m_cookieName;
- //mutable std::string m_shireURL;
- //mutable std::string m_authnRequest;
- //mutable CgiParse* m_parser;
- };
- */
}
#endif /* SHIB_TARGET_H */
static struct timeval TIMEOUT = { 25, 0 };
enum clnt_stat
-shibrpc_ping_1(int *argp, int *clnt_res, CLIENT *clnt)
+shibrpc_ping_2(int *argp, int *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, shibrpc_ping,
(xdrproc_t) xdr_int, (caddr_t) argp,
}
enum clnt_stat
-shibrpc_session_is_valid_1(shibrpc_session_is_valid_args_1 *argp, shibrpc_session_is_valid_ret_1 *clnt_res, CLIENT *clnt)
-{
- return (clnt_call(clnt, shibrpc_session_is_valid,
- (xdrproc_t) xdr_shibrpc_session_is_valid_args_1, (caddr_t) argp,
- (xdrproc_t) xdr_shibrpc_session_is_valid_ret_1, (caddr_t) clnt_res,
- TIMEOUT));
-}
-
-enum clnt_stat
-shibrpc_new_session_1(shibrpc_new_session_args_1 *argp, shibrpc_new_session_ret_1 *clnt_res, CLIENT *clnt)
+shibrpc_new_session_2(shibrpc_new_session_args_2 *argp, shibrpc_new_session_ret_2 *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, shibrpc_new_session,
- (xdrproc_t) xdr_shibrpc_new_session_args_1, (caddr_t) argp,
- (xdrproc_t) xdr_shibrpc_new_session_ret_1, (caddr_t) clnt_res,
+ (xdrproc_t) xdr_shibrpc_new_session_args_2, (caddr_t) argp,
+ (xdrproc_t) xdr_shibrpc_new_session_ret_2, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
-shibrpc_get_assertions_1(shibrpc_get_assertions_args_1 *argp, shibrpc_get_assertions_ret_1 *clnt_res, CLIENT *clnt)
+shibrpc_get_session_2(shibrpc_get_session_args_2 *argp, shibrpc_get_session_ret_2 *clnt_res, CLIENT *clnt)
{
- return (clnt_call(clnt, shibrpc_get_assertions,
- (xdrproc_t) xdr_shibrpc_get_assertions_args_1, (caddr_t) argp,
- (xdrproc_t) xdr_shibrpc_get_assertions_ret_1, (caddr_t) clnt_res,
+ return (clnt_call(clnt, shibrpc_get_session,
+ (xdrproc_t) xdr_shibrpc_get_session_args_2, (caddr_t) argp,
+ (xdrproc_t) xdr_shibrpc_get_session_ret_2, (caddr_t) clnt_res,
TIMEOUT));
}
#include "shibrpc.h"
bool_t
-shibrpc_ping_1_svc(int *argp, int *result, struct svc_req *rqstp)
+shibrpc_ping_2_svc(int *argp, int *result, struct svc_req *rqstp)
{
bool_t retval;
}
bool_t
-shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp, shibrpc_session_is_valid_ret_1 *result, struct svc_req *rqstp)
+shibrpc_new_session_2_svc(shibrpc_new_session_args_2 *argp, shibrpc_new_session_ret_2 *result, struct svc_req *rqstp)
{
bool_t retval;
}
bool_t
-shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp, shibrpc_new_session_ret_1 *result, struct svc_req *rqstp)
-{
- bool_t retval;
-
- /*
- * insert server code here
- */
-
- return retval;
-}
-
-bool_t
-shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *argp, shibrpc_get_assertions_ret_1 *result, struct svc_req *rqstp)
+shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *argp, shibrpc_get_session_ret_2 *result, struct svc_req *rqstp)
{
bool_t retval;
}
int
-shibrpc_prog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
+shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
{
xdr_free (xdr_result, result);
}
extern "C" bool_t
-shibrpc_ping_1_svc(int *argp, int *result, struct svc_req *rqstp)
+shibrpc_ping_2_svc(int *argp, int *result, struct svc_req *rqstp)
{
*result = (*argp)+1;
return TRUE;
}
}
-/*
-void set_rpc_status_x(ShibRpcError *error, ShibRpcStatus status,
- const char* msg=NULL, const XMLCh* origin=NULL)
-{
- if (!status) {
- set_rpc_status(error, status);
- return;
- }
- auto_ptr_char orig(origin);
- set_rpc_status(error, status, msg, orig.get());
-}
-*/
-
extern "C" bool_t
-shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp,
- shibrpc_session_is_valid_ret_1 *result,
- struct svc_req *rqstp)
+shibrpc_get_session_2_svc(
+ shibrpc_get_session_args_2 *argp,
+ shibrpc_get_session_ret_2 *result,
+ struct svc_req *rqstp
+ )
{
Category& log = get_category();
string ctx = get_threadid("session_is_valid");
}
memset (result, 0, sizeof (*result));
+ result->auth_statement.xml_string = strdup("");
log.debug ("checking: %s@%s (checkAddr=%s)",
- argp->cookie.cookie, argp->cookie.client_addr,
- argp->checkIPAddress ? "true" : "false");
+ argp->cookie, argp->client_addr, argp->checkIPAddress ? "true" : "false");
- // See if the cookie exists...
+ // See if the session exists...
+
IConfig* conf=ShibTargetConfig::getConfig().getINI();
Locker locker(conf);
log.debug ("application: %s", argp->application_id);
return TRUE;
}
- ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie.cookie,app);
+ 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 cookie");
+ set_rpc_status(&result->status, SHIBRPC_NO_SESSION, "No session exists for this key value");
return TRUE;
}
// TEST the session...
try {
Metadata m(app->getMetadataProviders());
- const IEntityDescriptor* origin=m.lookup(entry->getStatement()->getSubject()->getNameIdentifier()->getNameQualifier());
+ const IEntityDescriptor* origin=m.lookup(entry->getAuthnStatement()->getSubject()->getNameIdentifier()->getNameQualifier());
// Verify the address is the same
if (argp->checkIPAddress) {
log.debug ("Checking address against %s", entry->getClientAddress());
- if (strcmp (argp->cookie.client_addr, entry->getClientAddress())) {
+ if (strcmp (argp->client_addr, entry->getClientAddress())) {
log.debug ("IP Address mismatch");
throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
- "Your IP address does not match the address in the original authentication.", origin);
+ "Your IP address does not match the address recorded at the time the session was established.", origin);
}
}
// and that the session is still valid...
if (!entry->isValid(argp->lifetime, argp->timeout)) {
log.debug ("Session expired");
- throw ShibTargetException(SHIBRPC_SESSION_EXPIRED, "Your session has expired, must re-authenticate.", origin);
+ throw ShibTargetException(SHIBRPC_SESSION_EXPIRED, "Your session has expired, and you must re-authenticate.", origin);
}
- // and now try to prefetch the attributes .. this could cause an
- // "error", which is why we call it here.
try {
- entry->preFetch(15); // give a 15-second window for the RM
+ // Now grab the serialized authentication statement
+ ostringstream os;
+ os << *(entry->getAuthnStatement());
+ free(result->auth_statement.xml_string);
+ result->auth_statement.xml_string = strdup(os.str().c_str());
+
+ // grab the attributes for this session
+ Iterator<SAMLAssertion*> iter = entry->getAssertions();
+ u_int size = iter.size();
+
+ // if we have assertions...
+ if (size) {
+ // Build the response section
+ ShibRpcXML* av = (ShibRpcXML*) malloc (size * sizeof (ShibRpcXML));
+
+ // and then serialize them all...
+ u_int i = 0;
+ while (iter.hasNext()) {
+ SAMLAssertion* as = iter.next();
+ ostringstream os2;
+ os2 << *as;
+ av[i++].xml_string = strdup(os2.str().c_str());
+ }
+
+ // Set the results, once we know we've succeeded.
+ result->assertions.assertions_len = size;
+ result->assertions.assertions_val = av;
+ }
}
catch (SAMLException &e) {
- log.debug ("prefetch failed with a SAML Exception: %s", e.what());
+ log.error ("caught SAML exception: %s", e.what());
ostringstream os;
os << e;
throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), origin);
}
- catch (ShibTargetException&) {
- // These are caught and handled down below.
- throw;
- }
-#ifndef _DEBUG
- catch (...) {
- log.error ("prefetch caught an unknown exception");
- throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR,
- "An unknown error occured while pre-fetching attributes.", origin);
- }
-#endif
}
catch (ShibTargetException &e) {
- entry->unlock();
- conf->getSessionCache()->remove(argp->cookie.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.cookie <<
- ") with (applicationId: " <<
- argp->application_id <<
- "), request was from (ClientAddress: " <<
- argp->cookie.client_addr <<
- ")";
- stc.releaseTransactionLog();
- return TRUE;
+ 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;
+ }
+#endif
// Ok, just release it.
entry->unlock();
}
extern "C" bool_t
-shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
- shibrpc_new_session_ret_1 *result, struct svc_req *rqstp)
+shibrpc_new_session_2_svc(
+ shibrpc_new_session_args_2 *argp,
+ shibrpc_new_session_ret_2 *result,
+ struct svc_req *rqstp
+ )
{
Category& log = get_category();
string ctx=get_threadid("new_session");
// 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 ("shire location: %s", argp->shire_location);
+ log.debug ("recipient: %s", argp->recipient);
log.debug ("application: %s", argp->application_id);
- XMLByte* post=reinterpret_cast<XMLByte*>(argp->saml_post);
- auto_ptr_XMLCh location(argp->shire_location);
+ auto_ptr_XMLCh recipient(argp->recipient);
SAMLResponse* r = NULL;
const SAMLAuthenticationStatement* auth_st = NULL;
return TRUE;
}
+ // TODO: Sub in call to getReplayCache() as the determinant.
+ // For now, we always have a cache and use the flag...
pair<bool,bool> checkReplay=pair<bool,bool>(false,false);
const IPropertySet* props=app->getPropertySet("Sessions");
if (props)
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?");
- // And build the POST profile wrapper.
- log.debug("create the POST profile");
- ShibPOSTProfile profile(app->getMetadataProviders(),app->getRevocationProviders(),app->getTrustProviders());
-
try
{
- // Try and accept the response...
- log.debug ("Trying to accept the post");
- r = profile.accept(post,location.get(),300,app->getAudiences(),&origin);
+ // Try and run the profile.
+ log.debug ("Executing browser profile...");
+ bpr=app->getBrowserProfile()->receive(
+ &origin,
+ argp->packet,
+ recipient.get(),
+ SAMLBrowserProfile::Post, // For now, we only handle POST.
+ (!checkReplay.first || checkReplay.second) ? conf->getReplayCache() : NULL
+ );
// Try and map to metadata for support purposes.
const IEntityDescriptor* provider=m.lookup(origin);
throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,
"Unable to locate role-specific metadata for identity provider", provider);
- // Make sure we got a response
- if (!r)
- throw ShibTargetException(SHIBRPC_RESPONSE_MISSING, "Failed to accept the response.", role);
-
- // Find the SSO Assertion
- log.debug ("Get the SSOAssertion");
- const SAMLAssertion* ssoAssertion = profile.getSSOAssertion(*r,app->getAudiences());
-
- // Check against the replay cache?
- if (checkReplay.first && !checkReplay.second)
- log.warn("replay checking is off, this is a security risk unless you're testing");
- else {
- log.debug ("check replay cache");
- if (!profile.checkReplayCache(*ssoAssertion))
- throw ShibTargetException(SHIBRPC_ASSERTION_REPLAYED, "Duplicate assertion detected.", role);
- }
-
- // Get the authentication statement we need.
- log.debug ("get SSOStatement");
- auth_st = profile.getSSOStatement(*ssoAssertion);
-
// Maybe verify the origin address....
if (argp->checkIPAddress) {
- log.debug ("check IP Address");
+ log.debug ("verify client address");
// Verify the client address exists
- const XMLCh* ip = auth_st->getSubjectIP();
+ const XMLCh* ip = bpr.authnStatement->getSubjectIP();
if (ip && *ip) {
- log.debug ("verify client address");
-
// Verify the client address matches authentication
auto_ptr_char this_ip(ip);
if (strcmp(argp->client_addr, this_ip.get()))
role);
}
}
+
+ // 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.");
+ }
+ 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 (SAMLException &e)
- {
+ catch (ReplayedAssertionException& e) {
+ // Specific case where we have an error code.
+ throw ShibTargetException(SHIBRPC_ASSERTION_REPLAYED, e.what(), role);
+ }
+ catch (SAMLException& e) {
log.error ("caught SAML exception: %s", e.what());
ostringstream os;
os << e;
throw ShibTargetException (SHIBRPC_SAML_EXCEPTION, os.str().c_str(), role);
}
- catch (XMLException &e)
- {
- log.error ("received XML exception");
+ catch (XMLException& e) {
+ log.error ("caught XML exception");
auto_ptr_char msg(e.getMessage());
throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get(), role);
}
}
- catch (ShibTargetException &e) {
- log.info ("FAILED: %s", e.what());
- delete r;
+ 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");
- delete r;
+ bpr.clear();
if (origin) XMLString::release(&origin);
set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "An unknown exception occurred");
return TRUE;
// It passes all our tests -- create a new session.
log.info ("Creating new session");
- SAMLAuthenticationStatement* as=static_cast<SAMLAuthenticationStatement*>(auth_st->clone());
+ // Clone the statement so we can store it.
+ // TODO: we need to extract the Issuer and propagate that around as the origin site along
+ // with the statement and attribute assertions.
+ SAMLAuthenticationStatement* as=static_cast<SAMLAuthenticationStatement*>(bpr.authnStatement->clone());
- // Create a new cookie
+ // Create a new session key.
string cookie = conf->getSessionCache()->generateKey();
// Cache this session, possibly including response if attributes appear present.
bool attributesPushed=false;
- Iterator<SAMLAssertion*> assertions=r->getAssertions();
+ Iterator<SAMLAssertion*> assertions=bpr.response->getAssertions();
while (!attributesPushed && assertions.hasNext()) {
Iterator<SAMLStatement*> statements=assertions.next()->getStatements();
while (!attributesPushed && statements.hasNext()) {
attributesPushed=true;
}
}
- conf->getSessionCache()->insert(cookie.c_str(), app, as, argp->client_addr, (attributesPushed ? r : NULL), role);
+ conf->getSessionCache()->insert(cookie.c_str(), app, as, argp->client_addr, (attributesPushed ? bpr.response : NULL), role);
- // Maybe delete the response...
- if (!attributesPushed)
- delete r;
-
// 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
return TRUE;
}
-extern "C" bool_t
-shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *argp,
- shibrpc_get_assertions_ret_1 *result, struct svc_req *rqstp)
-{
- Category& log = get_category();
- string ctx = get_threadid("get_assertions");
- saml::NDC ndc(ctx);
-
- if (!argp || !result) {
- log.error ("Invalid RPC arguments");
- return FALSE;
- }
-
- memset (result, 0, sizeof (*result));
- result->auth_statement.xml_string = strdup("");
-
- log.debug ("get attrs for client at %s", argp->cookie.client_addr);
- log.debug ("cookie: %s", argp->cookie.cookie);
- log.debug ("application: %s", argp->application_id);
-
- // Find this session
- IConfig* conf=ShibTargetConfig::getConfig().getINI();
- Locker locker(conf);
-
- // Try and locate support metadata for errors we throw.
- 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_INTERNAL_ERROR, "Unable to locate application for session, deleted?");
- return TRUE;
- }
-
- ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie.cookie,app);
-
- // If it does not exist, leave now..
- if (!entry) {
- log.error ("No Session");
- set_rpc_status(&result->status, SHIBRPC_NO_SESSION, "getattrs Internal error: no session");
- return TRUE;
- }
-
- Metadata m(app->getMetadataProviders());
- const IEntityDescriptor* origin=m.lookup(entry->getStatement()->getSubject()->getNameIdentifier()->getNameQualifier());
-
- try {
- try {
- // Validate the client address (again?)
- if (argp->checkIPAddress && strcmp (argp->cookie.client_addr, entry->getClientAddress())) {
- entry->unlock();
- log.error("IP Mismatch");
- throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
- "Your IP address does not match the address in the original authentication.", origin);
- }
-
- // grab the attributes for this resource
- Iterator<SAMLAssertion*> iter = entry->getAssertions();
- u_int size = iter.size();
-
- // if we have assertions...
- if (size) {
-
- // Build the response section
- ShibRpcXML* av = (ShibRpcXML*) malloc (size * sizeof (ShibRpcXML));
-
- // and then serialize them all...
- u_int i = 0;
- while (iter.hasNext()) {
- SAMLAssertion* as = iter.next();
- ostringstream os;
- os << *as;
- av[i++].xml_string = strdup(os.str().c_str());
- }
-
- // Set the results, once we know we've succeeded.
- result->assertions.assertions_len = size;
- result->assertions.assertions_val = av;
- }
- }
- catch (SAMLException &e) {
- entry->unlock();
- log.error ("caught SAML exception: %s", e.what());
- ostringstream os;
- os << e;
- throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), origin);
- }
- }
- catch (ShibTargetException &e) {
- entry->unlock();
- set_rpc_status(&result->status, e);
- return TRUE;
- }
-#ifndef _DEBUG
- catch (...) {
- entry->unlock();
- log.error ("caught an unknown exception");
- throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR,
- "An unexpected error occured while fetching attributes.", origin);
- }
-#endif
-
-
- // Now grab the serialized authentication statement
- free(result->auth_statement.xml_string);
- result->auth_statement.xml_string = strdup(entry->getSerializedStatement());
-
- entry->unlock();
-
- // and let it fly
- set_rpc_status(&result->status, SHIBRPC_OK);
-
- log.debug ("returning");
- return TRUE;
-}
-
extern "C" int
-shibrpc_prog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
+shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
{
xdr_free (xdr_result, result);
#endif
void
-shibrpc_prog_1(struct svc_req *rqstp, register SVCXPRT *transp)
+shibrpc_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
- int shibrpc_ping_1_arg;
- shibrpc_session_is_valid_args_1 shibrpc_session_is_valid_1_arg;
- shibrpc_new_session_args_1 shibrpc_new_session_1_arg;
- shibrpc_get_assertions_args_1 shibrpc_get_assertions_1_arg;
+ int shibrpc_ping_2_arg;
+ shibrpc_new_session_args_2 shibrpc_new_session_2_arg;
+ shibrpc_get_session_args_2 shibrpc_get_session_2_arg;
} argument;
union {
- int shibrpc_ping_1_res;
- shibrpc_session_is_valid_ret_1 shibrpc_session_is_valid_1_res;
- shibrpc_new_session_ret_1 shibrpc_new_session_1_res;
- shibrpc_get_assertions_ret_1 shibrpc_get_assertions_1_res;
+ int shibrpc_ping_2_res;
+ shibrpc_new_session_ret_2 shibrpc_new_session_2_res;
+ shibrpc_get_session_ret_2 shibrpc_get_session_2_res;
} result;
bool_t retval;
xdrproc_t _xdr_argument, _xdr_result;
case shibrpc_ping:
_xdr_argument = (xdrproc_t) xdr_int;
_xdr_result = (xdrproc_t) xdr_int;
- local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_ping_1_svc;
- break;
-
- case shibrpc_session_is_valid:
- _xdr_argument = (xdrproc_t) xdr_shibrpc_session_is_valid_args_1;
- _xdr_result = (xdrproc_t) xdr_shibrpc_session_is_valid_ret_1;
- local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_session_is_valid_1_svc;
+ local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_ping_2_svc;
break;
case shibrpc_new_session:
- _xdr_argument = (xdrproc_t) xdr_shibrpc_new_session_args_1;
- _xdr_result = (xdrproc_t) xdr_shibrpc_new_session_ret_1;
- local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_new_session_1_svc;
+ _xdr_argument = (xdrproc_t) xdr_shibrpc_new_session_args_2;
+ _xdr_result = (xdrproc_t) xdr_shibrpc_new_session_ret_2;
+ local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_new_session_2_svc;
break;
- case shibrpc_get_assertions:
- _xdr_argument = (xdrproc_t) xdr_shibrpc_get_assertions_args_1;
- _xdr_result = (xdrproc_t) xdr_shibrpc_get_assertions_ret_1;
- local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_get_assertions_1_svc;
+ case shibrpc_get_session:
+ _xdr_argument = (xdrproc_t) xdr_shibrpc_get_session_args_2;
+ _xdr_result = (xdrproc_t) xdr_shibrpc_get_session_ret_2;
+ local = (bool_t (*) (char *, void *, struct svc_req *))shibrpc_get_session_2_svc;
break;
default:
return;
}
memset ((char *)&argument, 0, sizeof (argument));
- if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument)) {
+ if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
svcerr_decode (transp);
return;
}
retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp);
- if (retval > 0 && !svc_sendreply(transp, _xdr_result, (char *)&result)) {
+ if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) {
svcerr_systemerr (transp);
}
- if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument)) {
+ if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
fprintf (stderr, "%s", "unable to free arguments");
exit (1);
}
- if (!shibrpc_prog_1_freeresult (transp, _xdr_result, (caddr_t) &result))
+ if (!shibrpc_prog_2_freeresult (transp, _xdr_result, (caddr_t) &result))
fprintf (stderr, "%s", "unable to free results");
return;
}
bool_t
-xdr_ShibRpcHttpCookie_1 (XDR *xdrs, ShibRpcHttpCookie_1 *objp)
-{
- register int32_t *buf;
-
- if (!xdr_string (xdrs, &objp->cookie, ~0))
- return FALSE;
- if (!xdr_string (xdrs, &objp->client_addr, ~0))
- return FALSE;
- return TRUE;
-}
-
-bool_t
xdr_ShibRpcXML (XDR *xdrs, ShibRpcXML *objp)
{
register int32_t *buf;
}
bool_t
-xdr_shibrpc_session_is_valid_args_1 (XDR *xdrs, shibrpc_session_is_valid_args_1 *objp)
-{
- register int32_t *buf;
-
- if (!xdr_ShibRpcHttpCookie_1 (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_string (xdrs, &objp->application_id, ~0))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->checkIPAddress))
- return FALSE;
- if (!xdr_long (xdrs, &objp->lifetime))
- return FALSE;
- if (!xdr_long (xdrs, &objp->timeout))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_shibrpc_session_is_valid_ret_1 (XDR *xdrs, shibrpc_session_is_valid_ret_1 *objp)
-{
- register int32_t *buf;
-
- if (!xdr_ShibRpcError (xdrs, &objp->status))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_shibrpc_new_session_args_1 (XDR *xdrs, shibrpc_new_session_args_1 *objp)
+xdr_shibrpc_new_session_args_2 (XDR *xdrs, shibrpc_new_session_args_2 *objp)
{
register int32_t *buf;
if (!xdr_string (xdrs, &objp->application_id, ~0))
return FALSE;
- if (!xdr_string (xdrs, &objp->shire_location, ~0))
+ if (!xdr_string (xdrs, &objp->packet, ~0))
return FALSE;
- if (!xdr_string (xdrs, &objp->saml_post, ~0))
+ if (!xdr_string (xdrs, &objp->recipient, ~0))
return FALSE;
if (!xdr_string (xdrs, &objp->client_addr, ~0))
return FALSE;
}
bool_t
-xdr_shibrpc_new_session_ret_1 (XDR *xdrs, shibrpc_new_session_ret_1 *objp)
+xdr_shibrpc_new_session_ret_2 (XDR *xdrs, shibrpc_new_session_ret_2 *objp)
{
register int32_t *buf;
if (!xdr_ShibRpcError (xdrs, &objp->status))
return FALSE;
+ if (!xdr_string (xdrs, &objp->target, ~0))
+ return FALSE;
if (!xdr_string (xdrs, &objp->cookie, ~0))
return FALSE;
return TRUE;
}
bool_t
-xdr_shibrpc_get_assertions_args_1 (XDR *xdrs, shibrpc_get_assertions_args_1 *objp)
+xdr_shibrpc_get_session_args_2 (XDR *xdrs, shibrpc_get_session_args_2 *objp)
{
register int32_t *buf;
- if (!xdr_ShibRpcHttpCookie_1 (xdrs, &objp->cookie))
+ if (!xdr_string (xdrs, &objp->application_id, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->cookie, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->client_addr, ~0))
return FALSE;
if (!xdr_bool (xdrs, &objp->checkIPAddress))
return FALSE;
- if (!xdr_string (xdrs, &objp->application_id, ~0))
+ if (!xdr_long (xdrs, &objp->lifetime))
+ return FALSE;
+ if (!xdr_long (xdrs, &objp->timeout))
return FALSE;
return TRUE;
}
bool_t
-xdr_shibrpc_get_assertions_ret_1 (XDR *xdrs, shibrpc_get_assertions_ret_1 *objp)
+xdr_shibrpc_get_session_ret_2 (XDR *xdrs, shibrpc_get_session_ret_2 *objp)
{
register int32_t *buf;
};
typedef struct ShibRpcError ShibRpcError;
-struct ShibRpcHttpCookie_1 {
- char *cookie;
- char *client_addr;
-};
-typedef struct ShibRpcHttpCookie_1 ShibRpcHttpCookie_1;
-
struct ShibRpcXML {
char *xml_string;
};
typedef struct ShibRpcXML ShibRpcXML;
-struct shibrpc_session_is_valid_args_1 {
- ShibRpcHttpCookie_1 cookie;
+struct shibrpc_new_session_args_2 {
char *application_id;
- bool_t checkIPAddress;
- long lifetime;
- long timeout;
-};
-typedef struct shibrpc_session_is_valid_args_1 shibrpc_session_is_valid_args_1;
-
-struct shibrpc_session_is_valid_ret_1 {
- ShibRpcError status;
-};
-typedef struct shibrpc_session_is_valid_ret_1 shibrpc_session_is_valid_ret_1;
-
-struct shibrpc_new_session_args_1 {
- char *application_id;
- char *shire_location;
- char *saml_post;
+ char *packet;
+ char *recipient;
char *client_addr;
bool_t checkIPAddress;
};
-typedef struct shibrpc_new_session_args_1 shibrpc_new_session_args_1;
+typedef struct shibrpc_new_session_args_2 shibrpc_new_session_args_2;
-struct shibrpc_new_session_ret_1 {
+struct shibrpc_new_session_ret_2 {
ShibRpcError status;
+ char *target;
char *cookie;
};
-typedef struct shibrpc_new_session_ret_1 shibrpc_new_session_ret_1;
+typedef struct shibrpc_new_session_ret_2 shibrpc_new_session_ret_2;
-struct shibrpc_get_assertions_args_1 {
- ShibRpcHttpCookie_1 cookie;
- bool_t checkIPAddress;
+struct shibrpc_get_session_args_2 {
char *application_id;
+ char *cookie;
+ char *client_addr;
+ bool_t checkIPAddress;
+ long lifetime;
+ long timeout;
};
-typedef struct shibrpc_get_assertions_args_1 shibrpc_get_assertions_args_1;
+typedef struct shibrpc_get_session_args_2 shibrpc_get_session_args_2;
-struct shibrpc_get_assertions_ret_1 {
+struct shibrpc_get_session_ret_2 {
ShibRpcError status;
ShibRpcXML auth_statement;
struct {
ShibRpcXML *assertions_val;
} assertions;
};
-typedef struct shibrpc_get_assertions_ret_1 shibrpc_get_assertions_ret_1;
+typedef struct shibrpc_get_session_ret_2 shibrpc_get_session_ret_2;
#define SHIBRPC_PROG 123456
-#define SHIBRPC_VERS_1 1
+#define SHIBRPC_VERS_2 2
#if defined(__STDC__) || defined(__cplusplus)
#define shibrpc_ping 0
-extern enum clnt_stat shibrpc_ping_1(int *, int *, CLIENT *);
-extern bool_t shibrpc_ping_1_svc(int *, int *, struct svc_req *);
-#define shibrpc_session_is_valid 1
-extern enum clnt_stat shibrpc_session_is_valid_1(shibrpc_session_is_valid_args_1 *, shibrpc_session_is_valid_ret_1 *, CLIENT *);
-extern bool_t shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *, shibrpc_session_is_valid_ret_1 *, struct svc_req *);
-#define shibrpc_new_session 2
-extern enum clnt_stat shibrpc_new_session_1(shibrpc_new_session_args_1 *, shibrpc_new_session_ret_1 *, CLIENT *);
-extern bool_t shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *, shibrpc_new_session_ret_1 *, struct svc_req *);
-#define shibrpc_get_assertions 3
-extern enum clnt_stat shibrpc_get_assertions_1(shibrpc_get_assertions_args_1 *, shibrpc_get_assertions_ret_1 *, CLIENT *);
-extern bool_t shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *, shibrpc_get_assertions_ret_1 *, struct svc_req *);
-extern int shibrpc_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+extern enum clnt_stat shibrpc_ping_2(int *, int *, CLIENT *);
+extern bool_t shibrpc_ping_2_svc(int *, int *, struct svc_req *);
+#define shibrpc_new_session 1
+extern enum clnt_stat shibrpc_new_session_2(shibrpc_new_session_args_2 *, shibrpc_new_session_ret_2 *, CLIENT *);
+extern bool_t shibrpc_new_session_2_svc(shibrpc_new_session_args_2 *, shibrpc_new_session_ret_2 *, struct svc_req *);
+#define shibrpc_get_session 2
+extern enum clnt_stat shibrpc_get_session_2(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, CLIENT *);
+extern bool_t shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, struct svc_req *);
+extern int shibrpc_prog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
#else /* K&R C */
#define shibrpc_ping 0
-extern enum clnt_stat shibrpc_ping_1();
-extern bool_t shibrpc_ping_1_svc();
-#define shibrpc_session_is_valid 1
-extern enum clnt_stat shibrpc_session_is_valid_1();
-extern bool_t shibrpc_session_is_valid_1_svc();
-#define shibrpc_new_session 2
-extern enum clnt_stat shibrpc_new_session_1();
-extern bool_t shibrpc_new_session_1_svc();
-#define shibrpc_get_assertions 3
-extern enum clnt_stat shibrpc_get_assertions_1();
-extern bool_t shibrpc_get_assertions_1_svc();
-extern int shibrpc_prog_1_freeresult ();
+extern enum clnt_stat shibrpc_ping_2();
+extern bool_t shibrpc_ping_2_svc();
+#define shibrpc_new_session 1
+extern enum clnt_stat shibrpc_new_session_2();
+extern bool_t shibrpc_new_session_2_svc();
+#define shibrpc_get_session 2
+extern enum clnt_stat shibrpc_get_session_2();
+extern bool_t shibrpc_get_session_2_svc();
+extern int shibrpc_prog_2_freeresult ();
#endif /* K&R C */
/* the xdr functions */
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_ShibRpcHttpCookie_1 (XDR *, ShibRpcHttpCookie_1*);
extern bool_t xdr_ShibRpcXML (XDR *, ShibRpcXML*);
-extern bool_t xdr_shibrpc_session_is_valid_args_1 (XDR *, shibrpc_session_is_valid_args_1*);
-extern bool_t xdr_shibrpc_session_is_valid_ret_1 (XDR *, shibrpc_session_is_valid_ret_1*);
-extern bool_t xdr_shibrpc_new_session_args_1 (XDR *, shibrpc_new_session_args_1*);
-extern bool_t xdr_shibrpc_new_session_ret_1 (XDR *, shibrpc_new_session_ret_1*);
-extern bool_t xdr_shibrpc_get_assertions_args_1 (XDR *, shibrpc_get_assertions_args_1*);
-extern bool_t xdr_shibrpc_get_assertions_ret_1 (XDR *, shibrpc_get_assertions_ret_1*);
+extern bool_t xdr_shibrpc_new_session_args_2 (XDR *, shibrpc_new_session_args_2*);
+extern bool_t xdr_shibrpc_new_session_ret_2 (XDR *, shibrpc_new_session_ret_2*);
+extern bool_t xdr_shibrpc_get_session_args_2 (XDR *, shibrpc_get_session_args_2*);
+extern bool_t xdr_shibrpc_get_session_ret_2 (XDR *, shibrpc_get_session_ret_2*);
#else /* K&R C */
extern bool_t xdr_ShibRpcStatus ();
extern bool_t xdr_ShibRpcErr ();
extern bool_t xdr_ShibRpcError ();
-extern bool_t xdr_ShibRpcHttpCookie_1 ();
extern bool_t xdr_ShibRpcXML ();
-extern bool_t xdr_shibrpc_session_is_valid_args_1 ();
-extern bool_t xdr_shibrpc_session_is_valid_ret_1 ();
-extern bool_t xdr_shibrpc_new_session_args_1 ();
-extern bool_t xdr_shibrpc_new_session_ret_1 ();
-extern bool_t xdr_shibrpc_get_assertions_args_1 ();
-extern bool_t xdr_shibrpc_get_assertions_ret_1 ();
+extern bool_t xdr_shibrpc_new_session_args_2 ();
+extern bool_t xdr_shibrpc_new_session_ret_2 ();
+extern bool_t xdr_shibrpc_get_session_args_2 ();
+extern bool_t xdr_shibrpc_get_session_ret_2 ();
#endif /* K&R C */
ShibRpcErr e;
};
-/* A type to pass a Cookie, which contains the HTTP cookie string
- * and the IP Address of the client */
-struct ShibRpcHttpCookie_1 {
- string cookie<>;
- string client_addr<>;
-};
-
struct ShibRpcXML {
string xml_string<>;
};
/* function argument and response structures */
-struct shibrpc_session_is_valid_args_1 {
- ShibRpcHttpCookie_1 cookie;
- string application_id<>;
- bool checkIPAddress;
- long lifetime;
- long timeout;
-};
-
-struct shibrpc_session_is_valid_ret_1 {
- ShibRpcError status;
-};
-
-struct shibrpc_new_session_args_1 {
+struct shibrpc_new_session_args_2 {
string application_id<>;
- string shire_location<>;
- string saml_post<>;
+ string packet<>;
+ string recipient<>;
string client_addr<>;
bool checkIPAddress;
};
-struct shibrpc_new_session_ret_1 {
+struct shibrpc_new_session_ret_2 {
ShibRpcError status;
+ string target<>;
string cookie<>;
};
-
-struct shibrpc_get_assertions_args_1 {
- ShibRpcHttpCookie_1 cookie;
- bool checkIPAddress;
+struct shibrpc_get_session_args_2 {
string application_id<>;
+ string cookie<>;
+ string client_addr<>;
+ bool checkIPAddress;
+ long lifetime;
+ long timeout;
};
-struct shibrpc_get_assertions_ret_1 {
- ShibRpcError status;
- ShibRpcXML auth_statement;
- ShibRpcXML assertions<>;
+struct shibrpc_get_session_ret_2 {
+ ShibRpcError status;
+ ShibRpcXML auth_statement;
+ ShibRpcXML assertions<>;
};
+
/* Define the Shib Target RPC interface */
program SHIBRPC_PROG {
- version SHIBRPC_VERS_1 {
+ version SHIBRPC_VERS_2 {
/* Ping the rpcsvc to make sure it is alive. */
int shibrpc_ping (int) = 0;
- /* SHIRE RPCs */
-
- /* Is the HTTP Cookie valid? Is the session still active?
- * Returns 0 for TRUE, a non-zero error code for FALSE */
- shibrpc_session_is_valid_ret_1 shibrpc_session_is_valid (shibrpc_session_is_valid_args_1) = 1;
-
- /* Create a new session for this user (SAML POST Profile Consumer) */
- shibrpc_new_session_ret_1 shibrpc_new_session (shibrpc_new_session_args_1)
- = 2;
+ /* Session Cache Remoting RPCs */
- /* RM RPCs */
+ /* Create a new session for this user (SAML Browser Profile Consumer) */
+ shibrpc_new_session_ret_2 shibrpc_new_session (shibrpc_new_session_args_2) = 1;
- /* Get the assertions from the SHAR */
- shibrpc_get_assertions_ret_1 shibrpc_get_assertions (shibrpc_get_assertions_args_1) = 3;
+ /* Validate and access data associated with existing session.
+ * Returns 0 for TRUE, a non-zero error code for FALSE */
+ shibrpc_get_session_ret_2 shibrpc_get_session (shibrpc_get_session_args_2) = 2;
- } = 1;
-} = 123456; /* XXX: Pick an RPC Program Number */
+ } = 2;
+} = 123456; /* Arbitrary RPC Program Number */
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 log4cpp.lib xerces-c_2.lib wsock32.lib saml_5.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_5.dll" /libpath:"../../../opensaml/c/saml/Release" /export:shibrpc_prog_1 /export:shibrpc_ping_1
+# ADD LINK32 log4cpp.lib xerces-c_2.lib wsock32.lib saml_5.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_5.dll" /libpath:"../../../opensaml/c/saml/Release" /export:shibrpc_prog_2 /export:shibrpc_ping_2
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "shibtarget - Win32 Debug"
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 log4cppD.lib xerces-c_2D.lib wsock32.lib saml_5D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_5D.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /export:shibrpc_prog_1 /export:shibrpc_ping_1
+# ADD LINK32 log4cppD.lib xerces-c_2D.lib wsock32.lib saml_5D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_5D.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /export:shibrpc_prog_2 /export:shibrpc_ping_2
# SUBTRACT LINK32 /pdb:none
!ENDIF
# End Source File
# Begin Source File
-SOURCE=".\shib-rm.cpp"
-# End Source File
-# Begin Source File
-
SOURCE=".\shib-rpcerror.cpp"
# End Source File
# Begin Source File
Metadata.cpp \
ReloadableXMLFile.cpp \
ShibConfig.cpp \
- ShibPOSTProfile.cpp \
+ ShibBrowserProfile.cpp \
ShibBinding.cpp \
shib-threads.cpp
auto_ptr<SAMLResponse> r(m_binding->send(*ab, req, conf));
if (r->isSigned() && !t.validate(m_revocations,m_AA,*r))
throw TrustException("ShibBinding::send() unable to verify signed response");
-
- unsigned long i;
- Iterator<SAMLAssertion*> _a=r->getAssertions();
- for (i=0; i < _a.size(); i++) {
- // Check any conditions.
- Iterator<SAMLCondition*> conds=_a[i]->getConditions();
- while (conds.hasNext()) {
- SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
- if (!cond || !cond->eval(audiences)) {
- log.warn("assertion condition invalid, removing it");
- r->removeAssertion(i);
- i--;
- break;
- }
- }
- }
-
- for (i=0; i < _a.size(); i++) {
- // Check signature.
- if (_a[i]->isSigned() && !t.validate(m_revocations,m_AA,*(_a[i]))) {
- log.warn("signed assertion failed to validate, removing it");
- r->removeAssertion(i);
- i--;
- }
- }
return r.release();
}
catch (SAMLException& e) {
auto_ptr<SAMLResponse> r(m_binding->send(ab, req, conf));
if (r->isSigned() && !t.validate(m_revocations,m_AA,*r))
throw TrustException("ShibBinding::send() unable to verify signed response");
-
- unsigned long i;
- Iterator<SAMLAssertion*> _a=r->getAssertions();
- for (i=0; i < _a.size(); i++) {
- // Check any conditions.
- Iterator<SAMLCondition*> conds=_a[i]->getConditions();
- while (conds.hasNext()) {
- SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
- if (!cond || !cond->eval(audiences)) {
- log.warn("assertion condition invalid, removing it");
- r->removeAssertion(i);
- i--;
- }
- }
- }
-
- for (i=0; i < _a.size(); i++) {
- // Check signature.
- if (_a[i]->isSigned() && !t.validate(m_revocations,m_AA,*(_a[i]))) {
- log.warn("signed assertion failed to validate, removing it");
- r->removeAssertion(i);
- i--;
- }
- }
return r.release();
}
catch (SAMLException& e) {
--- /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.
+ */
+
+/* ShibBrowserProfile.cpp - Shibboleth-specific wrapper around SAML browser profile
+
+ Scott Cantor
+ 2/6/05
+
+ $History:$
+*/
+
+#include "internal.h"
+
+#include <ctime>
+
+#include <openssl/x509v3.h>
+
+using namespace shibboleth;
+using namespace saml;
+using namespace log4cpp;
+using namespace std;
+
+ShibBrowserProfile::ShibBrowserProfile(
+ const Iterator<IMetadata*>& metadatas,
+ const Iterator<IRevocation*>& revocations,
+ const Iterator<ITrust*>& trusts
+ ) : m_metadatas(metadatas), m_revocations(revocations), m_trusts(trusts)
+{
+ m_profile=SAMLBrowserProfile::getInstance();
+}
+
+ShibBrowserProfile::~ShibBrowserProfile()
+{
+ delete m_profile;
+}
+
+void ShibBrowserProfile::setVersion(int major, int minor)
+{
+ m_profile->setVersion(major,minor);
+}
+
+SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
+ XMLCh** pIssuer,
+ const char* packet,
+ const XMLCh* recipient,
+ int supportedProfiles,
+ IReplayCache* replayCache,
+ SAMLBinding* callback
+ )
+{
+#ifdef _DEBUG
+ saml::NDC("recieve");
+#endif
+ Category& log=Category::getInstance(SHIB_LOGCAT".ShibBrowserProfile");
+
+ // The built-in SAML functionality will do most of the basic non-crypto checks.
+ // Note that if the response only contains a status error, it gets tossed out
+ // as an exception.
+ SAMLBrowserProfile::BrowserProfileResponse bpr =
+ m_profile->receive(pIssuer, packet, recipient, supportedProfiles, replayCache, callback);
+
+ // Try and locate metadata for the IdP. We try Issuer first.
+ log.debug("searching metadata for assertion issuer...");
+ Metadata m(m_metadatas);
+ const IEntityDescriptor* provider=m.lookup(bpr.assertion->getIssuer());
+ if (provider) {
+ if (pIssuer)
+ *pIssuer=XMLString::replicate(bpr.assertion->getIssuer());
+ log.debug("matched assertion issuer against metadata");
+ }
+ else {
+ // Might be a down-level origin.
+ provider=m.lookup(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+ if (provider) {
+ if (pIssuer)
+ *pIssuer=XMLString::replicate(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+ log.debug("matched subject name qualifier against metadata");
+ }
+ }
+
+ // No metadata at all.
+ if (!provider) {
+ auto_ptr_char issuer(bpr.assertion->getIssuer());
+ auto_ptr_char nq(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+ log.error("assertion issuer not found in metadata (Issuer='%s', NameQualifier='%s'",
+ issuer.get(), (nq.get() ? nq.get() : "null"));
+ bpr.clear();
+ throw MetadataException("ShibBrowserProfile::receive() metadata lookup failed, unable to process assertion");
+ }
+
+ // Is this provider an IdP?
+ const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
+ if (role) {
+ // Use this role to evaluate the signature(s). If the response is unsigned, we know
+ // it was an artifact profile run.
+ Trust t(m_trusts);
+ if (bpr.response->isSigned()) {
+ log.debug("passing signed response to trust layer");
+ if (!t.validate(m_revocations,role,*bpr.response)) {
+ bpr.clear();
+ throw TrustException("ShibBrowserProfile::receive() unable to verify signed response");
+ }
+ }
+ // Assertion(s) signed?
+ Iterator<SAMLAssertion*> itera=bpr.response->getAssertions();
+ while (itera.hasNext()) {
+ SAMLAssertion* _a=itera.next();
+ if (_a->isSigned()) {
+ log.debug("passing signed assertion to trust layer");
+ if (!t.validate(m_revocations,role,*_a)) {
+ bpr.clear();
+ throw TrustException("ShibBrowserProfile::receive() unable to verify signed assertion");
+ }
+ }
+ }
+ return bpr;
+ }
+
+ auto_ptr_char issuer(bpr.assertion->getIssuer());
+ auto_ptr_char nq(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+ log.error("metadata for assertion issuer indicates no SAML 1.x identity provider role (Issuer='%s', NameQualifier='%s'",
+ issuer.get(), (nq.get() ? nq.get() : "null"));
+ bpr.clear();
+ throw MetadataException("ShibBrowserProfile::receive() metadata lookup failed, issuer not registered as SAML 1.x identity provider");
+}
+++ /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.
- */
-
-/* ShibPOSTProfile.cpp - Shibboleth-specific wrapper around SAML POST profile
-
- Scott Cantor
- 8/12/02
-
- $History:$
-*/
-
-#include "internal.h"
-
-#include <ctime>
-
-#include <openssl/x509v3.h>
-
-using namespace shibboleth;
-using namespace saml;
-using namespace log4cpp;
-using namespace std;
-
-ShibPOSTProfile::ShibPOSTProfile(
- const Iterator<IMetadata*>& metadatas,
- const Iterator<IRevocation*>& revocations,
- const Iterator<ITrust*>& trusts,
- const Iterator<ICredentials*>& creds
- ) : m_metadatas(metadatas), m_revocations(revocations), m_trusts(trusts), m_creds(creds) {}
-
-const SAMLAssertion* ShibPOSTProfile::getSSOAssertion(const SAMLResponse& r, const Iterator<const XMLCh*>& audiences)
-{
- return SAMLPOSTProfile::getSSOAssertion(r,audiences);
-}
-
-const SAMLAuthenticationStatement* ShibPOSTProfile::getSSOStatement(const SAMLAssertion& a)
-{
- return SAMLPOSTProfile::getSSOStatement(a);
-}
-
-const XMLCh* ShibPOSTProfile::getProviderId(const saml::SAMLResponse& r)
-{
- // Switch to Issuer by itself, stop using NameQualifier.
- Iterator<SAMLAssertion*> ia=r.getAssertions();
- if (ia.hasNext())
- return (ia.next())->getIssuer();
- return NULL;
-}
-
-SAMLResponse* ShibPOSTProfile::accept(
- const XMLByte* buf,
- const XMLCh* recipient,
- int ttlSeconds,
- const saml::Iterator<const XMLCh*>& audiences,
- XMLCh** pproviderId)
-{
- saml::NDC("accept");
- Category& log=Category::getInstance(SHIB_LOGCAT".ShibPOSTProfile");
-
- // The built-in SAML functionality will do most of the basic non-crypto checks.
- // Note that if the response only contains a status error, it gets tossed out
- // as an exception.
- auto_ptr<SAMLResponse> r(SAMLPOSTProfile::accept(buf, recipient, ttlSeconds, false));
-
- // Now we do some more non-crypto (ie. cheap) work to match up the origin site
- // with its associated data.
- const SAMLAssertion* assertion = NULL;
- const SAMLAuthenticationStatement* sso = NULL;
-
- try {
- assertion = getSSOAssertion(*(r.get()),audiences);
- sso = getSSOStatement(*assertion);
- }
- catch (...) {
- // We want to try our best to locate an origin site name so we can fill it in.
- if (pproviderId)
- *pproviderId=XMLString::replicate(getProviderId(*(r.get())));
- throw;
- }
-
- // Finish SAML processing.
- SAMLPOSTProfile::process(*(r.get()), recipient, ttlSeconds);
-
- // Try and locate metadata for the IdP. With this new version, we try Issuer first.
- log.debug("searching metadata for assertion issuer...");
- Metadata m(m_metadatas);
- const IEntityDescriptor* provider=m.lookup(assertion->getIssuer());
- if (provider) {
- if (pproviderId)
- *pproviderId=XMLString::replicate(assertion->getIssuer());
- log.debug("matched assertion issuer against metadata");
- }
- else {
- // Might be a down-level origin.
- provider=m.lookup(sso->getSubject()->getNameIdentifier()->getNameQualifier());
- if (provider) {
- if (pproviderId)
- *pproviderId=XMLString::replicate(sso->getSubject()->getNameIdentifier()->getNameQualifier());
- log.debug("matched subject name qualifier against metadata");
- }
- }
-
- // No metadata at all.
- if (!provider) {
- auto_ptr_char issuer(assertion->getIssuer());
- auto_ptr_char nq(sso->getSubject()->getNameIdentifier()->getNameQualifier());
- log.error("assertion issuer not found in metadata (Issuer='%s', NameQualifier='%s'",
- issuer.get(), (nq.get() ? nq.get() : "null"));
- throw MetadataException("ShibPOSTProfile::accept() metadata lookup failed, unable to process assertion");
- }
-
- // Is this provider an IdP?
- const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
- if (role) {
- log.debug("passing response to trust layer");
-
- // Use this role to evaluate the signature.
- Trust t(m_trusts);
- if (!t.validate(m_revocations,role,*r))
- throw TrustException("ShibPOSTProfile::accept() unable to verify signed response");
-
- // Assertion(s) signed?
- Iterator<SAMLAssertion*> itera=r->getAssertions();
- while (itera.hasNext()) {
- SAMLAssertion* _a=itera.next();
- if (_a->isSigned()) {
- log.debug("passing signed assertion to trust layer");
- if (!t.validate(m_revocations,role,*_a))
- throw TrustException("ShibPOSTProfile::accept() unable to verify signed assertion");
- }
- }
- return r.release();
- }
-
- auto_ptr_char issuer(assertion->getIssuer());
- auto_ptr_char nq(sso->getSubject()->getNameIdentifier()->getNameQualifier());
- log.error("metadata for assertion issuer indicates no SAML 1.x identity provider role (Issuer='%s', NameQualifier='%s'",
- issuer.get(), (nq.get() ? nq.get() : "null"));
- throw MetadataException("ShibPOSTProfile::accept() metadata lookup failed, issuer not registered as SAML 1.x identity provider");
-}
-
-SAMLResponse* ShibPOSTProfile::prepare(
- const IIDPSSODescriptor* role,
- const char* credResolverId,
- const XMLCh* recipient,
- const XMLCh* authMethod,
- const SAMLDateTime& authInstant,
- const XMLCh* name,
- const XMLCh* format,
- const XMLCh* nameQualifier,
- const XMLCh* subjectIP,
- const saml::Iterator<const XMLCh*>& audiences,
- const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings)
-{
- SAMLResponse* r = SAMLPOSTProfile::prepare(
- recipient,
- role->getEntityDescriptor()->getId(),
- audiences,
- name,
- nameQualifier,
- format,
- subjectIP,
- authMethod,
- authInstant,
- bindings
- );
-
- Credentials c(m_creds);
- const ICredResolver* cr=c.lookup(credResolverId);
- if (!cr) {
- delete r;
- throw CredentialException("ShibPOSTProfile::prepare() unable to access credential resolver");
- }
- XSECCryptoKey* key=cr->getKey();
- if (!key) {
- delete r;
- throw CredentialException("ShibPOSTProfile::prepare() unable to resolve signing key");
- }
-
- r->sign(SIGNATURE_RSA,key,cr->getCertificates());
- return r;
-}
-
-bool ShibPOSTProfile::checkReplayCache(const SAMLAssertion& a)
-{
- // Default implementation uses the basic replay cache implementation.
- return SAMLPOSTProfile::checkReplayCache(a);
-}
# End Source File
# Begin Source File
-SOURCE=.\ShibConfig.cpp
+SOURCE=.\ShibBrowserProfile.cpp
# End Source File
# Begin Source File
-SOURCE=.\ShibPOSTProfile.cpp
+SOURCE=.\ShibConfig.cpp
# End Source File
# End Target
# End Project
const IAttributeRule* m_rule;
};
- // Wrapper classes around the POST profile and SAML binding
+ // Subclasses around the OpenSAML browser profile and binding interfaces,
+ // these incoporate additional functionality using Shib-defined APIs.
- class SHIB_EXPORTS ShibPOSTProfile
+ class SHIB_EXPORTS ShibBrowserProfile : virtual public saml::SAMLBrowserProfile
{
public:
- ShibPOSTProfile(
+ ShibBrowserProfile(
const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*),
const saml::Iterator<IRevocation*>& revocations=EMPTY(IRevocation*),
- const saml::Iterator<ITrust*>& trusts=EMPTY(ITrust*),
- const saml::Iterator<ICredentials*>& creds=EMPTY(ICredentials*)
+ const saml::Iterator<ITrust*>& trusts=EMPTY(ITrust*)
);
- virtual ~ShibPOSTProfile() {}
+ virtual ~ShibBrowserProfile();
- virtual const saml::SAMLAssertion* getSSOAssertion(
- const saml::SAMLResponse& r, const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*)
- );
- virtual const saml::SAMLAuthenticationStatement* getSSOStatement(const saml::SAMLAssertion& a);
- virtual saml::SAMLResponse* accept(
- const XMLByte* buf,
- const XMLCh* recipient,
- int ttlSeconds,
- const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
- XMLCh** pproviderId=NULL
- );
- virtual saml::SAMLResponse* prepare(
- const IIDPSSODescriptor* role,
- const char* credResolverId,
+ virtual void setVersion(int major, int minor);
+ virtual saml::SAMLBrowserProfile::BrowserProfileResponse receive(
+ XMLCh** pIssuer,
+ const char* packet,
const XMLCh* recipient,
- const XMLCh* authMethod,
- const saml::SAMLDateTime& authInstant,
- const XMLCh* name,
- const XMLCh* format=Constants::SHIB_NAMEID_FORMAT_URI,
- const XMLCh* nameQualifier=NULL,
- const XMLCh* subjectIP=NULL,
- const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
- const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*)
+ int supportedProfiles,
+ saml::IReplayCache* replayCache=NULL,
+ saml::SAMLBinding* callback=NULL
);
- virtual bool checkReplayCache(const saml::SAMLAssertion& a);
- virtual const XMLCh* getProviderId(const saml::SAMLResponse& r);
- protected:
- const saml::Iterator<IMetadata*>& m_metadatas;
- const saml::Iterator<IRevocation*>& m_revocations;
- const saml::Iterator<ITrust*>& m_trusts;
- const saml::Iterator<ICredentials*>& m_creds;
+ private:
+ saml::SAMLBrowserProfile* m_profile;
+ saml::Iterator<IMetadata*> m_metadatas;
+ saml::Iterator<IRevocation*> m_revocations;
+ saml::Iterator<ITrust*> m_trusts;
};
class SHIB_EXPORTS ShibBinding
Metadata m(sites);
auto_ptr<XMLCh> recip(XMLString::transcode("https://shib2.internet2.edu/shib/SHIRE"));
- ShibPOSTProfile p (sites,EMPTY(IRevocation*),EMPTY(ITrust*),EMPTY(ICredentials*));
+ ShibBrowserProfile p (sites,EMPTY(IRevocation*),EMPTY(ITrust*));
char ch;
string buf;
cin >> ch;
}
- SAMLResponse* r2=p.accept((const XMLByte*)buf.c_str(),recip.get(),300);
- cout << "Consumed Response: " << endl << *r2 << endl;
-
- const SAMLAssertion* a=p.getSSOAssertion(*r2);
- const SAMLAuthenticationStatement* s=p.getSSOStatement(*a);
- if (!p.checkReplayCache(*a))
- throw ReplayedAssertionException("detected replay attack");
-
- delete r2;
+ SAMLBrowserProfile::BrowserProfileResponse bpr=p.receive(NULL,buf.c_str(),recip.get(),SAMLBrowserProfile::Post);
+ cout << "Consumed Response: " << endl << *bpr.response << endl;
+ bpr.clear();
}
catch(SAMLException& e)
{