* $Id$
*/
+#ifdef SOLARIS2
+#undef _XOPEN_SOURCE // causes gethostname conflict in unistd.h
+#endif
+
// SAML Runtime
#include <saml/saml.h>
#include <shib/shib.h>
static const char* g_UserDataKey = "_shib_check_user_";
}
+// per-server module configuration structure
+struct shib_server_config
+{
+ char* szScheme;
+};
+
+// creates the per-server configuration
+extern "C" void* create_shib_server_config(SH_AP_POOL* p, server_rec* s)
+{
+ shib_server_config* sc=(shib_server_config*)ap_pcalloc(p,sizeof(shib_server_config));
+ sc->szScheme = NULL;
+ return sc;
+}
+
+// overrides server configuration in virtual servers
+extern "C" void* merge_shib_server_config (SH_AP_POOL* p, void* base, void* sub)
+{
+ shib_server_config* sc=(shib_server_config*)ap_pcalloc(p,sizeof(shib_server_config));
+ shib_server_config* parent=(shib_server_config*)base;
+ shib_server_config* child=(shib_server_config*)sub;
+
+ if (child->szScheme)
+ sc->szScheme=ap_pstrdup(p,child->szScheme);
+ else if (parent->szScheme)
+ sc->szScheme=ap_pstrdup(p,parent->szScheme);
+ else
+ sc->szScheme=NULL;
+
+ return sc;
+}
+
// per-dir module configuration structure
struct shib_dir_config
{
return NULL;
}
+extern "C" const char* shib_set_server_string_slot(cmd_parms* parms, void*, const char* arg)
+{
+ char* base=(char*)ap_get_module_config(parms->server->module_config,&mod_shib);
+ int offset=(int)parms->info;
+ *((char**)(base + offset))=ap_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)
return SERVER_ERROR;
}
+static char* shib_get_targeturl(request_rec* r, const char* scheme=NULL)
+{
+ // On 1.3, this is always canonical, but on 2.0, UseCanonicalName comes into play.
+ // However, we also have a setting to forcibly replace the scheme for esoteric cases.
+ if (scheme) {
+ unsigned port = ap_get_server_port(r);
+ if ((!strcmp(scheme,"http") && port==80) || (!strcmp(scheme,"https") && port==443)) {
+ return ap_pstrcat(r->pool, scheme, "://", ap_get_server_name(r), r->unparsed_uri, NULL);
+ }
+ return ap_psprintf(r->pool, "%s://%s:%u%s", scheme, ap_get_server_name(r), port, r->unparsed_uri);
+ }
+ return ap_construct_url(r->pool,r->unparsed_uri,r);
+}
+
extern "C" int shib_check_user(request_rec* r)
{
ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_check_user: ENTER");
shib_dir_config* dc=(shib_dir_config*)ap_get_module_config(r->per_dir_config,&mod_shib);
+ shib_server_config* sc=(shib_server_config*)ap_get_module_config(r->server->module_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);
+ const char* targeturl=shib_get_targeturl(r,sc->szScheme);
// We lock the configuration system for the duration.
IConfig* conf=g_Config->getINI();
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
+ (sc-> szScheme ? sc-> szScheme : ap_http_method(r)), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri
);
pair<bool,const char*> application_id=settings.first->getString("applicationId");
const IApplication* application=conf->getApplication(application_id.second);
// Declare SHIRE object for this request.
SHIRE shire(application);
+ const char* shireURL=shire.getShireURL(targeturl);
+ if (!shireURL) {
+ ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
+ "shib_check_user: unable to map request to proper shireURL setting, check configuration");
+ return SERVER_ERROR;
+ }
+
// Get location of this application's assertion consumer service and see if this is it.
- if (strstr(targeturl,shire.getShireURL(targeturl))) {
+ if (strstr(targeturl,shireURL)) {
return shib_handler(r,application,shire);
}
// Do we have an access control plugin?
if (settings.second) {
Locker acllock(settings.second);
- if (!settings.second->authorized(assertions)) {
+ if (!settings.second->authorized(*sso_statement,assertions)) {
for (int k = 0; k < assertions.size(); k++)
delete assertions[k];
delete sso_statement;
Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
while (rules.hasNext()) {
const char* header=rules.next()->getHeader();
- if (header)
+ if (header) {
ap_table_unset(r->headers_in,header);
+ ap_table_set(r->headers_in,header,"");
+ }
}
}
catch(...) {
ap_table_unset(r->headers_in,"Shib-Origin-Site");
ap_table_unset(r->headers_in,"Shib-Authentication-Method");
ap_table_unset(r->headers_in,"Shib-NameIdentifier-Format");
- if (sso_statement) {
- auto_ptr_char os(sso_statement->getSubject()->getNameIdentifier()->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());
-
- // Export NameID?
- AAP wrapper(provs,sso_statement->getSubject()->getNameIdentifier()->getFormat(),Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
- if (!wrapper.fail() && wrapper->getHeader()) {
- auto_ptr_char form(sso_statement->getSubject()->getNameIdentifier()->getFormat());
- auto_ptr_char nameid(sso_statement->getSubject()->getNameIdentifier()->getName());
- ap_table_set(r->headers_in,"Shib-NameIdentifier-Format",form.get());
- if (!strcmp(wrapper->getHeader(),"REMOTE_USER"))
- SH_AP_USER(r)=ap_pstrdup(r->pool,nameid.get());
- else
- ap_table_set(r->headers_in,wrapper->getHeader(),nameid.get());
- }
+ auto_ptr_char os(sso_statement->getSubject()->getNameIdentifier()->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());
+
+ // Export NameID?
+ AAP wrapper(provs,sso_statement->getSubject()->getNameIdentifier()->getFormat(),Constants::SHIB_ATTRIBUTE_NAMESPACE_URI);
+ if (!wrapper.fail() && wrapper->getHeader()) {
+ auto_ptr_char form(sso_statement->getSubject()->getNameIdentifier()->getFormat());
+ auto_ptr_char nameid(sso_statement->getSubject()->getNameIdentifier()->getName());
+ ap_table_set(r->headers_in,"Shib-NameIdentifier-Format",form.get());
+ if (!strcmp(wrapper->getHeader(),"REMOTE_USER"))
+ SH_AP_USER(r)=ap_pstrdup(r->pool,nameid.get());
+ else
+ ap_table_set(r->headers_in,wrapper->getHeader(),nameid.get());
}
ap_table_unset(r->headers_in,"Shib-Application-ID");
extern "C" int shib_post_handler(request_rec* r)
{
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
+ ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),
"shib_post_handler(%d): ENTER", (int)getpid());
+ shib_server_config* sc=(shib_server_config*)ap_get_module_config(r->server->module_config,&mod_shib);
#ifndef SHIB_APACHE_13
// With 2.x, this handler always runs, though last.
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
+ (sc->szScheme ? sc->szScheme : ap_http_method(r)), ap_get_server_name(r), ap_get_server_port(r), r->unparsed_uri
);
pair<bool,const char*> application_id=settings.first->getString("applicationId");
const IApplication* application=conf->getApplication(application_id.second);
int shib_handler(request_rec* r, const IApplication* application, SHIRE& shire)
{
- // Prime the pump...
- const char* targeturl = ap_construct_url(r->pool,r->unparsed_uri,r);
+ shib_server_config* sc=(shib_server_config*)ap_get_module_config(r->server->module_config,&mod_shib);
+
+ const char* targeturl=shib_get_targeturl(r,sc->szScheme);
+
+ const char* shireURL=shire.getShireURL(targeturl);
+ if (!shireURL) {
+ ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(r),
+ "shib_post_handler: unable to map request to proper shireURL setting, check configuration");
+ return SERVER_ERROR;
+ }
// Make sure we only process the SHIRE requests.
- if (!strstr(targeturl,shire.getShireURL(targeturl)))
+ if (!strstr(targeturl,shireURL))
return DECLINED;
ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r),"shib_handler() running");
ap_hard_timeout("[mod_shib] CGI Parser", r);
memset(buff, 0, sizeof(buff));
while (ap_get_client_block(r, buff, sizeof(buff)-1) > 0) {
+ ap_reset_timeout(r);
cgistr += buff;
memset(buff, 0, sizeof(buff));
}
return shib_error_page(r, application, "access", markupProcessor);
}
+#ifndef SHIB_APACHE_13
/*
* shib_exit()
- * Cleanup the (per-process) pool info.
+ * Empty cleanup hook, Apache 2.x doesn't check NULL very well...
*/
-#ifdef SHIB_APACHE_13
-extern "C" void shib_exit(server_rec* s, SH_AP_POOL* p)
-{
-#else
extern "C" apr_status_t shib_exit(void* data)
{
- server_rec* s = NULL;
-#endif
-
- ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_exit(%d) dealing with g_Config..", (int)getpid());
-
- g_Config->shutdown();
- g_Config = NULL;
-
- ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_exit() done\n");
-#ifndef SHIB_APACHE_13
+ ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,NULL,"shib_exit() done\n");
return OK;
-#endif
}
+#endif
+/*
+ * shib_child_exit()
+ * Cleanup the (per-process) pool info.
+ */
#ifdef SHIB_APACHE_13
extern "C" void shib_child_exit(server_rec* s, SH_AP_POOL* p)
{
server_rec* s = NULL;
#endif
- ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_exit(%d)",
- (int)getpid());
+ ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_exit(%d) dealing with g_Config..", (int)getpid());
+ g_Config->shutdown();
+ g_Config = NULL;
+ ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_exit() done\n");
#ifndef SHIB_APACHE_13
return OK;
#ifdef SHIB_APACHE_13
extern "C" void shib_child_init(server_rec* s, SH_AP_POOL* p)
#else
-extern "C" int shib_post_config(apr_pool_t* pconf, apr_pool_t* plog,
- apr_pool_t* ptemp, server_rec* s)
+extern "C" void shib_child_init(apr_pool_t* p, server_rec* s)
#endif
{
// Initialize runtime components.
if (g_Config) {
ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() already initialized!");
-#ifdef SHIB_APACHE_13
exit(1);
-#else
- return OK;
-#endif
}
try {
}
// Set the cleanup handler
- apr_pool_cleanup_register(pconf, NULL, &shib_exit, &shib_child_exit);
+ apr_pool_cleanup_register(p, NULL, &shib_exit, &shib_child_exit);
ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() done");
-
-#ifndef SHIB_APACHE_13
- return OK;
-#endif
}
#ifdef SHIB_APACHE_13
{"ShibSchemaDir", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir,
RSRC_CONF, TAKE1, "Path to Shibboleth XML schema directory."},
+ {"ShibURLScheme", (config_fn_t)shib_set_server_string_slot,
+ (void *) XtOffsetOf (shib_server_config, szScheme),
+ RSRC_CONF, TAKE1, "URL scheme to force into generated URLs for a vhost."},
+
{"ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
(void *) XtOffsetOf (shib_dir_config, bBasicHijack),
OR_AUTHCFG, FLAG, "Respond to AuthType Basic and convert to shib?"},
NULL, /* initializer */
create_shib_dir_config, /* dir config creater */
merge_shib_dir_config, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
+ create_shib_server_config, /* server config */
+ merge_shib_server_config, /* merge server config */
shire_cmds, /* command table */
shib_handlers, /* handlers */
NULL, /* filename translation */
NULL, /* logger */
NULL, /* header parser */
shib_child_init, /* child_init */
- shib_exit, /* child_exit */
+ shib_child_exit, /* child_exit */
NULL /* post read-request */
};
extern "C" void shib_register_hooks (apr_pool_t *p)
{
- ap_hook_post_config(shib_post_config, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(shib_child_init, 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);
(config_fn_t)ap_set_global_string_slot, &g_szSchemaDir,
RSRC_CONF, "Path to Shibboleth XML schema directory."),
+ 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("ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
(void *) offsetof (shib_dir_config, bBasicHijack),
OR_AUTHCFG, "Respond to AuthType Basic and convert to shib?"),
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 */
+ create_shib_dir_config, /* create dir config */
+ merge_shib_dir_config, /* merge dir config --- default is to override */
+ create_shib_server_config, /* create server config */
+ merge_shib_server_config, /* merge server config */
+ shib_cmds, /* command table */
+ shib_register_hooks /* register hooks */
};
#else