# define _CRT_SECURE_NO_DEPRECATE 1
#endif
+#include <shibsp/AbstractSPRequest.h>
#include <shibsp/AccessControl.h>
#include <shibsp/exceptions.h>
#include <shibsp/RequestMapper.h>
#endif
using namespace shibsp;
-using namespace shibtarget;
using namespace xmltooling;
using namespace std;
namespace {
char* g_szSHIBConfig = NULL;
char* g_szSchemaDir = NULL;
- ShibTargetConfig* g_Config = NULL;
+ shibtarget::ShibTargetConfig* g_Config = NULL;
string g_unsetHeaderValue;
static const char* g_UserDataKey = "_shib_check_user_";
}
/********************************************************************************/
// Apache ShibTarget subclass(es) here.
-class ShibTargetApache : public ShibTarget
+class ShibTargetApache : public AbstractSPRequest
{
mutable string m_body;
mutable bool m_gotBody;
ShibTargetApache sta(r);
// Check user authentication and export information, then set the handler bypass
- pair<bool,long> res = sta.doCheckAuthN(true);
+ pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta,true);
apr_pool_userdata_setn((const void*)42,g_UserDataKey,NULL,r->pool);
if (res.first) return res.second;
// user auth was okay -- export the assertions now
- res = sta.doExportAssertions();
+ res = sta.getServiceProvider().doExport(sta);
if (res.first) return res.second;
// export happened successfully.. this user is ok.
try {
ShibTargetApache sta(r);
- pair<bool,long> res = sta.doHandler();
+ pair<bool,long> res = sta.getServiceProvider().doHandler(sta);
if (res.first) return res.second;
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "doHandler() did not do anything.");
try {
ShibTargetApache sta(r);
- pair<bool,long> res = sta.doCheckAuthZ();
+ pair<bool,long> res = sta.getServiceProvider().doAuthorization(sta);
if (res.first) return res.second;
// We're all okay.
}
}
else {
- saml::Iterator<shibboleth::IAAP*> provs=dynamic_cast<const IApplication&>(request.getApplication()).getAAPProviders();
+ saml::Iterator<shibboleth::IAAP*> provs=dynamic_cast<const shibtarget::IApplication&>(request.getApplication()).getAAPProviders();
shibboleth::AAP wrapper(provs,w);
if (wrapper.fail()) {
request.log(SPRequest::SPWarn, string("htAccessControl plugin didn't recognize require rule: ") + w);
}
try {
- g_Config=&ShibTargetConfig::getConfig();
+ g_Config=&shibtarget::ShibTargetConfig::getConfig();
SPConfig::getConfig().setFeatures(
SPConfig::Caching |
SPConfig::Listener |
#define _CRT_NONSTDC_NO_DEPRECATE 1
#define _CRT_SECURE_NO_DEPRECATE 1
+#include <shibsp/AbstractSPRequest.h>
#include <shibsp/SPConfig.h>
#include <xmltooling/util/NDC.h>
#include <httpext.h>
using namespace shibsp;
-using namespace shibtarget;
using namespace xmltooling;
using namespace std;
};
HINSTANCE g_hinstDLL;
- ShibTargetConfig* g_Config = NULL;
+ shibtarget::ShibTargetConfig* g_Config = NULL;
map<string,site_t> g_Sites;
bool g_bNormalizeRequest = true;
}
LPCSTR config=getenv("SHIBCONFIG");
if (!config)
config=SHIB_CONFIG;
- g_Config=&ShibTargetConfig::getConfig();
+ g_Config=&shibtarget::ShibTargetConfig::getConfig();
SPConfig::getConfig().setFeatures(
SPConfig::Listener |
SPConfig::Caching |
/****************************************************************************/
// ISAPI Filter
-class ShibTargetIsapiF : public ShibTarget
+class ShibTargetIsapiF : public AbstractSPRequest
{
PHTTP_FILTER_CONTEXT m_pfc;
PHTTP_FILTER_PREPROC_HEADERS m_pn;
ShibTargetIsapiF stf(pfc, pn, map_i->second);
// "false" because we don't override the Shib settings
- pair<bool,long> res = stf.doCheckAuthN();
+ pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
if (res.first) return res.second;
// "false" because we don't override the Shib settings
- res = stf.doExportAssertions();
+ res = stf.getServiceProvider().doExport(stf);
if (res.first) return res.second;
- res = stf.doCheckAuthZ();
+ res = stf.getServiceProvider().doAuthorization(stf);
if (res.first) return res.second;
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
-class ShibTargetIsapiE : public ShibTarget
+class ShibTargetIsapiE : public AbstractSPRequest
{
LPEXTENSION_CONTROL_BLOCK m_lpECB;
map<string,string> m_headers;
extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
{
- string targeturl;
- const IApplication* application=NULL;
try {
ostringstream threadid;
threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
return WriteClientError(lpECB, "Shibboleth Extension not configured for this web site.");
ShibTargetIsapiE ste(lpECB, map_i->second);
- pair<bool,long> res = ste.doHandler();
+ pair<bool,long> res = ste.getServiceProvider().doHandler(ste);
if (res.first) return res.second;
return WriteClientError(lpECB, "Shibboleth Extension failed to process request");
# define _CRT_SECURE_NO_DEPRECATE 1
#endif
+#include <shibsp/AbstractSPRequest.h>
#include <shibsp/RequestMapper.h>
#include <shibsp/SPConfig.h>
#include <xmltooling/util/NDC.h>
}
using namespace shibsp;
-using namespace shibtarget;
using namespace xmltooling;
using namespace std;
if (IO_ERROR==net_write(sn->csd,str,strlen(str))) return REQ_EXIT
namespace {
- ShibTargetConfig* g_Config=NULL;
+ shibtarget::ShibTargetConfig* g_Config=NULL;
string g_ServerName;
string g_ServerScheme;
string g_unsetHeaderValue;
config=getenv("SHIBCONFIG");
if (!config)
config=SHIB_CONFIG;
- g_Config=&ShibTargetConfig::getConfig();
+ g_Config=&shibtarget::ShibTargetConfig::getConfig();
SPConfig::getConfig().setFeatures(
SPConfig::Listener |
SPConfig::Caching |
/********************************************************************************/
// NSAPI Shib Target Subclass
-class ShibTargetNSAPI : public ShibTarget
+class ShibTargetNSAPI : public AbstractSPRequest
{
string m_uri;
mutable string m_body;
ShibTargetNSAPI stn(pb, sn, rq);
// Check user authentication
- pair<bool,long> res = stn.doCheckAuthN();
+ pair<bool,long> res = stn.getServiceProvider().doAuthentication(stn);
if (res.first) return (int)res.second;
// user authN was okay -- export the assertions now
// This seems to be required in order to eventually set
// the auth-user var.
pblock_nvinsert("auth-type","shibboleth",rq->vars);
- res = stn.doExportAssertions();
+ res = stn.getServiceProvider().doExport(stn);
if (res.first) return (int)res.second;
// Check the Authorization
- res = stn.doCheckAuthZ();
+ res = stn.getServiceProvider().doAuthorization(stn);
if (res.first) return (int)res.second;
// this user is ok.
try {
ShibTargetNSAPI stn(pb, sn, rq);
- pair<bool,long> res = stn.doHandler();
+ pair<bool,long> res = stn.getServiceProvider().doHandler(stn);
if (res.first) return (int)res.second;
return WriteClientError(sn, rq, FUNC, "Shibboleth handler did not do anything.");
shib-ccache.cpp \
shib-config.cpp \
shib-handlers.cpp \
- shib-ini.cpp \
- shib-target.cpp
+ shib-ini.cpp
# this is different from the project version
# http://sources.redhat.com/autobook/autobook/autobook_91.html
#include <saml/util/CommonDomainCookie.h>
#include <shibsp/AbstractHandler.h>
#include <shibsp/SPConfig.h>
+#include <shibsp/SPRequest.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
+++ /dev/null
-/*
- * Copyright 2001-2005 Internet2
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * shib-target.cpp -- The ShibTarget class, a superclass for general
- * target code
- *
- * Created by: Derek Atkins <derek@ihtfp.com>
- *
- * $Id$
- */
-
-#include "internal.h"
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include <fstream>
-
-#include <saml/SAMLConfig.h>
-#include <xercesc/util/Base64.hpp>
-#include <shibsp/AccessControl.h>
-#include <shibsp/RequestMapper.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/TemplateEngine.h>
-#include <xmltooling/util/XMLHelper.h>
-
-#ifndef HAVE_STRCASECMP
-# define strcasecmp stricmp
-#endif
-
-using namespace shibsp;
-using namespace shibtarget;
-using namespace shibboleth;
-using namespace saml;
-using namespace opensaml::saml2md;
-using namespace log4cpp;
-using namespace std;
-
-using xmltooling::TemplateEngine;
-using xmltooling::XMLToolingException;
-using xmltooling::XMLToolingConfig;
-using xmltooling::XMLHelper;
-
-namespace shibtarget {
-
- class ExtTemplateParameters : public TemplateEngine::TemplateParameters
- {
- const PropertySet* m_props;
- public:
- ExtTemplateParameters() : m_props(NULL) {}
- ~ExtTemplateParameters() {}
-
- void setPropertySet(const PropertySet* props) {
- m_props = props;
-
- // Create a timestamp.
- time_t now = time(NULL);
-#ifdef HAVE_CTIME_R
- char timebuf[32];
- m_map["now"] = ctime_r(&now,timebuf);
-#else
- m_map["now"] = ctime(&now);
-#endif
- }
-
- const char* getParameter(const char* name) const {
- const char* pch = TemplateParameters::getParameter(name);
- if (pch || !m_props)
- return pch;
- pair<bool,const char*> p = m_props->getString(name);
- return p.first ? p.second : NULL;
- }
- };
-
- long _sendError(SPRequest* st, const char* page, ExtTemplateParameters& tp, const XMLToolingException* ex=NULL);
-
- static const XMLCh SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
-}
-
-
-/*************************************************************************
- * Shib Target implementation
- */
-
-
-
-// These functions implement the server-agnostic shibboleth engine
-// The web server modules implement a subclass and then call into
-// these methods once they instantiate their request object.
-
-pair<bool,long> ShibTarget::doCheckAuthN(bool handler)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("doCheckAuthN");
-#endif
-
- const char* procState = "Request Processing Error";
- string targetURL = getRequestURL();
- ExtTemplateParameters tp;
-
- try {
- RequestMapper::Settings settings = getRequestSettings();
- const IApplication& app = dynamic_cast<const IApplication&>(getApplication());
-
- // If not SSL, check to see if we should block or redirect it.
- if (!strcmp("http",getScheme())) {
- pair<bool,const char*> redirectToSSL = settings.first->getString("redirectToSSL");
- if (redirectToSSL.first) {
- if (!strcasecmp("GET",getMethod()) || !strcasecmp("HEAD",getMethod())) {
- // Compute the new target URL
- string redirectURL = string("https://") + getHostname();
- if (strcmp(redirectToSSL.second,"443")) {
- redirectURL = redirectURL + ':' + redirectToSSL.second;
- }
- redirectURL += getRequestURI();
- return make_pair(true, sendRedirect(redirectURL.c_str()));
- }
- else {
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "ssl", tp));
- }
- }
- }
-
- const char* handlerURL=getHandlerURL(targetURL.c_str());
- if (!handlerURL)
- throw ConfigurationException("Cannot determine handler from resource URL, check configuration.");
-
- // If the request URL contains the handler base URL for this application, either dispatch
- // directly (mainly Apache 2.0) or just pass back control.
- if (strstr(targetURL.c_str(),handlerURL)) {
- if (handler)
- return doHandler();
- else
- return make_pair(true, returnOK());
- }
-
- // Three settings dictate how to proceed.
- pair<bool,const char*> authType = settings.first->getString("authType");
- pair<bool,bool> requireSession = settings.first->getBool("requireSession");
- pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
-
- // If no session is required AND the AuthType (an Apache-derived concept) isn't shibboleth,
- // then we ignore this request and consider it unprotected. Apache might lie to us if
- // ShibBasicHijack is on, but that's up to it.
- if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
-#ifdef HAVE_STRCASECMP
- (!authType.first || strcasecmp(authType.second,"shibboleth")))
-#else
- (!authType.first || _stricmp(authType.second,"shibboleth")))
-#endif
- return make_pair(true,returnDecline());
-
- // Fix for secadv 20050901
- clearHeaders();
-
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- const char* session_id = getCookie(shib_cookie.first.c_str());
- if (!session_id || !*session_id) {
- // No session. Maybe that's acceptable?
- if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
- return make_pair(true,returnOK());
-
- // No cookie, but we require a session. Initiate a new session using the indicated method.
- procState = "Session Initiator Error";
- const Handler* initiator=NULL;
- if (requireSessionWith.first) {
- initiator=app.getSessionInitiatorById(requireSessionWith.second);
- if (!initiator)
- throw ConfigurationException(
- "No session initiator found with id ($1), check requireSessionWith command.",
- xmltooling::params(1,requireSessionWith.second)
- );
- }
- else {
- initiator=app.getDefaultSessionInitiator();
- if (!initiator)
- throw ConfigurationException("No default session initiator found, check configuration.");
- }
-
- return initiator->run(*this,false);
- }
-
- procState = "Session Processing Error";
- const Session* session=NULL;
- try {
- session=getSession();
- // Make a localized exception throw if the session isn't valid.
- if (!session)
- throw RetryableProfileException("Session no longer valid.");
- }
- catch (exception& e) {
- log(SPWarn, string("session processing failed: ") + e.what());
-
- // If no session is required, bail now.
- if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
- // Has to be OK because DECLINED will just cause Apache
- // to fail when it can't locate anything to process the
- // AuthType. No session plus requireSession false means
- // do not authenticate the user at this time.
- return make_pair(true, returnOK());
-
- // Try and cast down.
- exception* base = &e;
- RetryableProfileException* trycast=dynamic_cast<RetryableProfileException*>(base);
- if (trycast) {
- // Session is invalid but we can retry -- initiate a new session.
- procState = "Session Initiator Error";
- const Handler* initiator=NULL;
- if (requireSessionWith.first) {
- initiator=app.getSessionInitiatorById(requireSessionWith.second);
- if (!initiator)
- throw ConfigurationException(
- "No session initiator found with id ($1), check requireSessionWith command.",
- xmltooling::params(1,requireSessionWith.second)
- );
- }
- else {
- initiator=app.getDefaultSessionInitiator();
- if (!initiator)
- throw ConfigurationException("No default session initiator found, check configuration.");
- }
- return initiator->run(*this,false);
- }
- throw; // send it to the outer handler
- }
-
- // We're done. Everything is okay. Nothing to report. Nothing to do..
- // Let the caller decide how to proceed.
- log(SPDebug, "doCheckAuthN succeeded");
- return make_pair(false,0);
- }
- catch (XMLToolingException& e) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = e.what();
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "session", tp, &e));
- }
-#ifndef _DEBUG
- catch (...) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = "Caught an unknown exception.";
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "session", tp));
- }
-#endif
-}
-
-pair<bool,long> ShibTarget::doHandler(void)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("doHandler");
-#endif
-
- const IApplication* app=NULL;
- ExtTemplateParameters tp;
- const char* procState = "Shibboleth Handler Error";
- string targetURL = getRequestURL();
-
- try {
- RequestMapper::Settings settings = getRequestSettings();
- app = dynamic_cast<const IApplication*>(&getApplication());
-
- const char* handlerURL=getHandlerURL(targetURL.c_str());
- if (!handlerURL)
- throw ConfigurationException("Cannot determine handler from resource URL, check configuration.");
-
- // Make sure we only process handler requests.
- if (!strstr(targetURL.c_str(),handlerURL))
- return make_pair(true, returnDecline());
-
- const PropertySet* sessionProps=app->getPropertySet("Sessions");
- if (!sessionProps)
- throw ConfigurationException("Unable to map request to application session settings, check configuration.");
-
- // Process incoming request.
- pair<bool,bool> handlerSSL=sessionProps->getBool("handlerSSL");
-
- // Make sure this is SSL, if it should be
- if ((!handlerSSL.first || handlerSSL.second) && strcmp(getScheme(),"https"))
- throw FatalProfileException("Blocked non-SSL access to Shibboleth handler.");
-
- // We dispatch based on our path info. We know the request URL begins with or equals the handler URL,
- // so the path info is the next character (or null).
- const Handler* handler=app->getHandler(targetURL.c_str() + strlen(handlerURL));
- if (!handler)
- throw opensaml::BindingException("Shibboleth handler invoked at an unconfigured location.");
-
- if (XMLHelper::isNodeNamed(handler->getElement(),samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME))
- procState = "Session Creation Error";
- else if (XMLString::equals(handler->getElement()->getLocalName(),SessionInitiator))
- procState = "Session Initiator Error";
- else if (XMLHelper::isNodeNamed(handler->getElement(),samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME))
- procState = "Session Termination Error";
- else
- procState = "Protocol Handler Error";
- pair<bool,long> hret=handler->run(*this);
-
- // Did the handler run successfully?
- if (hret.first)
- return hret;
-
- throw opensaml::BindingException("Configured Shibboleth handler failed to process the request.");
- }
- catch (MetadataException& e) {
- tp.m_map["errorText"] = e.what();
- // See if a metadata error page is installed.
- const PropertySet* props=app->getPropertySet("Errors");
- if (props) {
- pair<bool,const char*> p=props->getString("metadata");
- if (p.first) {
- tp.m_map["errorType"] = procState;
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "metadata", tp));
- }
- }
- throw;
- }
- catch (XMLToolingException& e) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = e.what();
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "session", tp, &e));
- }
-#ifndef _DEBUG
- catch (...) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = "Caught an unknown exception.";
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "session", tp));
- }
-#endif
-}
-
-pair<bool,long> ShibTarget::doCheckAuthZ(void)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("doCheckAuthZ");
-#endif
-
- const IApplication* app=NULL;
- ExtTemplateParameters tp;
- const char* procState = "Authorization Processing Error";
- string targetURL = getRequestURL();
-
- try {
- RequestMapper::Settings settings = getRequestSettings();
- app = dynamic_cast<const IApplication*>(&getApplication());
-
- // Three settings dictate how to proceed.
- pair<bool,const char*> authType = settings.first->getString("authType");
- pair<bool,bool> requireSession = settings.first->getBool("requireSession");
- pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
-
- // If no session is required AND the AuthType (an Apache-derived concept) isn't shibboleth,
- // then we ignore this request and consider it unprotected. Apache might lie to us if
- // ShibBasicHijack is on, but that's up to it.
- if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
-#ifdef HAVE_STRCASECMP
- (!authType.first || strcasecmp(authType.second,"shibboleth")))
-#else
- (!authType.first || _stricmp(authType.second,"shibboleth")))
-#endif
- return make_pair(true,returnDecline());
-
- // Do we have an access control plugin?
- if (settings.second) {
- const Session* session =NULL;
- pair<string,const char*> shib_cookie=app->getCookieNameProps("_shibsession_");
- const char *session_id = getCookie(shib_cookie.first.c_str());
- try {
- if (session_id && *session_id) {
- session = getSession();
- }
- }
- catch (exception&) {
- log(SPWarn, "doCheckAuthZ: unable to obtain session information to pass to access control provider");
- }
-
- xmltooling::Locker acllock(settings.second);
- if (settings.second->authorized(*this,session)) {
- // Let the caller decide how to proceed.
- log(SPDebug, "doCheckAuthZ: access control provider granted access");
- return make_pair(false,0);
- }
- else {
- log(SPWarn, "doCheckAuthZ: access control provider denied access");
- tp.m_map["requestURL"] = targetURL;
- return make_pair(true,_sendError(this, "access", tp));
- }
- return make_pair(false,0);
- }
- else
- return make_pair(true,returnDecline());
- }
- catch (exception& e) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = e.what();
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "access", tp));
- }
-#ifndef _DEBUG
- catch (...) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = "Caught an unknown exception.";
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "access", tp));
- }
-#endif
-}
-
-pair<bool,long> ShibTarget::doExportAssertions(bool requireSession)
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("doExportAssertions");
-#endif
-
- const IApplication* app=NULL;
- ExtTemplateParameters tp;
- const char* procState = "Attribute Processing Error";
- string targetURL = getRequestURL();
-
- try {
- RequestMapper::Settings settings = getRequestSettings();
- app = dynamic_cast<const IApplication*>(&getApplication());
-
- const Session* session=NULL;
- pair<string,const char*> shib_cookie=app->getCookieNameProps("_shibsession_");
- const char *session_id = getCookie(shib_cookie.first.c_str());
- try {
- if (session_id && *session_id) {
- session = getSession();
- }
- }
- catch (exception&) {
- log(SPWarn, "unable to obtain session information to export into request headers");
- // If we have to have a session, then this is a fatal error.
- if (requireSession)
- throw;
- }
-
- // Still no data?
- if (!session) {
- if (requireSession)
- throw RetryableProfileException("Unable to obtain session information for request.");
- else
- return make_pair(false,0); // just bail silently
- }
-
- /*
- TODO: port to new cache API
- // Extract data from session.
- pair<const char*,const SAMLSubject*> sub=m_cacheEntry->getSubject(false,true);
- pair<const char*,const SAMLResponse*> unfiltered=m_cacheEntry->getTokens(true,false);
- pair<const char*,const SAMLResponse*> filtered=m_cacheEntry->getTokens(false,true);
-
- // Maybe export the tokens.
- pair<bool,bool> exp=m_settings.first->getBool("exportAssertion");
- if (exp.first && exp.second && unfiltered.first && *unfiltered.first) {
- unsigned int outlen;
- XMLByte* serialized =
- Base64::encode(reinterpret_cast<XMLByte*>((char*)unfiltered.first), XMLString::stringLen(unfiltered.first), &outlen);
- XMLByte *pos, *pos2;
- for (pos=serialized, pos2=serialized; *pos2; pos2++)
- if (isgraph(*pos2))
- *pos++=*pos2;
- *pos=0;
- setHeader("Shib-Attributes", reinterpret_cast<char*>(serialized));
- XMLString::release(&serialized);
- }
-
- // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.
- setHeader("Shib-Origin-Site", m_cacheEntry->getProviderId());
- setHeader("Shib-Identity-Provider", m_cacheEntry->getProviderId());
- setHeader("Shib-Authentication-Method", m_cacheEntry->getAuthnContext());
-
- // Get the AAP providers, which contain the attribute policy info.
- Iterator<IAAP*> provs=m_app->getAAPProviders();
-
- // Export NameID?
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- xmltooling::Locker locker(aap);
- const XMLCh* format = sub.second->getNameIdentifier()->getFormat();
- const IAttributeRule* rule=aap->lookup(format ? format : SAMLNameIdentifier::UNSPECIFIED);
- if (rule && rule->getHeader()) {
- auto_ptr_char form(format ? format : SAMLNameIdentifier::UNSPECIFIED);
- auto_ptr_char nameid(sub.second->getNameIdentifier()->getName());
- setHeader("Shib-NameIdentifier-Format", form.get());
- if (!strcmp(rule->getHeader(),"REMOTE_USER"))
- setRemoteUser(nameid.get());
- else
- setHeader(rule->getHeader(), nameid.get());
- }
- }
-
- setHeader("Shib-Application-ID", m_app->getId());
-
- // Export the attributes.
- Iterator<SAMLAssertion*> a_iter(filtered.second ? filtered.second->getAssertions() : EMPTY(SAMLAssertion*));
- while (a_iter.hasNext()) {
- SAMLAssertion* assert=a_iter.next();
- Iterator<SAMLStatement*> statements=assert->getStatements();
- while (statements.hasNext()) {
- SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());
- if (!astate)
- continue;
- Iterator<SAMLAttribute*> attrs=astate->getAttributes();
- while (attrs.hasNext()) {
- SAMLAttribute* attr=attrs.next();
-
- // Are we supposed to export it?
- provs.reset();
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- xmltooling::Locker locker(aap);
- const IAttributeRule* rule=aap->lookup(attr->getName(),attr->getNamespace());
- if (!rule || !rule->getHeader())
- continue;
-
- Iterator<string> vals=attr->getSingleByteValues();
- if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())
- setRemoteUser(vals.next().c_str());
- else {
- int it=0;
- string header = getSecureHeader(rule->getHeader());
- if (!header.empty())
- it++;
- for (; vals.hasNext(); it++) {
- string value = vals.next();
- for (string::size_type pos = value.find_first_of(";", string::size_type(0));
- pos != string::npos;
- pos = value.find_first_of(";", pos)) {
- value.insert(pos, "\\");
- pos += 2;
- }
- if (it)
- header += ";";
- header += value;
- }
- setHeader(rule->getHeader(), header.c_str());
- }
- }
- }
- }
- }
- */
-
- return make_pair(false,0);
- }
- catch (XMLToolingException& e) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = e.what();
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "rm", tp, &e));
- }
-#ifndef _DEBUG
- catch (...) {
- tp.m_map["errorType"] = procState;
- tp.m_map["errorText"] = "Caught an unknown exception.";
- tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
- return make_pair(true,_sendError(this, "rm", tp));
- }
-#endif
-}
-
-/*************************************************************************
- * Shib Target Private implementation
- */
-
-long shibtarget::_sendError(
- SPRequest* st, const char* page, ExtTemplateParameters& tp, const XMLToolingException* ex
- )
-{
- st->setContentType("text/html");
- st->setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
- st->setResponseHeader("Cache-Control","private,no-store,no-cache");
-
- TemplateEngine* engine = XMLToolingConfig::getConfig().getTemplateEngine();
- const PropertySet* props=st->getApplication().getPropertySet("Errors");
- if (props) {
- pair<bool,const char*> p=props->getString(page);
- if (p.first) {
- ifstream infile(p.second);
- if (infile) {
- tp.setPropertySet(props);
- stringstream str;
- engine->run(infile, str, tp, ex);
- return st->sendResponse(str);
- }
- }
- else if (!strcmp(page,"access")) {
- istringstream msg("Access Denied");
- return static_cast<opensaml::GenericResponse*>(st)->sendResponse(msg, opensaml::HTTPResponse::SAML_HTTP_STATUS_FORBIDDEN);
- }
- }
-
- string errstr = string("sendError could not process error template (") + page + ")";
- st->log(SPRequest::SPError, errstr);
- istringstream msg("Internal Server Error. Please contact the site administrator.");
- return st->sendError(msg);
-}
-
-void ShibTarget::clearHeaders()
-{
- // Clear invariant stuff.
- clearHeader("Shib-Origin-Site");
- clearHeader("Shib-Identity-Provider");
- clearHeader("Shib-Authentication-Method");
- clearHeader("Shib-NameIdentifier-Format");
- clearHeader("Shib-Attributes");
- clearHeader("Shib-Application-ID");
-
- // Clear out the list of mapped attributes
- Iterator<IAAP*> provs=dynamic_cast<const IApplication&>(getApplication()).getAAPProviders();
- while (provs.hasNext()) {
- IAAP* aap=provs.next();
- xmltooling::Locker locker(aap);
- Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
- while (rules.hasNext()) {
- const char* header=rules.next()->getHeader();
- if (header)
- clearHeader(header);
- }
- }
-}
#define SHIB_TARGET_H
// New headers
-#include <shibsp/AbstractSPRequest.h>
#include <shibsp/Application.h>
#include <shibsp/Handler.h>
#include <shibsp/RequestMapper.h>
static ShibTargetConfig& getConfig();
};
- class ShibTargetPriv;
- class SHIBTARGET_EXPORTS ShibTarget : public shibsp::AbstractSPRequest {
- public:
- virtual ~ShibTarget() {}
-
- //
- // Note: Subclasses need not implement anything below this line
- //
-
- // These functions implement the server-agnostic shibboleth engine
- // The web server modules implement a subclass and then call into
- // these methods once they instantiate their request object.
- //
- // Return value:
- // these APIs will always return the result of sendPage(), sendRedirect(),
- // returnDecline(), or returnOK() in the void* portion of the return code.
- // Exactly what those values are is module- (subclass-) implementation
- // specific. The 'bool' part of the return value declares whether the
- // void* is valid or not. If the bool is true then the void* is valid.
- // If the bool is false then the API did not call any callback, the void*
- // is not valid, and the caller should continue processing (the API Call
- // finished successfully).
- //
- // 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,long> doCheckAuthN(bool handler = false);
- std::pair<bool,long> doHandler();
- std::pair<bool,long> doCheckAuthZ();
- std::pair<bool,long> doExportAssertions(bool requireSession = true);
-
- protected:
- ShibTarget() {}
-
- private:
- void clearHeaders();
- };
-
}
#endif /* SHIB_TARGET_H */
>
</File>
<File
- RelativePath="shib-target.cpp"
- >
- </File>
- <File
RelativePath="shib-target.h"
>
</File>
utilinclude_HEADERS = \
util/DOMPropertySet.h \
util/PropertySet.h \
- util/SPConstants.h
+ util/SPConstants.h \
+ util/TemplateParameters.h
noinst_HEADERS = \
internal.h \
remoting/impl/UnixListener.cpp \
security/PKIXTrustEngine.cpp \
util/DOMPropertySet.cpp \
- util/SPConstants.cpp
+ util/SPConstants.cpp \
+ util/TemplateParameters.cpp
# this is different from the project version
# http://sources.redhat.com/autobook/autobook/autobook_91.html
*/
#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "Application.h"
+#include "Handler.h"
#include "ServiceProvider.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+#include "util/TemplateParameters.h"
-#include <xercesc/dom/DOM.hpp>
+#include <fstream>
+#include <sstream>
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/util/SAMLConstants.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
using namespace xmltooling;
-using namespace xercesc;
using namespace std;
namespace shibsp {
//SHIBSP_DLLLOCAL PluginManager<ServiceProvider,const DOMElement*>::Factory XMLServiceProviderFactory;
+
+ long SHIBSP_DLLLOCAL sendError(
+ SPRequest& request, const Application* app, const char* page, TemplateParameters& tp, const XMLToolingException* ex=NULL
+ )
+ {
+ request.setContentType("text/html");
+ request.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
+ request.setResponseHeader("Cache-Control","private,no-store,no-cache");
+
+ const PropertySet* props=app ? app->getPropertySet("Errors") : NULL;
+ if (props) {
+ pair<bool,const char*> p=props->getString(page);
+ if (p.first) {
+ ifstream infile(p.second);
+ if (infile) {
+ tp.setPropertySet(props);
+ stringstream str;
+ XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, ex);
+ return request.sendResponse(str);
+ }
+ }
+ else if (!strcmp(page,"access")) {
+ istringstream msg("Access Denied");
+ return static_cast<opensaml::GenericResponse&>(request).sendResponse(msg, HTTPResponse::SAML_HTTP_STATUS_FORBIDDEN);
+ }
+ }
+
+ string errstr = string("sendError could not process error template (") + page + ")";
+ request.log(SPRequest::SPError, errstr);
+ istringstream msg("Internal Server Error. Please contact the site administrator.");
+ return request.sendError(msg);
+ }
+
+ void SHIBSP_DLLLOCAL clearHeaders(SPRequest& request) {
+ // Clear invariant stuff.
+ request.clearHeader("Shib-Origin-Site");
+ request.clearHeader("Shib-Identity-Provider");
+ request.clearHeader("Shib-Authentication-Method");
+ request.clearHeader("Shib-NameIdentifier-Format");
+ request.clearHeader("Shib-Attributes");
+ request.clearHeader("Shib-Application-ID");
+
+ // Clear out the list of mapped attributes
+ /* TODO: port
+ Iterator<IAAP*> provs=dynamic_cast<const IApplication&>(getApplication()).getAAPProviders();
+ while (provs.hasNext()) {
+ IAAP* aap=provs.next();
+ xmltooling::Locker locker(aap);
+ Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
+ while (rules.hasNext()) {
+ const char* header=rules.next()->getHeader();
+ if (header)
+ request.clearHeader(header);
+ }
+ }
+ */
+ }
+
+ static const XMLCh SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);\r
};
void SHIBSP_API shibsp::registerServiceProviders()
pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handler) const
{
- return make_pair(true,0);
+#ifdef _DEBUG\r
+ xmltooling::NDC ndc("doAuthentication");\r
+#endif\r
+\r
+ const Application* app=NULL;\r
+ const char* procState = "Request Processing Error";\r
+ string targetURL = request.getRequestURL();\r
+\r
+ try {\r
+ RequestMapper::Settings settings = request.getRequestSettings();\r
+ app = &(request.getApplication());\r
+\r
+ // If not SSL, check to see if we should block or redirect it.\r
+ if (!request.isSecure()) {\r
+ pair<bool,const char*> redirectToSSL = settings.first->getString("redirectToSSL");\r
+ if (redirectToSSL.first) {\r
+#ifdef HAVE_STRCASECMP\r
+ if (!strcasecmp("GET",request.getMethod()) || !strcasecmp("HEAD",request.getMethod())) {\r
+#else\r
+ if (!stricmp("GET",request.getMethod()) || !stricmp("HEAD",request.getMethod())) {\r
+#endif\r
+ // Compute the new target URL\r
+ string redirectURL = string("https://") + request.getHostname();\r
+ if (strcmp(redirectToSSL.second,"443")) {\r
+ redirectURL = redirectURL + ':' + redirectToSSL.second;\r
+ }\r
+ redirectURL += request.getRequestURI();\r
+ return make_pair(true, request.sendRedirect(redirectURL.c_str()));\r
+ }\r
+ else {\r
+ TemplateParameters tp;\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "ssl", tp));\r
+ }\r
+ }\r
+ }\r
+ \r
+ const char* handlerURL=request.getHandlerURL(targetURL.c_str());\r
+ if (!handlerURL)\r
+ throw ConfigurationException("Cannot determine handler from resource URL, check configuration.");\r
+\r
+ // If the request URL contains the handler base URL for this application, either dispatch\r
+ // directly (mainly Apache 2.0) or just pass back control.\r
+ if (strstr(targetURL.c_str(),handlerURL)) {\r
+ if (handler)\r
+ return doHandler(request);\r
+ else\r
+ return make_pair(true, request.returnOK());\r
+ }\r
+\r
+ // Three settings dictate how to proceed.\r
+ pair<bool,const char*> authType = settings.first->getString("authType");\r
+ pair<bool,bool> requireSession = settings.first->getBool("requireSession");\r
+ pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");\r
+\r
+ // If no session is required AND the AuthType (an Apache-derived concept) isn't shibboleth,\r
+ // then we ignore this request and consider it unprotected. Apache might lie to us if\r
+ // ShibBasicHijack is on, but that's up to it.\r
+ if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&\r
+#ifdef HAVE_STRCASECMP\r
+ (!authType.first || strcasecmp(authType.second,"shibboleth")))\r
+#else\r
+ (!authType.first || _stricmp(authType.second,"shibboleth")))\r
+#endif\r
+ return make_pair(true,request.returnDecline());\r
+\r
+ // Fix for secadv 20050901\r
+ clearHeaders(request);\r
+\r
+ pair<string,const char*> shib_cookie = app->getCookieNameProps("_shibsession_");\r
+ const char* session_id = request.getCookie(shib_cookie.first.c_str());\r
+ if (!session_id || !*session_id) {\r
+ // No session. Maybe that's acceptable?\r
+ if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)\r
+ return make_pair(true,request.returnOK());\r
+\r
+ // No cookie, but we require a session. Initiate a new session using the indicated method.\r
+ procState = "Session Initiator Error";\r
+ const Handler* initiator=NULL;\r
+ if (requireSessionWith.first) {\r
+ initiator=app->getSessionInitiatorById(requireSessionWith.second);\r
+ if (!initiator)\r
+ throw ConfigurationException(\r
+ "No session initiator found with id ($1), check requireSessionWith command.",\r
+ params(1,requireSessionWith.second)\r
+ );\r
+ }\r
+ else {\r
+ initiator=app->getDefaultSessionInitiator();\r
+ if (!initiator)\r
+ throw ConfigurationException("No default session initiator found, check configuration.");\r
+ }\r
+\r
+ return initiator->run(request,false);\r
+ }\r
+\r
+ procState = "Session Processing Error";\r
+ const Session* session=NULL;\r
+ try {\r
+ session=request.getSession();\r
+ // Make a localized exception throw if the session isn't valid.\r
+ if (!session)\r
+ throw RetryableProfileException("Session no longer valid.");\r
+ }\r
+ catch (exception& e) {\r
+ request.log(SPRequest::SPWarn, string("session processing failed: ") + e.what());\r
+\r
+ // If no session is required, bail now.\r
+ if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)\r
+ // Has to be OK because DECLINED will just cause Apache\r
+ // to fail when it can't locate anything to process the\r
+ // AuthType. No session plus requireSession false means\r
+ // do not authenticate the user at this time.\r
+ return make_pair(true, request.returnOK());\r
+\r
+ // Try and cast down.\r
+ exception* base = &e;\r
+ RetryableProfileException* trycast=dynamic_cast<RetryableProfileException*>(base);\r
+ if (trycast) {\r
+ // Session is invalid but we can retry -- initiate a new session.\r
+ procState = "Session Initiator Error";\r
+ const Handler* initiator=NULL;\r
+ if (requireSessionWith.first) {\r
+ initiator=app->getSessionInitiatorById(requireSessionWith.second);\r
+ if (!initiator)\r
+ throw ConfigurationException(\r
+ "No session initiator found with id ($1), check requireSessionWith command.",\r
+ params(1,requireSessionWith.second)\r
+ );\r
+ }\r
+ else {\r
+ initiator=app->getDefaultSessionInitiator();\r
+ if (!initiator)\r
+ throw ConfigurationException("No default session initiator found, check configuration.");\r
+ }\r
+ return initiator->run(request,false);\r
+ }\r
+ throw; // send it to the outer handler\r
+ }\r
+\r
+ // We're done. Everything is okay. Nothing to report. Nothing to do..\r
+ // Let the caller decide how to proceed.\r
+ request.log(SPRequest::SPDebug, "doAuthentication succeeded");\r
+ return make_pair(false,0);\r
+ }\r
+ catch (XMLToolingException& e) {\r
+ TemplateParameters tp;\r
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = e.what();\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "session", tp, &e));\r
+ }\r
+ catch (exception& e) {\r
+ TemplateParameters tp;\r
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = e.what();\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "session", tp));\r
+ }\r
+#ifndef _DEBUG\r
+ catch (...) {\r
+ TemplateParameters tp;\r
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = "Caught an unknown exception.";\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "session", tp));\r
+ }\r
+#endif\r
}
pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
{
- return make_pair(true,0);
+#ifdef _DEBUG\r
+ xmltooling::NDC ndc("doAuthorization");\r
+#endif\r
+\r
+ const Application* app=NULL;\r
+ const char* procState = "Authorization Processing Error";\r
+ string targetURL = request.getRequestURL();\r
+\r
+ try {\r
+ RequestMapper::Settings settings = request.getRequestSettings();\r
+ app = &(request.getApplication());\r
+\r
+ // Three settings dictate how to proceed.\r
+ pair<bool,const char*> authType = settings.first->getString("authType");\r
+ pair<bool,bool> requireSession = settings.first->getBool("requireSession");\r
+ pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");\r
+\r
+ // If no session is required AND the AuthType (an Apache-derived concept) isn't shibboleth,\r
+ // then we ignore this request and consider it unprotected. Apache might lie to us if\r
+ // ShibBasicHijack is on, but that's up to it.\r
+ if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&\r
+#ifdef HAVE_STRCASECMP\r
+ (!authType.first || strcasecmp(authType.second,"shibboleth")))\r
+#else\r
+ (!authType.first || _stricmp(authType.second,"shibboleth")))\r
+#endif\r
+ return make_pair(true,request.returnDecline());\r
+\r
+ // Do we have an access control plugin?\r
+ if (settings.second) {\r
+ const Session* session =NULL;\r
+ pair<string,const char*> shib_cookie=app->getCookieNameProps("_shibsession_");\r
+ const char *session_id = request.getCookie(shib_cookie.first.c_str());\r
+ try {\r
+ if (session_id && *session_id) {\r
+ session = request.getSession();\r
+ }\r
+ }\r
+ catch (exception&) {\r
+ request.log(SPRequest::SPWarn, "unable to obtain session information to pass to access control provider");\r
+ }\r
+ \r
+ Locker acllock(settings.second);\r
+ if (settings.second->authorized(request,session)) {\r
+ // Let the caller decide how to proceed.\r
+ request.log(SPRequest::SPDebug, "access control provider granted access");\r
+ return make_pair(false,0);\r
+ }\r
+ else {\r
+ request.log(SPRequest::SPWarn, "access control provider denied access");\r
+ TemplateParameters tp;\r
+ tp.m_map["requestURL"] = targetURL;\r
+ return make_pair(true,sendError(request, app, "access", tp));\r
+ }\r
+ return make_pair(false,0);\r
+ }\r
+ else\r
+ return make_pair(true,request.returnDecline());\r
+ }\r
+ catch (XMLToolingException& e) {
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;
+ tp.m_map["errorText"] = e.what();
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ return make_pair(true,sendError(request, app, "session", tp, &e));
+ }
+ catch (exception& e) {\r
+ TemplateParameters tp;\r
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = e.what();\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "access", tp));\r
+ }\r
+#ifndef _DEBUG\r
+ catch (...) {\r
+ TemplateParameters tp;\r
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = "Caught an unknown exception.";\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "access", tp));\r
+ }\r
+#endif\r
}
pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSession) const
{
- return make_pair(true,0);
+#ifdef _DEBUG\r
+ xmltooling::NDC ndc("doExport");\r
+#endif\r
+\r
+ const Application* app=NULL;\r
+ const char* procState = "Attribute Processing Error";\r
+ string targetURL = request.getRequestURL();\r
+\r
+ try {\r
+ RequestMapper::Settings settings = request.getRequestSettings();
+ app = &(request.getApplication());
+\r
+ const Session* session=NULL;\r
+ pair<string,const char*> shib_cookie=app->getCookieNameProps("_shibsession_");\r
+ const char *session_id = request.getCookie(shib_cookie.first.c_str());\r
+ try {\r
+ if (session_id && *session_id) {\r
+ session = request.getSession();\r
+ }\r
+ }\r
+ catch (exception&) {\r
+ request.log(SPRequest::SPWarn, "unable to obtain session information to export into request headers");\r
+ // If we have to have a session, then this is a fatal error.\r
+ if (requireSession)\r
+ throw;\r
+ }\r
+\r
+ // Still no data?\r
+ if (!session) {\r
+ if (requireSession)\r
+ throw RetryableProfileException("Unable to obtain session information for request.");\r
+ else\r
+ return make_pair(false,0); // just bail silently\r
+ }\r
+ \r
+ /*\r
+ TODO: port to new cache API\r
+ // Extract data from session.\r
+ pair<const char*,const SAMLSubject*> sub=m_cacheEntry->getSubject(false,true);\r
+ pair<const char*,const SAMLResponse*> unfiltered=m_cacheEntry->getTokens(true,false);\r
+ pair<const char*,const SAMLResponse*> filtered=m_cacheEntry->getTokens(false,true);\r
+\r
+ // Maybe export the tokens.\r
+ pair<bool,bool> exp=m_settings.first->getBool("exportAssertion");\r
+ if (exp.first && exp.second && unfiltered.first && *unfiltered.first) {\r
+ unsigned int outlen;\r
+ XMLByte* serialized =\r
+ Base64::encode(reinterpret_cast<XMLByte*>((char*)unfiltered.first), XMLString::stringLen(unfiltered.first), &outlen);\r
+ XMLByte *pos, *pos2;\r
+ for (pos=serialized, pos2=serialized; *pos2; pos2++)\r
+ if (isgraph(*pos2))\r
+ *pos++=*pos2;\r
+ *pos=0;\r
+ setHeader("Shib-Attributes", reinterpret_cast<char*>(serialized));\r
+ XMLString::release(&serialized);\r
+ }\r
+\r
+ // Export the SAML AuthnMethod and the origin site name, and possibly the NameIdentifier.\r
+ setHeader("Shib-Origin-Site", m_cacheEntry->getProviderId());\r
+ setHeader("Shib-Identity-Provider", m_cacheEntry->getProviderId());\r
+ setHeader("Shib-Authentication-Method", m_cacheEntry->getAuthnContext());\r
+ \r
+ // Get the AAP providers, which contain the attribute policy info.\r
+ Iterator<IAAP*> provs=m_app->getAAPProviders();\r
+\r
+ // Export NameID?\r
+ while (provs.hasNext()) {\r
+ IAAP* aap=provs.next();\r
+ xmltooling::Locker locker(aap);\r
+ const XMLCh* format = sub.second->getNameIdentifier()->getFormat();\r
+ const IAttributeRule* rule=aap->lookup(format ? format : SAMLNameIdentifier::UNSPECIFIED);\r
+ if (rule && rule->getHeader()) {\r
+ auto_ptr_char form(format ? format : SAMLNameIdentifier::UNSPECIFIED);\r
+ auto_ptr_char nameid(sub.second->getNameIdentifier()->getName());\r
+ setHeader("Shib-NameIdentifier-Format", form.get());\r
+ if (!strcmp(rule->getHeader(),"REMOTE_USER"))\r
+ setRemoteUser(nameid.get());\r
+ else\r
+ setHeader(rule->getHeader(), nameid.get());\r
+ }\r
+ }\r
+ \r
+ setHeader("Shib-Application-ID", m_app->getId());\r
+ \r
+ // Export the attributes.\r
+ Iterator<SAMLAssertion*> a_iter(filtered.second ? filtered.second->getAssertions() : EMPTY(SAMLAssertion*));\r
+ while (a_iter.hasNext()) {\r
+ SAMLAssertion* assert=a_iter.next();\r
+ Iterator<SAMLStatement*> statements=assert->getStatements();\r
+ while (statements.hasNext()) {\r
+ SAMLAttributeStatement* astate=dynamic_cast<SAMLAttributeStatement*>(statements.next());\r
+ if (!astate)\r
+ continue;\r
+ Iterator<SAMLAttribute*> attrs=astate->getAttributes();\r
+ while (attrs.hasNext()) {\r
+ SAMLAttribute* attr=attrs.next();\r
+ \r
+ // Are we supposed to export it?\r
+ provs.reset();\r
+ while (provs.hasNext()) {\r
+ IAAP* aap=provs.next();\r
+ xmltooling::Locker locker(aap);\r
+ const IAttributeRule* rule=aap->lookup(attr->getName(),attr->getNamespace());\r
+ if (!rule || !rule->getHeader())\r
+ continue;\r
+ \r
+ Iterator<string> vals=attr->getSingleByteValues();\r
+ if (!strcmp(rule->getHeader(),"REMOTE_USER") && vals.hasNext())\r
+ setRemoteUser(vals.next().c_str());\r
+ else {\r
+ int it=0;\r
+ string header = getSecureHeader(rule->getHeader());\r
+ if (!header.empty())\r
+ it++;\r
+ for (; vals.hasNext(); it++) {\r
+ string value = vals.next();\r
+ for (string::size_type pos = value.find_first_of(";", string::size_type(0));\r
+ pos != string::npos;\r
+ pos = value.find_first_of(";", pos)) {\r
+ value.insert(pos, "\\");\r
+ pos += 2;\r
+ }\r
+ if (it)\r
+ header += ";";\r
+ header += value;\r
+ }\r
+ setHeader(rule->getHeader(), header.c_str());\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ */\r
+ \r
+ return make_pair(false,0);\r
+ }\r
+ catch (XMLToolingException& e) {\r
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = e.what();\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "rm", tp, &e));\r
+ }\r
+ catch (exception& e) {
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;
+ tp.m_map["errorText"] = e.what();
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ return make_pair(true,sendError(request, app, "rm", tp));
+ }
+#ifndef _DEBUG\r
+ catch (...) {\r
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;\r
+ tp.m_map["errorText"] = "Caught an unknown exception.";\r
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));\r
+ return make_pair(true,sendError(request, app, "rm", tp));\r
+ }\r
+#endif\r
}
pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
{
- return make_pair(true,0);
+#ifdef _DEBUG
+ xmltooling::NDC ndc("doHandler");
+#endif
+
+ const Application* app=NULL;
+ const char* procState = "Shibboleth Handler Error";
+ string targetURL = request.getRequestURL();
+
+ try {
+ RequestMapper::Settings settings = request.getRequestSettings();
+ app = &(request.getApplication());
+
+ const char* handlerURL=request.getHandlerURL(targetURL.c_str());
+ if (!handlerURL)
+ throw ConfigurationException("Cannot determine handler from resource URL, check configuration.");
+
+ // Make sure we only process handler requests.
+ if (!strstr(targetURL.c_str(),handlerURL))
+ return make_pair(true, request.returnDecline());
+
+ const PropertySet* sessionProps=app->getPropertySet("Sessions");
+ if (!sessionProps)
+ throw ConfigurationException("Unable to map request to application session settings, check configuration.");
+
+ // Process incoming request.
+ pair<bool,bool> handlerSSL=sessionProps->getBool("handlerSSL");
+
+ // Make sure this is SSL, if it should be
+ if ((!handlerSSL.first || handlerSSL.second) && strcmp(request.getScheme(),"https"))
+ throw FatalProfileException("Blocked non-SSL access to Shibboleth handler.");
+
+ // We dispatch based on our path info. We know the request URL begins with or equals the handler URL,
+ // so the path info is the next character (or null).
+ const Handler* handler=app->getHandler(targetURL.c_str() + strlen(handlerURL));
+ if (!handler)
+ throw BindingException("Shibboleth handler invoked at an unconfigured location.");
+
+ if (XMLHelper::isNodeNamed(handler->getElement(),samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME))
+ procState = "Session Creation Error";
+ else if (XMLString::equals(handler->getElement()->getLocalName(),SessionInitiator))
+ procState = "Session Initiator Error";
+ else if (XMLHelper::isNodeNamed(handler->getElement(),samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME))
+ procState = "Session Termination Error";
+ else
+ procState = "Protocol Handler Error";
+ pair<bool,long> hret=handler->run(request);
+
+ // Did the handler run successfully?
+ if (hret.first)
+ return hret;
+
+ throw BindingException("Configured Shibboleth handler failed to process the request.");
+ }
+ catch (MetadataException& e) {
+ TemplateParameters tp;
+ tp.m_map["errorText"] = e.what();
+ // See if a metadata error page is installed.
+ const PropertySet* props=app->getPropertySet("Errors");
+ if (props) {
+ pair<bool,const char*> p=props->getString("metadata");
+ if (p.first) {
+ tp.m_map["errorType"] = procState;
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ return make_pair(true,sendError(request, app, "metadata", tp, &e));
+ }
+ }
+ throw;
+ }
+ catch (XMLToolingException& e) {
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;
+ tp.m_map["errorText"] = e.what();
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ return make_pair(true,sendError(request, app, "session", tp, &e));
+ }
+ catch (exception& e) {
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;
+ tp.m_map["errorText"] = e.what();
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ return make_pair(true,sendError(request, app, "session", tp));
+ }
+#ifndef _DEBUG
+ catch (...) {
+ TemplateParameters tp;
+ tp.m_map["errorType"] = procState;
+ tp.m_map["errorText"] = "Caught an unknown exception.";
+ tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+ return make_pair(true,sendError(request, app, "session", tp));
+ }
+#endif
}
class SHIBSP_API RequestMapper;
class SHIBSP_API SessionCache;
class SHIBSP_API SPRequest;
+ class SHIBSP_API TemplateParameters;
/**
* Interface to a Shibboleth ServiceProvider instance.
RelativePath=".\util\SPConstants.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\util\TemplateParameters.cpp"\r
+ >\r
+ </File>\r
</Filter>\r
<Filter\r
Name="security"\r
RelativePath=".\util\SPConstants.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath=".\util\TemplateParameters.h"\r
+ >\r
+ </File>\r
</Filter>\r
<Filter\r
Name="security"\r
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * TemplateParameters.cpp
+ *
+ * Supplies xmltooling TemplateEngine with additional parameters from a PropertySet.
+ */
+
+#include "internal.h"
+#include "util/TemplateParameters.h"
+
+#include <ctime>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+void TemplateParameters::setPropertySet(const PropertySet* props)
+{
+ m_props = props;
+
+ // Create a timestamp.
+ time_t now = time(NULL);
+#ifdef HAVE_CTIME_R
+ char timebuf[32];
+ m_map["now"] = ctime_r(&now,timebuf);
+#else
+ m_map["now"] = ctime(&now);
+#endif
+}
+
+const char* TemplateParameters::getParameter(const char* name) const
+{
+ const char* pch = TemplateEngine::TemplateParameters::getParameter(name);
+ if (pch || !m_props)
+ return pch;
+ pair<bool,const char*> p = m_props->getString(name);
+ return p.first ? p.second : NULL;
+}
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file shibsp/util/TemplateParameters.h
+ *
+ * Supplies xmltooling TemplateEngine with additional parameters from a PropertySet.
+ */
+
+#ifndef __shibsp_tempparams_h__
+#define __shibsp_tempparams_h__
+
+#include <shibsp/util/PropertySet.h>
+#include <xmltooling/util/TemplateEngine.h>
+
+namespace shibsp {
+
+ /**
+ * Supplies xmltooling TemplateEngine with additional parameters from a PropertySet.
+ */
+ class SHIBSP_API TemplateParameters : public xmltooling::TemplateEngine::TemplateParameters
+ {
+ public:
+ /**
+ * Constructor
+ *
+ * @param props a PropertySet to supply additional parameters
+ */
+ TemplateParameters(const PropertySet* props=NULL) {
+ setPropertySet(props);
+ }
+
+ virtual ~TemplateParameters() {}
+
+ /**
+ * Sets a PropertySet to supply additional parameters.
+ *
+ * @param props a PropertySet to supply additional parameters
+ */
+ void setPropertySet(const PropertySet* props);
+
+ const char* getParameter(const char* name) const;
+
+ private:
+ const PropertySet* m_props;
+ };
+};
+
+#endif /* __shibsp_tempparams_h__ */