- string targeturl;
- const IApplication* application=NULL;
- try
- {
- ostringstream threadid;
- threadid << "[" << getpid() << "] shib_handler" << '\0';
- saml::NDC ndc(threadid.str().c_str());
-
- // We lock the configuration system for the duration.
- IConfig* conf=g_Config->getINI();
- Locker locker(conf);
-
- // Map request to application and content settings.
- IRequestMapper* mapper=conf->getRequestMapper();
- Locker locker2(mapper);
- IRequestMapper::Settings settings=map_request(pb,sn,rq,mapper,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;
- if (!application || !sessionProps)
- return WriteClientError(sn,rq,FUNC,"Unable to map request to application settings, check configuration.");
-
- SHIRE shire(application);
-
- const char* shireURL=shire.getShireURL(targeturl.c_str());
- if (!shireURL)
- return WriteClientError(sn,rq,FUNC,"Unable to map request to proper shireURL setting, check configuration.");
-
- // Make sure we only process the SHIRE requests.
- if (!strstr(targeturl.c_str(),shireURL))
- return WriteClientError(sn,rq,FUNC,"NSAPI service function can only be invoked to process incoming sessions."
- "Make sure the mapped file extension or URL doesn't match actual content.");
-
- pair<const char*,const char*> shib_cookie=shire.getCookieNameProps();
-
- // Make sure this is SSL, if it should be
- pair<bool,bool> shireSSL=sessionProps->getBool("shireSSL");
- if (!shireSSL.first || shireSSL.second) {
- if (!security_active)
- throw ShibTargetException(SHIBRPC_OK,"blocked non-SSL access to Shibboleth session 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(sn,rq,FUNC,"HTML-based redirection requires a redirectPage property.");
-
- // If this is a GET, we manufacture an AuthnRequest.
- if (!strcasecmp(pblock_findval("method",rq->reqpb),"GET")) {
- const char* areq=pblock_findval("query",rq->reqpb) ? shire.getLazyAuthnRequest(pblock_findval("query",rq->reqpb)) : NULL;
- if (!areq)
- throw ShibTargetException(SHIBRPC_OK, "malformed arguments to request a new session");
- if (!httpRedirects.first || httpRedirects.second) {
- pblock_nvinsert("Content-Type","text/html",rq->srvhdrs);
- pblock_nvinsert("Content-Length","40",rq->srvhdrs);
- pblock_nvinsert("Expires","01-Jan-1997 12:00:00 GMT",rq->srvhdrs);
- pblock_nvinsert("Cache-Control","private,no-store,no-cache",rq->srvhdrs);
- pblock_nvinsert("Location",areq,rq->srvhdrs);
- protocol_status(sn,rq,PROTOCOL_REDIRECT,"302 Please wait");
- protocol_start_response(sn,rq);
- NET_WRITE("<HTML><BODY>Redirecting...</BODY></HTML>");
- return REQ_EXIT;
- }
- else {
- ShibMLP markupProcessor;
- markupProcessor.insert("requestURL",areq);
- return WriteRedirectPage(sn, rq, application, redirectPage.second, markupProcessor);
- }
- }
- else if (strcasecmp(pblock_findval("method",rq->reqpb),"POST"))
- throw ShibTargetException(SHIBRPC_OK,"blocked non-POST to Shibboleth session processor");
-
- // Make sure this POST is an appropriate content type
- char* content_type=NULL;
- if (request_header("content-type",&content_type,sn,rq)!=REQ_PROCEED ||
- !content_type || strcasecmp(content_type,"application/x-www-form-urlencoded"))
- throw ShibTargetException(SHIBRPC_OK,"blocked bad content-type to Shibboleth session processor");
-
- // Read the data.
- pair<const char*,const char*> elements=pair<const char*,const char*>(NULL,NULL);
- char* content_length=NULL;
- if (request_header("content-length",&content_length,sn,rq)!=REQ_PROCEED ||
- atoi(content_length) > 1024*1024) // 1MB?
- throw ShibTargetException(SHIBRPC_OK,"blocked too-large a post to Shibboleth session processor");
- else {
- char ch=IO_EOF+1;
- int cl=atoi(content_length);
- string cgistr;
- while (cl && ch!=IO_EOF) {
- ch=netbuf_getc(sn->inbuf);
-
- // Check for error.
- if(ch==IO_ERROR)
- break;
- cgistr+=ch;
- cl--;
- }
- if (cl)
- throw ShibTargetException(SHIBRPC_OK,"error reading POST data from browser");
- elements=shire.getFormSubmission(cgistr.c_str(),cgistr.length());
- }
-
- // Make sure the SAML Response parameter exists
- if (!elements.first || !*elements.first)
- throw ShibTargetException(SHIBRPC_OK, "Shibboleth POST failed to find SAMLResponse form element");
-
- // Make sure the target parameter exists
- if (!elements.second || !*elements.second)
- throw ShibTargetException(SHIBRPC_OK, "Shibboleth POST failed to find TARGET form element");
-
- // Process the post.
- string cookie;
- RPCError* status=NULL;
- ShibMLP markupProcessor;
- markupProcessor.insert("requestURL", targeturl.c_str());
- try {
- status = shire.sessionCreate(elements.first,pblock_findval("ip",sn->client),cookie);
- }
- catch (ShibTargetException &e) {
- markupProcessor.insert("errorType", "Session Creation Service Error");
- markupProcessor.insert("errorText", e.what());
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return WriteClientError(sn, rq, application, "shire", markupProcessor);
- }
-#ifndef _DEBUG
- catch (...) {
- markupProcessor.insert("errorType", "Session Creation Service Error");
- markupProcessor.insert("errorText", "Unexpected Exception");
- markupProcessor.insert("errorDesc", "An error occurred while processing your request.");
- return WriteClientError(sn, rq, application, "shire", markupProcessor);
- }
-#endif
-
- if (status->isError()) {
- if (status->isRetryable()) {
- delete status;
- const char* loc=shire.getAuthnRequest(elements.second);
- if (!httpRedirects.first || httpRedirects.second) {
- pblock_nvinsert("Content-Type","text/html",rq->srvhdrs);
- pblock_nvinsert("Content-Length","40",rq->srvhdrs);
- pblock_nvinsert("Expires","01-Jan-1997 12:00:00 GMT",rq->srvhdrs);
- pblock_nvinsert("Cache-Control","private,no-store,no-cache",rq->srvhdrs);
- pblock_nvinsert("Location",loc,rq->srvhdrs);
- protocol_status(sn,rq,PROTOCOL_REDIRECT,"302 Please wait");
- protocol_start_response(sn,rq);
- NET_WRITE("<HTML><BODY>Redirecting...</BODY></HTML>");
- return REQ_EXIT;
- }
- else {
- markupProcessor.insert("requestURL",loc);
- return WriteRedirectPage(sn, rq, application, redirectPage.second, markupProcessor);
- }
- }
-
- // Return this error to the user.
- markupProcessor.insert(*status);
- delete status;
- return WriteClientError(sn,rq,application,"shire",markupProcessor);
- }
- delete status;
-
- // We've got a good session, set the cookie and redirect to target.
- cookie = string(shib_cookie.first) + '=' + cookie + shib_cookie.second;
- pblock_nvinsert("Set-Cookie",cookie.c_str(),rq->srvhdrs);
- if (!httpRedirects.first || httpRedirects.second) {
- pblock_nvinsert("Content-Type","text/html",rq->srvhdrs);
- pblock_nvinsert("Content-Length","40",rq->srvhdrs);
- pblock_nvinsert("Expires","01-Jan-1997 12:00:00 GMT",rq->srvhdrs);
- pblock_nvinsert("Cache-Control","private,no-store,no-cache",rq->srvhdrs);
- pblock_nvinsert("Location",elements.second,rq->srvhdrs);
- protocol_status(sn,rq,PROTOCOL_REDIRECT,"302 Please wait");
- protocol_start_response(sn,rq);
- NET_WRITE("<HTML><BODY>Redirecting...</BODY></HTML>");
- return REQ_EXIT;
- }
- else {
- markupProcessor.insert("requestURL",elements.second);
- return WriteRedirectPage(sn, rq, application, redirectPage.second, markupProcessor);
- }