// globals
namespace {
+ static const XMLCh name[] = { chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull };
+ static const XMLCh port[] = { chLatin_p, chLatin_o, chLatin_r, chLatin_t, chNull };
+ static const XMLCh scheme[] = { chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_e, chNull };
+ static const XMLCh id[] = { chLatin_i, chLatin_d, chNull };
+ static const XMLCh Implementation[] =
+ { chLatin_I, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull };
+ static const XMLCh ISAPI[] = { chLatin_I, chLatin_S, chLatin_A, chLatin_P, chLatin_I, chNull };
+ static const XMLCh normalizeRequest[] =
+ { chLatin_n, chLatin_o, chLatin_r, chLatin_m, chLatin_a, chLatin_l, chLatin_i, chLatin_z, chLatin_e,
+ chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull
+ };
+ static const XMLCh Site[] = { chLatin_S, chLatin_i, chLatin_t, chLatin_e, chNull };
+
+ struct site_t {
+ site_t(const DOMElement* e)
+ {
+ auto_ptr_char n(e->getAttributeNS(NULL,name));
+ auto_ptr_char s(e->getAttributeNS(NULL,scheme));
+ auto_ptr_char p(e->getAttributeNS(NULL,port));
+ if (n.get()) m_name=n.get();
+ if (s.get()) m_scheme=s.get();
+ if (p.get()) m_port=p.get();
+ }
+ string m_scheme,m_name,m_port;
+ };
+
HINSTANCE g_hinstDLL;
ShibTargetConfig* g_Config = NULL;
- map<string,string> g_Sites;
+ map<string,site_t> g_Sites;
bool g_bNormalizeRequest = true;
}
return TRUE; // cleanup should happen when filter unloads
}
-static const XMLCh host[] = { chLatin_h, chLatin_o, chLatin_s, chLatin_t, chNull };
-static const XMLCh id[] = { chLatin_i, chLatin_d, chNull };
-static const XMLCh Implementation[] =
-{ chLatin_I, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chLatin_a, chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull };
-static const XMLCh ISAPI[] = { chLatin_I, chLatin_S, chLatin_A, chLatin_P, chLatin_I, chNull };
-static const XMLCh normalizeRequest[] =
-{ chLatin_n, chLatin_o, chLatin_r, chLatin_m, chLatin_a, chLatin_l, chLatin_i, chLatin_z, chLatin_e,
- chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull
-};
-static const XMLCh Site[] = { chLatin_S, chLatin_i, chLatin_t, chLatin_e, chNull };
-
extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
if (!pVer)
return FALSE;
+ else if (g_Config) {
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
+ "Reentrant filter initialization, ignoring...");
+ return TRUE;
+ }
try
{
impl=saml::XML::getFirstChildElement(impl,ShibTargetConfig::SHIBTARGET_NS,Site);
while (impl) {
auto_ptr_char id(impl->getAttributeNS(NULL,id));
- auto_ptr_char host(impl->getAttributeNS(NULL,host));
- if (id.get() && host.get())
- g_Sites[id.get()]=host.get();
+ if (id.get())
+ g_Sites.insert(pair<string,site_t>(id.get(),site_t(impl)));
impl=saml::XML::getNextSiblingElement(impl,ShibTargetConfig::SHIBTARGET_NS,Site);
}
}
catch (...)
{
LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Filter startup failed with an exception.");
+#ifdef _DEBUG
+ throw;
+#endif
return FALSE;
}
}
IRequestMapper::Settings map_request(
- PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, IRequestMapper* mapper, const char* hostname, string& target
+ PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, IRequestMapper* mapper, const site_t& site, string& target
)
{
- dynabuf port(10);
+ // URL path always come from IIS.
dynabuf url(256);
- GetServerVariable(pfc,"SERVER_PORT",port,10);
GetHeader(pn,pfc,"url",url,256,false);
+
+ // Port may come from IIS or from site def.
+ dynabuf port(11);
+ if (site.m_port.empty() || !g_bNormalizeRequest)
+ GetServerVariable(pfc,"SERVER_PORT",port,10);
+ else {
+ strncpy(port,site.m_port.c_str(),10);
+ static_cast<char*>(port)[10]=0;
+ }
- if (!url.empty())
- target=static_cast<char*>(url);
- if (port!=(pfc->fIsSecurePort ? "443" : "80"))
- target = ':' + static_cast<char*>(port) + target;
+ // Scheme may come from site def or be derived from IIS.
+ const char* scheme=site.m_scheme.c_str();
+ if (!scheme || !*scheme || !g_bNormalizeRequest)
+ scheme=pfc->fIsSecurePort ? "https" : "http";
+ // Start with scheme and hostname.
if (g_bNormalizeRequest) {
- target = string(pfc->fIsSecurePort ? "https://" : "http://") + hostname + target;
+ target = string(scheme) + "://" + site.m_name;
}
else {
dynabuf name(64);
GetServerVariable(pfc,"SERVER_NAME",name,64);
- target = string(pfc->fIsSecurePort ? "https://" : "http://") + static_cast<char*>(name) + target;
+ target = string(scheme) + "://" + static_cast<char*>(name);
}
- return mapper->getSettingsFromParsedURL((pfc->fIsSecurePort ? "https" : "http"),hostname,strtoul(port,NULL,10),url);
+
+ // If port is non-default, append it.
+ if ((!strcmp(scheme,"http") && port!="80") || (!strcmp(scheme,"https") && port!="443"))
+ target = target + ':' + static_cast<char*>(port);
+
+ // Append path.
+ if (!url.empty())
+ target+=static_cast<char*>(url);
+
+ return mapper->getSettingsFromParsedURL(scheme,site.m_name.c_str(),strtoul(port,NULL,10),url);
}
DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
{
LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Content-Type: text/html\r\n";
- pfc->AddResponseHeaders(pfc,const_cast<char*>(ctype),0);
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",0,0);
+ static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+ pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
"<H1>Shibboleth Filter Error</H1>";
DWORD resplen=strlen(xmsg);
if (!infile.fail()) {
const char* res = mlp.run(infile,props);
if (res) {
- static const char* ctype="Content-Type: text/html\r\n";
- pfc->AddResponseHeaders(pfc,const_cast<char*>(ctype),0);
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",0,0);
+ static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+ pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
DWORD resplen=strlen(res);
pfc->WriteClient(pfc,(LPVOID)res,&resplen,0);
return SF_STATUS_REQ_FINISHED;
return WriteClientError(pfc,"Unable to open error template, check settings.");
}
+DWORD WriteRedirectPage(PHTTP_FILTER_CONTEXT pfc, const IApplication* app, const char* file, ShibMLP& mlp, const char* headers=NULL)
+{
+ ifstream infile(file);
+ if (!infile.fail()) {
+ const char* res = mlp.run(infile,app->getPropertySet("Errors"));
+ if (res) {
+ char buf[255];
+ sprintf(buf,"Content-Length: %u\r\nContent-Type: text/html\r\n\r\n",strlen(res));
+ if (headers) {
+ string h(headers);
+ h+=buf;
+ pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)h.c_str(),0);
+ }
+ else
+ pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)buf,0);
+ DWORD resplen=strlen(res);
+ pfc->WriteClient(pfc,(LPVOID)res,&resplen,0);
+ return SF_STATUS_REQ_FINISHED;
+ }
+ }
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Extension unable to open redirect template.");
+ return WriteClientError(pfc,"Unable to open redirect template, check settings.");
+}
+
extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
{
// Is this a log notification?
GetServerVariable(pfc,"INSTANCE_ID",buf,10);
// Match site instance to host name, skip if no match.
- map<string,string>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
+ map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
if (map_i==g_Sites.end())
return SF_STATUS_REQ_NEXT_NOTIFICATION;
- const string& site=map_i->second;
-
ostringstream threadid;
threadid << "[" << getpid() << "] isapi_shib" << '\0';
saml::NDC ndc(threadid.str().c_str());
string targeturl;
IRequestMapper* mapper=conf->getRequestMapper();
Locker locker2(mapper);
- IRequestMapper::Settings settings=map_request(pfc,pn,mapper,site.c_str(),targeturl);
+ IRequestMapper::Settings settings=map_request(pfc,pn,mapper,map_i->second,targeturl);
pair<bool,const char*> application_id=settings.first->getString("applicationId");
const IApplication* application=conf->getApplication(application_id.second);
if (!application)
// Declare SHIRE object for this request.
SHIRE shire(application);
+
+ const char* shireURL=shire.getShireURL(targeturl.c_str());
+ if (!shireURL)
+ return WriteClientError(pfc,"Unable to map request to proper shireURL setting, check configuration.");
// If the user is accessing the SHIRE acceptance point, pass it on.
- if (targeturl.find(shire.getShireURL(targeturl.c_str()))!=string::npos)
+ if (targeturl.find(shireURL)!=string::npos)
return SF_STATUS_REQ_NEXT_NOTIFICATION;
// Now check the policy for this request.
pair<bool,bool> requireSession=settings.first->getBool("requireSession");
pair<const char*,const char*> shib_cookie=shire.getCookieNameProps();
+ pair<bool,bool> httpRedirects=application->getPropertySet("Sessions")->getBool("httpRedirects");
+ pair<bool,const char*> redirectPage=application->getPropertySet("Sessions")->getString("redirectPage");
+ if (httpRedirects.first && !httpRedirects.second && !redirectPage.first)
+ return WriteClientError(pfc,"HTML-based redirection requires a redirectPage property.");
// Check for session cookie.
const char* session_id=NULL;
return SF_STATUS_REQ_NEXT_NOTIFICATION;
// No acceptable cookie, and we require a session. Generate an AuthnRequest.
- string loc("Location: ");
- loc+=shire.getAuthnRequest(targeturl.c_str());
- pfc->AddResponseHeaders(pfc,const_cast<char*>(loc.c_str()),0);
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"302 Please Wait",0,0);
- return SF_STATUS_REQ_FINISHED;
+ const char* areq = shire.getAuthnRequest(targeturl.c_str());
+ if (!httpRedirects.first || httpRedirects.second) {
+ string hdrs=string("Location: ") + areq + "\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 40\r\n"
+ "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+ "Cache-Control: private,no-store,no-cache\r\n\r\n";
+ pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"302 Please Wait",(DWORD)hdrs.c_str(),0);
+ static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+ DWORD resplen=40;
+ pfc->WriteClient(pfc,(LPVOID)redmsg,&resplen,0);
+ return SF_STATUS_REQ_FINISHED;
+ }
+ else {
+ ShibMLP markupProcessor;
+ markupProcessor.insert("requestURL",areq);
+ return WriteRedirectPage(pfc, application, redirectPage.second, markupProcessor);
+ }
}
// Make sure this session is still valid.
else if (status->isRetryable()) {
// Oops, session is invalid. Generate AuthnRequest.
delete status;
- string loc("Location: ");
- loc+=shire.getAuthnRequest(targeturl.c_str());
- pfc->AddResponseHeaders(pfc,const_cast<char*>(loc.c_str()),0);
- pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"302 Please Wait",0,0);
- return SF_STATUS_REQ_FINISHED;
+ const char* areq = shire.getAuthnRequest(targeturl.c_str());
+ if (!httpRedirects.first || httpRedirects.second) {
+ string hdrs=string("Location: ") + areq + "\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 40\r\n"
+ "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+ "Cache-Control: private,no-store,no-cache\r\n\r\n";
+ pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"302 Please Wait",(DWORD)hdrs.c_str(),0);
+ static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+ DWORD resplen=40;
+ pfc->WriteClient(pfc,(LPVOID)redmsg,&resplen,0);
+ return SF_STATUS_REQ_FINISHED;
+ }
+ else {
+ markupProcessor.insert("requestURL",areq);
+ return WriteRedirectPage(pfc, application, redirectPage.second, markupProcessor);
+ }
}
else {
// return the error page to the user
// Do we have an access control plugin?
if (settings.second) {
Locker acllock(settings.second);
- if (!settings.second->authorized(assertions)) {
+ if (!settings.second->authorized(*sso_statement,assertions)) {
for (int k = 0; k < assertions.size(); k++)
delete assertions[k];
delete sso_statement;
pn->SetHeader(pfc,"Shib-NameIdentifier-Format:","");
// Export the SAML AuthnMethod and the origin site name.
- if (sso_statement) {
- auto_ptr_char os(sso_statement->getSubject()->getNameIdentifier()->getNameQualifier());
- auto_ptr_char am(sso_statement->getAuthMethod());
- pn->SetHeader(pfc,"Shib-Origin-Site:", const_cast<char*>(os.get()));
- pn->SetHeader(pfc,"Shib-Authentication-Method:", const_cast<char*>(am.get()));
-
- // Export NameID?
- AAP wrapper(provs,sso_statement->getSubject()->getNameIdentifier()->getFormat(),Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
- if (!wrapper.fail() && wrapper->getHeader()) {
- auto_ptr_char form(sso_statement->getSubject()->getNameIdentifier()->getFormat());
- auto_ptr_char nameid(sso_statement->getSubject()->getNameIdentifier()->getName());
- pn->SetHeader(pfc,"Shib-NameIdentifier-Format:",const_cast<char*>(form.get()));
- if (!strcmp(wrapper->getHeader(),"REMOTE_USER")) {
- char* principal=const_cast<char*>(nameid.get());
- pn->SetHeader(pfc,"remote-user:",principal);
- pfc->pFilterContext=pfc->AllocMem(pfc,strlen(principal)+1,0);
- if (pfc->pFilterContext)
- strcpy(static_cast<char*>(pfc->pFilterContext),principal);
- }
- else {
- string hname=string(wrapper->getHeader()) + ':';
- pn->SetHeader(pfc,const_cast<char*>(wrapper->getHeader()),const_cast<char*>(nameid.get()));
- }
+ auto_ptr_char os(sso_statement->getSubject()->getNameIdentifier()->getNameQualifier());
+ auto_ptr_char am(sso_statement->getAuthMethod());
+ pn->SetHeader(pfc,"Shib-Origin-Site:", const_cast<char*>(os.get()));
+ pn->SetHeader(pfc,"Shib-Authentication-Method:", const_cast<char*>(am.get()));
+
+ // Export NameID?
+ AAP wrapper(provs,sso_statement->getSubject()->getNameIdentifier()->getFormat(),Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
+ if (!wrapper.fail() && wrapper->getHeader()) {
+ auto_ptr_char form(sso_statement->getSubject()->getNameIdentifier()->getFormat());
+ auto_ptr_char nameid(sso_statement->getSubject()->getNameIdentifier()->getName());
+ pn->SetHeader(pfc,"Shib-NameIdentifier-Format:",const_cast<char*>(form.get()));
+ if (!strcmp(wrapper->getHeader(),"REMOTE_USER")) {
+ char* principal=const_cast<char*>(nameid.get());
+ pn->SetHeader(pfc,"remote-user:",principal);
+ pfc->pFilterContext=pfc->AllocMem(pfc,strlen(principal)+1,0);
+ if (pfc->pFilterContext)
+ strcpy(static_cast<char*>(pfc->pFilterContext),principal);
+ }
+ else {
+ string hname=string(wrapper->getHeader()) + ':';
+ pn->SetHeader(pfc,const_cast<char*>(wrapper->getHeader()),const_cast<char*>(nameid.get()));
}
}
}
IRequestMapper::Settings map_request(
- LPEXTENSION_CONTROL_BLOCK lpECB, IRequestMapper* mapper, const char* hostname, string& target
+ LPEXTENSION_CONTROL_BLOCK lpECB, IRequestMapper* mapper, const site_t& site, string& target
)
{
dynabuf ssl(5);
- dynabuf port(10);
- dynabuf url(256);
GetServerVariable(lpECB,"HTTPS",ssl,5);
- GetServerVariable(lpECB,"SERVER_PORT",port,10);
+ bool SSL=(ssl=="on" || ssl=="ON");
+
+ // URL path always come from IIS.
+ dynabuf url(256);
GetServerVariable(lpECB,"URL",url,255);
- bool SSL=(ssl=="on");
-
- if (!url.empty())
- target=static_cast<char*>(url);
- if (port!=(SSL ? "443" : "80"))
- target = ':' + static_cast<char*>(port) + target;
+ // Port may come from IIS or from site def.
+ dynabuf port(11);
+ if (site.m_port.empty() || !g_bNormalizeRequest)
+ GetServerVariable(lpECB,"SERVER_PORT",port,10);
+ else {
+ strncpy(port,site.m_port.c_str(),10);
+ static_cast<char*>(port)[10]=0;
+ }
+
+ // Scheme may come from site def or be derived from IIS.
+ const char* scheme=site.m_scheme.c_str();
+ if (!scheme || !*scheme || !g_bNormalizeRequest) {
+ scheme = SSL ? "https" : "http";
+ }
+
+ // Start with scheme and hostname.
if (g_bNormalizeRequest) {
- target = string(SSL ? "https://" : "http://") + hostname + target;
- return mapper->getSettingsFromParsedURL(lpECB->lpszMethod,hostname,strtoul(port,NULL,10),url);
+ target = string(scheme) + "://" + site.m_name;
}
else {
dynabuf name(64);
GetServerVariable(lpECB,"SERVER_NAME",name,64);
- target = string(SSL ? "https://" : "http://") + static_cast<char*>(name) + target;
- return mapper->getSettingsFromParsedURL((SSL ? "https" : "http"),name,strtoul(port,NULL,10),url);
+ target = string(scheme) + "://" + static_cast<char*>(name);
}
+
+ // If port is non-default, append it.
+ if ((!strcmp(scheme,"http") && port!="80") || (!strcmp(scheme,"https") && port!="443"))
+ target = target + ':' + static_cast<char*>(port);
+
+ // Append path.
+ if (!url.empty())
+ target+=static_cast<char*>(url);
+
+ return mapper->getSettingsFromParsedURL(scheme,site.m_name.c_str(),strtoul(port,NULL,10),url);
}
DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
{
LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
- static const char* ctype="Content-Type: text/html\r\n";
+ 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);
if (!infile.fail()) {
const char* res = mlp.run(infile,props);
if (res) {
- static const char* ctype="Content-Type: text/html\r\n";
+ 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);
DWORD resplen=strlen(res);
lpECB->WriteClient(lpECB->ConnID,(LPVOID)res,&resplen,0);
return WriteClientError(lpECB,"Unable to open error template, check settings.");
}
+DWORD WriteRedirectPage(LPEXTENSION_CONTROL_BLOCK lpECB, const IApplication* app, const char* file, ShibMLP& mlp, const char* headers=NULL)
+{
+ ifstream infile(file);
+ if (!infile.fail()) {
+ const char* res = mlp.run(infile,app->getPropertySet("Errors"));
+ if (res) {
+ char buf[255];
+ sprintf(buf,"Content-Length: %u\r\nContent-Type: text/html\r\n\r\n",strlen(res));
+ if (headers) {
+ string h(headers);
+ h+=buf;
+ lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)h.c_str());
+ }
+ else
+ lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)buf);
+ DWORD resplen=strlen(res);
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)res,&resplen,0);
+ return HSE_STATUS_SUCCESS;
+ }
+ }
+ LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Extension unable to open redirect template.");
+ return WriteClientError(lpECB,"Unable to open redirect template, check settings.");
+}
+
extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
{
string targeturl;
GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
// Match site instance to host name, skip if no match.
- map<string,string>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
+ map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
if (map_i==g_Sites.end())
return WriteClientError(lpECB,"Shibboleth filter not configured for this web site.");
- const string& site=map_i->second;
-
// We lock the configuration system for the duration.
IConfig* conf=g_Config->getINI();
Locker locker(conf);
// Map request to application and content settings.
- string targeturl;
IRequestMapper* mapper=conf->getRequestMapper();
Locker locker2(mapper);
- IRequestMapper::Settings settings=map_request(lpECB,mapper,site.c_str(),targeturl);
+ IRequestMapper::Settings settings=map_request(lpECB,mapper,map_i->second,targeturl);
pair<bool,const char*> application_id=settings.first->getString("applicationId");
application=conf->getApplication(application_id.second);
const IPropertySet* sessionProps=application ? application->getPropertySet("Sessions") : NULL;
return WriteClientError(lpECB,"Unable to map request to application session settings, check configuration.");
SHIRE shire(application);
+
+ const char* shireURL=shire.getShireURL(targeturl.c_str());
+ if (!shireURL)
+ return WriteClientError(lpECB,"Unable to map request to proper shireURL setting, check configuration.");
// Make sure we only process the SHIRE requests.
- if (!strstr(targeturl.c_str(),shire.getShireURL(targeturl.c_str())))
- return WriteClientError(lpECB,"The request's application and associated shireURL setting are inconsistent.");;
+ if (!strstr(targeturl.c_str(),shireURL))
+ return WriteClientError(lpECB,"ISAPI extension can only be invoked to process incoming sessions."
+ "Make sure the mapped file extension doesn't match actual content.");
pair<const char*,const char*> shib_cookie=shire.getCookieNameProps();
throw ShibTargetException(SHIBRPC_OK,"blocked non-SSL access to SHIRE POST processor");
}
+ pair<bool,bool> httpRedirects=sessionProps->getBool("httpRedirects");
+ pair<bool,const char*> redirectPage=sessionProps->getString("redirectPage");
+ if (httpRedirects.first && !httpRedirects.second && !redirectPage.first)
+ return WriteClientError(lpECB,"HTML-based redirection requires a redirectPage property.");
+
+ // Check for Mac web browser
+ /*
+ bool bSafari=false;
+ dynabuf agent(64);
+ GetServerVariable(lpECB,"HTTP_USER_AGENT",agent,64);
+ if (strstr(agent,"AppleWebKit/"))
+ bSafari=true;
+ */
+
// If this is a GET, we manufacture an AuthnRequest.
if (!stricmp(lpECB->lpszMethod,"GET")) {
const char* areq=lpECB->lpszQueryString ? shire.getLazyAuthnRequest(lpECB->lpszQueryString) : NULL;
if (!areq)
throw ShibTargetException(SHIBRPC_OK, "malformed arguments to request a new session");
- targeturl = string("Location: ") + areq + "\r\n"
- "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache\r\n"
- "Connection: close\r\n";
- HSE_SEND_HEADER_EX_INFO hinfo;
- hinfo.pszStatus="302 Moved";
- hinfo.pszHeader=targeturl.c_str();
- hinfo.cchStatus=9;
- hinfo.cchHeader=targeturl.length();
- hinfo.fKeepConn=FALSE;
- if (lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER_EX,&hinfo,0,0))
+ if (!httpRedirects.first || httpRedirects.second) {
+ string hdrs=string("Location: ") + areq + "\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 40\r\n"
+ "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+ "Cache-Control: private,no-store,no-cache\r\n\r\n";
+ lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"302 Moved",0,(LPDWORD)hdrs.c_str());
+ static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+ DWORD resplen=40;
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)redmsg,&resplen,HSE_IO_SYNC);
return HSE_STATUS_SUCCESS;
- return HSE_STATUS_ERROR;
+ }
+ else {
+ ShibMLP markupProcessor;
+ markupProcessor.insert("requestURL",areq);
+ return WriteRedirectPage(lpECB, application, redirectPage.second, markupProcessor);
+ }
}
else if (stricmp(lpECB->lpszMethod,"POST"))
throw ShibTargetException(SHIBRPC_OK,"blocked non-POST to SHIRE POST processor");
if (status->isRetryable()) {
delete status;
const char* loc=shire.getAuthnRequest(elements.second);
- DWORD len=strlen(loc);
- if (lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_URL_REDIRECT_RESP,(LPVOID)loc,&len,0))
+ if (!httpRedirects.first || httpRedirects.second) {
+ string hdrs=string("Location: ") + loc + "\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 40\r\n"
+ "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+ "Cache-Control: private,no-store,no-cache\r\n\r\n";
+ lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"302 Moved",0,(LPDWORD)hdrs.c_str());
+ static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+ DWORD resplen=40;
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)redmsg,&resplen,HSE_IO_SYNC);
return HSE_STATUS_SUCCESS;
- return HSE_STATUS_ERROR;
+ }
+ else {
+ markupProcessor.insert("requestURL",loc);
+ return WriteRedirectPage(lpECB, application, redirectPage.second, markupProcessor);
+ }
}
// Return this error to the user.
// We've got a good session, set the cookie and redirect to target.
cookie = string("Set-Cookie: ") + shib_cookie.first + '=' + cookie + shib_cookie.second + "\r\n"
- "Location: " + elements.second + "\r\n"
"Expires: 01-Jan-1997 12:00:00 GMT\r\n"
- "Cache-Control: private,no-store,no-cache\r\n"
- "Connection: close\r\n";
- HSE_SEND_HEADER_EX_INFO hinfo;
- hinfo.pszStatus="302 Moved";
- hinfo.pszHeader=cookie.c_str();
- hinfo.cchStatus=9;
- hinfo.cchHeader=cookie.length();
- hinfo.fKeepConn=FALSE;
- if (lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER_EX,&hinfo,0,0))
+ "Cache-Control: private,no-store,no-cache\r\n";
+ if (!httpRedirects.first || httpRedirects.second) {
+ cookie=cookie + "Content-Type: text/html\r\nLocation: " + elements.second + "\r\nContent-Length: 40\r\n\r\n";
+ lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"302 Moved",0,(LPDWORD)cookie.c_str());
+ static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
+ DWORD resplen=40;
+ lpECB->WriteClient(lpECB->ConnID,(LPVOID)redmsg,&resplen,HSE_IO_SYNC);
return HSE_STATUS_SUCCESS;
+ }
+ else {
+ markupProcessor.insert("requestURL",elements.second);
+ return WriteRedirectPage(lpECB, application, redirectPage.second, markupProcessor, cookie.c_str());
+ }
}
catch (ShibTargetException &e) {
if (application) {