/*\r
- * Copyright 2001-2007 Internet2\r
- * \r
+ * Copyright 2001-2009 Internet2\r
+ *\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
* You may obtain a copy of the License at\r
#include <xmltooling/util/XMLHelper.h>\r
#include <xercesc/util/XMLUniDefs.hpp>\r
\r
+#include <stdexcept>\r
#include <stdlib.h>\r
#ifdef HAVE_UNISTD_H\r
# include <unistd.h>\r
public:\r
map<string,string> m_request_headers;\r
\r
- ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0) : m_req(req) {\r
+ ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
+ : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {\r
const char* server_name_str = hostname;\r
if (!server_name_str || !*server_name_str)\r
server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
m_port = strtol(server_port_str, &server_port_str, 10);\r
if (*server_port_str) {\r
cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
- throw exception("Unable to determine server port.");\r
+ throw runtime_error("Unable to determine server port.");\r
}\r
}\r
\r
if (!server_scheme_str || !*server_scheme_str)\r
server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
m_scheme = server_scheme_str;\r
+\r
+ setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
}\r
\r
~ShibTargetFCGIAuth() { }\r
int getPort() const {\r
return m_port;\r
}\r
- const char* getRequestURI() const {\r
- return FCGX_GetParam("REQUEST_URI", m_req->envp);\r
- }\r
const char* getMethod() const {\r
return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
}\r
return s ? atol(s) : 0;\r
}\r
string getRemoteAddr() const {\r
+ string ret = AbstractSPRequest::getRemoteAddr();\r
+ if (!ret.empty())\r
+ return ret;\r
const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
return s ? s : "";\r
}\r
cerr << "shib: " << msg;\r
}\r
void clearHeader(const char* rawname, const char* cginame) {\r
- // no need, since request headers turn into actual environment variables\r
+ // No need, since we use environment variables.\r
}\r
void setHeader(const char* name, const char* value) {\r
if (value)\r
else\r
m_request_headers.erase(name);\r
}\r
- virtual string getHeader(const char* name) const {\r
+ string getHeader(const char* name) const {\r
+ // Look in the local map first.\r
map<string,string>::const_iterator i = m_request_headers.find(name);\r
if (i != m_request_headers.end())\r
return i->second;\r
- else\r
- return "";\r
+ // Nothing set locally and this isn't a "secure" call, so check the request.\r
+ string hdr("HTTP_");\r
+ for (; *name; ++name) {\r
+ if (*name=='-')\r
+ hdr += '_';\r
+ else\r
+ hdr += toupper(*name);\r
+ }\r
+ char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
+ return s ? s : "";\r
+ }\r
+ string getSecureHeader(const char* name) const {\r
+ // Look in the local map only.\r
+ map<string,string>::const_iterator i = m_request_headers.find(name);\r
+ if (i != m_request_headers.end())\r
+ return i->second;\r
+ return "";\r
}\r
void setRemoteUser(const char* user) {\r
if (user)\r
}\r
return "";\r
}\r
+ void setAuthType(const char* authtype) {\r
+ if (authtype)\r
+ m_request_headers["AUTH_TYPE"] = authtype;\r
+ else\r
+ m_request_headers.erase("AUTH_TYPE");\r
+ }\r
+ string getAuthType() const {\r
+ map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");\r
+ if (i != m_request_headers.end())\r
+ return i->second;\r
+ else {\r
+ char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);\r
+ if (auth_type)\r
+ return auth_type;\r
+ }\r
+ return "";\r
+ }\r
void setResponseHeader(const char* name, const char* value) {\r
+ AbstractSPRequest::setResponseHeader(name, value);\r
// Set for later.\r
if (value)\r
m_response_headers.insert(make_pair(name,value));\r
return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
}\r
const char* getRequestBody() const {\r
- throw exception("getRequestBody not implemented by FastCGI authorizer.");\r
+ throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");\r
}\r
- \r
+\r
long sendResponse(istream& in, long status) {\r
string hdr = string("Connection: close\r\n");\r
for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
// so custom Shib errors will get turned into a generic page.\r
const char* codestr="Status: 500 Server Error";\r
switch (status) {\r
- case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break;\r
- case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break;\r
+ case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break;\r
+ case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break;\r
+ case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break;\r
}\r
cout << codestr << "\r\n" << hdr << "\r\n";\r
char buf[1024];\r
}\r
\r
long sendRedirect(const char* url) {\r
+ AbstractSPRequest::sendRedirect(url);\r
string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
"Content-Type: text/html\r\n"\r
"Content-Length: 40\r\n"\r
return SHIB_RETURN_DONE;\r
}\r
\r
- long returnDecline() { \r
+ long returnDecline() {\r
return SHIB_RETURN_KO;\r
}\r
\r
\r
int main(void)\r
{\r
- const char* schemadir=getenv("SHIBSP_SCHEMAS");\r
- if (!schemadir)\r
- schemadir=SHIBSP_SCHEMAS;\r
- const char* config=getenv("SHIBSP_CONFIG");\r
- if (!config)\r
- config=SHIBSP_CONFIG;\r
-\r
- cerr << "SHIBSP_CONFIG = " << config << endl\r
- << "SHIBSP_SCHEMAS = " << schemadir << endl;\r
-\r
SPConfig* g_Config=&SPConfig::getConfig();\r
g_Config->setFeatures(\r
SPConfig::Listener |\r
SPConfig::Logging |\r
SPConfig::Handlers\r
);\r
- if (!g_Config->init(schemadir)) {\r
+ if (!g_Config->init()) {\r
cerr << "failed to initialize Shibboleth libraries" << endl;\r
exit(1);\r
}\r
\r
try {\r
- DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();\r
- XercesJanitor<DOMDocument> docjanitor(dummydoc);\r
- DOMElement* dummy = dummydoc->createElementNS(NULL,path);\r
- auto_ptr_XMLCh src(config);\r
- dummy->setAttributeNS(NULL,path,src.get());\r
- dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);\r
-\r
- g_Config->setServiceProvider(g_Config->ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));\r
- g_Config->getServiceProvider()->init();\r
+ if (!g_Config->instantiate(NULL, true))\r
+ throw runtime_error("unknown error");\r
}\r
catch (exception& ex) {\r
g_Config->term();\r
\r
FCGX_Init();\r
FCGX_InitRequest(&request, 0, 0);\r
- \r
+\r
cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
while (FCGX_Accept_r(&request) == 0)\r
{\r
try {\r
xmltooling::NDC ndc("FastCGI shibauthorizer");\r
ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
- \r
+\r
pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);\r
if (res.first) {\r
-#ifdef _DEBUG\r
- cerr << "shib: doAuthentication handled the request" << endl;\r
-#endif\r
+ sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");\r
switch(res.second) {\r
case SHIB_RETURN_OK:\r
print_ok(sta.m_request_headers);\r
continue;\r
- \r
+\r
case SHIB_RETURN_KO:\r
print_ok(sta.m_request_headers);\r
continue;\r
\r
case SHIB_RETURN_DONE:\r
continue;\r
- \r
+\r
default:\r
cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;\r
print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
continue;\r
}\r
}\r
- \r
+\r
res = sta.getServiceProvider().doExport(sta);\r
if (res.first) {\r
-#ifdef _DEBUG\r
- cerr << "shib: doExport handled request" << endl;\r
-#endif\r
+ sta.log(SPRequest::SPDebug, "shib: doExport handled request");\r
switch(res.second) {\r
case SHIB_RETURN_OK:\r
print_ok(sta.m_request_headers);\r
continue;\r
- \r
+\r
case SHIB_RETURN_KO:\r
print_ok(sta.m_request_headers);\r
continue;\r
\r
case SHIB_RETURN_DONE:\r
continue;\r
- \r
+\r
default:\r
cerr << "shib: doExport returned an unexpected result: " << res.second << endl;\r
print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
\r
res = sta.getServiceProvider().doAuthorization(sta);\r
if (res.first) {\r
-#ifdef _DEBUG\r
- cerr << "shib: doAuthorization handled request" << endl;\r
-#endif\r
+ sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");\r
switch(res.second) {\r
case SHIB_RETURN_OK:\r
print_ok(sta.m_request_headers);\r
continue;\r
- \r
+\r
case SHIB_RETURN_KO:\r
print_ok(sta.m_request_headers);\r
continue;\r
\r
case SHIB_RETURN_DONE:\r
continue;\r
- \r
+\r
default:\r
cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;\r
print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
}\r
\r
print_ok(sta.m_request_headers);\r
- \r
+\r
}\r
catch (exception& e) {\r
cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;\r
\r
if (g_Config)\r
g_Config->term();\r
- \r
+\r
return 0;\r
}\r