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>
27 #include <shib-target.h>
35 using namespace shibboleth;
36 using namespace shibtarget;
38 extern "C" module MODULE_VAR_EXPORT shire_module;
40 static char* g_szSHIREConfig = NULL;
41 static RPCHandle *rpc_handle = NULL;
42 static ShibTargetConfig * g_szConfig = NULL;
44 // per-server configuration structure
45 struct shire_server_config
47 char* szCookieName; // name of session token
48 char* szWAYFLocation; // URL of WAYF service
49 char* szSHIRELocation; // URL of SHIRE acceptance point
50 int bSSLOnly; // SSL only for this SHIRE?
51 int bNormalizeRequest; // normalize requested URL based on server name?
54 // creates the per-server configuration
55 extern "C" void* create_shire_server_config (pool * p, server_rec * s)
57 shire_server_config* sc=(shire_server_config*)ap_pcalloc(p,sizeof(shire_server_config));
59 sc->bNormalizeRequest = -1;
63 // overrides server configuration in virtual servers
64 extern "C" void* merge_shire_server_config (pool* p, void* base, void* sub)
66 shire_server_config* sc=(shire_server_config*)ap_pcalloc(p,sizeof(shire_server_config));
67 shire_server_config* parent=(shire_server_config*)base;
68 shire_server_config* child=(shire_server_config*)sub;
70 if (child->szCookieName)
71 sc->szCookieName=ap_pstrdup(p,child->szCookieName);
72 else if (parent->szCookieName)
73 sc->szCookieName=ap_pstrdup(p,parent->szCookieName);
75 sc->szCookieName=NULL;
77 if (child->szWAYFLocation)
78 sc->szWAYFLocation=ap_pstrdup(p,child->szWAYFLocation);
79 else if (parent->szWAYFLocation)
80 sc->szWAYFLocation=ap_pstrdup(p,parent->szWAYFLocation);
82 sc->szWAYFLocation=NULL;
84 if (child->szSHIRELocation)
85 sc->szSHIRELocation=ap_pstrdup(p,child->szSHIRELocation);
86 else if (parent->szSHIRELocation)
87 sc->szSHIRELocation=ap_pstrdup(p,parent->szSHIRELocation);
89 sc->szSHIRELocation=NULL;
91 sc->bSSLOnly=((child->bSSLOnly==-1) ? parent->bSSLOnly : child->bSSLOnly);
92 sc->bNormalizeRequest=((child->bNormalizeRequest==-1) ? parent->bNormalizeRequest : child->bNormalizeRequest);
96 // per-dir module configuration structure
97 struct shire_dir_config
99 int bBasicHijack; // activate for AuthType Basic?
100 int bSSLOnly; // only over SSL?
101 int checkIPAddress; // placeholder for check
102 SHIREConfig config; // SHIRE Configuration
105 // creates per-directory config structure
106 extern "C" void* create_shire_dir_config (pool* p, char* d)
108 shire_dir_config* dc=(shire_dir_config*)ap_pcalloc(p,sizeof(shire_dir_config));
109 dc->bBasicHijack = -1;
111 dc->checkIPAddress = -1;
112 dc->config.lifetime = -1;
113 dc->config.timeout = -1;
117 // overrides server configuration in directories
118 extern "C" void* merge_shire_dir_config (pool* p, void* base, void* sub)
120 shire_dir_config* dc=(shire_dir_config*)ap_pcalloc(p,sizeof(shire_dir_config));
121 shire_dir_config* parent=(shire_dir_config*)base;
122 shire_dir_config* child=(shire_dir_config*)sub;
124 dc->bSSLOnly=((child->bSSLOnly==-1) ? parent->bSSLOnly : child->bSSLOnly);
125 dc->bBasicHijack=((child->bBasicHijack==-1) ? parent->bBasicHijack : child->bBasicHijack);
126 dc->checkIPAddress=((child->checkIPAddress==-1) ? parent->checkIPAddress : child->checkIPAddress);
127 dc->config.lifetime=((child->config.lifetime==-1) ? parent->config.lifetime : child->config.lifetime);
128 dc->config.timeout=((child->config.timeout==-1) ? parent->config.timeout : child->config.timeout);
132 // generic global slot handlers
133 extern "C" const char* ap_set_global_string_slot(cmd_parms* parms, void*, const char* arg)
135 *((char**)(parms->info))=ap_pstrdup(parms->pool,arg);
139 // generic per-server slot handlers
140 extern "C" const char* ap_set_server_string_slot(cmd_parms* parms, void*, const char* arg)
142 char* base=(char*)ap_get_module_config(parms->server->module_config,&shire_module);
143 int offset=(int)parms->info;
144 *((char**)(base + offset))=ap_pstrdup(parms->pool,arg);
148 extern "C" const char* set_normalize(cmd_parms* parms, shire_server_config* sc, const char* arg)
150 sc->bNormalizeRequest=(atoi(arg) || !strcasecmp(arg, "on"));
154 // some shortcuts for directory config slots
155 extern "C" const char* set_lifetime(cmd_parms* parms, shire_dir_config* dc, const char* arg)
157 dc->config.lifetime=atoi(arg);
161 extern "C" const char* set_timeout(cmd_parms* parms, shire_dir_config* dc, const char* arg)
163 dc->config.timeout=atoi(arg);
170 typedef const char* (*config_fn_t)(void);
172 // SHIRE Module commands
174 static command_rec shire_cmds[] = {
175 {"SHIREConfig", (config_fn_t)ap_set_global_string_slot, &g_szSHIREConfig,
176 RSRC_CONF, TAKE1, "Path to SHIRE ini file."},
179 {"SHIRELocation", (config_fn_t)ap_set_server_string_slot,
180 (void *) XtOffsetOf (shire_server_config, szSHIRELocation),
181 RSRC_CONF, TAKE1, "URL of SHIRE handle acceptance point."},
182 {"SHIRESSLOnly", (config_fn_t)ap_set_flag_slot,
183 (void *) XtOffsetOf (shire_server_config, bSSLOnly),
184 RSRC_CONF, FLAG, "Require SSL when POSTING to the SHIRE?"},
185 {"WAYFLocation", (config_fn_t)ap_set_server_string_slot,
186 (void *) XtOffsetOf (shire_server_config, szWAYFLocation),
187 RSRC_CONF, TAKE1, "URL of WAYF service."},
188 {"ShibCookieName", (config_fn_t)ap_set_server_string_slot,
189 (void *) XtOffsetOf (shire_server_config, szCookieName),
190 RSRC_CONF, TAKE1, "Name of cookie to use as session token."},
193 {"ShibNormalizeRequest", (config_fn_t)set_normalize, NULL,
194 RSRC_CONF, TAKE1, "Normalize/convert browser requests using server name when redirecting."},
196 {"ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
197 (void *) XtOffsetOf (shire_dir_config, bBasicHijack),
198 OR_AUTHCFG, FLAG, "Respond to AuthType Basic and convert to shib?"},
199 {"ShibSSLOnly", (config_fn_t)ap_set_flag_slot,
200 (void *) XtOffsetOf (shire_dir_config, bSSLOnly),
201 OR_AUTHCFG, FLAG, "Require SSL when accessing a secured directory?"},
202 {"ShibCheckAddress", (config_fn_t)ap_set_flag_slot,
203 (void *) XtOffsetOf (shire_dir_config, checkIPAddress),
204 OR_AUTHCFG, FLAG, "Verify IP address of requester matches token?"},
205 {"ShibAuthLifetime", (config_fn_t)set_lifetime, NULL,
206 OR_AUTHCFG, TAKE1, "Lifetime of session in seconds."},
207 {"ShibAuthTimeout", (config_fn_t)set_timeout, NULL,
208 OR_AUTHCFG, TAKE1, "Timeout for session in seconds."},
217 * Things to do when the child process is initialized.
219 extern "C" void shire_child_init(server_rec* s, pool* p)
221 // Initialize runtime components.
224 ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,s,
225 "shire_child_init(): already initialized!");
230 g_szConfig = &(ShibTargetConfig::init(SHIBTARGET_SHIRE, g_szSHIREConfig));
231 } catch (runtime_error& e) {
232 ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,
233 "shire_child_init() failed to initialize SHIB Target");
237 // Create the RPC Handle.. Note: this should be per _thread_
238 // if there is some way to do that reasonably..
239 rpc_handle = new RPCHandle(SHIB_SHAR_SOCKET, SHIBRPC_PROG, SHIBRPC_VERS_1);
241 ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_init() done");
249 extern "C" void shire_child_exit(server_rec* s, pool* p)
252 g_szConfig->shutdown();
254 ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,s,"shire_child_exit() done");
257 inline char hexchar(unsigned short s)
259 return (s<=9) ? ('0' + s) : ('A' + s - 10);
262 static char* url_encode(request_rec* r, const char* s)
264 static char badchars[]="\"\\+<>#%{}|^~[]`;/?:@=&";
265 char* ret=(char*)ap_palloc(r->pool,sizeof(char)*3*strlen(s)+1);
267 unsigned long count=0;
270 if (strchr(badchars,*s)!=NULL || *s<=0x1F || *s>=0x7F)
273 ret[count++]=hexchar(*s >> 4);
274 ret[count++]=hexchar(*s & 0x0F);
283 static const char* get_target(request_rec* r, const char* target)
285 shire_server_config* sc=
286 (shire_server_config*)ap_get_module_config(r->server->module_config,&shire_module);
287 if (sc->bNormalizeRequest)
289 const char* colon=strchr(target,':');
290 const char* slash=strchr(colon+3,'/');
291 const char* second_colon=strchr(colon+3,':');
292 return ap_pstrcat(r->pool,ap_pstrndup(r->pool,target,colon+3-target),ap_get_server_name(r),
293 (second_colon && second_colon < slash) ? second_colon : slash,NULL);
298 static const char* get_shire_location(request_rec* r, const char* target, bool encode)
300 ShibINI& ini = g_szConfig->getINI();
301 const string& shire_location = ini.get (SHIBTARGET_HTTP, "shire");
303 const char* shire = shire_location.c_str();
307 return url_encode(r,shire);
309 return ap_pstrdup(r->pool,shire);
311 const char* colon=strchr(target,':');
312 const char* slash=strchr(colon+3,'/');
314 return url_encode(r,ap_pstrcat(r->pool,
315 ap_pstrndup(r->pool,target,slash-target),
318 return ap_pstrcat(r->pool, ap_pstrndup(r->pool,target,slash-target),
322 static bool is_shire_location(request_rec* r, const char* target)
324 const char* shire = get_shire_location(r, target, false);
326 if (!strstr(target, shire))
329 return (!strcmp(target,shire));
332 static int shire_error_page(request_rec* r, const char* filename, ShibMLP& mlp)
334 ifstream infile (filename);
336 ap_log_rerror(APLOG_MARK,APLOG_ERR,r,
337 "shire_error_page() cannot open %s", filename);
341 string res = mlp.run(infile);
342 r->content_type = ap_psprintf(r->pool, "text/html");
343 ap_send_http_header(r);
344 ap_rprintf(r, res.c_str());
348 extern "C" int shire_check_user(request_rec* r)
351 threadid << "[" << getpid() << "] shire" << '\0';
352 saml::NDC ndc(threadid.str());
354 ShibINI& ini = g_szConfig->getINI();
355 ShibMLP markupProcessor;
357 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
358 "shire_check_user: ENTER");
360 shire_server_config* sc=
361 (shire_server_config*)ap_get_module_config(r->server->module_config,&shire_module);
362 shire_dir_config* dc=
363 (shire_dir_config*)ap_get_module_config(r->per_dir_config,&shire_module);
365 const char* targeturl=get_target(r,ap_construct_url(r->pool,r->unparsed_uri,r));
367 const char * shire_location = get_shire_location(r,targeturl,true);
368 string shire_url = get_shire_location(r,targeturl,false);
369 dc->config.checkIPAddress = (dc->checkIPAddress == 1 ? true : false);
370 SHIRE shire(rpc_handle, dc->config, shire_url);
372 const string& shib_cookie = ini.get (SHIBTARGET_HTTP, "cookie");
373 const string& wayfLocation = ini.get (SHIBTARGET_HTTP, "wayfLocation");
374 const string& wayfError = ini.get (SHIBTARGET_HTTP, "wayfError");
377 bool has_tag = ini.get_tag (SHIBTARGET_HTTP, "supportContact", true, &tag);
378 markupProcessor.insert ("supportContact", has_tag ? tag : "");
379 has_tag = ini.get_tag (SHIBTARGET_HTTP, "logoLocation", true, &tag);
380 markupProcessor.insert ("logoLocation", has_tag ? tag : "");
381 markupProcessor.insert ("requestURL", targeturl);
383 if (is_shire_location (r, targeturl)) {
384 // Process SHIRE POST
386 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
387 "shire_check_user() Beginning SHIRE POST processing");
392 const string& sslonly = ini.get (SHIBTARGET_HTTP, "shireSSLOnly");
393 const char* sslonlyc = sslonly.c_str();
395 // Make sure this is SSL, if it should be
396 if ((*sslonlyc == 't' || *sslonlyc == 'T') &&
397 strcmp(ap_http_method(r),"https"))
398 throw ShibTargetException (SHIBRPC_OK,
399 "blocked non-SSL access to SHIRE POST processor");
401 // Make sure this is a POST
402 if (strcasecmp (r->method, "POST"))
403 throw ShibTargetException (SHIBRPC_OK,
404 "blocked non-POST to SHIRE POST processor");
406 // Sure sure this POST is an appropriate content type
407 const char *ct = ap_table_get (r->headers_in, "Content-type");
408 if (!ct || strcasecmp (ct, "application/x-www-form-urlencoded"))
409 throw ShibTargetException (SHIBRPC_OK,
411 "blocked bad content-type to SHIRE POST processor: %s",
414 // Make sure the "bytes sent" is a reasonable number
415 if (r->bytes_sent > 1024*1024) // 1MB?
416 throw ShibTargetException (SHIBRPC_OK,
417 "blocked too-large a post to SHIRE POST processor");
419 // Read the posted data
420 ApacheRequest *ap_req = ApacheRequest_new(r);
421 int err = ApacheRequest_parse(ap_req);
423 throw ShibTargetException (SHIBRPC_OK,
425 "ApacheRequest_parse() failed with %d.", err));
428 // Make sure the target parameter exists
429 const char *target = ApacheRequest_param(ap_req, "TARGET");
430 if (!target || *target == '\0')
432 throw ShibTargetException (SHIBRPC_OK,
433 "SHIRE POST failed to find TARGET");
435 // Make sure the SAML Response parameter exists
436 const char *post = ApacheRequest_param(ap_req, "SAMLResponse");
437 if (!post || *post == '\0')
439 throw ShibTargetException (SHIBRPC_OK,
440 "SHIRE POST failed to find SAMLResponse");
442 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
443 "shire_check_user() Processing POST for target: %s", target);
447 "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
448 "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
449 "c3VlSW5zdGFudD0iMjAwMi0wOS0xOVQwNTozMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
450 "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
451 "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
452 "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
453 "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
454 "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
455 "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTE5VDA1OjMwOjAwWiIgSXNzdWVy"
456 "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
457 "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
458 "dE9uT3JBZnRlcj0iMjAxMC0wOS0xOVQwNjozMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
459 "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
460 "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
461 "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
462 "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0xOVQwNTozMDowMFoiIEF1dGhl"
463 "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
464 "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
465 "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
466 "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
467 "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
468 "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
469 "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
470 "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
471 "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
472 "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
473 "c3NlcnRpb24+PC9SZXNwb25zZT4K";
477 "PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wi"
478 "IHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjA6cHJvdG9jb2wiIElz"
479 "c3VlSW5zdGFudD0iMjAwMi0wOS0yMFQyMzowMDowMFoiIE1ham9yVmVyc2lvbj0iMSIgTWlu"
480 "b3JWZXJzaW9uPSIwIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3Qvc2hpYmJvbGV0aC9T"
481 "SElSRSIgUmVzcG9uc2VJRD0iYmI3ZjZmYjQtMmU0YS00YzY1LTgzY2QtYjIyMjQ0OWQwYmY4"
482 "Ij48U3RhdHVzPjxTdGF0dXNDb2RlIFZhbHVlPSJzYW1scDpTdWNjZXNzIj48L1N0YXR1c0Nv"
483 "ZGU+PC9TdGF0dXM+PEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6"
484 "MS4wOmFzc2VydGlvbiIgQXNzZXJ0aW9uSUQ9IjZhYzUxYTg2LTJhNTgtNDM2My1hZjlkLTQy"
485 "YjQzYTRhMGNiZSIgSXNzdWVJbnN0YW50PSIyMDAyLTA5LTIwVDIzOjAwOjAwWiIgSXNzdWVy"
486 "PSJzaGlicHJvZDAuaW50ZXJuZXQyLmVkdSIgTWFqb3JWZXJzaW9uPSIxIiBNaW5vclZlcnNp"
487 "b249IjAiPjxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAwMi0wOS0xN1QwMjo1MDowMFoiIE5v"
488 "dE9uT3JBZnRlcj0iMjAxMC0wOS0xOVQwNjozMDowMFoiPjxBdWRpZW5jZVJlc3RyaWN0aW9u"
489 "Q29uZGl0aW9uPjxBdWRpZW5jZT5odHRwOi8vbWlkZGxld2FyZS5pbnRlcm5ldDIuZWR1L3No"
490 "aWJib2xldGgvY2x1YnMvY2x1YnNoaWIvMjAwMi8wNS88L0F1ZGllbmNlPjwvQXVkaWVuY2VS"
491 "ZXN0cmljdGlvbkNvbmRpdGlvbj48L0NvbmRpdGlvbnM+PEF1dGhlbnRpY2F0aW9uU3RhdGVt"
492 "ZW50IEF1dGhlbnRpY2F0aW9uSW5zdGFudD0iMjAwMi0wOS0yMFQyMzowMDowMFoiIEF1dGhl"
493 "bnRpY2F0aW9uTWV0aG9kPSJCYXNpYyI+PFN1YmplY3Q+PE5hbWVJZGVudGlmaWVyIE5hbWVR"
494 "dWFsaWZpZXI9ImV4YW1wbGUuZWR1Ij40YzBmYjg2Yi01NjQwLTQ1ZTUtOTM3Ny1mNTJkNjhh"
495 "ZDNiNjQ8L05hbWVJZGVudGlmaWVyPjxTdWJqZWN0Q29uZmlybWF0aW9uPjxDb25maXJtYXRp"
496 "b25NZXRob2Q+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmNtOkJlYXJlcjwvQ29uZmly"
497 "bWF0aW9uTWV0aG9kPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PFN1YmplY3RM"
498 "b2NhbGl0eSBJUEFkZHJlc3M9IjE4LjEwMS4xLjEyIj48L1N1YmplY3RMb2NhbGl0eT48QXV0"
499 "aG9yaXR5QmluZGluZyBBdXRob3JpdHlLaW5kPSJzYW1scDpBdHRyaWJ1dGVRdWVyeSIgQmlu"
500 "ZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4wOmJpbmRpbmdzOlNPQVAtYmluZGlu"
501 "ZyIgTG9jYXRpb249Imh0dHBzOi8vc2hpYnByb2QwLmludGVybmV0Mi5lZHUvc2hpYmJvbGV0"
502 "aC9BQSI+PC9BdXRob3JpdHlCaW5kaW5nPjwvQXV0aGVudGljYXRpb25TdGF0ZW1lbnQ+PC9B"
503 "c3NlcnRpb24+PC9SZXNwb25zZT4K";
508 RPCError* status = shire.sessionCreate(post, r->connection->remote_ip, cookie);
510 if (status->isError()) {
511 ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
512 "shire_check_user() POST process failed (%d): %s",
513 status->status, status->error_msg.c_str());
515 if (status->isRetryable()) {
516 ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
517 "shire_check_user() Retrying POST by redirecting to WAYF");
519 char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
520 "?shire=",shire_location,
521 "&target=",url_encode(r,target),NULL);
522 ap_table_setn(r->headers_out,"Location",wayf);
527 // return this error to the user.
528 markupProcessor.insert (*status);
530 return shire_error_page (r, wayfError.c_str(), markupProcessor);
534 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
535 "shire_check_user() POST process succeeded. New cookie: %s",
538 // We've got a good session, set the cookie...
539 char * domain = NULL;
540 char * new_cookie = ap_psprintf(r->pool, "%s=%s; path=/%s%s",
543 (domain ? "; domain=" : ""),
544 (domain ? domain : ""));
546 ap_table_setn(r->err_headers_out, "Set-Cookie", new_cookie);
547 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
548 "shire_check_user() Set cookie: %s", new_cookie);
550 // ... and redirect to the target
551 char* redir=ap_pstrcat(r->pool,url_encode(r,target),NULL);
552 ap_table_setn(r->headers_out, "Location", target);
555 } catch (ShibTargetException &e) {
556 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
557 "shire_check_user(): %s", e.what());
559 markupProcessor.insert ("errorType", "SHIRE Processing Error");
560 markupProcessor.insert ("errorText", e.what());
561 return shire_error_page (r, wayfError.c_str(), markupProcessor);
564 /**************************************************************************/
567 // Regular access to arbitrary resource...check AuthType
569 const char *auth_type=ap_auth_type (r);
573 if (strcasecmp(auth_type,"shibboleth"))
575 if (!strcasecmp(auth_type,"basic") && dc->bBasicHijack==1)
577 core_dir_config* conf=
578 (core_dir_config*)ap_get_module_config(r->per_dir_config,
579 ap_find_linked_module("http_core.c"));
580 conf->ap_auth_type="shibboleth";
586 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
587 "shire_check_user() Shib check for %s", targeturl);
590 if (dc->bSSLOnly==1 && strcmp(ap_http_method(r),"https"))
592 ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
593 "shire_check_user() blocked non-SSL access");
597 // We're in charge, so check for cookie.
598 const char* session_id=NULL;
599 const char* cookies=ap_table_get(r->headers_in,"Cookie");
602 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
603 "shire_check_user() cookies found: %s",
606 if (!cookies || !(session_id=strstr(cookies,shib_cookie.c_str())))
608 // No cookie. Redirect to WAYF.
609 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
610 "shire_check_user() no cookie found -- redirecting to WAYF");
611 char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
612 "?shire=",shire_location,
613 "&target=",url_encode(r,targeturl),NULL);
614 ap_table_setn(r->headers_out,"Location",wayf);
618 // Yep, we found a cookie -- pull it out (our session_id)
619 session_id+=strlen(shib_cookie.c_str()) + 1; /* Skip over the '=' */
620 char* cookiebuf = ap_pstrdup(r->pool,session_id);
621 char* cookieend = strchr(cookiebuf,';');
623 *cookieend = '\0'; /* Ignore anyting after a ; */
624 session_id=cookiebuf;
626 // Make sure this session is still valid
627 RPCError* status = shire.sessionIsValid(session_id, r->connection->remote_ip);
630 if (status->isError()) {
632 ap_log_rerror(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,r,
633 "shire_check_user() session invalid: %s",
634 status->error_msg.c_str());
636 // Oops, session is invalid. Redirect to WAYF.
637 char* wayf=ap_pstrcat(r->pool,wayfLocation.c_str(),
638 "?shire=",shire_location,
639 "&target=",url_encode(r,targeturl),NULL);
640 ap_table_setn(r->headers_out,"Location",wayf);
647 ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,r,
648 "shire_check_user() success");
653 ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,
654 "shire_check_user() server error");
659 module MODULE_VAR_EXPORT shire_module = {
660 STANDARD_MODULE_STUFF,
661 NULL, /* initializer */
662 create_shire_dir_config, /* dir config creater */
663 merge_shire_dir_config, /* dir merger --- default is to override */
664 create_shire_server_config, /* server config */
665 merge_shire_server_config, /* merge server config */
666 shire_cmds, /* command table */
668 NULL, /* filename translation */
669 shire_check_user, /* check_user_id */
670 NULL, /* check auth */
671 NULL, /* check access */
672 NULL, /* type_checker */
675 NULL, /* header parser */
676 shire_child_init, /* child_init */
677 shire_child_exit, /* child_exit */
678 NULL /* post read-request */