2 * mod_shire.cpp -- the SHIRE Apache Module
4 * Created by: Derek Atkins <derek@ihtfp.com>
9 // Apache specific header files
11 #include "http_config.h"
12 #include "http_protocol.h"
13 #include "http_main.h"
14 #include "util_script.h"
16 #include "http_core.h"
19 // For POST processing from Apache
20 #include <libapreq/apache_request.h>
23 #include <saml/saml.h>
24 #include <shib/shib.h>
25 #include <shib-target/shib-target.h>
33 using namespace shibboleth;
34 using namespace shibtarget;
36 extern "C" module MODULE_VAR_EXPORT shire_module;
38 static char* g_szSHIREConfig = NULL;
39 static RPCHandle *rpc_handle = NULL;
40 static ShibTargetConfig * g_szConfig = NULL;
42 // per-server configuration structure
43 struct shire_server_config
45 char* serverName; // Name of this server
48 // creates the per-server configuration
49 extern "C" void* create_shire_server_config (pool * p, server_rec * s)
51 shire_server_config* sc=(shire_server_config*)ap_pcalloc(p,sizeof(shire_server_config));
55 // overrides server configuration in virtual servers
56 extern "C" void* merge_shire_server_config (pool* p, void* base, void* sub)
58 shire_server_config* sc=(shire_server_config*)ap_pcalloc(p,sizeof(shire_server_config));
59 shire_server_config* parent=(shire_server_config*)base;
60 shire_server_config* child=(shire_server_config*)sub;
62 if (child->serverName)
63 sc->serverName=ap_pstrdup(p,child->serverName);
64 else if (parent->serverName)
65 sc->serverName=ap_pstrdup(p,parent->serverName);
72 // per-dir module configuration structure
73 struct shire_dir_config
75 int bBasicHijack; // activate for AuthType Basic?
76 int bSSLOnly; // only over SSL?
77 SHIREConfig config; // SHIRE Configuration
80 // creates per-directory config structure
81 extern "C" void* create_shire_dir_config (pool* p, char* d)
83 shire_dir_config* dc=(shire_dir_config*)ap_pcalloc(p,sizeof(shire_dir_config));
84 dc->bBasicHijack = -1;
86 dc->config.lifetime = -1;
87 dc->config.timeout = -1;
91 // overrides server configuration in directories
92 extern "C" void* merge_shire_dir_config (pool* p, void* base, void* sub)
94 shire_dir_config* dc=(shire_dir_config*)ap_pcalloc(p,sizeof(shire_dir_config));
95 shire_dir_config* parent=(shire_dir_config*)base;
96 shire_dir_config* child=(shire_dir_config*)sub;
98 dc->bBasicHijack=((child->bBasicHijack==-1) ? parent->bBasicHijack : child->bBasicHijack);
99 dc->bSSLOnly=((child->bSSLOnly==-1) ? parent->bSSLOnly : child->bSSLOnly);
100 dc->config.lifetime=((child->config.lifetime==-1) ? parent->config.lifetime : child->config.lifetime);
101 dc->config.timeout=((child->config.timeout==-1) ? parent->config.timeout : child->config.timeout);
105 // generic global slot handlers
106 extern "C" const char* ap_set_global_string_slot(cmd_parms* parms, void*, const char* arg)
108 *((char**)(parms->info))=ap_pstrdup(parms->pool,arg);
112 // generic per-server slot handlers
113 extern "C" const char* ap_set_server_string_slot(cmd_parms* parms, void*, const char* arg)
115 char* base=(char*)ap_get_module_config(parms->server->module_config,&shire_module);
116 int offset=(int)parms->info;
117 *((char**)(base + offset))=ap_pstrdup(parms->pool,arg);
121 // some shortcuts for directory config slots
122 extern "C" const char* set_lifetime(cmd_parms* parms, shire_dir_config* dc, const char* arg)
124 dc->config.lifetime=atoi(arg);
128 extern "C" const char* set_timeout(cmd_parms* parms, shire_dir_config* dc, const char* arg)
130 dc->config.timeout=atoi(arg);
137 typedef const char* (*config_fn_t)(void);
139 // SHIRE Module commands
141 static command_rec shire_cmds[] = {
142 {"SHIREConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIREConfig,
143 RSRC_CONF, TAKE1, "Path to SHIRE ini file."},
145 {"ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
146 (void *) XtOffsetOf (shire_dir_config, bBasicHijack),
147 OR_AUTHCFG, FLAG, "Respond to AuthType Basic and convert to shib?"},
148 {"ShibSSLOnly", (config_fn_t)ap_set_flag_slot,
149 (void *) XtOffsetOf (shire_dir_config, bSSLOnly),
150 OR_AUTHCFG, FLAG, "Require SSL when accessing a secured directory?"},
151 {"ShibAuthLifetime", (config_fn_t)set_lifetime, NULL,
152 OR_AUTHCFG, TAKE1, "Lifetime of session in seconds."},
153 {"ShibAuthTimeout", (config_fn_t)set_timeout, NULL,
154 OR_AUTHCFG, TAKE1, "Timeout for session in seconds."},
162 * Things to do when the child process is initialized.
164 extern "C" void shire_child_init(server_rec* s, pool* p)
166 // Initialize runtime components.
169 ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,s,
170 "shire_child_init(): already initialized!");
175 g_szConfig = &(ShibTargetConfig::init(SHIBTARGET_SHIRE, g_szSHIREConfig));
176 } catch (runtime_error& e) {
177 ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,
178 "shire_child_init() failed to initialize SHIB Target");
182 // Create the RPC Handle.. Note: this should be per _thread_
183 // if there is some way to do that reasonably..
184 rpc_handle = new RPCHandle(SHIB_SHAR_SOCKET, SHIBRPC_PROG, SHIBRPC_VERS_1);
186 ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_init() done");
194 extern "C" void shire_child_exit(server_rec* s, pool* p)
197 g_szConfig->shutdown();
199 ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_exit() done");
202 inline char hexchar(unsigned short s)
204 return (s<=9) ? ('0' + s) : ('A' + s - 10);
207 static char* url_encode(request_rec* r, const char* s)
209 static char badchars[]="\"\\+<>#%{}|^~[]`;/?:@=&";
210 char* ret=(char*)ap_palloc(r->pool,sizeof(char)*3*strlen(s)+1);
212 unsigned long count=0;
215 if (strchr(badchars,*s)!=NULL || *s<=0x1F || *s>=0x7F)
218 ret[count++]=hexchar(*s >> 4);
219 ret[count++]=hexchar(*s & 0x0F);
228 // Return the "name" of this server to look up configuration options
229 static const char* get_service_name(request_rec* r)
231 shire_server_config* sc =
232 (shire_server_config*) ap_get_module_config(r->server->module_config,
236 return sc->serverName;
238 return ap_get_server_name(r);
241 // return the "normalized" target URL
242 static const char* get_target(request_rec* r, const char* target)
244 const char* serverName = get_service_name(r);
246 if ((g_szConfig->getINI()).get_tag (serverName, "normalizeRequest", true, &tag))
248 if (ShibINI::boolean (tag))
250 const char* colon=strchr(target,':');
251 const char* slash=strchr(colon+3,'/');
252 const char* second_colon=strchr(colon+3,':');
253 return ap_pstrcat(r->pool,ap_pstrndup(r->pool,target,colon+3-target),
254 ap_get_server_name(r),
255 (second_colon && second_colon < slash) ?
256 second_colon : slash,
263 static const char* get_shire_location(request_rec* r, const char* target, bool encode)
265 ShibINI& ini = g_szConfig->getINI();
266 const char* serverName = get_service_name(r);
267 string shire_location;
269 if (! ini.get_tag (serverName, "shireURL", true, &shire_location)) {
270 ap_log_rerror(APLOG_MARK,APLOG_ERR,r,
271 "shire_get_location() no shireURL configuration for %s",
276 const char* shire = shire_location.c_str();
280 return url_encode(r,shire);
282 return ap_pstrdup(r->pool,shire);
284 const char* colon=strchr(target,':');
285 const char* slash=strchr(colon+3,'/');
287 return url_encode(r,ap_pstrcat(r->pool,
288 ap_pstrndup(r->pool,target,slash-target),
291 return ap_pstrcat(r->pool, ap_pstrndup(r->pool,target,slash-target),
295 static bool is_shire_location(request_rec* r, const char* target)
297 const char* shire = get_shire_location(r, target, false);
299 if (!shire) return false;
301 if (!strstr(target, shire))
304 return (!strcmp(target,shire));
307 static int shire_error_page(request_rec* r, const char* filename, ShibMLP& mlp)
309 ifstream infile (filename);
311 ap_log_rerror(APLOG_MARK,APLOG_ERR,r,
312 "shire_error_page() cannot open %s", filename);
316 string res = mlp.run(infile);
317 r->content_type = ap_psprintf(r->pool, "text/html");
318 ap_send_http_header(r);
319 ap_rprintf(r, res.c_str());
323 extern "C" int shire_check_user(request_rec* r)
326 threadid << "[" << getpid() << "] shire" << '\0';
327 saml::NDC ndc(threadid.str());
329 ShibINI& ini = g_szConfig->getINI();
330 ShibMLP markupProcessor;
332 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
333 "shire_check_user: ENTER");
335 shire_dir_config* dc=
336 (shire_dir_config*)ap_get_module_config(r->per_dir_config,&shire_module);
338 const char* targeturl=get_target(r,ap_construct_url(r->pool,r->unparsed_uri,r));
340 const char * shire_location = get_shire_location(r,targeturl,true);
341 if (!shire_location) return SERVER_ERROR;
342 string shire_url = get_shire_location(r,targeturl,false);
344 const char* serverName = get_service_name (r);
346 bool has_tag = ini.get_tag (serverName, "checkIPAddress", true, &tag);
347 dc->config.checkIPAddress = (has_tag ? ShibINI::boolean (tag) : false);
350 if (! ini.get_tag (serverName, "cookieName", true, &shib_cookie)) {
351 ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,r,
352 "shire_check_user: no cookieName configuration for %s",
358 if (! ini.get_tag (serverName, "wayfURL", true, &wayfLocation)) {
359 ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,r,
360 "shire_check_user: no wayfURL configuration for %s",
366 if (! ini.get_tag (serverName, "wayfError", true, &wayfError)) {
367 ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,r,
368 "shire_check_user: no wayfError configuration for %s",
373 ini.get_tag (serverName, "supportContact", true, &tag);
374 markupProcessor.insert ("supportContact", has_tag ? tag : "");
375 has_tag = ini.get_tag (serverName, "logoLocation", true, &tag);
376 markupProcessor.insert ("logoLocation", has_tag ? tag : "");
377 markupProcessor.insert ("requestURL", targeturl);
379 SHIRE shire(rpc_handle, dc->config, shire_url);
381 if (is_shire_location (r, targeturl)) {
382 // Process SHIRE POST
384 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
385 "shire_check_user() Beginning SHIRE POST processing");
391 if (! ini.get_tag (serverName, "shireSSLOnly", true, &sslonly))
392 ap_log_rerror(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,r,
393 "shire_check_user: no shireSSLOnly configuration");
395 // Make sure this is SSL, if it should be
396 if (ShibINI::boolean(sslonly) && strcmp(ap_http_method(r),"https"))
397 throw ShibTargetException (SHIBRPC_OK,
398 "blocked non-SSL access to SHIRE POST processor");
400 // Make sure this is a POST
401 if (strcasecmp (r->method, "POST"))
402 throw ShibTargetException (SHIBRPC_OK,
403 "blocked non-POST to SHIRE POST processor");
405 // Sure sure this POST is an appropriate content type
406 const char *ct = ap_table_get (r->headers_in, "Content-type");
407 if (!ct || strcasecmp (ct, "application/x-www-form-urlencoded"))
408 throw ShibTargetException (SHIBRPC_OK,
410 "blocked bad content-type to SHIRE POST processor: %s",
413 // Make sure the "bytes sent" is a reasonable number
414 if (r->bytes_sent > 1024*1024) // 1MB?
415 throw ShibTargetException (SHIBRPC_OK,
416 "blocked too-large a post to SHIRE POST processor");
418 // Read the posted data
419 ApacheRequest *ap_req = ApacheRequest_new(r);
420 int err = ApacheRequest_parse(ap_req);
422 throw ShibTargetException (SHIBRPC_OK,
424 "ApacheRequest_parse() failed with %d.", err));
427 // Make sure the target parameter exists
428 const char *target = ApacheRequest_param(ap_req, "TARGET");
429 if (!target || *target == '\0')
431 throw ShibTargetException (SHIBRPC_OK,
432 "SHIRE POST failed to find TARGET");
434 // Make sure the SAML Response parameter exists
435 const char *post = ApacheRequest_param(ap_req, "SAMLResponse");
436 if (!post || *post == '\0')
438 throw ShibTargetException (SHIBRPC_OK,
439 "SHIRE POST failed to find SAMLResponse");
441 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
442 "shire_check_user() Processing POST for target: %s", target);
446 "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
447 "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
448 "c3VlSW5zdGFudD0iMjAwMi0wOS0xOVQwNTozMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
449 "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
450 "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
451 "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
452 "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
453 "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
454 "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTE5VDA1OjMwOjAwWiIgSXNzdWVy"
455 "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
456 "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
457 "dE9uT3JBZnRlcj0iMjAxMC0wOS0xOVQwNjozMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
458 "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
459 "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
460 "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
461 "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0xOVQwNTozMDowMFoiIEF1dGhl"
462 "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
463 "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
464 "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
465 "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
466 "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
467 "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
468 "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
469 "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
470 "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
471 "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
472 "c3NlcnRpb24+PC9SZXNwb25zZT4K";
476 "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
477 "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
478 "c3VlSW5zdGFudD0iMjAwMi0wOS0yMFQyMzowMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
479 "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
480 "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
481 "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
482 "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
483 "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
484 "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTIwVDIzOjAwOjAwWiIgSXNzdWVy"
485 "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
486 "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
487 "dE9uT3JBZnRlcj0iMjAxMC0wOS0xOVQwNjozMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
488 "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
489 "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
490 "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
491 "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0yMFQyMzowMDowMFoiIEF1dGhl"
492 "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
493 "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
494 "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
495 "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
496 "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
497 "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
498 "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
499 "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
500 "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
501 "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
502 "c3NlcnRpb24+PC9SZXNwb25zZT4K";
507 RPCError* status = shire.sessionCreate(post, r->connection->remote_ip, cookie);
509 if (status->isError()) {
510 ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
511 "shire_check_user() POST process failed (%d): %s",
512 status->status, status->error_msg.c_str());
514 if (status->isRetryable()) {
515 ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
516 "shire_check_user() Retrying POST by redirecting to WAYF");
518 char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
519 "?shire=",shire_location,
520 "&target=",url_encode(r,target),NULL);
521 ap_table_setn(r->headers_out,"Location",wayf);
526 // return this error to the user.
527 markupProcessor.insert (*status);
529 return shire_error_page (r, wayfError.c_str(), markupProcessor);
533 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
534 "shire_check_user() POST process succeeded. New cookie: %s",
537 // We've got a good session, set the cookie...
538 char * domain = NULL;
539 char * new_cookie = ap_psprintf(r->pool, "%s=%s; path=/%s%s",
542 (domain ? "; domain=" : ""),
543 (domain ? domain : ""));
545 ap_table_setn(r->err_headers_out, "Set-Cookie", new_cookie);
546 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
547 "shire_check_user() Set cookie: %s", new_cookie);
549 // ... and redirect to the target
550 char* redir=ap_pstrcat(r->pool,url_encode(r,target),NULL);
551 ap_table_setn(r->headers_out, "Location", target);
554 } catch (ShibTargetException &e) {
555 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
556 "shire_check_user(): %s", e.what());
558 markupProcessor.insert ("errorType", "SHIRE Processing Error");
559 markupProcessor.insert ("errorText", e.what());
560 return shire_error_page (r, wayfError.c_str(), markupProcessor);
563 /**************************************************************************/
566 // Regular access to arbitrary resource...check AuthType
568 const char *auth_type=ap_auth_type (r);
572 if (strcasecmp(auth_type,"shibboleth"))
574 if (!strcasecmp(auth_type,"basic") && dc->bBasicHijack==1)
576 core_dir_config* conf=
577 (core_dir_config*)ap_get_module_config(r->per_dir_config,
578 ap_find_linked_module("http_core.c"));
579 conf->ap_auth_type="shibboleth";
585 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
586 "shire_check_user() Shib check for %s", targeturl);
589 if (dc->bSSLOnly==1 && strcmp(ap_http_method(r),"https"))
591 ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
592 "shire_check_user() blocked non-SSL access");
596 // We're in charge, so check for cookie.
597 const char* session_id=NULL;
598 const char* cookies=ap_table_get(r->headers_in,"Cookie");
601 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
602 "shire_check_user() cookies found: %s",
605 if (!cookies || !(session_id=strstr(cookies,shib_cookie.c_str())))
607 // No cookie. Redirect to WAYF.
608 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
609 "shire_check_user() no cookie found -- redirecting to WAYF");
610 char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
611 "?shire=",shire_location,
612 "&target=",url_encode(r,targeturl),NULL);
613 ap_table_setn(r->headers_out,"Location",wayf);
617 // Yep, we found a cookie -- pull it out (our session_id)
618 session_id+=strlen(shib_cookie.c_str()) + 1; /* Skip over the '=' */
619 char* cookiebuf = ap_pstrdup(r->pool,session_id);
620 char* cookieend = strchr(cookiebuf,';');
622 *cookieend = '\0'; /* Ignore anyting after a ; */
623 session_id=cookiebuf;
625 // Make sure this session is still valid
626 RPCError* status = shire.sessionIsValid(session_id, r->connection->remote_ip);
629 if (status->isError()) {
631 ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
632 "shire_check_user() session invalid: %s",
633 status->error_msg.c_str());
635 // Oops, session is invalid. Redirect to WAYF.
636 char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
637 "?shire=",shire_location,
638 "&target=",url_encode(r,targeturl),NULL);
639 ap_table_setn(r->headers_out,"Location",wayf);
646 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
647 "shire_check_user() success");
652 ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
653 "shire_check_user() server error");
658 module MODULE_VAR_EXPORT shire_module = {
659 STANDARD_MODULE_STUFF,
660 NULL, /* initializer */
661 create_shire_dir_config, /* dir config creater */
662 merge_shire_dir_config, /* dir merger --- default is to override */
663 create_shire_server_config, /* server config */
664 merge_shire_server_config, /* merge server config */
665 shire_cmds, /* command table */
667 NULL, /* filename translation */
668 shire_check_user, /* check_user_id */
669 NULL, /* check auth */
670 NULL, /* check access */
671 NULL, /* type_checker */
674 NULL, /* header parser */
675 shire_child_init, /* child_init */
676 shire_child_exit, /* child_exit */
677 NULL /* post read-request */