From 3ea6c86d5f174e63b72546d6443a517dc040fb60 Mon Sep 17 00:00:00 2001 From: cantor Date: Tue, 7 Aug 2007 21:54:19 +0000 Subject: [PATCH] Options for per-content error handling. Apache command for arbitrary request settings. git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2395 cb58f699-b61c-0410-a6fe-9272a202ed29 --- apache/mod_apache.cpp | 122 +++++++++++++++++++--------- apache/mod_shib_20.cpp | 4 +- apache/mod_shib_22.cpp | 3 + schemas/shibboleth-2.0-native-sp-config.xsd | 5 +- shibsp/ServiceProvider.cpp | 42 ++++++---- 5 files changed, 121 insertions(+), 55 deletions(-) diff --git a/apache/mod_apache.cpp b/apache/mod_apache.cpp index 6b14131..bfa823f 100644 --- a/apache/mod_apache.cpp +++ b/apache/mod_apache.cpp @@ -141,6 +141,8 @@ extern "C" void* merge_shib_server_config (SH_AP_POOL* p, void* base, void* sub) // per-dir module configuration structure struct shib_dir_config { + SH_AP_TABLE* tSettings; // generic table of extensible settings + // RM Configuration char* szAuthGrpFile; // Auth GroupFile name int bRequireAll; // all require directives must match, otherwise OR logic @@ -161,15 +163,16 @@ struct shib_dir_config extern "C" void* create_shib_dir_config (SH_AP_POOL* p, char* d) { shib_dir_config* dc=(shib_dir_config*)ap_pcalloc(p,sizeof(shib_dir_config)); + dc->tSettings = NULL; + dc->szAuthGrpFile = NULL; + dc->bRequireAll = -1; + dc->szApplicationId = NULL; + dc->szRequireWith = NULL; + dc->szRedirectToSSL = NULL; dc->bOff = -1; dc->bBasicHijack = -1; dc->bRequireSession = -1; dc->bExportAssertion = -1; - dc->bRequireAll = -1; - dc->szRedirectToSSL = NULL; - dc->szAuthGrpFile = NULL; - dc->szApplicationId = NULL; - dc->szRequireWith = NULL; dc->bUseEnvVars = -1; dc->bUseHeaders = -1; return dc; @@ -182,6 +185,17 @@ extern "C" void* merge_shib_dir_config (SH_AP_POOL* p, void* base, void* sub) shib_dir_config* parent=(shib_dir_config*)base; shib_dir_config* child=(shib_dir_config*)sub; + // The child supersedes any matching table settings in the parent. + dc->tSettings = NULL; + if (parent->tSettings) + dc->tSettings = ap_copy_table(p, parent->tSettings); + if (child->tSettings) { + if (dc->tSettings) + ap_overlap_tables(dc->tSettings, child->tSettings, AP_OVERLAP_TABLES_SET); + else + dc->tSettings = ap_copy_table(p, child->tSettings); + } + if (child->szAuthGrpFile) dc->szAuthGrpFile=ap_pstrdup(p,child->szAuthGrpFile); else if (parent->szAuthGrpFile) @@ -266,6 +280,14 @@ extern "C" const char* shib_ap_set_file_slot(cmd_parms* parms, return DECLINE_CMD; } +extern "C" const char* shib_table_set(cmd_parms* parms, shib_dir_config* dc, const char* arg1, const char* arg2) +{ + if (!dc->tSettings) + dc->tSettings = ap_make_table(parms->pool, 4); + ap_table_set(dc->tSettings, arg1, arg2); + return NULL; +} + /********************************************************************************/ // Apache ShibTarget subclass(es) here. @@ -701,10 +723,15 @@ pair ApacheRequestMapper::getBool(const char* name, const char* ns) c const PropertySet* s=reinterpret_cast(m_propsKey->getData()); if (sta && !ns) { // Override Apache-settable boolean properties. - if (name && !strcmp(name,"requireSession") && sta->m_dc->bRequireSession==1) - return make_pair(true,true); - else if (name && !strcmp(name,"exportAssertion") && sta->m_dc->bExportAssertion==1) - return make_pair(true,true); + if (name && !strcmp(name,"requireSession") && sta->m_dc->bRequireSession != -1) + return make_pair(true, sta->m_dc->bRequireSession==1); + else if (name && !strcmp(name,"exportAssertion") && sta->m_dc->bExportAssertion != -1) + return make_pair(true, sta->m_dc->bExportAssertion==1); + else if (sta->m_dc->tSettings) { + const char* prop = ap_table_get(sta->m_dc->tSettings, name); + if (prop) + return make_pair(true, !strcmp(prop, "true") || !strcmp(prop, "1") || !strcmp(prop, "On")); + } } return s ? s->getBool(name,ns) : make_pair(false,false); } @@ -730,6 +757,11 @@ pair ApacheRequestMapper::getString(const char* name, const ch return pair(true,sta->m_dc->szRequireWith); else if (name && !strcmp(name,"redirectToSSL") && sta->m_dc->szRedirectToSSL) return pair(true,sta->m_dc->szRedirectToSSL); + else if (sta->m_dc->tSettings) { + const char* prop = ap_table_get(sta->m_dc->tSettings, name); + if (prop) + return make_pair(true, prop); + } } return s ? s->getString(name,ns) : pair(false,NULL); } @@ -747,7 +779,12 @@ pair ApacheRequestMapper::getUnsignedInt(const char* name, co if (sta && !ns) { // Override Apache-settable int properties. if (name && !strcmp(name,"redirectToSSL") && sta->m_dc->szRedirectToSSL) - return pair(true,strtol(sta->m_dc->szRedirectToSSL,NULL,10)); + return pair(true, strtol(sta->m_dc->szRedirectToSSL, NULL, 10)); + else if (sta->m_dc->tSettings) { + const char* prop = ap_table_get(sta->m_dc->tSettings, name); + if (prop) + return make_pair(true, strtol(prop, NULL, 10)); + } } return s ? s->getUnsignedInt(name,ns) : pair(false,0); } @@ -760,6 +797,11 @@ pair ApacheRequestMapper::getInt(const char* name, const char* ns) con // Override Apache-settable int properties. if (name && !strcmp(name,"redirectToSSL") && sta->m_dc->szRedirectToSSL) return pair(true,atoi(sta->m_dc->szRedirectToSSL)); + else if (sta->m_dc->tSettings) { + const char* prop = ap_table_get(sta->m_dc->tSettings, name); + if (prop) + return make_pair(true, atoi(prop)); + } } return s ? s->getInt(name,ns) : pair(false,0); } @@ -1225,6 +1267,9 @@ static command_rec shire_cmds[] = { (void *) XtOffsetOf (shib_server_config, szScheme), RSRC_CONF, TAKE1, "URL scheme to force into generated URLs for a vhost"}, + {"ShibRequestSetting", (config_fn_t)shib_table_set, NULL, + OR_AUTHCFG, TAKE2, "Set arbitrary Shibboleth request property for content"}, + {"ShibDisable", (config_fn_t)ap_set_flag_slot, (void *) XtOffsetOf (shib_dir_config, bOff), OR_AUTHCFG, FLAG, "Disable all Shib module activity here to save processing effort"}, @@ -1282,12 +1327,12 @@ module MODULE_VAR_EXPORT mod_shib = { shib_auth_checker, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ - shib_fixups, /* fixups */ + NULL,//shib_fixups, /* fixups */ NULL, /* logger */ NULL, /* header parser */ shib_child_init, /* child_init */ shib_child_exit, /* child_exit */ - shib_post_read /* post read-request */ + NULL//shib_post_read /* post read-request */ }; #elif defined(SHIB_APACHE_20) || defined(SHIB_APACHE_22) @@ -1312,56 +1357,55 @@ extern "C" void shib_register_hooks (apr_pool_t *p) 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("ShibCatalogs", - (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir, - RSRC_CONF, "Paths of XML schema catalogs"), - AP_INIT_TAKE1("ShibSchemaDir", - (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir, - RSRC_CONF, "Paths of XML schema catalogs (deprecated in favor of ShibCatalogs)"), - - AP_INIT_TAKE1("ShibURLScheme", - (config_fn_t)shib_set_server_string_slot, - (void *) offsetof (shib_server_config, szScheme), - RSRC_CONF, "URL scheme to force into generated URLs for a vhost"), - - AP_INIT_FLAG("ShibDisable", (config_fn_t)ap_set_flag_slot, + 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("ShibCatalogs", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir, + RSRC_CONF, "Paths of XML schema catalogs"), + AP_INIT_TAKE1("ShibSchemaDir", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir, + RSRC_CONF, "Paths of XML schema catalogs (deprecated in favor of ShibCatalogs)"), + + AP_INIT_TAKE1("ShibURLScheme", (config_fn_t)shib_set_server_string_slot, + (void *) offsetof (shib_server_config, szScheme), + RSRC_CONF, "URL scheme to force into generated URLs for a vhost"), + + AP_INIT_TAKE2("ShibRequestSetting", (config_fn_t)shib_table_set, NULL, + OR_AUTHCFG, "Set arbitrary Shibboleth request property for content"), + + AP_INIT_FLAG("ShibDisable", (config_fn_t)ap_set_flag_slot, (void *) offsetof (shib_dir_config, bOff), OR_AUTHCFG, "Disable all Shib module activity here to save processing effort"), - AP_INIT_TAKE1("ShibApplicationId", (config_fn_t)ap_set_string_slot, + AP_INIT_TAKE1("ShibApplicationId", (config_fn_t)ap_set_string_slot, (void *) offsetof (shib_dir_config, szApplicationId), OR_AUTHCFG, "Set Shibboleth applicationId property for content"), - AP_INIT_FLAG("ShibBasicHijack", (config_fn_t)ap_set_flag_slot, + 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 shibboleth"), - AP_INIT_FLAG("ShibRequireSession", (config_fn_t)ap_set_flag_slot, + 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_TAKE1("ShibRequireSessionWith", (config_fn_t)ap_set_string_slot, + AP_INIT_TAKE1("ShibRequireSessionWith", (config_fn_t)ap_set_string_slot, (void *) offsetof (shib_dir_config, szRequireWith), OR_AUTHCFG, "Initiates a new session if one does not exist using a specific SessionInitiator"), - AP_INIT_FLAG("ShibExportAssertion", (config_fn_t)ap_set_flag_slot, + AP_INIT_FLAG("ShibExportAssertion", (config_fn_t)ap_set_flag_slot, (void *) offsetof (shib_dir_config, bExportAssertion), OR_AUTHCFG, "Export SAML attribute assertion(s) to Shib-Attributes header"), - AP_INIT_TAKE1("ShibRedirectToSSL", (config_fn_t)ap_set_string_slot, + AP_INIT_TAKE1("ShibRedirectToSSL", (config_fn_t)ap_set_string_slot, (void *) offsetof (shib_dir_config, szRedirectToSSL), OR_AUTHCFG, "Redirect non-SSL requests to designated port"), - AP_INIT_TAKE1("AuthGroupFile", (config_fn_t)shib_ap_set_file_slot, + AP_INIT_TAKE1("AuthGroupFile", (config_fn_t)shib_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, + AP_INIT_FLAG("ShibRequireAll", (config_fn_t)ap_set_flag_slot, (void *) offsetof (shib_dir_config, bRequireAll), OR_AUTHCFG, "All require directives must match"), - AP_INIT_FLAG("ShibUseEnvironment", (config_fn_t)ap_set_flag_slot, + AP_INIT_FLAG("ShibUseEnvironment", (config_fn_t)ap_set_flag_slot, (void *) offsetof (shib_dir_config, bUseEnvVars), OR_AUTHCFG, "Export attributes using environment variables (default)"), - AP_INIT_FLAG("ShibUseHeaders", (config_fn_t)ap_set_flag_slot, + AP_INIT_FLAG("ShibUseHeaders", (config_fn_t)ap_set_flag_slot, (void *) offsetof (shib_dir_config, bUseHeaders), OR_AUTHCFG, "Export attributes using custom HTTP headers"), - {NULL} + {NULL} }; module AP_MODULE_DECLARE_DATA mod_shib = { diff --git a/apache/mod_shib_20.cpp b/apache/mod_shib_20.cpp index 5db15c7..065b24e 100644 --- a/apache/mod_shib_20.cpp +++ b/apache/mod_shib_20.cpp @@ -47,10 +47,12 @@ #define ap_clear_pool apr_pool_clear #define ap_destroy_pool apr_pool_destroy #define ap_make_table apr_table_make +#define ap_copy_table apr_table_copy #define ap_overlay_tables apr_table_overlay +#define ap_overlap_tables apr_table_overlap #define ap_table_elts apr_table_elts #define ap_is_empty_table apr_is_empty_table - +#define AP_OVERLAP_TABLES_SET APR_OVERLAP_TABLES_SET #define ap_send_http_header(r) #define ap_hard_timeout(str,r) diff --git a/apache/mod_shib_22.cpp b/apache/mod_shib_22.cpp index c84cd1b..5cab9e4 100644 --- a/apache/mod_shib_22.cpp +++ b/apache/mod_shib_22.cpp @@ -44,12 +44,15 @@ #define ap_table_setn apr_table_setn #define ap_table_unset apr_table_unset #define ap_table_set apr_table_set +#define ap_copy_table apr_table_copy #define ap_overlay_tables apr_table_overlay +#define ap_overlap_tables apr_table_overlap #define ap_table_elts apr_table_elts #define ap_is_empty_table apr_is_empty_table #define ap_clear_pool apr_pool_clear #define ap_destroy_pool apr_pool_destroy #define ap_make_table apr_table_make +#define AP_OVERLAP_TABLES_SET APR_OVERLAP_TABLES_SET #define ap_send_http_header(r) #define ap_hard_timeout(str,r) diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd index 7c8f170..15d340a 100644 --- a/schemas/shibboleth-2.0-native-sp-config.xsd +++ b/schemas/shibboleth-2.0-native-sp-config.xsd @@ -279,6 +279,10 @@ + + + + @@ -560,7 +564,6 @@ - diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp index 5af4e4b..c4b70b8 100644 --- a/shibsp/ServiceProvider.cpp +++ b/shibsp/ServiceProvider.cpp @@ -61,23 +61,37 @@ namespace shibsp { request.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT"); request.setResponseHeader("Cache-Control","private,no-store,no-cache"); + // Error templates come from the request's settings or from the Errors property set. + pair pathname = pair(false,NULL); + try { + RequestMapper::Settings settings = request.getRequestSettings(); + string pagename(page); + pagename += "Error"; + pathname = settings.first->getString(pagename.c_str()); + } + catch (exception& ex) { + request.log(SPRequest::SPError, ex.what()); + } + + // Nothing for request, so check app properties. const PropertySet* props=app ? app->getPropertySet("Errors") : NULL; - if (props) { - pair 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, tp.getRichException()); - return request.sendResponse(str); - } - } - else if (!strcmp(page,"access")) { - istringstream msg("Access Denied"); - return request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN); + if (!pathname.first && props) + pathname=props->getString(page); + + if (pathname.first) { + ifstream infile(pathname.second); + if (infile) { + tp.setPropertySet(props); + stringstream str; + XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, tp.getRichException()); + return request.sendResponse(str); } } + + if (!strcmp(page,"access")) { + istringstream msg("Access Denied"); + return request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN); + } string errstr = string("sendError could not process error template (") + page + ")"; request.log(SPRequest::SPError, errstr); -- 2.1.4