From: Derek Atkins Date: Thu, 8 Apr 2004 15:03:39 +0000 (+0000) Subject: Remove old apache-1.3 and apache-2.0 code, as we now use the combined module X-Git-Tag: 1.2.1~252 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-sp.git;a=commitdiff_plain;h=13a288bd0e877a7f5740f50c55418e67800ecc4e Remove old apache-1.3 and apache-2.0 code, as we now use the combined module --- diff --git a/Makefile.am b/Makefile.am index 3dd5d71..fea6bc7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,5 +25,4 @@ WANT_SUBDIRS = @WANT_SUBDIRS@ SUBDIRS = $(WANT_SUBDIRS) DIST_SUBDIRS = doc oncrpc shib schemas configs shib-target shar test \ - mod_shire apache-2.0 apache siterefresh shib-mysql-ccache \ - xmlproviders + apache siterefresh shib-mysql-ccache xmlproviders diff --git a/apache-2.0/.gitignore b/apache-2.0/.gitignore deleted file mode 100644 index 9d7d30d..0000000 --- a/apache-2.0/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -/Makefile.in -/Makefile -/.libs -/.deps -/*.lo -/*.la -/Debug -/*.plg -/Release -/*.dep -/*.mak \ No newline at end of file diff --git a/apache-2.0/Makefile.am b/apache-2.0/Makefile.am deleted file mode 100644 index 0210da7..0000000 --- a/apache-2.0/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -## $Id$ - -AUTOMAKE_OPTIONS = foreign - -if USE_OUR_ONCRPC -RPC_CFLAGS = -I${top_srcdir}/oncrpc -endif - -modshibdir = $(libexecdir) -modshib_LTLIBRARIES = mod_shib.la - -mod_shib_la_SOURCES = mod_shib.cpp - -AM_CXXFLAGS = $(APXS2_CFLAGS) -I$(APXS2_INCLUDE) $(RPC_CFLAGS) - -mod_shib_la_LIBADD = $(top_builddir)/shib/libshib.la $(top_builddir)/shib-target/libshib-target.la - -mod_shib_la_LDFLAGS = -module -avoid-version - -if DO_APXS2_INSTALL -install-exec-local: - $(APXS2) -i -A -n shib .libs/mod_shib.so -endif - -EXTRA_DIST = mod_shib.dsp diff --git a/apache-2.0/apache2.dsp b/apache-2.0/apache2.dsp deleted file mode 100644 index fee35e2..0000000 --- a/apache-2.0/apache2.dsp +++ /dev/null @@ -1,95 +0,0 @@ -# Microsoft Developer Studio Project File - Name="apache2" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=apache2 - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "apache2.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "apache2.mak" CFG="apache2 - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "apache2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "apache2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "apache2 - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APACHE2_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\oncrpc" /I ".." /I "..\..\..\opensaml\c" /I "\Apache2\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 saml_4.lib libapr.lib libhttpd.lib /nologo /dll /machine:I386 /out:"Release/mod_shib.dll" /libpath:"../../../opensaml/c/saml/Release" /libpath:"\httpd-2.0.48\srclib\apr\Release" /libpath:"\httpd-2.0.48\Release" - -!ELSEIF "$(CFG)" == "apache2 - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APACHE2_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\oncrpc" /I ".." /I "..\..\..\opensaml\c" /I "\Apache2\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /FR /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 saml_4D.lib libapr.lib libhttpd.lib /nologo /dll /debug /machine:I386 /out:"Debug/mod_shib.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /libpath:"\httpd-2.0.48\srclib\apr\Debug" /libpath:"\httpd-2.0.48\Debug" - -!ENDIF - -# Begin Target - -# Name "apache2 - Win32 Release" -# Name "apache2 - Win32 Debug" -# Begin Source File - -SOURCE=.\mod_shib.cpp -# End Source File -# End Target -# End Project diff --git a/apache-2.0/mod_shib.cpp b/apache-2.0/mod_shib.cpp deleted file mode 100644 index 1ea22ca..0000000 --- a/apache-2.0/mod_shib.cpp +++ /dev/null @@ -1,1036 +0,0 @@ -/* - * mod_shib.cpp -- Shibboleth module for Apache-2.0 - * - * Created by: Derek Atkins - * - * $Id$ - */ - -// SAML Runtime -#include -#include -#include -#include -#include - -// Apache specific header files -#include -#include -#include -#include -#include -#include -#define CORE_PRIVATE -#include -#include -#include - -#include -#include - -//#include - -#ifdef HAVE_UNISTD_H -#include // for getpid() -#endif - -using namespace std; -using namespace saml; -using namespace shibboleth; -using namespace shibtarget; - -extern "C" AP_MODULE_DECLARE_DATA module mod_shib; -int shib_handler(request_rec* r, const IApplication* application, const IPropertySet* sessionProps, SHIRE& shire); - -namespace { - char* g_szSHIBConfig = NULL; - char* g_szSchemaDir = NULL; - ShibTargetConfig* g_Config = NULL; - bool g_bApacheConf = false; - static const char* g_UserDataKey = "_shib_check_user_"; -} - -// per-dir module configuration structure -struct shib_dir_config -{ - // RM Configuration - char* szAuthGrpFile; // Auth GroupFile name - int bRequireAll; // all require directives must match, otherwise OR logic - - // SHIRE Configuration - int bBasicHijack; // activate for AuthType Basic? - int bRequireSession; // require a session? - int bExportAssertion; // export SAML assertion to the environment? -}; - -// creates per-directory config structure -extern "C" void* create_shib_dir_config (apr_pool_t* p, char* d) -{ - shib_dir_config* dc=(shib_dir_config*)apr_pcalloc(p,sizeof(shib_dir_config)); - dc->bBasicHijack = -1; - dc->bRequireSession = -1; - dc->bExportAssertion = -1; - dc->bRequireAll = -1; - dc->szAuthGrpFile = NULL; - return dc; -} - -// overrides server configuration in directories -extern "C" void* merge_shib_dir_config (apr_pool_t* p, void* base, void* sub) -{ - shib_dir_config* dc=(shib_dir_config*)apr_pcalloc(p,sizeof(shib_dir_config)); - shib_dir_config* parent=(shib_dir_config*)base; - shib_dir_config* child=(shib_dir_config*)sub; - - if (child->szAuthGrpFile) - dc->szAuthGrpFile=apr_pstrdup(p,child->szAuthGrpFile); - else if (parent->szAuthGrpFile) - dc->szAuthGrpFile=apr_pstrdup(p,parent->szAuthGrpFile); - else - dc->szAuthGrpFile=NULL; - - dc->bBasicHijack=((child->bBasicHijack==-1) ? parent->bBasicHijack : child->bBasicHijack); - dc->bRequireSession=((child->bRequireSession==-1) ? parent->bRequireSession : child->bRequireSession); - dc->bExportAssertion=((child->bExportAssertion==-1) ? parent->bExportAssertion : child->bExportAssertion); - dc->bRequireAll=((child->bRequireAll==-1) ? parent->bRequireAll : child->bRequireAll); - - return dc; -} - -// generic global slot handlers -extern "C" const char* ap_set_global_string_slot(cmd_parms* parms, void*, - const char* arg) -{ - *((char**)(parms->info))=apr_pstrdup(parms->pool,arg); - return NULL; -} - -typedef const char* (*config_fn_t)(void); - -static int shib_error_page(request_rec* r, const IApplication* app, const char* page, ShibMLP& mlp) -{ - const IPropertySet* props=app->getPropertySet("Errors"); - if (props) { - pair p=props->getString(page); - if (p.first) { - ifstream infile(p.second); - if (!infile.fail()) { - const char* res = mlp.run(infile); - if (res) { - r->content_type = apr_psprintf(r->pool, "text/html"); - //ap_send_http_header(r); - ap_rprintf(r, res); - return DONE; - } - } - } - } - - ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r, - "shire_error_page() could not process shire error template for application %s",app->getId()); - return HTTP_INTERNAL_SERVER_ERROR; -} - -extern "C" int shib_check_user(request_rec* r) -{ - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user: ENTER"); - shib_dir_config* dc=(shib_dir_config*)ap_get_module_config(r->per_dir_config,&mod_shib); - - ostringstream threadid; - threadid << "[" << getpid() << "] shib_check_user" << '\0'; - saml::NDC ndc(threadid.str().c_str()); - - // This will always be normalized, because Apache uses ap_get_server_name in this API call. - const char* targeturl=ap_construct_url(r->pool,r->unparsed_uri,r); - - // 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=mapper->getSettingsFromParsedURL( - ap_http_method(r), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri - ); - pair application_id=settings.first->getString("applicationId"); - const IApplication* application=conf->getApplication(application_id.second); - const IPropertySet* sessionProps=application ? application->getPropertySet("Sessions") : NULL; - if (!application || !sessionProps) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_check_user: unable to map request to application session settings, check configuration"); - return HTTP_INTERNAL_SERVER_ERROR; - } - - // Declare SHIRE object for this request. - SHIRE shire(application); - - // Get location of this application's assertion consumer service and see if this is it. - if (strstr(targeturl,shire.getShireURL(targeturl))) { - return shib_handler(r,application,sessionProps,shire); - } - - // We can short circuit the handler if we run this... - apr_pool_userdata_setn((const void*)42,g_UserDataKey,NULL,r->pool); - - // Regular access to arbitrary resource...check AuthType - const char *auth_type=ap_auth_type(r); - if (!auth_type) - return DECLINED; - - if (strcasecmp(auth_type,"shibboleth")) { - if (!strcasecmp(auth_type,"basic") && dc->bBasicHijack==1) { - core_dir_config* conf= - (core_dir_config*)ap_get_module_config(r->per_dir_config, - ap_find_linked_module("http_core.c")); - conf->ap_auth_type="shibboleth"; - } - else - return DECLINED; - } - - pair requireSession = pair(false,false); - if (g_bApacheConf) { - // By default, we will require a session. - if (dc->bRequireSession!=0) - requireSession.second=true; - } - else - requireSession = settings.first->getBool("requireSession"); - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user: session check for %s",targeturl); - - pair shib_cookie=sessionProps->getString("cookieName"); - if (!shib_cookie.first) { - ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,0,r, - "shib_check_user: no cookieName set for %s", application_id.second); - return HTTP_INTERNAL_SERVER_ERROR; - } - - // We're in charge, so check for cookie. - const char* session_id=NULL; - const char* cookies=apr_table_get(r->headers_in,"Cookie"); - - if (cookies) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user() cookies found: %s",cookies); - if (session_id=strstr(cookies,shib_cookie.second)) { - // Yep, we found a cookie -- pull it out (our session_id) - session_id+=strlen(shib_cookie.second) + 1; /* Skip over the '=' */ - char* cookiebuf = apr_pstrdup(r->pool,session_id); - char* cookieend = strchr(cookiebuf,';'); - if (cookieend) - *cookieend = '\0'; /* Ignore anyting after a ; */ - session_id=cookiebuf; - } - } - - if (!session_id || !*session_id) { - // If no session required, bail now. - if (!requireSession.second) - return OK; - - // No acceptable cookie, and we require a session. Generate an AuthnRequest. - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user: no cookie found -- redirecting to WAYF"); - apr_table_setn(r->headers_out,"Location",apr_pstrdup(r->pool,shire.getAuthnRequest(targeturl))); - return HTTP_MOVED_TEMPORARILY; - } - - // Make sure this session is still valid - RPCError* status = NULL; - ShibMLP markupProcessor(application); - markupProcessor.insert("requestURL", targeturl); - - try { - status = shire.sessionIsValid(session_id, r->connection->remote_ip); - } - catch (ShibTargetException &e) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user(): %s", e.what()); - markupProcessor.insert("errorType", "Session Processing Error"); - markupProcessor.insert("errorText", e.what()); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "shire", markupProcessor); - } -#ifndef _DEBUG - catch (...) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user(): caught unexpected error"); - markupProcessor.insert("errorType", "Session Processing Error"); - markupProcessor.insert("errorText", "Unexpected Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "shire", markupProcessor); - } -#endif - - // Check the status - if (status->isError()) { - ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,0,r, - "shib_check_user() session invalid: %s", status->getText()); - - // If no session required, bail now. - if (!requireSession.second) - return OK; - else if (status->isRetryable()) { - // Oops, session is invalid. Generate AuthnRequest. - apr_table_setn(r->headers_out,"Location",apr_pstrdup(r->pool,shire.getAuthnRequest(targeturl))); - delete status; - return HTTP_MOVED_TEMPORARILY; - } - else { - // return the error page to the user - markupProcessor.insert(*status); - delete status; - return shib_error_page(r, application, "shire", markupProcessor); - } - } - - delete status; - // set the authtype - r->ap_auth_type = "shibboleth"; - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_check_user(): session successfully verified"); - - // This is code transferred in from the auth check to export the attributes. - // We could even combine the isSessionValid/getAssertions API...? - - RM rm(application); - vector assertions; - SAMLAuthenticationStatement* sso_statement=NULL; - - try { - status = rm.getAssertions(session_id, r->connection->remote_ip, assertions, &sso_statement); - } - catch (ShibTargetException &e) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r,"shib_check_user(): %s", e.what()); - markupProcessor.insert("errorType", "Attribute Processing Error"); - markupProcessor.insert("errorText", e.what()); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "rm", markupProcessor); - } -#ifndef _DEBUG - catch (...) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r,"shib_check_user(): caught unexpected error"); - markupProcessor.insert("errorType", "Attribute Processing Error"); - markupProcessor.insert("errorText", "Unexpected Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "rm", markupProcessor); - } -#endif - - if (status->isError()) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shire_check_user() getAssertions failed: %s", status->getText()); - - markupProcessor.insert(*status); - delete status; - return shib_error_page(r, application, "rm", markupProcessor); - } - delete status; - - // Do we have an access control plugin? - if (settings.second) { - Locker acllock(settings.second); - if (!settings.second->authorized(assertions)) { - for (int k = 0; k < assertions.size(); k++) - delete assertions[k]; - delete sso_statement; - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r,"shib_check_user(): access control provider denied access"); - return shib_error_page(r, application, "access", markupProcessor); - } - } - - // Get the AAP providers, which contain the attribute policy info. - Iterator provs=application->getAAPProviders(); - - // Clear out the list of mapped attributes - while (provs.hasNext()) { - IAAP* aap=provs.next(); - aap->lock(); - try { - Iterator rules=aap->getAttributeRules(); - while (rules.hasNext()) { - const char* header=rules.next()->getHeader(); - if (header) - apr_table_unset(r->headers_in,header); - } - } - catch(...) { - aap->unlock(); - for (int k = 0; k < assertions.size(); k++) - delete assertions[k]; - delete sso_statement; - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_check_user(): caught unexpected error while clearing headers"); - markupProcessor.insert("errorType", "Attribute Processing Error"); - markupProcessor.insert("errorText", "Unexpected Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "rm", markupProcessor); - } - aap->unlock(); - } - provs.reset(); - - // Maybe export the first assertion. - apr_table_unset(r->headers_in,"Shib-Attributes"); - pair exp=pair(false,false); - if (g_bApacheConf && dc->bExportAssertion==1) - exp.second=exp.first=true; - else if (!g_bApacheConf) - exp=settings.first->getBool("exportAssertion"); - if (exp.first && exp.second && assertions.size()) { - string assertion; - RM::serialize(*(assertions[0]), assertion); - apr_table_set(r->headers_in,"Shib-Attributes", assertion.c_str()); - } - - // Export the SAML AuthnMethod and the origin site name. - apr_table_unset(r->headers_in,"Shib-Origin-Site"); - apr_table_unset(r->headers_in,"Shib-Authentication-Method"); - if (sso_statement) { - auto_ptr_char os(sso_statement->getSubject()->getNameQualifier()); - auto_ptr_char am(sso_statement->getAuthMethod()); - apr_table_set(r->headers_in,"Shib-Origin-Site", os.get()); - apr_table_set(r->headers_in,"Shib-Authentication-Method", am.get()); - } - - apr_table_unset(r->headers_in,"Shib-Application-ID"); - apr_table_set(r->headers_in,"Shib-Application-ID",application_id.second); - - // Export the attributes. - Iterator a_iter(assertions); - while (a_iter.hasNext()) { - SAMLAssertion* assert=a_iter.next(); - Iterator statements=assert->getStatements(); - while (statements.hasNext()) { - SAMLAttributeStatement* astate=dynamic_cast(statements.next()); - if (!astate) - continue; - Iterator attrs=astate->getAttributes(); - while (attrs.hasNext()) { - SAMLAttribute* attr=attrs.next(); - - // Are we supposed to export it? - AAP wrapper(provs,attr->getName(),attr->getNamespace()); - if (wrapper.fail()) - continue; - - Iterator vals=attr->getSingleByteValues(); - if (!strcmp(wrapper->getHeader(),"REMOTE_USER") && vals.hasNext()) - r->user=apr_pstrdup(r->pool,vals.next().c_str()); - else { - int it=0; - char* header = (char*)apr_table_get(r->headers_in, wrapper->getHeader()); - if (header) { - header=apr_pstrdup(r->pool, header); - it++; - } - else - header = apr_pstrdup(r->pool, ""); - 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; - } - header=apr_pstrcat(r->pool, header, (it ? ";" : ""), value.c_str(), NULL); - } - apr_table_setn(r->headers_in, wrapper->getHeader(), header); - } - } - } - } - - // clean up memory - for (int k = 0; k < assertions.size(); k++) - delete assertions[k]; - delete sso_statement; - - return OK; -} - -extern "C" int shib_post_handler(request_rec* r) -{ - // With 2.x, this handler always runs, though last. We check if shib_check_user ran, - // because it will detect a SHIRE request and dispatch it directly. - void* data; - apr_pool_userdata_get(&data,g_UserDataKey,r->pool); - if (data==(const void*)42) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_post_handler skipped since check_user ran"); - return DECLINED; - } - - ostringstream threadid; - threadid << "[" << getpid() << "] shib_post_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=mapper->getSettingsFromParsedURL( - ap_http_method(r), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri - ); - pair application_id=settings.first->getString("applicationId"); - const IApplication* application=conf->getApplication(application_id.second); - const IPropertySet* sessionProps=application ? application->getPropertySet("Sessions") : NULL; - if (!application || !sessionProps) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_post_handler: unable to map request to application session settings, check configuration"); - return HTTP_INTERNAL_SERVER_ERROR; - } - - // Declare SHIRE object for this request. - SHIRE shire(application); - - return shib_handler(r, application, sessionProps, shire); -} - -int shib_handler(request_rec* r, const IApplication* application, const IPropertySet* sessionProps, SHIRE& shire) -{ - // Prime the pump... - const char* targeturl = ap_construct_url(r->pool,r->unparsed_uri,r); - - // Make sure we only process the SHIRE requests. - if (!strstr(targeturl,shire.getShireURL(targeturl))) - return DECLINED; - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_handler() running"); - - pair shib_cookie=sessionProps->getString("cookieName"); - pair shib_cookie_props=sessionProps->getString("cookieProps"); - if (!shib_cookie.first) { - ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,0,r, - "shire_handler: no cookieName set for %s", application->getId()); - return HTTP_INTERNAL_SERVER_ERROR; - } - - ShibMLP markupProcessor(application); - markupProcessor.insert("requestURL", targeturl); - - // Process SHIRE request - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_handler() Beginning SHIRE processing"); - - try { - pair shireSSL=sessionProps->getBool("shireSSL"); - - // Make sure this is SSL, if it should be - if ((!shireSSL.first || shireSSL.second) && strcmp(ap_http_method(r),"https")) - throw ShibTargetException(SHIBRPC_OK, "blocked non-SSL access to session creation service"); - - // If this is a GET, we manufacture an AuthnRequest. - if (!strcasecmp(r->method,"GET")) { - const char* areq=r->args ? shire.getLazyAuthnRequest(r->args) : NULL; - if (!areq) - throw ShibTargetException(SHIBRPC_OK, "malformed arguments to request a new session"); - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool,areq)); - return HTTP_MOVED_TEMPORARILY; - } - else if (strcasecmp(r->method,"POST")) { - throw ShibTargetException(SHIBRPC_OK, "blocked non-POST to SHIRE POST processor"); - } - - // Sure sure this POST is an appropriate content type - const char *ct = apr_table_get(r->headers_in, "Content-type"); - if (!ct || strcasecmp(ct, "application/x-www-form-urlencoded")) - throw ShibTargetException (SHIBRPC_OK, - apr_psprintf(r->pool, "blocked bad content-type to SHIRE POST processor: %s", (ct ? ct : ""))); - - // Read the posted data - if (ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) - throw ShibTargetException (SHIBRPC_OK, "CGI setup_client_block failed"); - if (!ap_should_client_block(r)) - throw ShibTargetException (SHIBRPC_OK, "CGI should_client_block failed"); - if (r->remaining > 1024*1024) - throw ShibTargetException (SHIBRPC_OK, "CGI length too long..."); - - string cgistr; - char buff[HUGE_STRING_LEN]; - //apr_hard_timeout("[mod_shib] CGI Parser", r); - memset(buff, 0, sizeof(buff)); - while (ap_get_client_block(r, buff, sizeof(buff)-1) > 0) { - cgistr += buff; - memset(buff, 0, sizeof(buff)); - } - //ap_kill_timeout(r); - - // Parse the submission. - pair elements=shire.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"); - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_handler() Processing POST for target: %s", elements.second); - - // process the post - string cookie; - RPCError* status = shire.sessionCreate(elements.first, r->connection->remote_ip, cookie); - - if (status->isError()) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_handler() POST process failed (%d): %s", status->getCode(), status->getText()); - - if (status->isRetryable()) { - ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,0,r, - "shib_handler() retryable error, generating new AuthnRequest"); - apr_table_setn(r->headers_out,"Location",apr_pstrdup(r->pool,shire.getAuthnRequest(elements.second))); - return HTTP_MOVED_TEMPORARILY; - } - - // return this error to the user. - markupProcessor.insert(*status); - delete status; - return shib_error_page(r, application, "shire", markupProcessor); - } - delete status; - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_handler() POST process succeeded. New cookie: %s", cookie.c_str()); - - // We've got a good session, set the cookie... - char* val = apr_psprintf(r->pool,"%s=%s%s",shib_cookie.second,cookie.c_str(), - shib_cookie_props.first ? shib_cookie_props.second : "; path=/"); - apr_table_setn(r->err_headers_out, "Set-Cookie", val); - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_handler() setting cookie: %s",val); - - // ... and redirect to the target - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool,elements.second)); - return HTTP_MOVED_TEMPORARILY; - } - catch (ShibTargetException &e) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_post_handler(): %s", e.what()); - markupProcessor.insert("errorType", "Session Creation Service Error"); - markupProcessor.insert("errorText", e.what()); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "shire", markupProcessor); - } -#ifndef _DEBUG - catch (...) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_handler(): unexpected exception"); - markupProcessor.insert("errorType", "Session Creation Service Error"); - markupProcessor.insert("errorText", "Unknown Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shib_error_page(r, application, "shire", markupProcessor); - } -#endif - - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r,"shib_handler() server error"); - return HTTP_INTERNAL_SERVER_ERROR; -} - -static apr_table_t* groups_for_user(request_rec* r, const char* user, char* grpfile) -{ - ap_configfile_t* f; - apr_table_t* grps=apr_table_make(r->pool,15); - char l[MAX_STRING_LEN]; - const char *group_name, *ll, *w; - - if (ap_pcfg_openfile(&f,r->pool,grpfile) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r, - "groups_for_user() could not open group file: %s\n", grpfile); - return NULL; - } - - apr_pool_t* sp; - if (apr_pool_create(&sp,r->pool) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK,APLOG_ERR,0,r, - "groups_for_user() could not create a subpool"); - return NULL; - } - - while (!(ap_cfg_getline(l,MAX_STRING_LEN,f))) { - if ((*l=='#') || (!*l)) - continue; - ll = l; - apr_pool_clear(sp); - - group_name=ap_getword(sp,&ll,':'); - - while (*ll) { - w=ap_getword_conf(sp,&ll); - if (!strcmp(w,user)) { - apr_table_setn(grps,apr_pstrdup(r->pool,group_name),"in"); - break; - } - } - } - ap_cfg_closefile(f); - apr_pool_destroy(sp); - return grps; -} - -/* - * shib_auth_checker() -- a simple resource manager to - * process the .htaccess settings and copy attributes - * into the HTTP headers. - */ -extern "C" int shib_auth_checker(request_rec *r) -{ - shib_dir_config* dc= - (shib_dir_config*)ap_get_module_config(r->per_dir_config,&mod_shib); - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_auth_checker() executing"); - - // Regular access to arbitrary resource...check AuthType - const char* auth_type=ap_auth_type(r); - if (!auth_type || strcasecmp(auth_type,"shibboleth")) - return DECLINED; - - ostringstream threadid; - threadid << "[" << getpid() << "] shibrm" << '\0'; - saml::NDC ndc(threadid.str().c_str()); - - // We lock the configuration system for the duration. - IConfig* conf=g_Config->getINI(); - Locker locker(conf); - - const char* application_id=apr_table_get(r->headers_in,"Shib-Application-ID"); - const IApplication* application=NULL; - if (application_id) - application = conf->getApplication(application_id); - - // mod_auth clone - - int m=r->method_number; - bool method_restricted=false; - const char *t, *w; - - const apr_array_header_t* reqs_arr=ap_requires(r); - if (!reqs_arr) - return OK; - - require_line* reqs=(require_line*)reqs_arr->elts; - - //XXX - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"REQUIRE nelts: %d", reqs_arr->nelts); - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"REQUIRE all: %d", dc->bRequireAll); - - vector auth_OK(reqs_arr->nelts,false); - -#define SHIB_AP_CHECK_IS_OK { \ - if (dc->bRequireAll < 1) \ - return OK; \ - auth_OK[x] = true; \ - continue; \ -} - - for (int x=0; xnelts; x++) { - auth_OK[x] = false; - - if (!(reqs[x].method_mask & (1 << m))) - continue; - method_restricted=true; - - t = reqs[x].requirement; - w = ap_getword_white(r->pool, &t); - - if (!strcmp(w,"valid-user")) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, "shib_auth_checker() accepting valid-user"); - SHIB_AP_CHECK_IS_OK; - } - else if (!strcmp(w,"user") && r->user) { - bool regexp=false; - while (*t) { - w=ap_getword_conf(r->pool,&t); - if (*w=='~') { - regexp=true; - continue; - } - - if (regexp) { - try { - // To do regex matching, we have to convert from UTF-8. - auto_ptr trans(fromUTF8(w)); - RegularExpression re(trans.get()); - auto_ptr trans2(fromUTF8(r->user)); - if (re.matches(trans2.get())) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() accepting user: %s",w); - SHIB_AP_CHECK_IS_OK; - } - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_auth_checker caught exception while parsing regular expression (%s): %s",w,tmp.get()); - } - } - else if (!strcmp(r->user,w)) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_auth_checker() accepting user: %s",w); - SHIB_AP_CHECK_IS_OK; - } - } - } - else if (!strcmp(w,"group")) { - apr_table_t* grpstatus=NULL; - if (dc->szAuthGrpFile && r->user) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() using groups file: %s\n", dc->szAuthGrpFile); - grpstatus=groups_for_user(r,r->user,dc->szAuthGrpFile); - } - if (!grpstatus) - return DECLINED; - - while (*t) { - w=ap_getword_conf(r->pool,&t); - if (apr_table_get(grpstatus,w)) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,"shib_auth_checker() accepting group: %s",w); - SHIB_AP_CHECK_IS_OK; - } - } - } - else { - Iterator provs=application ? application->getAAPProviders() : EMPTY(IAAP*); - AAP wrapper(provs,w); - if (wrapper.fail()) { - ap_log_rerror(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,0,r, - "shib_auth_checker() didn't recognize require rule: %s\n",w); - continue; - } - - bool regexp=false; - const char* vals=apr_table_get(r->headers_in,wrapper->getHeader()); - while (*t && vals) { - w=ap_getword_conf(r->pool,&t); - if (*w=='~') { - regexp=true; - continue; - } - - try { - auto_ptr re; - if (regexp) { - delete re.release(); - auto_ptr trans(fromUTF8(w)); - auto_ptr 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) { - ap_log_rerror(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,0,r, - "shib_auth_checker() invalid header encoding %s: starts with semicolon", vals); - return HTTP_INTERNAL_SERVER_ERROR; - } - - 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 trans(fromUTF8(val.c_str())); - if (re->matches(trans.get())) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - } - else if (val==w) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - else { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() expecting %s, got %s: authorization not granted", w, val.c_str()); - } - } - } - - string val = vals_str.substr(j, vals_str.length()-j); - if (regexp) { - auto_ptr trans(fromUTF8(val.c_str())); - if (re->matches(trans.get())) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - } - else if (val==w) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - else { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r, - "shib_auth_checker() expecting %s, got %s: authorization not granted", w, val.c_str()); - } - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_auth_checker caught exception while parsing regular expression (%s): %s",w,tmp.get()); - } - } - } - } - - // check if all require directives are true - bool auth_all_OK = true; - for (int i= 0; inelts; i++) { - auth_all_OK &= auth_OK[i]; - } - if (auth_all_OK) - return OK; - - if (!method_restricted) - return OK; - - if (!application_id) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_check_auth: Shib-Application-ID header not found in request"); - return HTTP_FORBIDDEN; - } - else if (!application) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,0,r, - "shib_check_auth: unable to map request to application settings, check configuration"); - return HTTP_FORBIDDEN; - } - - ShibMLP markupProcessor(application); - markupProcessor.insert("requestURL", ap_construct_url(r->pool,r->unparsed_uri,r)); - return shib_error_page(r, application, "access", markupProcessor); -} - -/* - * shib_exit() - * Cleanup the (per-process) pool info. - */ -extern "C" apr_status_t shib_exit(void* data) -{ - g_Config->shutdown(); - g_Config = NULL; - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,NULL,"shib_exit() done"); - return OK; -} - -static const XMLCh Apache[] = -{ chLatin_A, chLatin_p, chLatin_a, chLatin_c, chLatin_h, chLatin_e, chNull }; -static const XMLCh apacheConfig[] = -{ chLatin_a, chLatin_p, chLatin_a, chLatin_c, chLatin_h, chLatin_e, - chLatin_C, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, 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 }; - -/* - * shib_post_config() - * Things to do at process startup after the configs are read - */ -extern "C" int shib_post_config(apr_pool_t* pconf, apr_pool_t* plog, - apr_pool_t* ptemp, server_rec* s) -{ - // Initialize runtime components. - - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,s,"shib_post_config() starting"); - - if (g_Config) { - ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,0,s,"shib_post_config(): already initialized"); - return OK; - } - - try { - g_Config=&ShibTargetConfig::getConfig(); - g_Config->setFeatures( - ShibTargetConfig::Listener | - ShibTargetConfig::Metadata | - ShibTargetConfig::AAP | - ShibTargetConfig::RequestMapper | - ShibTargetConfig::SHIREExtensions - ); - if (!g_Config->init(g_szSchemaDir,g_szSHIBConfig)) { - ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,0,s,"shib_post_config(): already initialized!"); - exit(1); - } - - // Access the implementation-specifics for whether to use old Apache config style... - IConfig* conf=g_Config->getINI(); - Locker locker(conf); - const IPropertySet* props=conf->getPropertySet("SHIRE"); - if (props) { - const DOMElement* impl=saml::XML::getFirstChildElement( - props->getElement(),ShibTargetConfig::SHIBTARGET_NS,Implementation - ); - if (impl && (impl=saml::XML::getFirstChildElement(impl,ShibTargetConfig::SHIBTARGET_NS,Apache))) { - const XMLCh* flag=impl->getAttributeNS(NULL,apacheConfig); - if (flag && (*flag==chDigit_1 || *flag==chLatin_t)) - g_bApacheConf=true; - } - } - } - catch (...) { - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,s, - "shib_post_config() failed to initialize SHIB Target"); - exit (1); - } - - // Set the cleanup handler - apr_pool_cleanup_register(pconf, NULL, shib_exit, NULL); - - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,s,"shib_post_config() done"); - - return OK; -} - -extern "C" void shib_register_hooks (apr_pool_t *p) -{ - ap_hook_post_config(shib_post_config, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_check_user_id(shib_check_user, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_auth_checker(shib_auth_checker, NULL, NULL, APR_HOOK_FIRST); - ap_hook_handler(shib_post_handler, NULL, NULL, APR_HOOK_LAST); -} - -// SHIB Module commands - -extern "C" { -static command_rec shib_cmds[] = { - AP_INIT_TAKE1("ShibConfig", - (config_fn_t)ap_set_global_string_slot, &g_szSHIBConfig, - RSRC_CONF, "Path to shibboleth.xml config file."), - AP_INIT_TAKE1("ShibSchemaDir", - (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir, - RSRC_CONF, "Path to Shibboleth XML schema directory."), - - AP_INIT_FLAG("ShibBasicHijack", (config_fn_t)ap_set_flag_slot, - (void *) offsetof (shib_dir_config, bBasicHijack), - OR_AUTHCFG, "Respond to AuthType Basic and convert to shib?"), - AP_INIT_FLAG("ShibRequireSession", (config_fn_t)ap_set_flag_slot, - (void *) offsetof (shib_dir_config, bRequireSession), - OR_AUTHCFG, "Initiates a new session if one does not exist."), - AP_INIT_FLAG("ShibExportAssertion", (config_fn_t)ap_set_flag_slot, - (void *) offsetof (shib_dir_config, bExportAssertion), - OR_AUTHCFG, "Export SAML assertion to Shibboleth-defined header?"), - AP_INIT_TAKE1("AuthGroupFile", (config_fn_t)ap_set_file_slot, - (void *) offsetof (shib_dir_config, szAuthGrpFile), - OR_AUTHCFG, "text file containing group names and member user IDs"), - AP_INIT_FLAG("ShibRequireAll", (config_fn_t)ap_set_flag_slot, - (void *) offsetof (shib_dir_config, bRequireAll), - OR_AUTHCFG, "All require directives must match!"), - - {NULL} -}; - -module AP_MODULE_DECLARE_DATA mod_shib = { - STANDARD20_MODULE_STUFF, - create_shib_dir_config, /* create dir config */ - merge_shib_dir_config, /* merge dir config --- default is to override */ - NULL, /* create server config */ - NULL, /* merge server config */ - shib_cmds, /* command table */ - shib_register_hooks /* register hooks */ -}; -} // extern "C" diff --git a/configure.ac b/configure.ac index ad6087d..89579ce 100644 --- a/configure.ac +++ b/configure.ac @@ -174,7 +174,7 @@ fi AM_CONDITIONAL(USE_OUR_ONCRPC,test "$rpctest" = "no") -# Apache 1.3 (mod_shire) +# Apache 1.3 (mod_shib_13) # --with-apache-13 (static build, no idea how to do this yet, so not supported) # --with-apxs (DSO build, the normal way, uses apxs to derive build flags) # --without-apxs (DSO build, you tell us how to build using the environment) @@ -320,17 +320,12 @@ if test "$WANT_APACHE_13" = "yes"; then AC_SUBST(APXS_INCLUDE) AC_SUBST(APXS_LIBEXEC) AC_SUBST(APXS_SYSCONFDIR) - - # output the Apache 1.3 makefiles - WANT_SUBDIRS="$WANT_SUBDIRS mod_shire" fi -# always output the Makefile, even if we don't use it -AC_CONFIG_FILES([mod_shire/Makefile]) AM_CONDITIONAL(HAVE_APXS,test -n "$APXS") AM_CONDITIONAL(DO_APXS_INSTALL,test -n "$APXS_INSTALL") -# Apache 2.0 (mod_shib in apache-2.0) +# Apache 2.0 (mod_shib_20) # --with-apache-20 (static build, no idea how to do this yet, so not supported) # --with-apxs2 (DSO build, the normal way, uses apxs to derive build flags) # --without-apxs2 (DSO build, you tell us how to build using the environment) @@ -477,12 +472,7 @@ if test "$WANT_APACHE_20" = "yes"; then AC_SUBST(APXS2_INCLUDE) AC_SUBST(APXS2_LIBEXEC) AC_SUBST(APXS2_SYSCONFDIR) - - # output the Apache 2.0 makefiles - WANT_SUBDIRS="$WANT_SUBDIRS apache-2.0" fi -# always output the Makefile, even if we don't use it -AC_CONFIG_FILES([apache-2.0/Makefile]) AM_CONDITIONAL(HAVE_APXS2,test -n "$APXS2") AM_CONDITIONAL(DO_APXS2_INSTALL,test -n "$APXS2_INSTALL") diff --git a/mod_shire/.gitignore b/mod_shire/.gitignore deleted file mode 100644 index 9d7d30d..0000000 --- a/mod_shire/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -/Makefile.in -/Makefile -/.libs -/.deps -/*.lo -/*.la -/Debug -/*.plg -/Release -/*.dep -/*.mak \ No newline at end of file diff --git a/mod_shire/Makefile.am b/mod_shire/Makefile.am deleted file mode 100644 index edf3fe7..0000000 --- a/mod_shire/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -## $Id$ - -AUTOMAKE_OPTIONS = foreign - -if USE_OUR_ONCRPC -RPC_CFLAGS = -I${top_srcdir}/oncrpc -endif - -shiredir = $(libexecdir) -shire_LTLIBRARIES = mod_shire.la - -mod_shire_la_SOURCES = mod_shire.cpp - -AM_CXXFLAGS = $(APXS_CFLAGS) -I$(APXS_INCLUDE) $(RPC_CFLAGS) - -mod_shire_la_LIBADD = $(top_builddir)/shib/libshib.la $(top_builddir)/shib-target/libshib-target.la - -mod_shire_la_LDFLAGS = -module -avoid-version - -if DO_APXS_INSTALL -install-exec-local: - $(APXS) -i -A -n shire .libs/mod_shire.so -endif - -EXTRA_DIST = mod_shire.dsp diff --git a/mod_shire/mod_shire.cpp b/mod_shire/mod_shire.cpp deleted file mode 100644 index 064d07e..0000000 --- a/mod_shire/mod_shire.cpp +++ /dev/null @@ -1,1000 +0,0 @@ -/* - * mod_shire.cpp -- the SHIRE Apache Module - * - * Created by: Derek Atkins - * - * $Id$ - */ - -// SAML Runtime -#include -#include -#include -#include -#include - -#undef _XPG4_2 - -// Apache specific header files -#include -#include -#include -#include -#define CORE_PRIVATE -#include -#include - -#include -#include - -using namespace std; -using namespace saml; -using namespace shibboleth; -using namespace shibtarget; - -extern "C" module MODULE_VAR_EXPORT shire_module; -int shire_handler(request_rec* r, const IApplication* application, const IPropertySet* sessionProps, SHIRE& shire); - -namespace { - char* g_szSHIBConfig = NULL; - char* g_szSchemaDir = NULL; - ShibTargetConfig* g_Config = NULL; - bool g_bApacheConf = false; -} - -// per-dir module configuration structure -struct shire_dir_config -{ - // RM Configuration - char* szAuthGrpFile; // Auth GroupFile name - int bRequireAll; // all require directives must match, otherwise OR logic - - // SHIRE Configuration - int bBasicHijack; // activate for AuthType Basic? - int bRequireSession; // require a session? - int bExportAssertion; // export SAML assertion to the environment? -}; - -// creates per-directory config structure -extern "C" void* create_shire_dir_config (pool* p, char* d) -{ - shire_dir_config* dc=(shire_dir_config*)ap_pcalloc(p,sizeof(shire_dir_config)); - dc->bBasicHijack = -1; - dc->bRequireSession = -1; - dc->bExportAssertion = -1; - dc->bRequireAll = -1; - dc->szAuthGrpFile = NULL; - return dc; -} - -// overrides server configuration in directories -extern "C" void* merge_shire_dir_config (pool* p, void* base, void* sub) -{ - shire_dir_config* dc=(shire_dir_config*)ap_pcalloc(p,sizeof(shire_dir_config)); - shire_dir_config* parent=(shire_dir_config*)base; - shire_dir_config* child=(shire_dir_config*)sub; - - if (child->szAuthGrpFile) - dc->szAuthGrpFile=ap_pstrdup(p,child->szAuthGrpFile); - else if (parent->szAuthGrpFile) - dc->szAuthGrpFile=ap_pstrdup(p,parent->szAuthGrpFile); - else - dc->szAuthGrpFile=NULL; - - dc->bBasicHijack=((child->bBasicHijack==-1) ? parent->bBasicHijack : child->bBasicHijack); - dc->bRequireSession=((child->bRequireSession==-1) ? parent->bRequireSession : child->bRequireSession); - dc->bExportAssertion=((child->bExportAssertion==-1) ? parent->bExportAssertion : child->bExportAssertion); - dc->bRequireAll=((child->bRequireAll==-1) ? parent->bRequireAll : child->bRequireAll); - return dc; -} - -// generic global slot handlers -extern "C" const char* ap_set_global_string_slot(cmd_parms* parms, void*, const char* arg) -{ - *((char**)(parms->info))=ap_pstrdup(parms->pool,arg); - return NULL; -} - -typedef const char* (*config_fn_t)(void); - -// SHIRE Module commands - -static command_rec shire_cmds[] = { - {"SHIREConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIBConfig, - RSRC_CONF, TAKE1, "Path to shibboleth.xml config file."}, - {"ShibConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIBConfig, - RSRC_CONF, TAKE1, "Path to shibboleth.xml config file."}, - {"ShibSchemaDir", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir, - RSRC_CONF, TAKE1, "Path to Shibboleth XML schema directory."}, - - {"ShibBasicHijack", (config_fn_t)ap_set_flag_slot, - (void *) XtOffsetOf (shire_dir_config, bBasicHijack), - OR_AUTHCFG, FLAG, "Respond to AuthType Basic and convert to shib?"}, - {"ShibRequireSession", (config_fn_t)ap_set_flag_slot, - (void *) XtOffsetOf (shire_dir_config, bRequireSession), - OR_AUTHCFG, FLAG, "Initiates a new session if one does not exist."}, - {"ShibExportAssertion", (config_fn_t)ap_set_flag_slot, - (void *) XtOffsetOf (shire_dir_config, bExportAssertion), - OR_AUTHCFG, FLAG, "Export SAML assertion to Shibboleth-defined header?"}, - {"AuthGroupFile", (config_fn_t)ap_set_file_slot, - (void *) XtOffsetOf (shire_dir_config, szAuthGrpFile), - OR_AUTHCFG, TAKE1, "text file containing group names and member user IDs"}, - {"ShibRequireAll", (config_fn_t)ap_set_flag_slot, - (void *) XtOffsetOf (shire_dir_config, bRequireAll), - OR_AUTHCFG, FLAG, "All require directives must match!"}, - - {NULL} -}; - -static const XMLCh Apache[] = -{ chLatin_A, chLatin_p, chLatin_a, chLatin_c, chLatin_h, chLatin_e, chNull }; -static const XMLCh apacheConfig[] = -{ chLatin_a, chLatin_p, chLatin_a, chLatin_c, chLatin_h, chLatin_e, - chLatin_C, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, 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 }; - -/* - * shire_child_init() - * Things to do when the child process is initialized. - */ -extern "C" void shire_child_init(server_rec* s, pool* p) -{ - // Initialize runtime components. - - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_init() starting"); - - if (g_Config) { - ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,s,"shire_child_init(): already initialized!"); - exit(1); - } - - try { - g_Config=&ShibTargetConfig::getConfig(); - g_Config->setFeatures( - ShibTargetConfig::Listener | - ShibTargetConfig::Metadata | - ShibTargetConfig::AAP | - ShibTargetConfig::RequestMapper | - ShibTargetConfig::SHIREExtensions - ); - if (!g_Config->init(g_szSchemaDir,g_szSHIBConfig)) { - ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,s,"shire_child_init(): already initialized!"); - exit(1); - } - - // Access the implementation-specifics for whether to use old Apache config style... - IConfig* conf=g_Config->getINI(); - Locker locker(conf); - const IPropertySet* props=conf->getPropertySet("SHIRE"); - if (props) { - const DOMElement* impl=saml::XML::getFirstChildElement( - props->getElement(),ShibTargetConfig::SHIBTARGET_NS,Implementation - ); - if (impl && (impl=saml::XML::getFirstChildElement(impl,ShibTargetConfig::SHIBTARGET_NS,Apache))) { - const XMLCh* flag=impl->getAttributeNS(NULL,apacheConfig); - if (flag && (*flag==chDigit_1 || *flag==chLatin_t)) - g_bApacheConf=true; - } - } - } - catch (...) { - ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,s,"shire_child_init() failed to initialize SHIB Target"); - exit (1); - } - - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s, - "shire_child_init() done, apacheConfig set to %s", g_bApacheConf ? "true" : "false"); -} - - -/* - * shire_child_exit() - * Cleanup. - */ -extern "C" void shire_child_exit(server_rec* s, pool* p) -{ - g_Config->shutdown(); - g_Config = NULL; - ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_exit() done"); -} - -static int shire_error_page(request_rec* r, const IApplication* app, const char* page, ShibMLP& mlp) -{ - const IPropertySet* props=app->getPropertySet("Errors"); - if (props) { - pair p=props->getString(page); - if (p.first) { - ifstream infile(p.second); - if (!infile.fail()) { - const char* res = mlp.run(infile); - if (res) { - r->content_type = ap_psprintf(r->pool, "text/html"); - ap_send_http_header(r); - ap_rprintf(r, res); - return DONE; - } - } - } - } - - ap_log_rerror(APLOG_MARK,APLOG_ERR,r, - "shire_error_page() could not process shire error template for application %s",app->getId()); - return SERVER_ERROR; -} - -extern "C" int shire_check_user(request_rec* r) -{ - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_user: ENTER"); - shire_dir_config* dc=(shire_dir_config*)ap_get_module_config(r->per_dir_config,&shire_module); - - ostringstream threadid; - threadid << "[" << getpid() << "] shire" << '\0'; - saml::NDC ndc(threadid.str().c_str()); - - // This will always be normalized, because Apache uses ap_get_server_name in this API call. - const char* targeturl=ap_construct_url(r->pool,r->unparsed_uri,r); - - // 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=mapper->getSettingsFromParsedURL( - ap_http_method(r), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri - ); - pair application_id=settings.first->getString("applicationId"); - const IApplication* application=conf->getApplication(application_id.second); - const IPropertySet* sessionProps=application ? application->getPropertySet("Sessions") : NULL; - if (!application || !sessionProps) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_user: unable to map request to application session settings, check configuration"); - return SERVER_ERROR; - } - - // Declare SHIRE object for this request. - SHIRE shire(application); - - // Get location of this application's assertion consumer service and see if this is it. - if (strstr(targeturl,shire.getShireURL(targeturl))) { - return shire_handler(r,application,sessionProps,shire); - } - - // Regular access to arbitrary resource...check AuthType - const char *auth_type=ap_auth_type(r); - if (!auth_type) - return DECLINED; - - if (strcasecmp(auth_type,"shibboleth")) { - if (!strcasecmp(auth_type,"basic") && dc->bBasicHijack==1) { - core_dir_config* conf= - (core_dir_config*)ap_get_module_config(r->per_dir_config, - ap_find_linked_module("http_core.c")); - conf->ap_auth_type="shibboleth"; - } - else - return DECLINED; - } - - pair requireSession = pair(false,false); - if (g_bApacheConf) { - // By default, we will require a session. - if (dc->bRequireSession!=0) - requireSession.second=true; - } - else - requireSession = settings.first->getBool("requireSession"); - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_user: session check for %s",targeturl); - - pair shib_cookie=sessionProps->getString("cookieName"); - if (!shib_cookie.first) { - ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,r, - "shire_check_user: no cookieName set for %s", application_id.second); - return SERVER_ERROR; - } - - // We're in charge, so check for cookie. - const char* session_id=NULL; - const char* cookies=ap_table_get(r->headers_in,"Cookie"); - - if (cookies) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_user: cookies found: %s",cookies); - if (session_id=strstr(cookies,shib_cookie.second)) { - // Yep, we found a cookie -- pull it out (our session_id) - session_id+=strlen(shib_cookie.second) + 1; /* Skip over the '=' */ - char* cookiebuf = ap_pstrdup(r->pool,session_id); - char* cookieend = strchr(cookiebuf,';'); - if (cookieend) - *cookieend = '\0'; /* Ignore anyting after a ; */ - session_id=cookiebuf; - } - } - - if (!session_id || !*session_id) { - // If no session required, bail now. - if (!requireSession.second) - return OK; - - // No acceptable cookie, and we require a session. Generate an AuthnRequest. - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_user: no cookie found -- redirecting to WAYF"); - ap_table_setn(r->headers_out,"Location",ap_pstrdup(r->pool,shire.getAuthnRequest(targeturl))); - return REDIRECT; - } - - // Make sure this session is still valid. - RPCError* status = NULL; - ShibMLP markupProcessor(application); - markupProcessor.insert("requestURL", targeturl); - - try { - status = shire.sessionIsValid(session_id, r->connection->remote_ip); - } - catch (ShibTargetException &e) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"shire_check_user(): %s", e.what()); - markupProcessor.insert("errorType", "Session Processing Error"); - markupProcessor.insert("errorText", e.what()); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "shire", markupProcessor); - } -#ifndef _DEBUG - catch (...) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"shire_check_user(): caught unexpected error"); - markupProcessor.insert("errorType", "Session Processing Error"); - markupProcessor.insert("errorText", "Unexpected Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "shire", markupProcessor); - } -#endif - - // Check the status - if (status->isError()) { - ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r, - "shire_check_user() session invalid: %s", status->getText()); - - // If no session required, bail now. - if (!requireSession.second) - return DECLINED; - else if (status->isRetryable()) { - // Oops, session is invalid. Generate AuthnRequest. - ap_table_setn(r->headers_out,"Location",ap_pstrdup(r->pool,shire.getAuthnRequest(targeturl))); - delete status; - return REDIRECT; - } - else { - // return the error page to the user - markupProcessor.insert(*status); - delete status; - return shire_error_page(r, application, "shire", markupProcessor); - } - } - - delete status; - // set the connection authtype - if (r->connection) - r->connection->ap_auth_type = "shibboleth"; - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_user: session successfully verified"); - - // This is code transferred in from mod_shibrm to export the attributes. - // We could even combine the isSessionValid/getAssertions API...? - - RM rm(application); - vector assertions; - SAMLAuthenticationStatement* sso_statement=NULL; - - try { - status = rm.getAssertions(session_id, r->connection->remote_ip, assertions, &sso_statement); - } - catch (ShibTargetException &e) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"shire_check_user(): %s", e.what()); - markupProcessor.insert("errorType", "Attribute Processing Error"); - markupProcessor.insert("errorText", e.what()); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "rm", markupProcessor); - } -#ifndef _DEBUG - catch (...) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"shire_check_user(): caught unexpected error"); - markupProcessor.insert("errorType", "Attribute Processing Error"); - markupProcessor.insert("errorText", "Unexpected Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "rm", markupProcessor); - } -#endif - - if (status->isError()) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_user() getAssertions failed: %s", status->getText()); - - markupProcessor.insert(*status); - delete status; - return shire_error_page(r, application, "rm", markupProcessor); - } - delete status; - - // Do we have an access control plugin? - if (settings.second) { - Locker acllock(settings.second); - if (!settings.second->authorized(assertions)) { - for (int k = 0; k < assertions.size(); k++) - delete assertions[k]; - delete sso_statement; - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"shire_check_user(): access control provider denied access"); - return shire_error_page(r, application, "access", markupProcessor); - } - } - - // Get the AAP providers, which contain the attribute policy info. - Iterator provs=application->getAAPProviders(); - - // Clear out the list of mapped attributes - while (provs.hasNext()) { - IAAP* aap=provs.next(); - aap->lock(); - try { - Iterator rules=aap->getAttributeRules(); - while (rules.hasNext()) { - const char* header=rules.next()->getHeader(); - if (header) - ap_table_unset(r->headers_in,header); - } - } - catch(...) { - aap->unlock(); - for (int k = 0; k < assertions.size(); k++) - delete assertions[k]; - delete sso_statement; - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_user(): caught unexpected error while clearing headers"); - markupProcessor.insert("errorType", "Attribute Processing Error"); - markupProcessor.insert("errorText", "Unexpected Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "rm", markupProcessor); - } - aap->unlock(); - } - provs.reset(); - - // Maybe export the first assertion. - ap_table_unset(r->headers_in,"Shib-Attributes"); - pair exp=pair(false,false); - if (g_bApacheConf && dc->bExportAssertion==1) - exp.second=exp.first=true; - else if (!g_bApacheConf) - exp=settings.first->getBool("exportAssertion"); - if (exp.first && exp.second && assertions.size()) { - string assertion; - RM::serialize(*(assertions[0]), assertion); - ap_table_set(r->headers_in,"Shib-Attributes", assertion.c_str()); - } - - // Export the SAML AuthnMethod and the origin site name. - ap_table_unset(r->headers_in,"Shib-Origin-Site"); - ap_table_unset(r->headers_in,"Shib-Authentication-Method"); - if (sso_statement) { - auto_ptr_char os(sso_statement->getSubject()->getNameQualifier()); - auto_ptr_char am(sso_statement->getAuthMethod()); - ap_table_set(r->headers_in,"Shib-Origin-Site", os.get()); - ap_table_set(r->headers_in,"Shib-Authentication-Method", am.get()); - } - - ap_table_unset(r->headers_in,"Shib-Application-ID"); - ap_table_set(r->headers_in,"Shib-Application-ID",application_id.second); - - // Export the attributes. - Iterator a_iter(assertions); - while (a_iter.hasNext()) { - SAMLAssertion* assert=a_iter.next(); - Iterator statements=assert->getStatements(); - while (statements.hasNext()) { - SAMLAttributeStatement* astate=dynamic_cast(statements.next()); - if (!astate) - continue; - Iterator attrs=astate->getAttributes(); - while (attrs.hasNext()) { - SAMLAttribute* attr=attrs.next(); - - // Are we supposed to export it? - AAP wrapper(provs,attr->getName(),attr->getNamespace()); - if (wrapper.fail()) - continue; - - Iterator vals=attr->getSingleByteValues(); - if (!strcmp(wrapper->getHeader(),"REMOTE_USER") && vals.hasNext()) - r->connection->user=ap_pstrdup(r->pool,vals.next().c_str()); - else { - int it=0; - char* header = (char*)ap_table_get(r->headers_in, wrapper->getHeader()); - if (header) { - header=ap_pstrdup(r->pool, header); - it++; - } - else - header = ap_pstrdup(r->pool, ""); - 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; - } - header=ap_pstrcat(r->pool, header, (it ? ";" : ""), value.c_str(), NULL); - } - ap_table_setn(r->headers_in, wrapper->getHeader(), header); - } - } - } - } - - // clean up memory - for (int k = 0; k < assertions.size(); k++) - delete assertions[k]; - delete sso_statement; - - return OK; -} - -extern "C" int shire_post_handler(request_rec* r) -{ - ostringstream threadid; - threadid << "[" << getpid() << "] shire_post_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=mapper->getSettingsFromParsedURL( - ap_http_method(r), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri - ); - pair application_id=settings.first->getString("applicationId"); - const IApplication* application=conf->getApplication(application_id.second); - const IPropertySet* sessionProps=application ? application->getPropertySet("Sessions") : NULL; - if (!application || !sessionProps) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_post_handler: unable to map request to application session settings, check configuration"); - return SERVER_ERROR; - } - - // Declare SHIRE object for this request. - SHIRE shire(application); - - return shire_handler(r, application, sessionProps, shire); -} - -int shire_handler(request_rec* r, const IApplication* application, const IPropertySet* sessionProps, SHIRE& shire) -{ - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_handler() ENTER"); - - // Prime the pump... - const char* targeturl = ap_construct_url(r->pool,r->unparsed_uri,r); - shire.getShireURL(targeturl); - - pair shib_cookie=sessionProps->getString("cookieName"); - pair shib_cookie_props=sessionProps->getString("cookieProps"); - if (!shib_cookie.first) { - ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,r, - "shire_handler: no cookieName set for %s", application->getId()); - return SERVER_ERROR; - } - - ShibMLP markupProcessor(application); - markupProcessor.insert("requestURL", targeturl); - - // Process SHIRE request - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, "shire_handler() Beginning SHIRE processing"); - - try { - pair shireSSL=sessionProps->getBool("shireSSL"); - - // Make sure this is SSL, if it should be - if ((!shireSSL.first || shireSSL.second) && strcmp(ap_http_method(r),"https")) - throw ShibTargetException(SHIBRPC_OK, "blocked non-SSL access to session creation service"); - - // If this is a GET, we manufacture an AuthnRequest. - if (!strcasecmp(r->method,"GET")) { - const char* areq=r->args ? shire.getLazyAuthnRequest(r->args) : NULL; - if (!areq) - throw ShibTargetException(SHIBRPC_OK, "malformed arguments to request a new session"); - ap_table_setn(r->headers_out, "Location", ap_pstrdup(r->pool,areq)); - return REDIRECT; - } - else if (strcasecmp(r->method,"POST")) { - throw ShibTargetException(SHIBRPC_OK, "blocked non-POST to SHIRE POST processor"); - } - - // Sure sure this POST is an appropriate content type - const char *ct = ap_table_get(r->headers_in, "Content-type"); - if (!ct || strcasecmp(ct, "application/x-www-form-urlencoded")) - throw ShibTargetException(SHIBRPC_OK, - ap_psprintf(r->pool, "blocked bad content-type to SHIRE POST processor: %s", (ct ? ct : ""))); - - // Read the posted data - if (ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) - throw ShibTargetException(SHIBRPC_OK, "CGI setup_client_block failed"); - if (!ap_should_client_block(r)) - throw ShibTargetException(SHIBRPC_OK, "CGI should_client_block failed"); - if (r->remaining > 1024*1024) - throw ShibTargetException (SHIBRPC_OK, "CGI length too long..."); - string cgistr; - char buff[HUGE_STRING_LEN]; - ap_hard_timeout("mod_shire", r); - memset(buff, 0, sizeof(buff)); - while (ap_get_client_block(r, buff, sizeof(buff)-1) > 0) { - cgistr += buff; - memset(buff, 0, sizeof(buff)); - } - ap_kill_timeout(r); - - // Parse the submission. - pair elements=shire.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"); - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_handler() Processing POST for target: %s", elements.second); - - // process the post - string cookie; - RPCError* status = shire.sessionCreate(elements.first, r->connection->remote_ip, cookie); - - if (status->isError()) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_handler() POST process failed (%d): %s", status->getCode(), status->getText()); - - if (status->isRetryable()) { - delete status; - ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r, - "shire_handler() retryable error, generating new AuthnRequest"); - ap_table_setn(r->headers_out,"Location",ap_pstrdup(r->pool,shire.getAuthnRequest(elements.second))); - return REDIRECT; - } - - // return this error to the user. - markupProcessor.insert(*status); - delete status; - return shire_error_page(r, application, "shire", markupProcessor); - } - delete status; - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_handler() POST process succeeded. New session: %s", cookie.c_str()); - - // We've got a good session, set the cookie... - char* val = ap_psprintf(r->pool,"%s=%s%s",shib_cookie.second,cookie.c_str(), - shib_cookie_props.first ? shib_cookie_props.second : "; path=/"); - ap_table_setn(r->err_headers_out, "Set-Cookie", val); - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, "shire_handler() setting cookie: %s", val); - - // ... and redirect to the target - ap_table_setn(r->headers_out, "Location", ap_pstrdup(r->pool,elements.second)); - return REDIRECT; - } - catch (ShibTargetException &e) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, "shire_handler() caught exception: %s", e.what()); - markupProcessor.insert("errorType", "Session Creation Service Error"); - markupProcessor.insert("errorText", e.what()); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "shire", markupProcessor); - } -#ifndef _DEBUG - catch (...) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_handler(): unexpected exception"); - markupProcessor.insert("errorType", "Session Creation Service Error"); - markupProcessor.insert("errorText", "Unknown Exception"); - markupProcessor.insert("errorDesc", "An error occurred while processing your request."); - return shire_error_page(r, application, "shire", markupProcessor); - } -#endif - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"shire_handler() server error"); - return SERVER_ERROR; -} - -static table* groups_for_user(request_rec* r, const char* user, char* grpfile) -{ - configfile_t* f; - table* grps=ap_make_table(r->pool,15); - char l[MAX_STRING_LEN]; - const char *group_name, *ll, *w; - - if (!(f=ap_pcfg_openfile(r->pool,grpfile))) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG,r,"groups_for_user() could not open group file: %s\n",grpfile); - return NULL; - } - - pool* sp=ap_make_sub_pool(r->pool); - - while (!(ap_cfg_getline(l,MAX_STRING_LEN,f))) { - if ((*l=='#') || (!*l)) - continue; - ll = l; - ap_clear_pool(sp); - - group_name=ap_getword(sp,&ll,':'); - - while (*ll) { - w=ap_getword_conf(sp,&ll); - if (!strcmp(w,user)) { - ap_table_setn(grps,ap_pstrdup(r->pool,group_name),"in"); - break; - } - } - } - ap_cfg_closefile(f); - ap_destroy_pool(sp); - return grps; -} - -extern "C" int shire_check_auth(request_rec* r) -{ - shire_dir_config* dc= - (shire_dir_config*)ap_get_module_config(r->per_dir_config,&shire_module); - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_auth() executing"); - - // Regular access to arbitrary resource...check AuthType - const char* auth_type=ap_auth_type(r); - if (!auth_type || strcasecmp(auth_type,"shibboleth")) - return DECLINED; - - ostringstream threadid; - threadid << "[" << getpid() << "] shibrm" << '\0'; - saml::NDC ndc(threadid.str().c_str()); - - // We lock the configuration system for the duration. - IConfig* conf=g_Config->getINI(); - Locker locker(conf); - - const char* application_id=ap_table_get(r->headers_in,"Shib-Application-ID"); - const IApplication* application=NULL; - if (application_id) - application = conf->getApplication(application_id); - - // mod_auth clone - - int m=r->method_number; - bool method_restricted=false; - const char *t, *w; - - const array_header* reqs_arr=ap_requires(r); - if (!reqs_arr) - return OK; - - require_line* reqs=(require_line*)reqs_arr->elts; - - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"REQUIRE nelts: %d", reqs_arr->nelts); - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"REQUIRE all: %d", dc->bRequireAll); - - vector auth_OK(reqs_arr->nelts,false); - -#define SHIB_AP_CHECK_IS_OK { \ - if (dc->bRequireAll < 1) \ - return OK; \ - auth_OK[x] = true; \ - continue; \ -} - - for (int x=0; xnelts; x++) { - auth_OK[x] = false; - if (!(reqs[x].method_mask & (1 << m))) - continue; - method_restricted=true; - - t = reqs[x].requirement; - w = ap_getword_white(r->pool, &t); - - if (!strcmp(w,"valid-user")) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_auth() accepting valid-user"); - SHIB_AP_CHECK_IS_OK; - } - else if (!strcmp(w,"user") && r->connection->user) { - bool regexp=false; - while (*t) { - w=ap_getword_conf(r->pool,&t); - if (*w=='~') { - regexp=true; - continue; - } - - if (regexp) { - try { - // To do regex matching, we have to convert from UTF-8. - auto_ptr trans(fromUTF8(w)); - RegularExpression re(trans.get()); - auto_ptr trans2(fromUTF8(r->connection->user)); - if (re.matches(trans2.get())) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_auth() accepting user: %s",w); - SHIB_AP_CHECK_IS_OK; - } - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_auth caught exception while parsing regular expression (%s): %s",w,tmp.get()); - } - } - else if (!strcmp(r->connection->user,w)) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_auth() accepting user: %s",w); - SHIB_AP_CHECK_IS_OK; - } - } - } - else if (!strcmp(w,"group")) { - table* grpstatus=NULL; - if (dc->szAuthGrpFile && r->connection->user) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_auth() using groups file: %s\n",dc->szAuthGrpFile); - grpstatus=groups_for_user(r,r->connection->user,dc->szAuthGrpFile); - } - if (!grpstatus) - return DECLINED; - - while (*t) { - w=ap_getword_conf(r->pool,&t); - if (ap_table_get(grpstatus,w)) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,"shire_check_auth() accepting group: %s",w); - SHIB_AP_CHECK_IS_OK; - } - } - } - else { - Iterator provs=application ? application->getAAPProviders() : EMPTY(IAAP*); - AAP wrapper(provs,w); - if (wrapper.fail()) { - ap_log_rerror(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,r, - "shire_check_auth() didn't recognize require rule: %s\n",w); - continue; - } - - bool regexp=false; - const char* vals=ap_table_get(r->headers_in,wrapper->getHeader()); - while (*t && vals) { - w=ap_getword_conf(r->pool,&t); - if (*w=='~') { - regexp=true; - continue; - } - - try { - auto_ptr re; - if (regexp) { - delete re.release(); - auto_ptr trans(fromUTF8(w)); - auto_ptr 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) { - ap_log_rerror(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,r, - "shire_check_auth() invalid header encoding %s: starts with semicolon", vals); - return SERVER_ERROR; - } - - 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 trans(fromUTF8(val.c_str())); - if (re->matches(trans.get())) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_check_auth() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - } - else if (val==w) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_check_auth() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - else { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_check_auth() expecting %s, got %s: authorization not granted", w, val.c_str()); - } - } - } - - string val = vals_str.substr(j, vals_str.length()-j); - if (regexp) { - auto_ptr trans(fromUTF8(val.c_str())); - if (re->matches(trans.get())) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_check_auth() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - } - else if (val==w) { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_check_auth() expecting %s, got %s: authorization granted", w, val.c_str()); - SHIB_AP_CHECK_IS_OK; - } - else { - ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r, - "shire_check_auth() expecting %s, got %s: authorization not granted", w, val.c_str()); - } - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_auth caught exception while parsing regular expression (%s): %s",w,tmp.get()); - } - } - } - } - - // check if all require directives are true - bool auth_all_OK = true; - for (int i= 0; inelts; i++) { - auth_all_OK &= auth_OK[i]; - } - if (auth_all_OK) - return OK; - - if (!method_restricted) - return OK; - - if (!application_id) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_auth: Shib-Application-ID header not found in request"); - return HTTP_FORBIDDEN; - } - else if (!application) { - ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r, - "shire_check_auth: unable to map request to application settings, check configuration"); - return HTTP_FORBIDDEN; - } - - ShibMLP markupProcessor(application); - markupProcessor.insert("requestURL", ap_construct_url(r->pool,r->unparsed_uri,r)); - return shire_error_page(r, application, "access", markupProcessor); -} - - -extern "C"{ -handler_rec shire_handlers[] = { - { "shib-shire-post", shire_post_handler }, - { NULL } -}; - -module MODULE_VAR_EXPORT shire_module = { - STANDARD_MODULE_STUFF, - NULL, /* initializer */ - create_shire_dir_config, /* dir config creater */ - merge_shire_dir_config, /* dir merger --- default is to override */ - NULL, /* server config */ - NULL, /* merge server config */ - shire_cmds, /* command table */ - shire_handlers, /* handlers */ - NULL, /* filename translation */ - shire_check_user, /* check_user_id */ - shire_check_auth, /* check auth */ - NULL, /* check access */ - NULL, /* type_checker */ - NULL, /* fixups */ - NULL, /* logger */ - NULL, /* header parser */ - shire_child_init, /* child_init */ - shire_child_exit, /* child_exit */ - NULL /* post read-request */ -}; -} diff --git a/mod_shire/mod_shire.dsp b/mod_shire/mod_shire.dsp deleted file mode 100644 index f40ead3..0000000 --- a/mod_shire/mod_shire.dsp +++ /dev/null @@ -1,95 +0,0 @@ -# Microsoft Developer Studio Project File - Name="mod_shire" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=mod_shire - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "mod_shire.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mod_shire.mak" CFG="mod_shire - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "mod_shire - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_shire - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "mod_shire - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MOD_SHIRE_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\oncrpc" /I ".." /I "..\..\..\opensaml\c" /I "\Apache\include" /D "NDEBUG" /D "_USRDLL" /D "MOD_SHIRE_EXPORTS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EAPI" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 saml_4.lib ApacheCore.lib /nologo /dll /machine:I386 /libpath:"../../../opensaml/c/saml/Release" /libpath:"\Apache\libexec" - -!ELSEIF "$(CFG)" == "mod_shire - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MOD_SHIRE_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\oncrpc" /I ".." /I "..\..\..\opensaml\c" /I "\Apache\include" /D "_DEBUG" /D "_AFXDLL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EAPI" /FR /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 saml_4D.lib ApacheCore.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /libpath:"\Apache\libexec" - -!ENDIF - -# Begin Target - -# Name "mod_shire - Win32 Release" -# Name "mod_shire - Win32 Debug" -# Begin Source File - -SOURCE=.\mod_shire.cpp -# End Source File -# End Target -# End Project