From 9e7f48f80953e4a1a0462ebc88827946716bdec7 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Sat, 31 Oct 2009 20:34:11 +0000 Subject: [PATCH] Clean up svn props. --- .cproject | 234 +++- .project | 96 +- adfs/Makefile.am | 50 +- adfs/resource.h | 30 +- doc/CREDITS.txt | 0 doc/README.txt | 2 +- doc/RELEASE.txt | 4 +- fastcgi/Makefile.am | 60 +- fastcgi/resource.h | 30 +- fastcgi/shibauthorizer.cpp | 856 +++++++------- fastcgi/shibresponder.cpp | 800 ++++++------- memcache-store/Makefile.am | 40 +- memcache-store/memcache-store.cpp | 1616 +++++++++++++------------- memcache-store/resource.h | 28 +- odbc-store/resource.h | 28 +- schemas/WS-Trust.xsd | 226 ++-- schemas/shibboleth-2.0-afp.xsd | 26 +- schemas/shibboleth-2.0-native-sp-config.xsd | 1444 +++++++++++------------ shibd/shibd.cpp | 806 ++++++------- shibd/shibd_win32.cpp | 1058 ++++++++--------- shibsp/attribute/DOMAttributeDecoder.cpp | 452 +++---- shibsp/attribute/KeyInfoAttributeDecoder.cpp | 320 ++--- shibsp/attribute/NameIDAttributeDecoder.cpp | 468 ++++---- shibsp/attribute/StringAttributeDecoder.cpp | 296 ++--- shibsp/attribute/XMLAttributeDecoder.cpp | 276 ++--- shibsp/impl/ChainingAccessControl.cpp | 292 ++--- shibsp/impl/XMLAccessControl.cpp | 890 +++++++------- shibsp/paths.h.in | 106 +- shibsp/resource.h | 30 +- shibsp/util/SPConstants.cpp | 232 ++-- util/mdquery.cpp | 324 +++--- 31 files changed, 5584 insertions(+), 5536 deletions(-) mode change 100755 => 100644 doc/CREDITS.txt diff --git a/.cproject b/.cproject index 0f46347..4d44992 100644 --- a/.cproject +++ b/.cproject @@ -1,20 +1,104 @@ - - - + + - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -97,51 +181,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/.project b/.project index 4dea911..0579a7a 100644 --- a/.project +++ b/.project @@ -3,108 +3,26 @@ cpp-sp + cpp-opensaml2 + cpp-xmltooling - org.eclipse.cdt.make.core.makeBuilder - + org.eclipse.linuxtools.cdt.autotools.genmakebuilder - - org.eclipse.cdt.core.errorOutputParser - org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.VCErrorParser; - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.build.arguments - - - - org.eclipse.cdt.make.core.build.command - nmake - - - org.eclipse.cdt.make.core.build.location - - - - org.eclipse.cdt.make.core.build.target.auto - all - - - org.eclipse.cdt.make.core.build.target.clean - - - - org.eclipse.cdt.make.core.build.target.inc - all - - - org.eclipse.cdt.make.core.buildArguments - - - - org.eclipse.cdt.make.core.buildCommand - nmake - - - org.eclipse.cdt.make.core.buildLocation - - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - false - - - org.eclipse.cdt.make.core.enableFullBuild - false - - - org.eclipse.cdt.make.core.enabledIncrementalBuild - false - - - org.eclipse.cdt.make.core.environment - - - - org.eclipse.cdt.make.core.fullBuildTarget - clean all - - - org.eclipse.cdt.make.core.incrementalBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - false - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - false - - org.eclipse.cdt.make.core.ScannerConfigBuilder + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder org.eclipse.cdt.core.cnature - org.eclipse.cdt.make.core.makeNature org.eclipse.cdt.core.ccnature - org.eclipse.cdt.make.core.ScannerConfigNature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.linuxtools.cdt.autotools.autotoolsNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature diff --git a/adfs/Makefile.am b/adfs/Makefile.am index 82913b5..196504b 100644 --- a/adfs/Makefile.am +++ b/adfs/Makefile.am @@ -1,25 +1,25 @@ -AUTOMAKE_OPTIONS = foreign - -plugindir = $(libdir)/@PACKAGE@ -plugin_LTLIBRARIES = adfs.la adfs-lite.la - -adfs_la_LIBADD = \ - $(top_builddir)/shibsp/libshibsp.la - -adfs_la_SOURCES = \ - adfs.cpp - -adfs_lite_la_LIBADD = \ - $(top_builddir)/shibsp/libshibsp-lite.la - -adfs_lite_la_SOURCES = \ - adfs.cpp - -adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) -adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS) -adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE - -install-exec-hook: - for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done - -EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc +AUTOMAKE_OPTIONS = foreign + +plugindir = $(libdir)/@PACKAGE@ +plugin_LTLIBRARIES = adfs.la adfs-lite.la + +adfs_la_LIBADD = \ + $(top_builddir)/shibsp/libshibsp.la + +adfs_la_SOURCES = \ + adfs.cpp + +adfs_lite_la_LIBADD = \ + $(top_builddir)/shibsp/libshibsp-lite.la + +adfs_lite_la_SOURCES = \ + adfs.cpp + +adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) +adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS) +adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE + +install-exec-hook: + for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done + +EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc diff --git a/adfs/resource.h b/adfs/resource.h index 95f2c63..3ba1cce 100644 --- a/adfs/resource.h +++ b/adfs/resource.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by adfs.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by adfs.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/doc/CREDITS.txt b/doc/CREDITS.txt old mode 100755 new mode 100644 diff --git a/doc/README.txt b/doc/README.txt index 6443108..e21e018 100644 --- a/doc/README.txt +++ b/doc/README.txt @@ -1,4 +1,4 @@ -Version 2.2.1 +Version 2.3 Welcome to Internet2's Shibboleth diff --git a/doc/RELEASE.txt b/doc/RELEASE.txt index 66ee2a7..51a97cc 100644 --- a/doc/RELEASE.txt +++ b/doc/RELEASE.txt @@ -1,14 +1,14 @@ Release Notes Shibboleth Native SP -2.2.1 +2.3 NOTE: The shibboleth2.xml configuration format in this release is fully compatible with the 2.1 release, but there are some small changes required to eliminate various warnings about deprecated options. List of issues addressed by this release: -https://bugs.internet2.edu/jira/secure/IssueNavigator.jspa?reset=true&&pid=10011&fixfor=10232&status=5&status=6&sorter/field=issuekey&sorter/order=ASC +https://bugs.internet2.edu/jira/browse/SSPCPP/fixforversion/10261 Fully Supported diff --git a/fastcgi/Makefile.am b/fastcgi/Makefile.am index f0bec65..1c4ba8c 100644 --- a/fastcgi/Makefile.am +++ b/fastcgi/Makefile.am @@ -1,30 +1,30 @@ -AUTOMAKE_OPTIONS = foreign - -if BUILD_FASTCGI - -fastcgidir = $(libdir)/@PACKAGE@ - -fastcgi_PROGRAMS = shibauthorizer shibresponder - -shibauthorizer_SOURCES = shibauthorizer.cpp -shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE) -shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) -shibauthorizer_LDADD = \ - $(top_builddir)/shibsp/libshibsp-lite.la - -shibresponder_SOURCES = shibresponder.cpp -shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE) -shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) -shibresponder_LDADD = \ - $(top_builddir)/shibsp/libshibsp-lite.la - -endif - -EXTRA_DIST = \ - shibauthorizer.cpp \ - shibauthorizer.vcproj \ - shibauthorizer.rc \ - shibresponder.cpp \ - shibresponder.vcproj \ - shibresponder.rc \ - resource.h +AUTOMAKE_OPTIONS = foreign + +if BUILD_FASTCGI + +fastcgidir = $(libdir)/@PACKAGE@ + +fastcgi_PROGRAMS = shibauthorizer shibresponder + +shibauthorizer_SOURCES = shibauthorizer.cpp +shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE) +shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) +shibauthorizer_LDADD = \ + $(top_builddir)/shibsp/libshibsp-lite.la + +shibresponder_SOURCES = shibresponder.cpp +shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE) +shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS) +shibresponder_LDADD = \ + $(top_builddir)/shibsp/libshibsp-lite.la + +endif + +EXTRA_DIST = \ + shibauthorizer.cpp \ + shibauthorizer.vcproj \ + shibauthorizer.rc \ + shibresponder.cpp \ + shibresponder.vcproj \ + shibresponder.rc \ + resource.h diff --git a/fastcgi/resource.h b/fastcgi/resource.h index 55162af..f3772c1 100644 --- a/fastcgi/resource.h +++ b/fastcgi/resource.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by isapi_shib.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by isapi_shib.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/fastcgi/shibauthorizer.cpp b/fastcgi/shibauthorizer.cpp index 4d9a4e5..26eb501 100644 --- a/fastcgi/shibauthorizer.cpp +++ b/fastcgi/shibauthorizer.cpp @@ -1,428 +1,428 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer - - Andre Cruz -*/ - -#define SHIBSP_LITE -#include "config_win32.h" - -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#define _CRT_SECURE_NO_DEPRECATE 1 -#define _SCL_SECURE_NO_WARNINGS 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef HAVE_UNISTD_H -# include -# include -#endif -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace xercesc; -using namespace std; - -static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); -static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); - -typedef enum { - SHIB_RETURN_OK, - SHIB_RETURN_KO, - SHIB_RETURN_DONE -} shib_return_t; - -class ShibTargetFCGIAuth : public AbstractSPRequest -{ - FCGX_Request* m_req; - int m_port; - string m_scheme,m_hostname; - multimap m_response_headers; -public: - map m_request_headers; - - ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0) - : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) { - const char* server_name_str = hostname; - if (!server_name_str || !*server_name_str) - server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); - m_hostname = server_name_str; - - m_port = port; - if (!m_port) { - char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); - m_port = strtol(server_port_str, &server_port_str, 10); - if (*server_port_str) { - cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; - throw runtime_error("Unable to determine server port."); - } - } - - const char* server_scheme_str = scheme; - if (!server_scheme_str || !*server_scheme_str) - server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; - m_scheme = server_scheme_str; - - setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); - } - - ~ShibTargetFCGIAuth() { } - - const char* getScheme() const { - return m_scheme.c_str(); - } - const char* getHostname() const { - return m_hostname.c_str(); - } - int getPort() const { - return m_port; - } - const char* getMethod() const { - return FCGX_GetParam("REQUEST_METHOD", m_req->envp); - } - string getContentType() const { - const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); - return s ? s : ""; - } - long getContentLength() const { - const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); - return s ? atol(s) : 0; - } - string getRemoteAddr() const { - string ret = AbstractSPRequest::getRemoteAddr(); - if (!ret.empty()) - return ret; - const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); - return s ? s : ""; - } - void log(SPLogLevel level, const string& msg) const { - AbstractSPRequest::log(level,msg); - if (level >= SPError) - cerr << "shib: " << msg; - } - void clearHeader(const char* rawname, const char* cginame) { - // No need, since we use environment variables. - } - void setHeader(const char* name, const char* value) { - if (value) - m_request_headers[name] = value; - else - m_request_headers.erase(name); - } - string getHeader(const char* name) const { - // Look in the local map first. - map::const_iterator i = m_request_headers.find(name); - if (i != m_request_headers.end()) - return i->second; - // Nothing set locally and this isn't a "secure" call, so check the request. - string hdr("HTTP_"); - for (; *name; ++name) { - if (*name=='-') - hdr += '_'; - else - hdr += toupper(*name); - } - char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); - return s ? s : ""; - } - string getSecureHeader(const char* name) const { - // Look in the local map only. - map::const_iterator i = m_request_headers.find(name); - if (i != m_request_headers.end()) - return i->second; - return ""; - } - void setRemoteUser(const char* user) { - if (user) - m_request_headers["REMOTE_USER"] = user; - else - m_request_headers.erase("REMOTE_USER"); - } - string getRemoteUser() const { - map::const_iterator i = m_request_headers.find("REMOTE_USER"); - if (i != m_request_headers.end()) - return i->second; - else { - char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp); - if (remote_user) - return remote_user; - } - return ""; - } - void setAuthType(const char* authtype) { - if (authtype) - m_request_headers["AUTH_TYPE"] = authtype; - else - m_request_headers.erase("AUTH_TYPE"); - } - string getAuthType() const { - map::const_iterator i = m_request_headers.find("AUTH_TYPE"); - if (i != m_request_headers.end()) - return i->second; - else { - char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp); - if (auth_type) - return auth_type; - } - return ""; - } - void setResponseHeader(const char* name, const char* value) { - AbstractSPRequest::setResponseHeader(name, value); - // Set for later. - if (value) - m_response_headers.insert(make_pair(name,value)); - else - m_response_headers.erase(name); - } - const char* getQueryString() const { - return FCGX_GetParam("QUERY_STRING", m_req->envp); - } - const char* getRequestBody() const { - throw runtime_error("getRequestBody not implemented by FastCGI authorizer."); - } - - long sendResponse(istream& in, long status) { - string hdr = string("Connection: close\r\n"); - for (multimap::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - - // We can't return 200 OK here or else the filter is bypassed - // so custom Shib errors will get turned into a generic page. - const char* codestr="Status: 500 Server Error"; - switch (status) { - case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break; - case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break; - case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break; - } - cout << codestr << "\r\n" << hdr << "\r\n"; - char buf[1024]; - while (in) { - in.read(buf,1024); - cout.write(buf, in.gcount()); - } - return SHIB_RETURN_DONE; - } - - long sendRedirect(const char* url) { - AbstractSPRequest::sendRedirect(url); - string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 40\r\n" - "Expires: 01-Jan-1997 12:00:00 GMT\r\n" - "Cache-Control: private,no-store,no-cache\r\n"; - for (multimap::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - hdr += "\r\n"; - - cout << hdr << "Redirecting..."; - return SHIB_RETURN_DONE; - } - - long returnDecline() { - return SHIB_RETURN_KO; - } - - long returnOK() { - return SHIB_RETURN_OK; - } - - const vector& getClientCertificates() const { - static vector g_NoCerts; - return g_NoCerts; - } -}; - -static void print_ok(const map& headers) -{ - cout << "Status: 200 OK" << "\r\n"; - for (map::const_iterator iter = headers.begin(); iter != headers.end(); iter++) { - cout << "Variable-" << iter->first << ": " << iter->second << "\r\n"; - } - cout << "\r\n"; -} - -static void print_error(const char* msg) -{ - cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; -} - -int main(void) -{ - SPConfig* g_Config=&SPConfig::getConfig(); - g_Config->setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::RequestMapping | - SPConfig::InProcess | - SPConfig::Logging | - SPConfig::Handlers - ); - if (!g_Config->init()) { - cerr << "failed to initialize Shibboleth libraries" << endl; - exit(1); - } - - try { - if (!g_Config->instantiate(NULL, true)) - throw runtime_error("unknown error"); - } - catch (exception& ex) { - g_Config->term(); - cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; - exit(1); - } - - string g_ServerScheme; - string g_ServerName; - int g_ServerPort=0; - - // Load "authoritative" URL fields. - char* var = getenv("SHIBSP_SERVER_NAME"); - if (var) - g_ServerName = var; - var = getenv("SHIBSP_SERVER_SCHEME"); - if (var) - g_ServerScheme = var; - var = getenv("SHIBSP_SERVER_PORT"); - if (var) - g_ServerPort = atoi(var); - - streambuf* cout_streambuf = cout.rdbuf(); - streambuf* cerr_streambuf = cerr.rdbuf(); - - FCGX_Request request; - - FCGX_Init(); - FCGX_InitRequest(&request, 0, 0); - - cout << "Shibboleth initialization complete. Starting request loop." << endl; - while (FCGX_Accept_r(&request) == 0) - { - // Note that the default bufsize (0) will cause the use of iostream - // methods that require positioning (such as peek(), seek(), - // unget() and putback()) to fail (in favour of more efficient IO). - fcgi_streambuf cout_fcgi_streambuf(request.out); - fcgi_streambuf cerr_fcgi_streambuf(request.err); - - cout.rdbuf(&cout_fcgi_streambuf); - cerr.rdbuf(&cerr_fcgi_streambuf); - - try { - xmltooling::NDC ndc("FastCGI shibauthorizer"); - ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); - - pair res = sta.getServiceProvider().doAuthentication(sta); - if (res.first) { - sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_KO: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_DONE: - continue; - - default: - cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth authorizer returned an unexpected result."); - continue; - } - } - - res = sta.getServiceProvider().doExport(sta); - if (res.first) { - sta.log(SPRequest::SPDebug, "shib: doExport handled request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_KO: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_DONE: - continue; - - default: - cerr << "shib: doExport returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth authorizer returned an unexpected result."); - continue; - } - } - - res = sta.getServiceProvider().doAuthorization(sta); - if (res.first) { - sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_KO: - print_ok(sta.m_request_headers); - continue; - - case SHIB_RETURN_DONE: - continue; - - default: - cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth authorizer returned an unexpected result."); - continue; - } - } - - print_ok(sta.m_request_headers); - - } - catch (exception& e) { - cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl; - print_error("FastCGI Shibboleth authorizer caught an exception, check log for details."); - } - - // If the output streambufs had non-zero bufsizes and - // were constructed outside of the accept loop (i.e. - // their destructor won't be called here), they would - // have to be flushed here. - } - cout << "Request loop ended." << endl; - - cout.rdbuf(cout_streambuf); - cerr.rdbuf(cerr_streambuf); - - if (g_Config) - g_Config->term(); - - return 0; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer + + Andre Cruz +*/ + +#define SHIBSP_LITE +#include "config_win32.h" + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _SCL_SECURE_NO_WARNINGS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_UNISTD_H +# include +# include +#endif +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); +static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); + +typedef enum { + SHIB_RETURN_OK, + SHIB_RETURN_KO, + SHIB_RETURN_DONE +} shib_return_t; + +class ShibTargetFCGIAuth : public AbstractSPRequest +{ + FCGX_Request* m_req; + int m_port; + string m_scheme,m_hostname; + multimap m_response_headers; +public: + map m_request_headers; + + ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0) + : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) { + const char* server_name_str = hostname; + if (!server_name_str || !*server_name_str) + server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); + m_hostname = server_name_str; + + m_port = port; + if (!m_port) { + char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); + m_port = strtol(server_port_str, &server_port_str, 10); + if (*server_port_str) { + cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; + throw runtime_error("Unable to determine server port."); + } + } + + const char* server_scheme_str = scheme; + if (!server_scheme_str || !*server_scheme_str) + server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; + m_scheme = server_scheme_str; + + setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); + } + + ~ShibTargetFCGIAuth() { } + + const char* getScheme() const { + return m_scheme.c_str(); + } + const char* getHostname() const { + return m_hostname.c_str(); + } + int getPort() const { + return m_port; + } + const char* getMethod() const { + return FCGX_GetParam("REQUEST_METHOD", m_req->envp); + } + string getContentType() const { + const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); + return s ? s : ""; + } + long getContentLength() const { + const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); + return s ? atol(s) : 0; + } + string getRemoteAddr() const { + string ret = AbstractSPRequest::getRemoteAddr(); + if (!ret.empty()) + return ret; + const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); + return s ? s : ""; + } + void log(SPLogLevel level, const string& msg) const { + AbstractSPRequest::log(level,msg); + if (level >= SPError) + cerr << "shib: " << msg; + } + void clearHeader(const char* rawname, const char* cginame) { + // No need, since we use environment variables. + } + void setHeader(const char* name, const char* value) { + if (value) + m_request_headers[name] = value; + else + m_request_headers.erase(name); + } + string getHeader(const char* name) const { + // Look in the local map first. + map::const_iterator i = m_request_headers.find(name); + if (i != m_request_headers.end()) + return i->second; + // Nothing set locally and this isn't a "secure" call, so check the request. + string hdr("HTTP_"); + for (; *name; ++name) { + if (*name=='-') + hdr += '_'; + else + hdr += toupper(*name); + } + char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); + return s ? s : ""; + } + string getSecureHeader(const char* name) const { + // Look in the local map only. + map::const_iterator i = m_request_headers.find(name); + if (i != m_request_headers.end()) + return i->second; + return ""; + } + void setRemoteUser(const char* user) { + if (user) + m_request_headers["REMOTE_USER"] = user; + else + m_request_headers.erase("REMOTE_USER"); + } + string getRemoteUser() const { + map::const_iterator i = m_request_headers.find("REMOTE_USER"); + if (i != m_request_headers.end()) + return i->second; + else { + char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp); + if (remote_user) + return remote_user; + } + return ""; + } + void setAuthType(const char* authtype) { + if (authtype) + m_request_headers["AUTH_TYPE"] = authtype; + else + m_request_headers.erase("AUTH_TYPE"); + } + string getAuthType() const { + map::const_iterator i = m_request_headers.find("AUTH_TYPE"); + if (i != m_request_headers.end()) + return i->second; + else { + char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp); + if (auth_type) + return auth_type; + } + return ""; + } + void setResponseHeader(const char* name, const char* value) { + AbstractSPRequest::setResponseHeader(name, value); + // Set for later. + if (value) + m_response_headers.insert(make_pair(name,value)); + else + m_response_headers.erase(name); + } + const char* getQueryString() const { + return FCGX_GetParam("QUERY_STRING", m_req->envp); + } + const char* getRequestBody() const { + throw runtime_error("getRequestBody not implemented by FastCGI authorizer."); + } + + long sendResponse(istream& in, long status) { + string hdr = string("Connection: close\r\n"); + for (multimap::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) + hdr += i->first + ": " + i->second + "\r\n"; + + // We can't return 200 OK here or else the filter is bypassed + // so custom Shib errors will get turned into a generic page. + const char* codestr="Status: 500 Server Error"; + switch (status) { + case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break; + case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break; + case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break; + } + cout << codestr << "\r\n" << hdr << "\r\n"; + char buf[1024]; + while (in) { + in.read(buf,1024); + cout.write(buf, in.gcount()); + } + return SHIB_RETURN_DONE; + } + + long sendRedirect(const char* url) { + AbstractSPRequest::sendRedirect(url); + string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 40\r\n" + "Expires: 01-Jan-1997 12:00:00 GMT\r\n" + "Cache-Control: private,no-store,no-cache\r\n"; + for (multimap::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i) + hdr += i->first + ": " + i->second + "\r\n"; + hdr += "\r\n"; + + cout << hdr << "Redirecting..."; + return SHIB_RETURN_DONE; + } + + long returnDecline() { + return SHIB_RETURN_KO; + } + + long returnOK() { + return SHIB_RETURN_OK; + } + + const vector& getClientCertificates() const { + static vector g_NoCerts; + return g_NoCerts; + } +}; + +static void print_ok(const map& headers) +{ + cout << "Status: 200 OK" << "\r\n"; + for (map::const_iterator iter = headers.begin(); iter != headers.end(); iter++) { + cout << "Variable-" << iter->first << ": " << iter->second << "\r\n"; + } + cout << "\r\n"; +} + +static void print_error(const char* msg) +{ + cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; +} + +int main(void) +{ + SPConfig* g_Config=&SPConfig::getConfig(); + g_Config->setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::RequestMapping | + SPConfig::InProcess | + SPConfig::Logging | + SPConfig::Handlers + ); + if (!g_Config->init()) { + cerr << "failed to initialize Shibboleth libraries" << endl; + exit(1); + } + + try { + if (!g_Config->instantiate(NULL, true)) + throw runtime_error("unknown error"); + } + catch (exception& ex) { + g_Config->term(); + cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; + exit(1); + } + + string g_ServerScheme; + string g_ServerName; + int g_ServerPort=0; + + // Load "authoritative" URL fields. + char* var = getenv("SHIBSP_SERVER_NAME"); + if (var) + g_ServerName = var; + var = getenv("SHIBSP_SERVER_SCHEME"); + if (var) + g_ServerScheme = var; + var = getenv("SHIBSP_SERVER_PORT"); + if (var) + g_ServerPort = atoi(var); + + streambuf* cout_streambuf = cout.rdbuf(); + streambuf* cerr_streambuf = cerr.rdbuf(); + + FCGX_Request request; + + FCGX_Init(); + FCGX_InitRequest(&request, 0, 0); + + cout << "Shibboleth initialization complete. Starting request loop." << endl; + while (FCGX_Accept_r(&request) == 0) + { + // Note that the default bufsize (0) will cause the use of iostream + // methods that require positioning (such as peek(), seek(), + // unget() and putback()) to fail (in favour of more efficient IO). + fcgi_streambuf cout_fcgi_streambuf(request.out); + fcgi_streambuf cerr_fcgi_streambuf(request.err); + + cout.rdbuf(&cout_fcgi_streambuf); + cerr.rdbuf(&cerr_fcgi_streambuf); + + try { + xmltooling::NDC ndc("FastCGI shibauthorizer"); + ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); + + pair res = sta.getServiceProvider().doAuthentication(sta); + if (res.first) { + sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_KO: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_DONE: + continue; + + default: + cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth authorizer returned an unexpected result."); + continue; + } + } + + res = sta.getServiceProvider().doExport(sta); + if (res.first) { + sta.log(SPRequest::SPDebug, "shib: doExport handled request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_KO: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_DONE: + continue; + + default: + cerr << "shib: doExport returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth authorizer returned an unexpected result."); + continue; + } + } + + res = sta.getServiceProvider().doAuthorization(sta); + if (res.first) { + sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_KO: + print_ok(sta.m_request_headers); + continue; + + case SHIB_RETURN_DONE: + continue; + + default: + cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth authorizer returned an unexpected result."); + continue; + } + } + + print_ok(sta.m_request_headers); + + } + catch (exception& e) { + cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl; + print_error("FastCGI Shibboleth authorizer caught an exception, check log for details."); + } + + // If the output streambufs had non-zero bufsizes and + // were constructed outside of the accept loop (i.e. + // their destructor won't be called here), they would + // have to be flushed here. + } + cout << "Request loop ended." << endl; + + cout.rdbuf(cout_streambuf); + cerr.rdbuf(cerr_streambuf); + + if (g_Config) + g_Config->term(); + + return 0; +} diff --git a/fastcgi/shibresponder.cpp b/fastcgi/shibresponder.cpp index 78a3c9d..3c76ff7 100644 --- a/fastcgi/shibresponder.cpp +++ b/fastcgi/shibresponder.cpp @@ -1,400 +1,400 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler - - Andre Cruz -*/ - -#define SHIBSP_LITE -#include "config_win32.h" - -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#define _CRT_SECURE_NO_DEPRECATE 1 -#define _SCL_SECURE_NO_WARNINGS 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef HAVE_UNISTD_H -# include -# include -#endif -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace xercesc; -using namespace std; - -static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); -static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); - -typedef enum { - SHIB_RETURN_OK, - SHIB_RETURN_KO, - SHIB_RETURN_DONE -} shib_return_t; - -class ShibTargetFCGI : public AbstractSPRequest -{ - FCGX_Request* m_req; - const char* m_body; - multimap m_headers; - int m_port; - string m_scheme,m_hostname; - -public: - ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0) - : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) { - - const char* server_name_str = hostname; - if (!server_name_str || !*server_name_str) - server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); - m_hostname = server_name_str; - - m_port = port; - if (!m_port) { - char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); - m_port = strtol(server_port_str, &server_port_str, 10); - if (*server_port_str) { - cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; - throw runtime_error("Unable to determine server port."); - } - } - - const char* server_scheme_str = scheme; - if (!server_scheme_str || !*server_scheme_str) - server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; - m_scheme = server_scheme_str; - - setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); - } - - ~ShibTargetFCGI() { } - - const char* getScheme() const { - return m_scheme.c_str(); - } - const char* getHostname() const { - return m_hostname.c_str(); - } - int getPort() const { - return m_port; - } - const char* getMethod() const { - return FCGX_GetParam("REQUEST_METHOD", m_req->envp); - } - string getContentType() const { - const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); - return s ? s : ""; - } - long getContentLength() const { - const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); - return s ? atol(s) : 0; - } - string getRemoteUser() const { - const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp); - return s ? s : ""; - } - string getRemoteAddr() const { - string ret = AbstractSPRequest::getRemoteAddr(); - if (!ret.empty()) - return ret; - const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); - return s ? s : ""; - } - void log(SPLogLevel level, const string& msg) const { - AbstractSPRequest::log(level,msg); - if (level >= SPError) - cerr << "shib: " << msg; - } - - string getHeader(const char* name) const { - string hdr("HTTP_"); - for (; *name; ++name) { - if (*name=='-') - hdr += '_'; - else - hdr += toupper(*name); - } - char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); - return s ? s : ""; - } - - void setResponseHeader(const char* name, const char* value) { - AbstractSPRequest::setResponseHeader(name, value); - // Set for later. - if (value) - m_headers.insert(make_pair(name,value)); - else - m_headers.erase(name); - } - - const char* getQueryString() const { - return FCGX_GetParam("QUERY_STRING", m_req->envp); - } - - const char* getRequestBody() const { - return m_body; - } - - long sendResponse(istream& in, long status) { - string hdr = string("Connection: close\r\n"); - for (multimap::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - - const char* codestr="Status: 200 OK"; - switch (status) { - case XMLTOOLING_HTTP_STATUS_ERROR: codestr="Status: 500 Server Error"; break; - case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break; - case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break; - case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break; - } - cout << codestr << "\r\n" << hdr << "\r\n"; - char buf[1024]; - while (in) { - in.read(buf,1024); - cout.write(buf, in.gcount()); - } - return SHIB_RETURN_DONE; - } - - long sendRedirect(const char* url) { - AbstractSPRequest::sendRedirect(url); - string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 40\r\n" - "Expires: 01-Jan-1997 12:00:00 GMT\r\n" - "Cache-Control: private,no-store,no-cache\r\n"; - for (multimap::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) - hdr += i->first + ": " + i->second + "\r\n"; - hdr += "\r\n"; - - cout << hdr << "Redirecting..."; - return SHIB_RETURN_DONE; - } - - long returnDecline() { - return SHIB_RETURN_KO; - } - long returnOK() { - return SHIB_RETURN_OK; - } - - const vector& getClientCertificates() const { - static vector g_NoCerts; - return g_NoCerts; - } - - // Not used in the extension. - - virtual void clearHeader(const char* rawname, const char* cginame) { - throw runtime_error("clearHeader not implemented by FastCGI responder."); - } - - virtual void setHeader(const char* name, const char* value) { - throw runtime_error("setHeader not implemented by FastCGI responder."); - } - - virtual void setRemoteUser(const char* user) { - throw runtime_error("setRemoteUser not implemented by FastCGI responder."); - } -}; - -// Maximum number of bytes allowed to be read from stdin -static const unsigned long STDIN_MAX = 1000000; - -static long gstdin(FCGX_Request* request, char** content) -{ - char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp); - unsigned long clen = STDIN_MAX; - - if (clenstr) { - clen = strtol(clenstr, &clenstr, 10); - if (*clenstr) { - cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl; - clen = STDIN_MAX; - } - - // *always* put a cap on the amount of data that will be read - if (clen > STDIN_MAX) - clen = STDIN_MAX; - - *content = new char[clen]; - - cin.read(*content, clen); - clen = cin.gcount(); - } - else { - // *never* read stdin when CONTENT_LENGTH is missing or unparsable - *content = 0; - clen = 0; - } - - // Chew up any remaining stdin - this shouldn't be necessary - // but is because mod_fastcgi doesn't handle it correctly. - - // ignore() doesn't set the eof bit in some versions of glibc++ - // so use gcount() instead of eof()... - do cin.ignore(1024); while (cin.gcount() == 1024); - - return clen; -} - -static void print_ok() { - cout << "Status: 200 OK" << "\r\n\r\n"; -} - -static void print_error(const char* msg) { - cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; -} - -int main(void) -{ - SPConfig* g_Config=&SPConfig::getConfig(); - g_Config->setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::RequestMapping | - SPConfig::InProcess | - SPConfig::Logging | - SPConfig::Handlers - ); - if (!g_Config->init()) { - cerr << "failed to initialize Shibboleth libraries" << endl; - exit(1); - } - - try { - if (!g_Config->instantiate(NULL, true)) - throw runtime_error("unknown error"); - } - catch (exception& ex) { - g_Config->term(); - cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; - exit(1); - } - - string g_ServerScheme; - string g_ServerName; - int g_ServerPort=0; - - // Load "authoritative" URL fields. - char* var = getenv("SHIBSP_SERVER_NAME"); - if (var) - g_ServerName = var; - var = getenv("SHIBSP_SERVER_SCHEME"); - if (var) - g_ServerScheme = var; - var = getenv("SHIBSP_SERVER_PORT"); - if (var) - g_ServerPort = atoi(var); - - streambuf* cin_streambuf = cin.rdbuf(); - streambuf* cout_streambuf = cout.rdbuf(); - streambuf* cerr_streambuf = cerr.rdbuf(); - - FCGX_Request request; - - FCGX_Init(); - FCGX_InitRequest(&request, 0, 0); - - cout << "Shibboleth initialization complete. Starting request loop." << endl; - while (FCGX_Accept_r(&request) == 0) { - // Note that the default bufsize (0) will cause the use of iostream - // methods that require positioning (such as peek(), seek(), - // unget() and putback()) to fail (in favour of more efficient IO). - fcgi_streambuf cin_fcgi_streambuf(request.in); - fcgi_streambuf cout_fcgi_streambuf(request.out); - fcgi_streambuf cerr_fcgi_streambuf(request.err); - - cin.rdbuf(&cin_fcgi_streambuf); - cout.rdbuf(&cout_fcgi_streambuf); - cerr.rdbuf(&cerr_fcgi_streambuf); - - // Although FastCGI supports writing before reading, - // many http clients (browsers) don't support it (so - // the connection deadlocks until a timeout expires!). - char* content; - gstdin(&request, &content); - - try { - xmltooling::NDC ndc("FastCGI shibresponder"); - ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); - - pair res = stf.getServiceProvider().doHandler(stf); - if (res.first) { - stf.log(SPRequest::SPDebug, "shib: doHandler handled the request"); - switch(res.second) { - case SHIB_RETURN_OK: - print_ok(); - break; - - case SHIB_RETURN_KO: - cerr << "shib: doHandler failed to handle the request" << endl; - print_error("FastCGI Shibboleth responder should only be used for Shibboleth protocol requests."); - break; - - case SHIB_RETURN_DONE: - // response already handled - break; - - default: - cerr << "shib: doHandler returned an unexpected result: " << res.second << endl; - print_error("FastCGI Shibboleth responder returned an unexpected result."); - break; - } - } - else { - cerr << "shib: doHandler failed to handle request." << endl; - print_error("FastCGI Shibboleth responder failed to process request."); - } - - } - catch (exception& e) { - cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl; - print_error("FastCGI Shibboleth responder caught an exception, check log for details."); - } - - delete[] content; - - // If the output streambufs had non-zero bufsizes and - // were constructed outside of the accept loop (i.e. - // their destructor won't be called here), they would - // have to be flushed here. - } - - cout << "Request loop ended." << endl; - - cin.rdbuf(cin_streambuf); - cout.rdbuf(cout_streambuf); - cerr.rdbuf(cerr_streambuf); - - if (g_Config) - g_Config->term(); - - return 0; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler + + Andre Cruz +*/ + +#define SHIBSP_LITE +#include "config_win32.h" + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _SCL_SECURE_NO_WARNINGS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_UNISTD_H +# include +# include +#endif +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); +static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e); + +typedef enum { + SHIB_RETURN_OK, + SHIB_RETURN_KO, + SHIB_RETURN_DONE +} shib_return_t; + +class ShibTargetFCGI : public AbstractSPRequest +{ + FCGX_Request* m_req; + const char* m_body; + multimap m_headers; + int m_port; + string m_scheme,m_hostname; + +public: + ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0) + : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) { + + const char* server_name_str = hostname; + if (!server_name_str || !*server_name_str) + server_name_str = FCGX_GetParam("SERVER_NAME", req->envp); + m_hostname = server_name_str; + + m_port = port; + if (!m_port) { + char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp); + m_port = strtol(server_port_str, &server_port_str, 10); + if (*server_port_str) { + cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl; + throw runtime_error("Unable to determine server port."); + } + } + + const char* server_scheme_str = scheme; + if (!server_scheme_str || !*server_scheme_str) + server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http"; + m_scheme = server_scheme_str; + + setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp)); + } + + ~ShibTargetFCGI() { } + + const char* getScheme() const { + return m_scheme.c_str(); + } + const char* getHostname() const { + return m_hostname.c_str(); + } + int getPort() const { + return m_port; + } + const char* getMethod() const { + return FCGX_GetParam("REQUEST_METHOD", m_req->envp); + } + string getContentType() const { + const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp); + return s ? s : ""; + } + long getContentLength() const { + const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp); + return s ? atol(s) : 0; + } + string getRemoteUser() const { + const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp); + return s ? s : ""; + } + string getRemoteAddr() const { + string ret = AbstractSPRequest::getRemoteAddr(); + if (!ret.empty()) + return ret; + const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp); + return s ? s : ""; + } + void log(SPLogLevel level, const string& msg) const { + AbstractSPRequest::log(level,msg); + if (level >= SPError) + cerr << "shib: " << msg; + } + + string getHeader(const char* name) const { + string hdr("HTTP_"); + for (; *name; ++name) { + if (*name=='-') + hdr += '_'; + else + hdr += toupper(*name); + } + char* s = FCGX_GetParam(hdr.c_str(), m_req->envp); + return s ? s : ""; + } + + void setResponseHeader(const char* name, const char* value) { + AbstractSPRequest::setResponseHeader(name, value); + // Set for later. + if (value) + m_headers.insert(make_pair(name,value)); + else + m_headers.erase(name); + } + + const char* getQueryString() const { + return FCGX_GetParam("QUERY_STRING", m_req->envp); + } + + const char* getRequestBody() const { + return m_body; + } + + long sendResponse(istream& in, long status) { + string hdr = string("Connection: close\r\n"); + for (multimap::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) + hdr += i->first + ": " + i->second + "\r\n"; + + const char* codestr="Status: 200 OK"; + switch (status) { + case XMLTOOLING_HTTP_STATUS_ERROR: codestr="Status: 500 Server Error"; break; + case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED: codestr="Status: 401 Authorization Required"; break; + case XMLTOOLING_HTTP_STATUS_FORBIDDEN: codestr="Status: 403 Forbidden"; break; + case XMLTOOLING_HTTP_STATUS_NOTFOUND: codestr="Status: 404 Not Found"; break; + } + cout << codestr << "\r\n" << hdr << "\r\n"; + char buf[1024]; + while (in) { + in.read(buf,1024); + cout.write(buf, in.gcount()); + } + return SHIB_RETURN_DONE; + } + + long sendRedirect(const char* url) { + AbstractSPRequest::sendRedirect(url); + string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 40\r\n" + "Expires: 01-Jan-1997 12:00:00 GMT\r\n" + "Cache-Control: private,no-store,no-cache\r\n"; + for (multimap::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i) + hdr += i->first + ": " + i->second + "\r\n"; + hdr += "\r\n"; + + cout << hdr << "Redirecting..."; + return SHIB_RETURN_DONE; + } + + long returnDecline() { + return SHIB_RETURN_KO; + } + long returnOK() { + return SHIB_RETURN_OK; + } + + const vector& getClientCertificates() const { + static vector g_NoCerts; + return g_NoCerts; + } + + // Not used in the extension. + + virtual void clearHeader(const char* rawname, const char* cginame) { + throw runtime_error("clearHeader not implemented by FastCGI responder."); + } + + virtual void setHeader(const char* name, const char* value) { + throw runtime_error("setHeader not implemented by FastCGI responder."); + } + + virtual void setRemoteUser(const char* user) { + throw runtime_error("setRemoteUser not implemented by FastCGI responder."); + } +}; + +// Maximum number of bytes allowed to be read from stdin +static const unsigned long STDIN_MAX = 1000000; + +static long gstdin(FCGX_Request* request, char** content) +{ + char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp); + unsigned long clen = STDIN_MAX; + + if (clenstr) { + clen = strtol(clenstr, &clenstr, 10); + if (*clenstr) { + cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl; + clen = STDIN_MAX; + } + + // *always* put a cap on the amount of data that will be read + if (clen > STDIN_MAX) + clen = STDIN_MAX; + + *content = new char[clen]; + + cin.read(*content, clen); + clen = cin.gcount(); + } + else { + // *never* read stdin when CONTENT_LENGTH is missing or unparsable + *content = 0; + clen = 0; + } + + // Chew up any remaining stdin - this shouldn't be necessary + // but is because mod_fastcgi doesn't handle it correctly. + + // ignore() doesn't set the eof bit in some versions of glibc++ + // so use gcount() instead of eof()... + do cin.ignore(1024); while (cin.gcount() == 1024); + + return clen; +} + +static void print_ok() { + cout << "Status: 200 OK" << "\r\n\r\n"; +} + +static void print_error(const char* msg) { + cout << "Status: 500 Server Error" << "\r\n\r\n" << msg; +} + +int main(void) +{ + SPConfig* g_Config=&SPConfig::getConfig(); + g_Config->setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::RequestMapping | + SPConfig::InProcess | + SPConfig::Logging | + SPConfig::Handlers + ); + if (!g_Config->init()) { + cerr << "failed to initialize Shibboleth libraries" << endl; + exit(1); + } + + try { + if (!g_Config->instantiate(NULL, true)) + throw runtime_error("unknown error"); + } + catch (exception& ex) { + g_Config->term(); + cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl; + exit(1); + } + + string g_ServerScheme; + string g_ServerName; + int g_ServerPort=0; + + // Load "authoritative" URL fields. + char* var = getenv("SHIBSP_SERVER_NAME"); + if (var) + g_ServerName = var; + var = getenv("SHIBSP_SERVER_SCHEME"); + if (var) + g_ServerScheme = var; + var = getenv("SHIBSP_SERVER_PORT"); + if (var) + g_ServerPort = atoi(var); + + streambuf* cin_streambuf = cin.rdbuf(); + streambuf* cout_streambuf = cout.rdbuf(); + streambuf* cerr_streambuf = cerr.rdbuf(); + + FCGX_Request request; + + FCGX_Init(); + FCGX_InitRequest(&request, 0, 0); + + cout << "Shibboleth initialization complete. Starting request loop." << endl; + while (FCGX_Accept_r(&request) == 0) { + // Note that the default bufsize (0) will cause the use of iostream + // methods that require positioning (such as peek(), seek(), + // unget() and putback()) to fail (in favour of more efficient IO). + fcgi_streambuf cin_fcgi_streambuf(request.in); + fcgi_streambuf cout_fcgi_streambuf(request.out); + fcgi_streambuf cerr_fcgi_streambuf(request.err); + + cin.rdbuf(&cin_fcgi_streambuf); + cout.rdbuf(&cout_fcgi_streambuf); + cerr.rdbuf(&cerr_fcgi_streambuf); + + // Although FastCGI supports writing before reading, + // many http clients (browsers) don't support it (so + // the connection deadlocks until a timeout expires!). + char* content; + gstdin(&request, &content); + + try { + xmltooling::NDC ndc("FastCGI shibresponder"); + ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort); + + pair res = stf.getServiceProvider().doHandler(stf); + if (res.first) { + stf.log(SPRequest::SPDebug, "shib: doHandler handled the request"); + switch(res.second) { + case SHIB_RETURN_OK: + print_ok(); + break; + + case SHIB_RETURN_KO: + cerr << "shib: doHandler failed to handle the request" << endl; + print_error("FastCGI Shibboleth responder should only be used for Shibboleth protocol requests."); + break; + + case SHIB_RETURN_DONE: + // response already handled + break; + + default: + cerr << "shib: doHandler returned an unexpected result: " << res.second << endl; + print_error("FastCGI Shibboleth responder returned an unexpected result."); + break; + } + } + else { + cerr << "shib: doHandler failed to handle request." << endl; + print_error("FastCGI Shibboleth responder failed to process request."); + } + + } + catch (exception& e) { + cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl; + print_error("FastCGI Shibboleth responder caught an exception, check log for details."); + } + + delete[] content; + + // If the output streambufs had non-zero bufsizes and + // were constructed outside of the accept loop (i.e. + // their destructor won't be called here), they would + // have to be flushed here. + } + + cout << "Request loop ended." << endl; + + cin.rdbuf(cin_streambuf); + cout.rdbuf(cout_streambuf); + cerr.rdbuf(cerr_streambuf); + + if (g_Config) + g_Config->term(); + + return 0; +} diff --git a/memcache-store/Makefile.am b/memcache-store/Makefile.am index 9d46119..fa11fd8 100644 --- a/memcache-store/Makefile.am +++ b/memcache-store/Makefile.am @@ -1,20 +1,20 @@ -AUTOMAKE_OPTIONS = foreign - -plugindir = $(libdir)/@PACKAGE@ -plugin_LTLIBRARIES = memcache-store.la - -AM_CFLAGS = $(MEMCACHED_CFLAGS) -AM_CXXFLAGS = $(MEMCACHED_CFLAGS) - -memcache_store_la_LIBADD = \ - $(MEMCACHED_LIBS) - -memcache_store_la_SOURCES = \ - memcache-store.cpp - -memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) - -install-exec-hook: - for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done - -EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h +AUTOMAKE_OPTIONS = foreign + +plugindir = $(libdir)/@PACKAGE@ +plugin_LTLIBRARIES = memcache-store.la + +AM_CFLAGS = $(MEMCACHED_CFLAGS) +AM_CXXFLAGS = $(MEMCACHED_CFLAGS) + +memcache_store_la_LIBADD = \ + $(MEMCACHED_LIBS) + +memcache_store_la_SOURCES = \ + memcache-store.cpp + +memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS) + +install-exec-hook: + for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done + +EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h diff --git a/memcache-store/memcache-store.cpp b/memcache-store/memcache-store.cpp index 6724232..49d238d 100644 --- a/memcache-store/memcache-store.cpp +++ b/memcache-store/memcache-store.cpp @@ -1,808 +1,808 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * memcache-store.cpp - * - * Storage Service using memcache (pre memcache tags) - */ - -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#ifdef WIN32 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -# define _CRT_SECURE_NO_DEPRECATE 1 -# define MCEXT_EXPORTS __declspec(dllexport) -#else -# define MCEXT_EXPORTS -#endif - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace xmltooling::logging; -using namespace xmltooling; -using namespace xercesc; -using namespace std; - -namespace xmltooling { - static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s); - static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x); - static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p); - static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t); - static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t); - static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t); - static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t); - static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t); - - class mc_record { - public: - string value; - time_t expiration; - mc_record(){}; - mc_record(string _v, time_t _e) : - value(_v), expiration(_e) - {} - }; - - class MemcacheBase { - public: - MemcacheBase(const DOMElement* e); - ~MemcacheBase(); - - bool addMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix = true); - bool setMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix = true); - bool replaceMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix = true); - bool getMemcache(const char *key, - string &dest, - uint32_t *flags, - bool use_prefix = true); - bool deleteMemcache(const char *key, - time_t timeout, - bool use_prefix = true); - - void serialize(mc_record &source, string &dest); - void serialize(list &source, string &dest); - void deserialize(string &source, mc_record &dest); - void deserialize(string &source, list &dest); - - bool addSessionToUser(string &key, string &user); - bool addLock(string what, bool use_prefix = true); - void deleteLock(string what, bool use_prefix = true); - - protected: - const DOMElement* m_root; // can only use this during initialization - Category& log; - memcached_st *memc; - string m_prefix; - Mutex* m_lock; - }; - - class MemcacheStorageService : public StorageService, public MemcacheBase { - - public: - MemcacheStorageService(const DOMElement* e); - ~MemcacheStorageService(); - - bool createString(const char* context, const char* key, const char* value, time_t expiration); - int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0); - int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0); - bool deleteString(const char* context, const char* key); - - bool createText(const char* context, const char* key, const char* value, time_t expiration) { - return createString(context, key, value, expiration); - } - int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) { - return readString(context, key, pvalue, pexpiration, version); - } - int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) { - return updateString(context, key, value, expiration, version); - } - bool deleteText(const char* context, const char* key) { - return deleteString(context, key); - } - - void reap(const char* context) {} - - void updateContext(const char* context, time_t expiration); - void deleteContext(const char* context); - - private: - - Category& m_log; - bool m_buildMap; - - - }; - - StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) { - return new MemcacheStorageService(e); - } - -}; - -bool MemcacheBase::addLock(string what, bool use_prefix) { - string lock_name = what + ":LOCK"; - string set_val = "1"; - unsigned tries = 5; - while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) { - if (tries-- == 0) { - log.debug("Unable to get lock %s... FAILED.", lock_name.c_str()); - return false; - } - log.debug("Unable to get lock %s... Retrying.", lock_name.c_str()); - - // sleep 100ms -#ifdef WIN32 - Sleep(100); -#else - struct timeval tv = { 0, 100000 }; - select(0, 0, 0, 0, &tv); -#endif - } - return true; -} - -void MemcacheBase::deleteLock(string what, bool use_prefix) { - - string lock_name = what + ":LOCK"; - deleteMemcache(lock_name.c_str(), 0, use_prefix); - return; - -} - -void MemcacheBase::deserialize(string &source, mc_record &dest) { - istringstream is(source, stringstream::in | stringstream::out); - is >> dest.expiration; - is.ignore(1); // ignore delimiter - dest.value = is.str().c_str() + is.tellg(); -} - -void MemcacheBase::deserialize(string &source, list &dest) { - istringstream is(source, stringstream::in | stringstream::out); - while (!is.eof()) { - string s; - is >> s; - dest.push_back(s); - } -} - -void MemcacheBase::serialize(mc_record &source, string &dest) { - ostringstream os(stringstream::in | stringstream::out); - os << source.expiration; - os << "-"; // delimiter - os << source.value; - dest = os.str(); -} - -void MemcacheBase::serialize(list &source, string &dest) { - ostringstream os(stringstream::in | stringstream::out); - for(list::iterator iter = source.begin(); iter != source.end(); iter++) { - if (iter != source.begin()) { - os << endl; - } - os << *iter; - } - dest = os.str(); -} - -bool MemcacheBase::addSessionToUser(string &key, string &user) { - - if (! addLock(user, false)) { - return false; - } - - // Aquired lock - - string sessid = m_prefix + key; // add specific prefix to session - string delimiter = ";"; - string user_key = "UDATA:"; - user_key += user; - string user_val; - uint32_t flags; - bool result = getMemcache(user_key.c_str(), user_val, &flags, false); - - if (result) { - bool already_there = false; - // skip delimiters at beginning. - string::size_type lastPos = user_val.find_first_not_of(delimiter, 0); - - // find first "non-delimiter". - string::size_type pos = user_val.find_first_of(delimiter, lastPos); - - while (string::npos != pos || string::npos != lastPos) { - // found a token, add it to the vector. - string session = user_val.substr(lastPos, pos - lastPos); - if (strcmp(session.c_str(), sessid.c_str()) == 0) { - already_there = true; - break; - } - - // skip delimiters. Note the "not_of" - lastPos = user_val.find_first_not_of(delimiter, pos); - - // find next "non-delimiter" - pos = user_val.find_first_of(delimiter, lastPos); - } - - if (!already_there) { - user_val += delimiter + sessid; - replaceMemcache(user_key.c_str(), user_val, 0, 0, false); - } - } else { - addMemcache(user_key.c_str(), sessid, 0, 0, false); - } - - deleteLock(user, false); - return true; - -} - -bool MemcacheBase::deleteMemcache(const char *key, - time_t timeout, - bool use_prefix) { - memcached_return rv; - string final_key; - bool success; - - if (use_prefix) { - final_key = m_prefix + key; - } else { - final_key = key; - } - - m_lock->lock(); - rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout); - m_lock->unlock(); - - if (rv == MEMCACHED_SUCCESS) { - success = true; - } else if (rv == MEMCACHED_NOTFOUND) { - // Key wasn't there... No biggie. - success = false; - } else if (rv == MEMCACHED_ERRNO) { - // System error - string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); - log.error(error); - throw IOException(error); - } else { - string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv); - log.error(error); - throw IOException(error); - } - - return success; -} - -bool MemcacheBase::getMemcache(const char *key, - string &dest, - uint32_t *flags, - bool use_prefix) { - memcached_return rv; - size_t len; - char *result; - string final_key; - bool success; - - if (use_prefix) { - final_key = m_prefix + key; - } else { - final_key = key; - } - - m_lock->lock(); - result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv); - m_lock->unlock(); - - if (rv == MEMCACHED_SUCCESS) { - dest = result; - free(result); - success = true; - } else if (rv == MEMCACHED_NOTFOUND) { - log.debug("Key %s not found in memcache...", key); - success = false; - } else if (rv == MEMCACHED_ERRNO) { - // System error - string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); - log.error(error); - throw IOException(error); - } else { - string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv); - log.error(error); - throw IOException(error); - } - - return success; -} - -bool MemcacheBase::addMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix) { - - memcached_return rv; - string final_key; - bool success; - - if (use_prefix) { - final_key = m_prefix + key; - } else { - final_key = key; - } - - m_lock->lock(); - rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); - m_lock->unlock(); - - if (rv == MEMCACHED_SUCCESS) { - success = true; - } else if (rv == MEMCACHED_NOTSTORED) { - // already there - success = false; - } else if (rv == MEMCACHED_ERRNO) { - // System error - string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); - log.error(error); - throw IOException(error); - } else { - string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv); - log.error(error); - throw IOException(error); - } - - return success; -} - -bool MemcacheBase::setMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix) { - - memcached_return rv; - string final_key; - bool success; - - if (use_prefix) { - final_key = m_prefix + key; - } else { - final_key = key; - } - - m_lock->lock(); - rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); - m_lock->unlock(); - - if (rv == MEMCACHED_SUCCESS) { - success = true; - } else if (rv == MEMCACHED_ERRNO) { - // System error - string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); - log.error(error); - throw IOException(error); - } else { - string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv); - log.error(error); - throw IOException(error); - } - - return success; -} - -bool MemcacheBase::replaceMemcache(const char *key, - string &value, - time_t timeout, - uint32_t flags, - bool use_prefix) { - - memcached_return rv; - string final_key; - bool success; - - if (use_prefix) { - final_key = m_prefix + key; - } else { - final_key = key; - } - - m_lock->lock(); - rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); - m_lock->unlock(); - - if (rv == MEMCACHED_SUCCESS) { - success = true; - } else if (rv == MEMCACHED_NOTSTORED) { - // not there - success = false; - } else if (rv == MEMCACHED_ERRNO) { - // System error - string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); - log.error(error); - throw IOException(error); - } else { - string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv); - log.error(error); - throw IOException(error); - } - - return success; -} - -MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") { - - auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL); - if (p.get() && *p.get()) { - log.debug("INIT: GOT key prefix: %s", p.get()); - m_prefix = p.get(); - } - - m_lock = Mutex::create(); - log.debug("Lock created"); - - memc = memcached_create(NULL); - if (memc == NULL) { - throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed"); - } - - log.debug("Memcache created"); - - unsigned int hash = MEMCACHED_HASH_CRC; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash); - log.debug("CRC hash set"); - - int32_t send_timeout = 1000000; - const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL; - if (tag && *tag) { - send_timeout = XMLString::parseInt(tag); - } - log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout); - - int32_t recv_timeout = 1000000; - tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL; - if (tag && *tag) { - recv_timeout = XMLString::parseInt(tag); - } - log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout); - - int32_t poll_timeout = 1000; - tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL; - if (tag && *tag) { - poll_timeout = XMLString::parseInt(tag); - } - log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout); - - int32_t fail_limit = 5; - tag = e ? e->getAttributeNS(NULL, failLimit) : NULL; - if (tag && *tag) { - fail_limit = XMLString::parseInt(tag); - } - log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit); - - int32_t retry_timeout = 30; - tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL; - if (tag && *tag) { - retry_timeout = XMLString::parseInt(tag); - } - log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout); - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout); - - // Grab hosts from the configuration. - e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL; - if (!e || !e->hasChildNodes()) { - throw XMLToolingException("Memcache StorageService requires Hosts element in configuration."); - } - auto_ptr_char h(e->getFirstChild()->getNodeValue()); - log.debug("INIT: GOT Hosts: %s", h.get()); - memcached_server_st *servers; - servers = memcached_servers_parse(const_cast(h.get())); - log.debug("Got %u hosts.", memcached_server_list_count(servers)); - if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) { - throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed"); - } - memcached_server_list_free(servers); - - log.debug("Memcache object initialized"); -} - -MemcacheBase::~MemcacheBase() { - memcached_free(memc); - delete m_lock; - log.debug("Base object destroyed"); -} - -MemcacheStorageService::MemcacheStorageService(const DOMElement* e) - : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) { - - const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL; - if (tag && *tag && XMLString::parseInt(tag) != 0) { - m_buildMap = true; - m_log.debug("Cache built with buildMap ON"); - } - -} - -MemcacheStorageService::~MemcacheStorageService() { - - -} - -bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) { - - log.debug("createString ctx: %s - key: %s", context, key); - - string final_key = string(context) + ":" + string(key); - - mc_record rec(value, expiration); - string final_value; - serialize(rec, final_value); - - bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version - - if (result && m_buildMap) { - log.debug("Got result, updating map"); - - string map_name = context; - // we need to update the context map - if (! addLock(map_name)) { - log.error("Unable to get lock for context %s!", context); - deleteMemcache(final_key.c_str(), 0); - return false; - } - - string ser_arr; - uint32_t flags; - bool result = getMemcache(map_name.c_str(), ser_arr, &flags); - - list contents; - if (result) { - log.debug("Match found. Parsing..."); - - deserialize(ser_arr, contents); - - log.debug("Iterating retrieved session map..."); - list::iterator iter; - for(iter = contents.begin(); - iter != contents.end(); - iter++) { - log.debug("value = " + *iter); - } - - } else { - log.debug("New context: %s", map_name.c_str()); - - } - - contents.push_back(key); - serialize(contents, ser_arr); - setMemcache(map_name.c_str(), ser_arr, expiration, 0); - - deleteLock(map_name); - } - - return result; - -} - -int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) { - - log.debug("readString ctx: %s - key: %s", context, key); - - string final_key = string(context) + ":" + string(key); - uint32_t rec_version; - string value; - - if (m_buildMap) { - log.debug("Checking context"); - - string map_name = context; - string ser_arr; - uint32_t flags; - bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags); - - if (!ctx_found) { - return 0; - } - } - - bool found = getMemcache(final_key.c_str(), value, &rec_version); - if (!found) { - return 0; - } - - if (version && rec_version <= (uint32_t)version) { - return version; - } - - if (pexpiration || pvalue) { - mc_record rec; - deserialize(value, rec); - - if (pexpiration) { - *pexpiration = rec.expiration; - } - - if (pvalue) { - *pvalue = rec.value; - } - } - - return rec_version; - -} - -int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) { - - log.debug("updateString ctx: %s - key: %s", context, key); - - time_t final_exp = expiration; - time_t *want_expiration = NULL; - if (! final_exp) { - want_expiration = &final_exp; - } - - int read_res = readString(context, key, NULL, want_expiration, version); - - if (!read_res) { - // not found - return read_res; - } - - if (version && version != read_res) { - // version incorrect - return -1; - } - - // Proceding with update - string final_key = string(context) + ":" + string(key); - mc_record rec(value, final_exp); - string final_value; - serialize(rec, final_value); - - replaceMemcache(final_key.c_str(), final_value, final_exp, ++version); - return version; - -} - -bool MemcacheStorageService::deleteString(const char* context, const char* key) { - - log.debug("deleteString ctx: %s - key: %s", context, key); - - string final_key = string(context) + ":" + string(key); - - // Not updating context map, if there is one. There is no need. - - return deleteMemcache(final_key.c_str(), 0); - -} - -void MemcacheStorageService::updateContext(const char* context, time_t expiration) { - - log.debug("updateContext ctx: %s", context); - - if (!m_buildMap) { - log.error("updateContext invoked on a Storage with no context map built!"); - return; - } - - string map_name = context; - string ser_arr; - uint32_t flags; - bool result = getMemcache(map_name.c_str(), ser_arr, &flags); - - list contents; - if (result) { - log.debug("Match found. Parsing..."); - - deserialize(ser_arr, contents); - - log.debug("Iterating retrieved session map..."); - list::iterator iter; - for(iter = contents.begin(); - iter != contents.end(); - iter++) { - - // Update expiration times - string value; - int read_res = readString(context, iter->c_str(), &value, NULL, 0); - - if (!read_res) { - // not found - continue; - } - - updateString(context, iter->c_str(), value.c_str(), expiration, read_res); - } - replaceMemcache(map_name.c_str(), ser_arr, expiration, flags); - } - -} - -void MemcacheStorageService::deleteContext(const char* context) { - - log.debug("deleteContext ctx: %s", context); - - if (!m_buildMap) { - log.error("deleteContext invoked on a Storage with no context map built!"); - return; - } - - string map_name = context; - string ser_arr; - uint32_t flags; - bool result = getMemcache(map_name.c_str(), ser_arr, &flags); - - list contents; - if (result) { - log.debug("Match found. Parsing..."); - - deserialize(ser_arr, contents); - - log.debug("Iterating retrieved session map..."); - list::iterator iter; - for(iter = contents.begin(); - iter != contents.end(); - iter++) { - string final_key = map_name + *iter; - deleteMemcache(final_key.c_str(), 0); - } - - deleteMemcache(map_name.c_str(), 0); - } - -} - -extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) { - // Register this SS type - XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory); - return 0; -} - -extern "C" void MCEXT_EXPORTS xmltooling_extension_term() { - XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE"); -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * memcache-store.cpp + * + * Storage Service using memcache (pre memcache tags) + */ + +#if defined (_MSC_VER) || defined(__BORLANDC__) +# include "config_win32.h" +#else +# include "config.h" +#endif + +#ifdef WIN32 +# define _CRT_NONSTDC_NO_DEPRECATE 1 +# define _CRT_SECURE_NO_DEPRECATE 1 +# define MCEXT_EXPORTS __declspec(dllexport) +#else +# define MCEXT_EXPORTS +#endif + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace xercesc; +using namespace std; + +namespace xmltooling { + static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s); + static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x); + static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p); + static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t); + static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t); + static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t); + static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t); + static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t); + + class mc_record { + public: + string value; + time_t expiration; + mc_record(){}; + mc_record(string _v, time_t _e) : + value(_v), expiration(_e) + {} + }; + + class MemcacheBase { + public: + MemcacheBase(const DOMElement* e); + ~MemcacheBase(); + + bool addMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix = true); + bool setMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix = true); + bool replaceMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix = true); + bool getMemcache(const char *key, + string &dest, + uint32_t *flags, + bool use_prefix = true); + bool deleteMemcache(const char *key, + time_t timeout, + bool use_prefix = true); + + void serialize(mc_record &source, string &dest); + void serialize(list &source, string &dest); + void deserialize(string &source, mc_record &dest); + void deserialize(string &source, list &dest); + + bool addSessionToUser(string &key, string &user); + bool addLock(string what, bool use_prefix = true); + void deleteLock(string what, bool use_prefix = true); + + protected: + const DOMElement* m_root; // can only use this during initialization + Category& log; + memcached_st *memc; + string m_prefix; + Mutex* m_lock; + }; + + class MemcacheStorageService : public StorageService, public MemcacheBase { + + public: + MemcacheStorageService(const DOMElement* e); + ~MemcacheStorageService(); + + bool createString(const char* context, const char* key, const char* value, time_t expiration); + int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0); + int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0); + bool deleteString(const char* context, const char* key); + + bool createText(const char* context, const char* key, const char* value, time_t expiration) { + return createString(context, key, value, expiration); + } + int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) { + return readString(context, key, pvalue, pexpiration, version); + } + int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) { + return updateString(context, key, value, expiration, version); + } + bool deleteText(const char* context, const char* key) { + return deleteString(context, key); + } + + void reap(const char* context) {} + + void updateContext(const char* context, time_t expiration); + void deleteContext(const char* context); + + private: + + Category& m_log; + bool m_buildMap; + + + }; + + StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) { + return new MemcacheStorageService(e); + } + +}; + +bool MemcacheBase::addLock(string what, bool use_prefix) { + string lock_name = what + ":LOCK"; + string set_val = "1"; + unsigned tries = 5; + while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) { + if (tries-- == 0) { + log.debug("Unable to get lock %s... FAILED.", lock_name.c_str()); + return false; + } + log.debug("Unable to get lock %s... Retrying.", lock_name.c_str()); + + // sleep 100ms +#ifdef WIN32 + Sleep(100); +#else + struct timeval tv = { 0, 100000 }; + select(0, 0, 0, 0, &tv); +#endif + } + return true; +} + +void MemcacheBase::deleteLock(string what, bool use_prefix) { + + string lock_name = what + ":LOCK"; + deleteMemcache(lock_name.c_str(), 0, use_prefix); + return; + +} + +void MemcacheBase::deserialize(string &source, mc_record &dest) { + istringstream is(source, stringstream::in | stringstream::out); + is >> dest.expiration; + is.ignore(1); // ignore delimiter + dest.value = is.str().c_str() + is.tellg(); +} + +void MemcacheBase::deserialize(string &source, list &dest) { + istringstream is(source, stringstream::in | stringstream::out); + while (!is.eof()) { + string s; + is >> s; + dest.push_back(s); + } +} + +void MemcacheBase::serialize(mc_record &source, string &dest) { + ostringstream os(stringstream::in | stringstream::out); + os << source.expiration; + os << "-"; // delimiter + os << source.value; + dest = os.str(); +} + +void MemcacheBase::serialize(list &source, string &dest) { + ostringstream os(stringstream::in | stringstream::out); + for(list::iterator iter = source.begin(); iter != source.end(); iter++) { + if (iter != source.begin()) { + os << endl; + } + os << *iter; + } + dest = os.str(); +} + +bool MemcacheBase::addSessionToUser(string &key, string &user) { + + if (! addLock(user, false)) { + return false; + } + + // Aquired lock + + string sessid = m_prefix + key; // add specific prefix to session + string delimiter = ";"; + string user_key = "UDATA:"; + user_key += user; + string user_val; + uint32_t flags; + bool result = getMemcache(user_key.c_str(), user_val, &flags, false); + + if (result) { + bool already_there = false; + // skip delimiters at beginning. + string::size_type lastPos = user_val.find_first_not_of(delimiter, 0); + + // find first "non-delimiter". + string::size_type pos = user_val.find_first_of(delimiter, lastPos); + + while (string::npos != pos || string::npos != lastPos) { + // found a token, add it to the vector. + string session = user_val.substr(lastPos, pos - lastPos); + if (strcmp(session.c_str(), sessid.c_str()) == 0) { + already_there = true; + break; + } + + // skip delimiters. Note the "not_of" + lastPos = user_val.find_first_not_of(delimiter, pos); + + // find next "non-delimiter" + pos = user_val.find_first_of(delimiter, lastPos); + } + + if (!already_there) { + user_val += delimiter + sessid; + replaceMemcache(user_key.c_str(), user_val, 0, 0, false); + } + } else { + addMemcache(user_key.c_str(), sessid, 0, 0, false); + } + + deleteLock(user, false); + return true; + +} + +bool MemcacheBase::deleteMemcache(const char *key, + time_t timeout, + bool use_prefix) { + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_NOTFOUND) { + // Key wasn't there... No biggie. + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::getMemcache(const char *key, + string &dest, + uint32_t *flags, + bool use_prefix) { + memcached_return rv; + size_t len; + char *result; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + dest = result; + free(result); + success = true; + } else if (rv == MEMCACHED_NOTFOUND) { + log.debug("Key %s not found in memcache...", key); + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::addMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix) { + + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_NOTSTORED) { + // already there + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::setMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix) { + + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +bool MemcacheBase::replaceMemcache(const char *key, + string &value, + time_t timeout, + uint32_t flags, + bool use_prefix) { + + memcached_return rv; + string final_key; + bool success; + + if (use_prefix) { + final_key = m_prefix + key; + } else { + final_key = key; + } + + m_lock->lock(); + rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags); + m_lock->unlock(); + + if (rv == MEMCACHED_SUCCESS) { + success = true; + } else if (rv == MEMCACHED_NOTSTORED) { + // not there + success = false; + } else if (rv == MEMCACHED_ERRNO) { + // System error + string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)); + log.error(error); + throw IOException(error); + } else { + string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv); + log.error(error); + throw IOException(error); + } + + return success; +} + +MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") { + + auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL); + if (p.get() && *p.get()) { + log.debug("INIT: GOT key prefix: %s", p.get()); + m_prefix = p.get(); + } + + m_lock = Mutex::create(); + log.debug("Lock created"); + + memc = memcached_create(NULL); + if (memc == NULL) { + throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed"); + } + + log.debug("Memcache created"); + + unsigned int hash = MEMCACHED_HASH_CRC; + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash); + log.debug("CRC hash set"); + + int32_t send_timeout = 1000000; + const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL; + if (tag && *tag) { + send_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout); + + int32_t recv_timeout = 1000000; + tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL; + if (tag && *tag) { + recv_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout); + + int32_t poll_timeout = 1000; + tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL; + if (tag && *tag) { + poll_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout); + + int32_t fail_limit = 5; + tag = e ? e->getAttributeNS(NULL, failLimit) : NULL; + if (tag && *tag) { + fail_limit = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit); + + int32_t retry_timeout = 30; + tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL; + if (tag && *tag) { + retry_timeout = XMLString::parseInt(tag); + } + log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout); + + // Grab hosts from the configuration. + e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL; + if (!e || !e->hasChildNodes()) { + throw XMLToolingException("Memcache StorageService requires Hosts element in configuration."); + } + auto_ptr_char h(e->getFirstChild()->getNodeValue()); + log.debug("INIT: GOT Hosts: %s", h.get()); + memcached_server_st *servers; + servers = memcached_servers_parse(const_cast(h.get())); + log.debug("Got %u hosts.", memcached_server_list_count(servers)); + if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) { + throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed"); + } + memcached_server_list_free(servers); + + log.debug("Memcache object initialized"); +} + +MemcacheBase::~MemcacheBase() { + memcached_free(memc); + delete m_lock; + log.debug("Base object destroyed"); +} + +MemcacheStorageService::MemcacheStorageService(const DOMElement* e) + : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) { + + const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL; + if (tag && *tag && XMLString::parseInt(tag) != 0) { + m_buildMap = true; + m_log.debug("Cache built with buildMap ON"); + } + +} + +MemcacheStorageService::~MemcacheStorageService() { + + +} + +bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) { + + log.debug("createString ctx: %s - key: %s", context, key); + + string final_key = string(context) + ":" + string(key); + + mc_record rec(value, expiration); + string final_value; + serialize(rec, final_value); + + bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version + + if (result && m_buildMap) { + log.debug("Got result, updating map"); + + string map_name = context; + // we need to update the context map + if (! addLock(map_name)) { + log.error("Unable to get lock for context %s!", context); + deleteMemcache(final_key.c_str(), 0); + return false; + } + + string ser_arr; + uint32_t flags; + bool result = getMemcache(map_name.c_str(), ser_arr, &flags); + + list contents; + if (result) { + log.debug("Match found. Parsing..."); + + deserialize(ser_arr, contents); + + log.debug("Iterating retrieved session map..."); + list::iterator iter; + for(iter = contents.begin(); + iter != contents.end(); + iter++) { + log.debug("value = " + *iter); + } + + } else { + log.debug("New context: %s", map_name.c_str()); + + } + + contents.push_back(key); + serialize(contents, ser_arr); + setMemcache(map_name.c_str(), ser_arr, expiration, 0); + + deleteLock(map_name); + } + + return result; + +} + +int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) { + + log.debug("readString ctx: %s - key: %s", context, key); + + string final_key = string(context) + ":" + string(key); + uint32_t rec_version; + string value; + + if (m_buildMap) { + log.debug("Checking context"); + + string map_name = context; + string ser_arr; + uint32_t flags; + bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags); + + if (!ctx_found) { + return 0; + } + } + + bool found = getMemcache(final_key.c_str(), value, &rec_version); + if (!found) { + return 0; + } + + if (version && rec_version <= (uint32_t)version) { + return version; + } + + if (pexpiration || pvalue) { + mc_record rec; + deserialize(value, rec); + + if (pexpiration) { + *pexpiration = rec.expiration; + } + + if (pvalue) { + *pvalue = rec.value; + } + } + + return rec_version; + +} + +int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) { + + log.debug("updateString ctx: %s - key: %s", context, key); + + time_t final_exp = expiration; + time_t *want_expiration = NULL; + if (! final_exp) { + want_expiration = &final_exp; + } + + int read_res = readString(context, key, NULL, want_expiration, version); + + if (!read_res) { + // not found + return read_res; + } + + if (version && version != read_res) { + // version incorrect + return -1; + } + + // Proceding with update + string final_key = string(context) + ":" + string(key); + mc_record rec(value, final_exp); + string final_value; + serialize(rec, final_value); + + replaceMemcache(final_key.c_str(), final_value, final_exp, ++version); + return version; + +} + +bool MemcacheStorageService::deleteString(const char* context, const char* key) { + + log.debug("deleteString ctx: %s - key: %s", context, key); + + string final_key = string(context) + ":" + string(key); + + // Not updating context map, if there is one. There is no need. + + return deleteMemcache(final_key.c_str(), 0); + +} + +void MemcacheStorageService::updateContext(const char* context, time_t expiration) { + + log.debug("updateContext ctx: %s", context); + + if (!m_buildMap) { + log.error("updateContext invoked on a Storage with no context map built!"); + return; + } + + string map_name = context; + string ser_arr; + uint32_t flags; + bool result = getMemcache(map_name.c_str(), ser_arr, &flags); + + list contents; + if (result) { + log.debug("Match found. Parsing..."); + + deserialize(ser_arr, contents); + + log.debug("Iterating retrieved session map..."); + list::iterator iter; + for(iter = contents.begin(); + iter != contents.end(); + iter++) { + + // Update expiration times + string value; + int read_res = readString(context, iter->c_str(), &value, NULL, 0); + + if (!read_res) { + // not found + continue; + } + + updateString(context, iter->c_str(), value.c_str(), expiration, read_res); + } + replaceMemcache(map_name.c_str(), ser_arr, expiration, flags); + } + +} + +void MemcacheStorageService::deleteContext(const char* context) { + + log.debug("deleteContext ctx: %s", context); + + if (!m_buildMap) { + log.error("deleteContext invoked on a Storage with no context map built!"); + return; + } + + string map_name = context; + string ser_arr; + uint32_t flags; + bool result = getMemcache(map_name.c_str(), ser_arr, &flags); + + list contents; + if (result) { + log.debug("Match found. Parsing..."); + + deserialize(ser_arr, contents); + + log.debug("Iterating retrieved session map..."); + list::iterator iter; + for(iter = contents.begin(); + iter != contents.end(); + iter++) { + string final_key = map_name + *iter; + deleteMemcache(final_key.c_str(), 0); + } + + deleteMemcache(map_name.c_str(), 0); + } + +} + +extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) { + // Register this SS type + XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory); + return 0; +} + +extern "C" void MCEXT_EXPORTS xmltooling_extension_term() { + XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE"); +} diff --git a/memcache-store/resource.h b/memcache-store/resource.h index 42c4d44..bd4e56a 100644 --- a/memcache-store/resource.h +++ b/memcache-store/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by memcache-store.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by memcache-store.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/odbc-store/resource.h b/odbc-store/resource.h index 7a79a45..625d6ee 100644 --- a/odbc-store/resource.h +++ b/odbc-store/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by odbc-store.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by odbc-store.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/schemas/WS-Trust.xsd b/schemas/WS-Trust.xsd index 8c10883..d1e2a9f 100644 --- a/schemas/WS-Trust.xsd +++ b/schemas/WS-Trust.xsd @@ -1,113 +1,113 @@ - - - - - - - - - - - - - Actual content model is non-deterministic, hence wildcard. The following shows intended content model: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + Actual content model is non-deterministic, hence wildcard. The following shows intended content model: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schemas/shibboleth-2.0-afp.xsd b/schemas/shibboleth-2.0-afp.xsd index 675f41f..ded4423 100644 --- a/schemas/shibboleth-2.0-afp.xsd +++ b/schemas/shibboleth-2.0-afp.xsd @@ -4,10 +4,10 @@ xmlns="http://www.w3.org/2001/XMLSchema" xmlns:afp="urn:mace:shibboleth:2.0:afp" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" - elementFormDefault="qualified"> - - - + elementFormDefault="qualified"> + + + Schema for the attribute filter policies. @@ -51,7 +51,7 @@ Defines an attribute rule that may be reused across multiple filter policies. - + @@ -67,10 +67,10 @@ such as a federation site, should be signed. - - + + - + @@ -120,13 +120,13 @@ - - + + A rule that describes how values of an attribute will be filtered. - + @@ -158,7 +158,7 @@ - + @@ -202,4 +202,4 @@ - \ No newline at end of file + diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd index 99c9be6..24a051e 100644 --- a/schemas/shibboleth-2.0-native-sp-config.xsd +++ b/schemas/shibboleth-2.0-native-sp-config.xsd @@ -1,724 +1,724 @@ - - - - - - - - - - 2.0 schema for XML-based configuration of Shibboleth Native SP instances. - First appearing in Shibboleth 2.0 release. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Root of configuration - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + 2.0 schema for XML-based configuration of Shibboleth Native SP instances. + First appearing in Shibboleth 2.0 release. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Root of configuration + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - Container for extension libraries and custom configuration - - - - - - - - - - - - - - - - - - - - - References StorageService plugins - - - - - - - - - - - - - - - - - - References SessionCache plugins - - - - - - - - - - - - - - - - - - Ties ReplayCache to a custom StorageService - - - - - - - - - - Customizes an ArtifactMap - - - - - - - - - - - - Container for out-of-process (shibd) configuration - - - - - - - - - - - - - - - - Container for configuration of locally integrated or platform-specific - features (e.g. web server filters) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A simple example access policy language extension that supersedes Apache .htaccess - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Built-in request mapping syntax, decomposes URLs into Host/Path/Path/... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Container for default settings and application-specific overrides - - - - - - - - - - - - - - - - - - - - - - - - - - - - Container for application-specific overrides - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Container for specifying protocol handlers and session policy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Used to reference Policy elements from profile endpoints. - - - - - - Used to specify handlers that can issue AuthnRequests or perform discovery - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Used to specify handlers that can issue LogoutRequests - - - - - - - - - - - - - - - - - - - - - Container for error templates and associated details - - - - - - - - - - - - - - - - - - - - - - - Container for specifying settings to use with particular peers - - - - - - - - - - - - - Used to specify locations to receive application notifications - - - - - - - - - - - - - - - - - - - Container for specifying sets of policy rules to apply to incoming messages - - - - - - Specifies a set of SecurityPolicyRule plugins - - - - - - - - - - - - - - - - - - Implementation-specific option to pass to SOAPTransport provider. - - - - - - - - - - - - + + + + + + + Container for extension libraries and custom configuration + + + + + + + + + + + + + + + + + + + + + References StorageService plugins + + + + + + + + + + + + + + + + + + References SessionCache plugins + + + + + + + + + + + + + + + + + + Ties ReplayCache to a custom StorageService + + + + + + + + + + Customizes an ArtifactMap + + + + + + + + + + + + Container for out-of-process (shibd) configuration + + + + + + + + + + + + + + + + Container for configuration of locally integrated or platform-specific + features (e.g. web server filters) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A simple example access policy language extension that supersedes Apache .htaccess + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Built-in request mapping syntax, decomposes URLs into Host/Path/Path/... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Container for default settings and application-specific overrides + + + + + + + + + + + + + + + + + + + + + + + + + + + + Container for application-specific overrides + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Container for specifying protocol handlers and session policy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Used to reference Policy elements from profile endpoints. + + + + + + Used to specify handlers that can issue AuthnRequests or perform discovery + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Used to specify handlers that can issue LogoutRequests + + + + + + + + + + + + + + + + + + + + + Container for error templates and associated details + + + + + + + + + + + + + + + + + + + + + + + Container for specifying settings to use with particular peers + + + + + + + + + + + + + Used to specify locations to receive application notifications + + + + + + + + + + + + + + + + + + + Container for specifying sets of policy rules to apply to incoming messages + + + + + + Specifies a set of SecurityPolicyRule plugins + + + + + + + + + + + + + + + + + + Implementation-specific option to pass to SOAPTransport provider. + + + + + + + + + + + + diff --git a/shibd/shibd.cpp b/shibd/shibd.cpp index 4c86dae..2ac256d 100644 --- a/shibd/shibd.cpp +++ b/shibd/shibd.cpp @@ -1,403 +1,403 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shar.cpp -- the shibd "main" code. All the functionality is elsewhere - * - * Created By: Derek Atkins - * - * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $ - */ - - -// eventually we might be able to support autoconf via cygwin... -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#ifdef WIN32 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -# define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -#include - -#ifdef HAVE_UNISTD_H -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace std; - -bool shibd_shutdown = false; -const char* shar_config = NULL; -const char* shar_schemadir = NULL; -const char* shar_prefix = NULL; -bool shar_checkonly = false; -bool shar_version = false; -static bool unlink_socket = false; -const char* pidfile = NULL; - -#ifdef WIN32 - -//#include - -#define nNoMansLandSize 4 -typedef struct _CrtMemBlockHeader -{ - struct _CrtMemBlockHeader * pBlockHeaderNext; - struct _CrtMemBlockHeader * pBlockHeaderPrev; - char * szFileName; - int nLine; - size_t nDataSize; - int nBlockUse; - long lRequest; - unsigned char gap[nNoMansLandSize]; - /* followed by: - * unsigned char data[nDataSize]; - * unsigned char anotherGap[nNoMansLandSize]; - */ -} _CrtMemBlockHeader; - -/* -int MyAllocHook(int nAllocType, void *pvData, - size_t nSize, int nBlockUse, long lRequest, - const unsigned char * szFileName, int nLine) -{ - if ( nBlockUse == _CRT_BLOCK ) - return( TRUE ); - if (nAllocType == _HOOK_FREE) { - _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1); - if (ptr->nDataSize == 8192) - fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize); - } - else if (nAllocType == _HOOK_ALLOC && nSize == 8192) - fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize); - return (TRUE); -} -*/ - -int real_main(int preinit) -{ - SPConfig& conf=SPConfig::getConfig(); - if (preinit) { - - // Initialize the SP library. - conf.setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::Metadata | - SPConfig::Trust | - SPConfig::Credentials | - SPConfig::AttributeResolution | - SPConfig::Handlers | - SPConfig::OutOfProcess | - (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) - ); - if (!conf.init(shar_schemadir, shar_prefix)) { - fprintf(stderr, "configuration is invalid, see console for specific problems\n"); - return -1; - } - - if (!conf.instantiate(shar_config)) { - fprintf(stderr, "configuration is invalid, check console for specific problems\n"); - conf.term(); - return -2; - } - - // If just a test run, bail. - if (shar_checkonly) { - fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n"); - return 0; - } - } - else { - - //_CrtSetAllocHook(MyAllocHook); - - if (!shar_checkonly) { - // Run the listener. - ListenerService* listener = conf.getServiceProvider()->getListenerService(); - if (!listener->init(unlink_socket)) { - fprintf(stderr, "listener failed to initialize\n"); - conf.term(); - return -3; - } - else if (!listener->run(&shibd_shutdown)) { - fprintf(stderr, "listener failed during service\n"); - listener->term(); - conf.term(); - return -3; - } - listener->term(); - } - - conf.term(); - } - return 0; -} - -#else - -int daemon_wait = 3; -bool shibd_running = false; -bool daemonize = true; - -static void term_handler(int arg) -{ - shibd_shutdown = true; -} - -static void run_handler(int arg) -{ - shibd_running = true; -} - -static void child_handler(int arg) -{ - // Terminate the parent's wait/sleep if the newly born daemon dies early. -} - -static int setup_signals(void) -{ - struct sigaction sa; - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = SIG_IGN; - sa.sa_flags = SA_RESTART; - - if (sigaction(SIGPIPE, &sa, NULL) < 0) { - return -1; - } - - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = term_handler; - sa.sa_flags = SA_RESTART; - - if (sigaction(SIGHUP, &sa, NULL) < 0) { - return -1; - } - if (sigaction(SIGINT, &sa, NULL) < 0) { - return -1; - } - if (sigaction(SIGQUIT, &sa, NULL) < 0) { - return -1; - } - if (sigaction(SIGTERM, &sa, NULL) < 0) { - return -1; - } - - if (daemonize) { - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = run_handler; - - if (sigaction(SIGUSR1, &sa, NULL) < 0) { - return -1; - } - - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = child_handler; - - if (sigaction(SIGCHLD, &sa, NULL) < 0) { - return -1; - } - } - - return 0; -} - -static void usage(char* whoami) -{ - fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami); - fprintf(stderr, " -d\tinstallation prefix to use.\n"); - fprintf(stderr, " -c\tconfig file to use.\n"); - fprintf(stderr, " -x\tXML schema catalogs to use.\n"); - fprintf(stderr, " -t\ttest configuration file for problems.\n"); - fprintf(stderr, " -f\tforce removal of listener socket.\n"); - fprintf(stderr, " -F\tstay in the foreground.\n"); - fprintf(stderr, " -p\tpid file to use.\n"); - fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n"); - fprintf(stderr, " -v\tprint software version.\n"); - fprintf(stderr, " -h\tprint this help message.\n"); - exit(1); -} - -static int parse_args(int argc, char* argv[]) -{ - int opt; - - while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) { - switch (opt) { - case 'd': - shar_prefix=optarg; - break; - case 'c': - shar_config=optarg; - break; - case 'x': - shar_schemadir=optarg; - break; - case 'f': - unlink_socket = true; - break; - case 'F': - daemonize = false; - break; - case 't': - shar_checkonly=true; - daemonize=false; - break; - case 'v': - shar_version=true; - break; - case 'p': - pidfile=optarg; - break; - case 'w': - if (optarg) - daemon_wait = atoi(optarg); - if (daemon_wait <= 0) - daemon_wait = 3; - break; - default: - return -1; - } - } - return 0; -} - -int main(int argc, char *argv[]) -{ - if (parse_args(argc, argv) != 0) - usage(argv[0]); - else if (shar_version) { - fprintf(stdout, PACKAGE_STRING"\n"); - return 0; - } - - if (setup_signals() != 0) - return -1; - - // initialize the shib-target library - SPConfig& conf=SPConfig::getConfig(); - conf.setFeatures( - SPConfig::Listener | - SPConfig::Caching | - SPConfig::Metadata | - SPConfig::Trust | - SPConfig::Credentials | - SPConfig::AttributeResolution | - SPConfig::Handlers | - SPConfig::OutOfProcess | - (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) - ); - if (!conf.init(shar_schemadir, shar_prefix)) { - fprintf(stderr, "configuration is invalid, check console for specific problems\n"); - return -1; - } - - if (daemonize) { - // We must fork() early, while we're single threaded. - // StorageService cleanup thread is about to start. - switch (fork()) { - case 0: - break; - case -1: - perror("forking"); - exit(EXIT_FAILURE); - default: - sleep(daemon_wait); - exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE); - } - } - - if (!conf.instantiate(shar_config)) { - fprintf(stderr, "configuration is invalid, check console for specific problems\n"); - conf.term(); - return -2; - } - - if (shar_checkonly) - fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n"); - else { - // Init the listener. - ListenerService* listener = conf.getServiceProvider()->getListenerService(); - if (!listener->init(unlink_socket)) { - fprintf(stderr, "listener failed to initialize\n"); - conf.term(); - return -3; - } - - if (daemonize) { - if (setsid() == -1) { - perror("setsid"); - exit(EXIT_FAILURE); - } - if (chdir("/") == -1) { - perror("chdir to root"); - exit(EXIT_FAILURE); - } - - if (pidfile) { - FILE* pidf = fopen(pidfile, "w"); - if (pidf) { - fprintf(pidf, "%d\n", getpid()); - fclose(pidf); - } - else { - perror(pidfile); - } - } - - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); - - // Signal our parent that we are A-OK. - kill(getppid(), SIGUSR1); - } - - // Run the listener. - if (!listener->run(&shibd_shutdown)) { - fprintf(stderr, "listener failure during service\n"); - listener->term(); - conf.term(); - if (pidfile) - unlink(pidfile); - return -3; - } - listener->term(); - } - - conf.term(); - if (pidfile) - unlink(pidfile); - return 0; -} - -#endif +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * shar.cpp -- the shibd "main" code. All the functionality is elsewhere + * + * Created By: Derek Atkins + * + * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $ + */ + + +// eventually we might be able to support autoconf via cygwin... +#if defined (_MSC_VER) || defined(__BORLANDC__) +# include "config_win32.h" +#else +# include "config.h" +#endif + +#ifdef WIN32 +# define _CRT_NONSTDC_NO_DEPRECATE 1 +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include + +#ifdef HAVE_UNISTD_H +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +bool shibd_shutdown = false; +const char* shar_config = NULL; +const char* shar_schemadir = NULL; +const char* shar_prefix = NULL; +bool shar_checkonly = false; +bool shar_version = false; +static bool unlink_socket = false; +const char* pidfile = NULL; + +#ifdef WIN32 + +//#include + +#define nNoMansLandSize 4 +typedef struct _CrtMemBlockHeader +{ + struct _CrtMemBlockHeader * pBlockHeaderNext; + struct _CrtMemBlockHeader * pBlockHeaderPrev; + char * szFileName; + int nLine; + size_t nDataSize; + int nBlockUse; + long lRequest; + unsigned char gap[nNoMansLandSize]; + /* followed by: + * unsigned char data[nDataSize]; + * unsigned char anotherGap[nNoMansLandSize]; + */ +} _CrtMemBlockHeader; + +/* +int MyAllocHook(int nAllocType, void *pvData, + size_t nSize, int nBlockUse, long lRequest, + const unsigned char * szFileName, int nLine) +{ + if ( nBlockUse == _CRT_BLOCK ) + return( TRUE ); + if (nAllocType == _HOOK_FREE) { + _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1); + if (ptr->nDataSize == 8192) + fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize); + } + else if (nAllocType == _HOOK_ALLOC && nSize == 8192) + fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize); + return (TRUE); +} +*/ + +int real_main(int preinit) +{ + SPConfig& conf=SPConfig::getConfig(); + if (preinit) { + + // Initialize the SP library. + conf.setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::Metadata | + SPConfig::Trust | + SPConfig::Credentials | + SPConfig::AttributeResolution | + SPConfig::Handlers | + SPConfig::OutOfProcess | + (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) + ); + if (!conf.init(shar_schemadir, shar_prefix)) { + fprintf(stderr, "configuration is invalid, see console for specific problems\n"); + return -1; + } + + if (!conf.instantiate(shar_config)) { + fprintf(stderr, "configuration is invalid, check console for specific problems\n"); + conf.term(); + return -2; + } + + // If just a test run, bail. + if (shar_checkonly) { + fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n"); + return 0; + } + } + else { + + //_CrtSetAllocHook(MyAllocHook); + + if (!shar_checkonly) { + // Run the listener. + ListenerService* listener = conf.getServiceProvider()->getListenerService(); + if (!listener->init(unlink_socket)) { + fprintf(stderr, "listener failed to initialize\n"); + conf.term(); + return -3; + } + else if (!listener->run(&shibd_shutdown)) { + fprintf(stderr, "listener failed during service\n"); + listener->term(); + conf.term(); + return -3; + } + listener->term(); + } + + conf.term(); + } + return 0; +} + +#else + +int daemon_wait = 3; +bool shibd_running = false; +bool daemonize = true; + +static void term_handler(int arg) +{ + shibd_shutdown = true; +} + +static void run_handler(int arg) +{ + shibd_running = true; +} + +static void child_handler(int arg) +{ + // Terminate the parent's wait/sleep if the newly born daemon dies early. +} + +static int setup_signals(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_IGN; + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGPIPE, &sa, NULL) < 0) { + return -1; + } + + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = term_handler; + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGHUP, &sa, NULL) < 0) { + return -1; + } + if (sigaction(SIGINT, &sa, NULL) < 0) { + return -1; + } + if (sigaction(SIGQUIT, &sa, NULL) < 0) { + return -1; + } + if (sigaction(SIGTERM, &sa, NULL) < 0) { + return -1; + } + + if (daemonize) { + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = run_handler; + + if (sigaction(SIGUSR1, &sa, NULL) < 0) { + return -1; + } + + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = child_handler; + + if (sigaction(SIGCHLD, &sa, NULL) < 0) { + return -1; + } + } + + return 0; +} + +static void usage(char* whoami) +{ + fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami); + fprintf(stderr, " -d\tinstallation prefix to use.\n"); + fprintf(stderr, " -c\tconfig file to use.\n"); + fprintf(stderr, " -x\tXML schema catalogs to use.\n"); + fprintf(stderr, " -t\ttest configuration file for problems.\n"); + fprintf(stderr, " -f\tforce removal of listener socket.\n"); + fprintf(stderr, " -F\tstay in the foreground.\n"); + fprintf(stderr, " -p\tpid file to use.\n"); + fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n"); + fprintf(stderr, " -v\tprint software version.\n"); + fprintf(stderr, " -h\tprint this help message.\n"); + exit(1); +} + +static int parse_args(int argc, char* argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) { + switch (opt) { + case 'd': + shar_prefix=optarg; + break; + case 'c': + shar_config=optarg; + break; + case 'x': + shar_schemadir=optarg; + break; + case 'f': + unlink_socket = true; + break; + case 'F': + daemonize = false; + break; + case 't': + shar_checkonly=true; + daemonize=false; + break; + case 'v': + shar_version=true; + break; + case 'p': + pidfile=optarg; + break; + case 'w': + if (optarg) + daemon_wait = atoi(optarg); + if (daemon_wait <= 0) + daemon_wait = 3; + break; + default: + return -1; + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + if (parse_args(argc, argv) != 0) + usage(argv[0]); + else if (shar_version) { + fprintf(stdout, PACKAGE_STRING"\n"); + return 0; + } + + if (setup_signals() != 0) + return -1; + + // initialize the shib-target library + SPConfig& conf=SPConfig::getConfig(); + conf.setFeatures( + SPConfig::Listener | + SPConfig::Caching | + SPConfig::Metadata | + SPConfig::Trust | + SPConfig::Credentials | + SPConfig::AttributeResolution | + SPConfig::Handlers | + SPConfig::OutOfProcess | + (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging) + ); + if (!conf.init(shar_schemadir, shar_prefix)) { + fprintf(stderr, "configuration is invalid, check console for specific problems\n"); + return -1; + } + + if (daemonize) { + // We must fork() early, while we're single threaded. + // StorageService cleanup thread is about to start. + switch (fork()) { + case 0: + break; + case -1: + perror("forking"); + exit(EXIT_FAILURE); + default: + sleep(daemon_wait); + exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE); + } + } + + if (!conf.instantiate(shar_config)) { + fprintf(stderr, "configuration is invalid, check console for specific problems\n"); + conf.term(); + return -2; + } + + if (shar_checkonly) + fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n"); + else { + // Init the listener. + ListenerService* listener = conf.getServiceProvider()->getListenerService(); + if (!listener->init(unlink_socket)) { + fprintf(stderr, "listener failed to initialize\n"); + conf.term(); + return -3; + } + + if (daemonize) { + if (setsid() == -1) { + perror("setsid"); + exit(EXIT_FAILURE); + } + if (chdir("/") == -1) { + perror("chdir to root"); + exit(EXIT_FAILURE); + } + + if (pidfile) { + FILE* pidf = fopen(pidfile, "w"); + if (pidf) { + fprintf(pidf, "%d\n", getpid()); + fclose(pidf); + } + else { + perror(pidfile); + } + } + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); + + // Signal our parent that we are A-OK. + kill(getppid(), SIGUSR1); + } + + // Run the listener. + if (!listener->run(&shibd_shutdown)) { + fprintf(stderr, "listener failure during service\n"); + listener->term(); + conf.term(); + if (pidfile) + unlink(pidfile); + return -3; + } + listener->term(); + } + + conf.term(); + if (pidfile) + unlink(pidfile); + return 0; +} + +#endif diff --git a/shibd/shibd_win32.cpp b/shibd/shibd_win32.cpp index b196ea8..7a9a602 100644 --- a/shibd/shibd_win32.cpp +++ b/shibd/shibd_win32.cpp @@ -1,529 +1,529 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shar_win32.cpp -- the SHAR "main" code on Win32 - * - * Created By: Scott Cantor (cantor.2@osu.edu) - * - * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $ - */ - -#include "config_win32.h" - -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#define _CRT_SECURE_NO_DEPRECATE 1 - -#include -#include -#include - -using namespace std; - -extern bool shibd_shutdown; // signals shutdown to Unix side -extern const char* shar_schemadir; -extern const char* shar_config; -extern const char* shar_prefix; -extern bool shar_checkonly; - -// internal variables -SERVICE_STATUS ssStatus; // current status of the service -SERVICE_STATUS_HANDLE sshStatusHandle; -DWORD dwErr = 0; -BOOL bConsole = FALSE; -char szErr[256]; -LPCSTR lpszInstall = NULL; -LPCSTR lpszRemove = NULL; - -// internal function prototypes -VOID WINAPI service_ctrl(DWORD dwCtrlCode); -VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv); -VOID CmdInstallService(LPCSTR); -VOID CmdRemoveService(LPCSTR); -LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ); - -BOOL LogEvent( - LPCTSTR lpUNCServerName, - WORD wType, - DWORD dwEventID, - PSID lpUserSid, - LPCTSTR message); - -VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv); -VOID ServiceStop(); -BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); -void AddToMessageLog(LPSTR lpszMsg); - -BOOL WINAPI BreakHandler(DWORD dwCtrlType) -{ - switch(dwCtrlType) - { - case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate - case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode - ServiceStop(); - return TRUE; - } - return FALSE; -} - - -int real_main(int); // The revised two-phase main() in shar.cpp - -int main(int argc, char *argv[]) -{ - int i=1; - while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/'))) - { - if (_stricmp("install", argv[i]+1) == 0) - { - if (argc > ++i) - lpszInstall = argv[i++]; - } - else if (_stricmp("remove", argv[i]+1) == 0) - { - if (argc > ++i) - lpszRemove = argv[i++]; - } - else if (_stricmp( "console", argv[i]+1) == 0) - { - i++; - bConsole = TRUE; - } - else if (_stricmp( "check", argv[i]+1) == 0) - { - i++; - bConsole = TRUE; - shar_checkonly=true; - } - else if (_stricmp( "config", argv[i]+1) == 0) - { - if (argc > ++i) - shar_config = argv[i++]; - } - else if (_stricmp( "prefix", argv[i]+1) == 0) - { - if (argc > ++i) - shar_prefix = argv[i++]; - } - else if (_stricmp( "catalogs", argv[i]+1) == 0) - { - if (argc > ++i) - shar_schemadir = argv[i++]; - } - else - { - goto dispatch; - } - } - - if (bConsole) - { - // Install break handler, then run the C routine twice, once to setup, once to start running. - SetConsoleCtrlHandler(&BreakHandler,TRUE); - if ((i=real_main(1))!=0) - { - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); - return i; - } - return real_main(0); - } - else if (lpszInstall) - { - CmdInstallService(lpszInstall); - return 0; - } - else if (lpszRemove) - { - CmdRemoveService(lpszRemove); - return 0; - } - - - // if it doesn't match any of the above parameters - // the service control manager may be starting the service - // so we must call StartServiceCtrlDispatcher - dispatch: - // this is just to be friendly - printf("%s -install to install the named service\n", argv[0]); - printf("%s -remove to remove the named service\n", argv[0]); - printf("%s -console to run as a console app for debugging\n", argv[0]); - printf("%s -check to run as a console app and check configuration\n", argv[0]); - printf("\t-prefix to specify the installation directory\n"); - printf("\t-config to specify the config file to use\n"); - printf("\t-catalogs to specify schema catalogs\n"); - printf("\nService starting.\nThis may take several seconds. Please wait.\n" ); - - SERVICE_TABLE_ENTRY dispatchTable[] = - { - { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main }, - { NULL, NULL } - }; - - if (!StartServiceCtrlDispatcher(dispatchTable)) - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed."); - return 0; -} - -// -// FUNCTION: ServiceStart -// -// PURPOSE: Actual code of the service -// that does the work. -// -VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv) -{ - - if (real_main(1)!=0) - { - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); - return; - } - - LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully."); - - if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0)) - return; - - real_main(0); -} - - -// -// FUNCTION: ServiceStop -// -// PURPOSE: Stops the service -// -VOID ServiceStop() -{ - if (!bConsole) - LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping..."); - shibd_shutdown=true; -} - - -void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv) -{ - - // register our service control handler: - sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl); - if (!sshStatusHandle) - goto cleanup; - - // SERVICE_STATUS members that don't change in example - ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - ssStatus.dwServiceSpecificExitCode = 0; - - - // report the status to the service control manager. - if (!ReportStatusToSCMgr( - SERVICE_START_PENDING, // service state - NO_ERROR, // exit code - 3000)) // wait hint - goto cleanup; - - - ServiceStart(dwArgc, lpszArgv); - -cleanup: - - // try to report the stopped status to the service control manager. - // - if (sshStatusHandle) - (VOID)ReportStatusToSCMgr( - SERVICE_STOPPED, - dwErr, - 0); - - return; -} - - -// -// FUNCTION: service_ctrl -// -// PURPOSE: This function is called by the SCM whenever -// ControlService() is called on this service. -// -// PARAMETERS: -// dwCtrlCode - type of control requested -// -// RETURN VALUE: -// none -// -VOID WINAPI service_ctrl(DWORD dwCtrlCode) -{ - // Handle the requested control code. - // - switch(dwCtrlCode) - { - // Stop the service. - // - case SERVICE_CONTROL_STOP: - ssStatus.dwCurrentState = SERVICE_STOP_PENDING; - ServiceStop(); - break; - - // Update the service status. - // - case SERVICE_CONTROL_INTERROGATE: - break; - - // invalid control code - // - default: - break; - - } - - ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); -} - - -// -// FUNCTION: ReportStatusToSCMgr() -// -// PURPOSE: Sets the current status of the service and -// reports it to the Service Control Manager -// -// PARAMETERS: -// dwCurrentState - the state of the service -// dwWin32ExitCode - error code to report -// dwWaitHint - worst case estimate to next checkpoint -// -// RETURN VALUE: -// TRUE - success -// FALSE - failure -// -BOOL ReportStatusToSCMgr(DWORD dwCurrentState, - DWORD dwWin32ExitCode, - DWORD dwWaitHint) -{ - static DWORD dwCheckPoint = 1; - BOOL fResult = TRUE; - - - if (!bConsole) // when console we don't report to the SCM - { - if (dwCurrentState == SERVICE_START_PENDING) - ssStatus.dwControlsAccepted = 0; - else - ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - - ssStatus.dwCurrentState = dwCurrentState; - ssStatus.dwWin32ExitCode = dwWin32ExitCode; - ssStatus.dwWaitHint = dwWaitHint; - - if ( ( dwCurrentState == SERVICE_RUNNING ) || - ( dwCurrentState == SERVICE_STOPPED ) ) - ssStatus.dwCheckPoint = 0; - else - ssStatus.dwCheckPoint = dwCheckPoint++; - - - // Report the status of the service to the service control manager. - // - if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) - LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed."); - } - return fResult; -} - - -/////////////////////////////////////////////////////////////////// -// -// The following code handles service installation and removal -// -// -void CmdInstallService(LPCSTR name) -{ - SC_HANDLE schService; - SC_HANDLE schSCManager; - - char szPath[256]; - - if ( GetModuleFileName( NULL, szPath, 256 ) == 0 ) - { - printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256)); - return; - } - - string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")"; - string realName = string("shibd_") + name; - string cmd(szPath); - if (shar_prefix) - cmd = cmd + " -prefix " + shar_prefix; - if (shar_config) - cmd = cmd + " -config " + shar_config; - if (shar_schemadir) - cmd = cmd + " -schemadir " + shar_schemadir; - - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) - SC_MANAGER_ALL_ACCESS // access required - ); - - - if ( schSCManager ) - { - schService = CreateService( - schSCManager, // SCManager database - realName.c_str(), // name of service - dispName.c_str(), // name to display - SERVICE_ALL_ACCESS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type - SERVICE_AUTO_START, // start type - SERVICE_ERROR_NORMAL, // error control type - cmd.c_str(), // service's command line - NULL, // no load ordering group - NULL, // no tag identifier - NULL, // dependencies - NULL, // LocalSystem account - NULL); // no password - - if ( schService ) - { - printf("%s installed.\n", realName.c_str()); - CloseServiceHandle(schService); - } - else - { - printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256)); - } - - CloseServiceHandle(schSCManager); - } - else - printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); -} - -void CmdRemoveService(LPCSTR name) -{ - SC_HANDLE schService; - SC_HANDLE schSCManager; - char realName[512]; - - _snprintf(realName,sizeof(realName),"shibd_%s",name); - - schSCManager = OpenSCManager( - NULL, // machine (NULL == local) - NULL, // database (NULL == default) - SC_MANAGER_ALL_ACCESS // access required - ); - if ( schSCManager ) - { - schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS); - - if (schService) - { - // try to stop the service - if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) - { - printf("Stopping shibd (%s).", name); - Sleep( 1000 ); - - while( QueryServiceStatus( schService, &ssStatus ) ) - { - if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) - { - printf("."); - Sleep( 1000 ); - } - else - break; - } - - if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) - printf("\n%s stopped.\n", realName); - else - printf("\n%s failed to stop.\n", realName); - - } - - // now remove the service - if( DeleteService(schService) ) - printf("%s removed.\n", realName); - else - printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256)); - - - CloseServiceHandle(schService); - } - else - printf("OpenService failed - %s\n", GetLastErrorText(szErr,256)); - - CloseServiceHandle(schSCManager); - } - else - printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); -} - - -// -// FUNCTION: GetLastErrorText -// -// PURPOSE: copies error message text to string -// -// PARAMETERS: -// lpszBuf - destination buffer -// dwSize - size of buffer -// -// RETURN VALUE: -// destination buffer -// -// COMMENTS: -// -LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ) -{ - DWORD dwRet; - LPSTR lpszTemp = NULL; - - dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, - NULL, - GetLastError(), - LANG_NEUTRAL, - (LPSTR)&lpszTemp, - 0, - NULL ); - - // supplied buffer is not long enough - if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) - lpszBuf[0] = '\0'; - else - { - lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character - sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() ); - } - - if ( lpszTemp ) - LocalFree((HLOCAL) lpszTemp ); - - return lpszBuf; -} - -BOOL LogEvent( - LPCSTR lpUNCServerName, - WORD wType, - DWORD dwEventID, - PSID lpUserSid, - LPCSTR message) -{ - LPCSTR messages[] = {message, NULL}; - - HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon"); - BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL); - return (DeregisterEventSource(hElog) && res); -} +/* + * Copyright 2001-2007 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * shar_win32.cpp -- the SHAR "main" code on Win32 + * + * Created By: Scott Cantor (cantor.2@osu.edu) + * + * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $ + */ + +#include "config_win32.h" + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 + +#include +#include +#include + +using namespace std; + +extern bool shibd_shutdown; // signals shutdown to Unix side +extern const char* shar_schemadir; +extern const char* shar_config; +extern const char* shar_prefix; +extern bool shar_checkonly; + +// internal variables +SERVICE_STATUS ssStatus; // current status of the service +SERVICE_STATUS_HANDLE sshStatusHandle; +DWORD dwErr = 0; +BOOL bConsole = FALSE; +char szErr[256]; +LPCSTR lpszInstall = NULL; +LPCSTR lpszRemove = NULL; + +// internal function prototypes +VOID WINAPI service_ctrl(DWORD dwCtrlCode); +VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv); +VOID CmdInstallService(LPCSTR); +VOID CmdRemoveService(LPCSTR); +LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ); + +BOOL LogEvent( + LPCTSTR lpUNCServerName, + WORD wType, + DWORD dwEventID, + PSID lpUserSid, + LPCTSTR message); + +VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv); +VOID ServiceStop(); +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); +void AddToMessageLog(LPSTR lpszMsg); + +BOOL WINAPI BreakHandler(DWORD dwCtrlType) +{ + switch(dwCtrlType) + { + case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate + case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in console mode + ServiceStop(); + return TRUE; + } + return FALSE; +} + + +int real_main(int); // The revised two-phase main() in shar.cpp + +int main(int argc, char *argv[]) +{ + int i=1; + while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/'))) + { + if (_stricmp("install", argv[i]+1) == 0) + { + if (argc > ++i) + lpszInstall = argv[i++]; + } + else if (_stricmp("remove", argv[i]+1) == 0) + { + if (argc > ++i) + lpszRemove = argv[i++]; + } + else if (_stricmp( "console", argv[i]+1) == 0) + { + i++; + bConsole = TRUE; + } + else if (_stricmp( "check", argv[i]+1) == 0) + { + i++; + bConsole = TRUE; + shar_checkonly=true; + } + else if (_stricmp( "config", argv[i]+1) == 0) + { + if (argc > ++i) + shar_config = argv[i++]; + } + else if (_stricmp( "prefix", argv[i]+1) == 0) + { + if (argc > ++i) + shar_prefix = argv[i++]; + } + else if (_stricmp( "catalogs", argv[i]+1) == 0) + { + if (argc > ++i) + shar_schemadir = argv[i++]; + } + else + { + goto dispatch; + } + } + + if (bConsole) + { + // Install break handler, then run the C routine twice, once to setup, once to start running. + SetConsoleCtrlHandler(&BreakHandler,TRUE); + if ((i=real_main(1))!=0) + { + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); + return i; + } + return real_main(0); + } + else if (lpszInstall) + { + CmdInstallService(lpszInstall); + return 0; + } + else if (lpszRemove) + { + CmdRemoveService(lpszRemove); + return 0; + } + + + // if it doesn't match any of the above parameters + // the service control manager may be starting the service + // so we must call StartServiceCtrlDispatcher + dispatch: + // this is just to be friendly + printf("%s -install to install the named service\n", argv[0]); + printf("%s -remove to remove the named service\n", argv[0]); + printf("%s -console to run as a console app for debugging\n", argv[0]); + printf("%s -check to run as a console app and check configuration\n", argv[0]); + printf("\t-prefix to specify the installation directory\n"); + printf("\t-config to specify the config file to use\n"); + printf("\t-catalogs to specify schema catalogs\n"); + printf("\nService starting.\nThis may take several seconds. Please wait.\n" ); + + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main }, + { NULL, NULL } + }; + + if (!StartServiceCtrlDispatcher(dispatchTable)) + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed."); + return 0; +} + +// +// FUNCTION: ServiceStart +// +// PURPOSE: Actual code of the service +// that does the work. +// +VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv) +{ + + if (real_main(1)!=0) + { + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details"); + return; + } + + LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully."); + + if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0)) + return; + + real_main(0); +} + + +// +// FUNCTION: ServiceStop +// +// PURPOSE: Stops the service +// +VOID ServiceStop() +{ + if (!bConsole) + LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping..."); + shibd_shutdown=true; +} + + +void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv) +{ + + // register our service control handler: + sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl); + if (!sshStatusHandle) + goto cleanup; + + // SERVICE_STATUS members that don't change in example + ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ssStatus.dwServiceSpecificExitCode = 0; + + + // report the status to the service control manager. + if (!ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000)) // wait hint + goto cleanup; + + + ServiceStart(dwArgc, lpszArgv); + +cleanup: + + // try to report the stopped status to the service control manager. + // + if (sshStatusHandle) + (VOID)ReportStatusToSCMgr( + SERVICE_STOPPED, + dwErr, + 0); + + return; +} + + +// +// FUNCTION: service_ctrl +// +// PURPOSE: This function is called by the SCM whenever +// ControlService() is called on this service. +// +// PARAMETERS: +// dwCtrlCode - type of control requested +// +// RETURN VALUE: +// none +// +VOID WINAPI service_ctrl(DWORD dwCtrlCode) +{ + // Handle the requested control code. + // + switch(dwCtrlCode) + { + // Stop the service. + // + case SERVICE_CONTROL_STOP: + ssStatus.dwCurrentState = SERVICE_STOP_PENDING; + ServiceStop(); + break; + + // Update the service status. + // + case SERVICE_CONTROL_INTERROGATE: + break; + + // invalid control code + // + default: + break; + + } + + ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); +} + + +// +// FUNCTION: ReportStatusToSCMgr() +// +// PURPOSE: Sets the current status of the service and +// reports it to the Service Control Manager +// +// PARAMETERS: +// dwCurrentState - the state of the service +// dwWin32ExitCode - error code to report +// dwWaitHint - worst case estimate to next checkpoint +// +// RETURN VALUE: +// TRUE - success +// FALSE - failure +// +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, + DWORD dwWin32ExitCode, + DWORD dwWaitHint) +{ + static DWORD dwCheckPoint = 1; + BOOL fResult = TRUE; + + + if (!bConsole) // when console we don't report to the SCM + { + if (dwCurrentState == SERVICE_START_PENDING) + ssStatus.dwControlsAccepted = 0; + else + ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + ssStatus.dwCurrentState = dwCurrentState; + ssStatus.dwWin32ExitCode = dwWin32ExitCode; + ssStatus.dwWaitHint = dwWaitHint; + + if ( ( dwCurrentState == SERVICE_RUNNING ) || + ( dwCurrentState == SERVICE_STOPPED ) ) + ssStatus.dwCheckPoint = 0; + else + ssStatus.dwCheckPoint = dwCheckPoint++; + + + // Report the status of the service to the service control manager. + // + if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) + LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed."); + } + return fResult; +} + + +/////////////////////////////////////////////////////////////////// +// +// The following code handles service installation and removal +// +// +void CmdInstallService(LPCSTR name) +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + char szPath[256]; + + if ( GetModuleFileName( NULL, szPath, 256 ) == 0 ) + { + printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256)); + return; + } + + string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")"; + string realName = string("shibd_") + name; + string cmd(szPath); + if (shar_prefix) + cmd = cmd + " -prefix " + shar_prefix; + if (shar_config) + cmd = cmd + " -config " + shar_config; + if (shar_schemadir) + cmd = cmd + " -schemadir " + shar_schemadir; + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + + + if ( schSCManager ) + { + schService = CreateService( + schSCManager, // SCManager database + realName.c_str(), // name of service + dispName.c_str(), // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_WIN32_OWN_PROCESS, // service type + SERVICE_AUTO_START, // start type + SERVICE_ERROR_NORMAL, // error control type + cmd.c_str(), // service's command line + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // dependencies + NULL, // LocalSystem account + NULL); // no password + + if ( schService ) + { + printf("%s installed.\n", realName.c_str()); + CloseServiceHandle(schService); + } + else + { + printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256)); + } + + CloseServiceHandle(schSCManager); + } + else + printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); +} + +void CmdRemoveService(LPCSTR name) +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + char realName[512]; + + _snprintf(realName,sizeof(realName),"shibd_%s",name); + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + if ( schSCManager ) + { + schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS); + + if (schService) + { + // try to stop the service + if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) + { + printf("Stopping shibd (%s).", name); + Sleep( 1000 ); + + while( QueryServiceStatus( schService, &ssStatus ) ) + { + if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) + { + printf("."); + Sleep( 1000 ); + } + else + break; + } + + if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) + printf("\n%s stopped.\n", realName); + else + printf("\n%s failed to stop.\n", realName); + + } + + // now remove the service + if( DeleteService(schService) ) + printf("%s removed.\n", realName); + else + printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256)); + + + CloseServiceHandle(schService); + } + else + printf("OpenService failed - %s\n", GetLastErrorText(szErr,256)); + + CloseServiceHandle(schSCManager); + } + else + printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256)); +} + + +// +// FUNCTION: GetLastErrorText +// +// PURPOSE: copies error message text to string +// +// PARAMETERS: +// lpszBuf - destination buffer +// dwSize - size of buffer +// +// RETURN VALUE: +// destination buffer +// +// COMMENTS: +// +LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize ) +{ + DWORD dwRet; + LPSTR lpszTemp = NULL; + + dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, + GetLastError(), + LANG_NEUTRAL, + (LPSTR)&lpszTemp, + 0, + NULL ); + + // supplied buffer is not long enough + if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) ) + lpszBuf[0] = '\0'; + else + { + lpszTemp[lstrlen(lpszTemp)-2] = '\0'; //remove cr and newline character + sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() ); + } + + if ( lpszTemp ) + LocalFree((HLOCAL) lpszTemp ); + + return lpszBuf; +} + +BOOL LogEvent( + LPCSTR lpUNCServerName, + WORD wType, + DWORD dwEventID, + PSID lpUserSid, + LPCSTR message) +{ + LPCSTR messages[] = {message, NULL}; + + HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon"); + BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL); + return (DeregisterEventSource(hElog) && res); +} diff --git a/shibsp/attribute/DOMAttributeDecoder.cpp b/shibsp/attribute/DOMAttributeDecoder.cpp index 98cb87c..d996be3 100644 --- a/shibsp/attribute/DOMAttributeDecoder.cpp +++ b/shibsp/attribute/DOMAttributeDecoder.cpp @@ -1,226 +1,226 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * DOMAttributeDecoder.cpp - * - * Decodes a DOM into an ExtensibleAttribute. - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/ExtensibleAttribute.h" - -#include -#include -#include - -using namespace shibsp; -using namespace opensaml; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder - { - public: - DOMAttributeDecoder(const DOMElement* e); - ~DOMAttributeDecoder() {} - - Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - DDF convert(DOMElement* e, bool nameit=true) const; - auto_ptr_char m_formatter; - map,string> m_tagMap; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e) - { - return new DOMAttributeDecoder(e); - } - - static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g); - static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m); - static const XMLCh _to[] = UNICODE_LITERAL_2(t,o); - static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); -}; - -DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e) - : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) -{ - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); - - e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL; - while (e) { - if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) { - auto_ptr f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from))); - auto_ptr_char t(e->getAttributeNS(NULL, _to)); - if (f.get() && t.get() && *t.get()) { - if (log.isDebugEnabled()) - log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get()); - m_tagMap.insert( - pair< const pair,string>( - pair(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull), - t.get() - ) - ); - } - } - e = XMLHelper::getNextSiblingElement(e, Mapping); - } -} - -Attribute* DOMAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); - - if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { - log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); - return NULL; - } - - auto_ptr attr(new ExtensibleAttribute(ids, m_formatter.get())); - DDF dest = attr->getValues(); - vector::const_iterator v,stop; - - const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - DOMElement* e = (*v)->getDOM(); - if (e) { - DDF converted = convert(e, false); - if (!converted.isnull()) - dest.add(converted); - } - else - log.warn("skipping AttributeValue without a backing DOM"); - } - - return dest.integer() ? _decode(attr.release()) : NULL; -} - -DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const -{ - const XMLCh* nsURI; - const XMLCh* local; - map,string>::const_iterator mapping; - DDF obj = DDF(NULL).structure(); - - if (nameit) { - // Name this structure. - nsURI = e->getNamespaceURI(); - local = e->getLocalName(); - mapping = m_tagMap.find(pair(local,nsURI)); - if (mapping == m_tagMap.end()) { - auto_ptr_char temp(local); - obj.name(temp.get()); - } - else { - obj.name(mapping->second.c_str()); - } - } - - // Process non-xmlns attributes. - DOMNamedNodeMap* attrs = e->getAttributes(); - for (XMLSize_t a = attrs->getLength(); a > 0; --a) { - DOMNode* attr = attrs->item(a-1); - nsURI = attr->getNamespaceURI(); - if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS)) - continue; - local = attr->getLocalName(); - mapping = m_tagMap.find(pair(local, nsURI ? nsURI : &chNull)); - if (mapping == m_tagMap.end()) { - auto_ptr_char temp(local); - obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false); - } - else { - obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false); - } - } - - DOMElement* child = XMLHelper::getFirstChildElement(e); - if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) { - // Attach a _text member if a text node is present. - obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false); - } - else { - while (child) { - // Convert the child element. - DDF converted = convert(child); - if (!converted.isnull()) { - // Now identify it and attach it. - if (obj[converted.name()].isnull()) { - // We're a new child, so just attach as a structure member. - obj.add(converted); - } - else if (obj[converted.name()].islist()) { - // We're already a repeating child, so add it to the list. - obj[converted.name()].add(converted); - } - else if (obj[converted.name()].isstruct()) { - // This is the complex case where we see a child for the second - // time and have to convert a structure member into a named list. - DDF newlist = DDF(converted.name()).list(); - newlist.add(obj[converted.name()].remove()); - newlist.add(converted); - obj.add(newlist); - } - } - child = XMLHelper::getNextSiblingElement(child); - } - } - - // If we're empty, just delete. - if (obj.integer() == 0) - obj.destroy(); - return obj; -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * DOMAttributeDecoder.cpp + * + * Decodes a DOM into an ExtensibleAttribute. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/ExtensibleAttribute.h" + +#include +#include +#include + +using namespace shibsp; +using namespace opensaml; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder + { + public: + DOMAttributeDecoder(const DOMElement* e); + ~DOMAttributeDecoder() {} + + Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + DDF convert(DOMElement* e, bool nameit=true) const; + auto_ptr_char m_formatter; + map,string> m_tagMap; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e) + { + return new DOMAttributeDecoder(e); + } + + static const XMLCh Mapping[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g); + static const XMLCh _from[] = UNICODE_LITERAL_4(f,r,o,m); + static const XMLCh _to[] = UNICODE_LITERAL_2(t,o); + static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); +}; + +DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e) + : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) +{ + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); + + e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL; + while (e) { + if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) { + auto_ptr f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from))); + auto_ptr_char t(e->getAttributeNS(NULL, _to)); + if (f.get() && t.get() && *t.get()) { + if (log.isDebugEnabled()) + log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get()); + m_tagMap.insert( + pair< const pair,string>( + pair(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull), + t.get() + ) + ); + } + } + e = XMLHelper::getNextSiblingElement(e, Mapping); + } +} + +Attribute* DOMAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM"); + + if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { + log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); + return NULL; + } + + auto_ptr attr(new ExtensibleAttribute(ids, m_formatter.get())); + DDF dest = attr->getValues(); + vector::const_iterator v,stop; + + const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + DOMElement* e = (*v)->getDOM(); + if (e) { + DDF converted = convert(e, false); + if (!converted.isnull()) + dest.add(converted); + } + else + log.warn("skipping AttributeValue without a backing DOM"); + } + + return dest.integer() ? _decode(attr.release()) : NULL; +} + +DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const +{ + const XMLCh* nsURI; + const XMLCh* local; + map,string>::const_iterator mapping; + DDF obj = DDF(NULL).structure(); + + if (nameit) { + // Name this structure. + nsURI = e->getNamespaceURI(); + local = e->getLocalName(); + mapping = m_tagMap.find(pair(local,nsURI)); + if (mapping == m_tagMap.end()) { + auto_ptr_char temp(local); + obj.name(temp.get()); + } + else { + obj.name(mapping->second.c_str()); + } + } + + // Process non-xmlns attributes. + DOMNamedNodeMap* attrs = e->getAttributes(); + for (XMLSize_t a = attrs->getLength(); a > 0; --a) { + DOMNode* attr = attrs->item(a-1); + nsURI = attr->getNamespaceURI(); + if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS)) + continue; + local = attr->getLocalName(); + mapping = m_tagMap.find(pair(local, nsURI ? nsURI : &chNull)); + if (mapping == m_tagMap.end()) { + auto_ptr_char temp(local); + obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false); + } + else { + obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false); + } + } + + DOMElement* child = XMLHelper::getFirstChildElement(e); + if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) { + // Attach a _text member if a text node is present. + obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false); + } + else { + while (child) { + // Convert the child element. + DDF converted = convert(child); + if (!converted.isnull()) { + // Now identify it and attach it. + if (obj[converted.name()].isnull()) { + // We're a new child, so just attach as a structure member. + obj.add(converted); + } + else if (obj[converted.name()].islist()) { + // We're already a repeating child, so add it to the list. + obj[converted.name()].add(converted); + } + else if (obj[converted.name()].isstruct()) { + // This is the complex case where we see a child for the second + // time and have to convert a structure member into a named list. + DDF newlist = DDF(converted.name()).list(); + newlist.add(obj[converted.name()].remove()); + newlist.add(converted); + obj.add(newlist); + } + } + child = XMLHelper::getNextSiblingElement(child); + } + } + + // If we're empty, just delete. + if (obj.integer() == 0) + obj.destroy(); + return obj; +} diff --git a/shibsp/attribute/KeyInfoAttributeDecoder.cpp b/shibsp/attribute/KeyInfoAttributeDecoder.cpp index 5857952..17a4683 100644 --- a/shibsp/attribute/KeyInfoAttributeDecoder.cpp +++ b/shibsp/attribute/KeyInfoAttributeDecoder.cpp @@ -1,160 +1,160 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * KeyInfoAttributeDecoder.cpp - * - * Decodes KeyInfo information into a SimpleAttribute. - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/SimpleAttribute.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace shibsp; -using namespace opensaml; -using namespace xmlsignature; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder - { - public: - KeyInfoAttributeDecoder(const DOMElement* e); - ~KeyInfoAttributeDecoder() { - delete m_keyInfoResolver; - } - - Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - void extract(const KeyInfo* k, vector& dest) const { - auto_ptr cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS)); - if (cred.get()) { - dest.push_back(string()); - dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash); - if (dest.back().empty()) - dest.pop_back(); - } - } - - const KeyInfoResolver* getKeyInfoResolver() const { - return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver(); - } - - bool m_hash; - KeyInfoResolver* m_keyInfoResolver; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e) - { - return new KeyInfoAttributeDecoder(e); - } - - static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r); - static const XMLCh _hash[] = UNICODE_LITERAL_4(h,a,s,h); - static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); -}; - -KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) { - const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL; - m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1)); - e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL; - if (e) { - auto_ptr_char t(e->getAttributeNS(NULL, _type)); - if (t.get() && *t.get()) - m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e); - else - throw UnknownExtensionException(" element found with no type attribute"); - } -} - -Attribute* KeyInfoAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo"); - - if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { - log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); - return NULL; - } - - auto_ptr attr(new SimpleAttribute(ids)); - vector& dest = attr->getValues(); - vector::const_iterator v,stop; - - const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - const KeyInfo* k = dynamic_cast(*v); - if (k) - extract(k, dest); - else if ((*v)->hasChildren()) { - const list& children = (*v)->getOrderedChildren(); - for (list::const_iterator vv = children.begin(); vv!=children.end(); ++vv) { - if (k=dynamic_cast(*vv)) - extract(k, dest); - else - log.warn("skipping AttributeValue without a recognizable KeyInfo"); - } - } - } - - return dest.empty() ? NULL : _decode(attr.release()); -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * KeyInfoAttributeDecoder.cpp + * + * Decodes KeyInfo information into a SimpleAttribute. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/SimpleAttribute.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace opensaml; +using namespace xmlsignature; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder + { + public: + KeyInfoAttributeDecoder(const DOMElement* e); + ~KeyInfoAttributeDecoder() { + delete m_keyInfoResolver; + } + + Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + void extract(const KeyInfo* k, vector& dest) const { + auto_ptr cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS)); + if (cred.get()) { + dest.push_back(string()); + dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash); + if (dest.back().empty()) + dest.pop_back(); + } + } + + const KeyInfoResolver* getKeyInfoResolver() const { + return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver(); + } + + bool m_hash; + KeyInfoResolver* m_keyInfoResolver; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e) + { + return new KeyInfoAttributeDecoder(e); + } + + static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r); + static const XMLCh _hash[] = UNICODE_LITERAL_4(h,a,s,h); + static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); +}; + +KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) { + const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL; + m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1)); + e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL; + if (e) { + auto_ptr_char t(e->getAttributeNS(NULL, _type)); + if (t.get() && *t.get()) + m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e); + else + throw UnknownExtensionException(" element found with no type attribute"); + } +} + +Attribute* KeyInfoAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo"); + + if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { + log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); + return NULL; + } + + auto_ptr attr(new SimpleAttribute(ids)); + vector& dest = attr->getValues(); + vector::const_iterator v,stop; + + const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + const KeyInfo* k = dynamic_cast(*v); + if (k) + extract(k, dest); + else if ((*v)->hasChildren()) { + const list& children = (*v)->getOrderedChildren(); + for (list::const_iterator vv = children.begin(); vv!=children.end(); ++vv) { + if (k=dynamic_cast(*vv)) + extract(k, dest); + else + log.warn("skipping AttributeValue without a recognizable KeyInfo"); + } + } + } + + return dest.empty() ? NULL : _decode(attr.release()); +} diff --git a/shibsp/attribute/NameIDAttributeDecoder.cpp b/shibsp/attribute/NameIDAttributeDecoder.cpp index 903bc33..82ff313 100644 --- a/shibsp/attribute/NameIDAttributeDecoder.cpp +++ b/shibsp/attribute/NameIDAttributeDecoder.cpp @@ -1,234 +1,234 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * NameIDAttributeDecoder.cpp - * - * Decodes SAML into NameIDAttributes - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/NameIDAttribute.h" - -#include -#include - -using namespace shibsp; -using namespace opensaml::saml1; -using namespace opensaml::saml2; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); - static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s); - - class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder - { - public: - NameIDAttributeDecoder(const DOMElement* e) - : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) { - const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL; - if (flag && (*flag == chLatin_t || *flag == chDigit_1)) - m_defaultQualifiers = true; - } - ~NameIDAttributeDecoder() {} - - shibsp::Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - void extract( - const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const; - void extract( - const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const; - auto_ptr_char m_formatter; - bool m_defaultQualifiers; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e) - { - return new NameIDAttributeDecoder(e); - } -}; - -shibsp::Attribute* NameIDAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - auto_ptr nameid( - new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER) - ); - vector& dest = nameid->getValues(); - vector::const_iterator v,stop; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID"); - - if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { - const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - const NameIDType* n2 = dynamic_cast(*v); - if (n2) - extract(n2, dest, assertingParty, relyingParty); - else { - const NameIdentifier* n1=dynamic_cast(*v); - if (n1) - extract(n1, dest, assertingParty, relyingParty); - else if ((*v)->hasChildren()) { - const list& values = (*v)->getOrderedChildren(); - for (list::const_iterator vv = values.begin(); vv!=values.end(); ++vv) { - if (n2=dynamic_cast(*vv)) - extract(n2, dest, assertingParty, relyingParty); - else if (n1=dynamic_cast(*vv)) - extract(n1, dest, assertingParty, relyingParty); - else - log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier"); - } - } - } - } - - return dest.empty() ? NULL : _decode(nameid.release()); - } - - const NameIDType* saml2name = dynamic_cast(xmlObject); - if (saml2name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml2name->getFormat()); - log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); - } - extract(saml2name, dest, assertingParty, relyingParty); - } - else { - const NameIdentifier* saml1name = dynamic_cast(xmlObject); - if (saml1name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml1name->getFormat()); - log.debug( - "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", - ids.front().c_str(), f.get() ? f.get() : "unspecified" - ); - } - extract(saml1name, dest, assertingParty, relyingParty); - } - else { - log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); - return NULL; - } - } - - return dest.empty() ? NULL : _decode(nameid.release()); -} - -void NameIDAttributeDecoder::extract( - const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const -{ - auto_arrayptr name(toUTF8(n->getName())); - if (name.get() && *name.get()) { - dest.push_back(NameIDAttribute::Value()); - NameIDAttribute::Value& val = dest.back(); - val.m_Name = name.get(); - char* str = toUTF8(n->getFormat()); - if (str) { - val.m_Format = str; - delete[] str; - } - - str = toUTF8(n->getNameQualifier()); - if (str && *str) - val.m_NameQualifier = str; - else if (m_defaultQualifiers && assertingParty) - val.m_NameQualifier = assertingParty; - delete[] str; - - str = toUTF8(n->getSPNameQualifier()); - if (str && *str) - val.m_SPNameQualifier = str; - else if (m_defaultQualifiers && relyingParty) - val.m_SPNameQualifier = relyingParty; - delete[] str; - - str = toUTF8(n->getSPProvidedID()); - if (str) { - val.m_SPProvidedID = str; - delete[] str; - } - } -} - -void NameIDAttributeDecoder::extract( - const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const -{ - auto_arrayptr name(toUTF8(n->getName())); - if (name.get() && *name.get()) { - dest.push_back(NameIDAttribute::Value()); - NameIDAttribute::Value& val = dest.back(); - val.m_Name = name.get(); - char* str = toUTF8(n->getFormat()); - if (str) { - val.m_Format = str; - delete[] str; - } - - str = toUTF8(n->getNameQualifier()); - if (str && *str) - val.m_NameQualifier = str; - else if (m_defaultQualifiers && assertingParty) - val.m_NameQualifier = assertingParty; - delete[] str; - - if (m_defaultQualifiers && relyingParty) - val.m_SPNameQualifier = relyingParty; - } -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * NameIDAttributeDecoder.cpp + * + * Decodes SAML into NameIDAttributes + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/NameIDAttribute.h" + +#include +#include + +using namespace shibsp; +using namespace opensaml::saml1; +using namespace opensaml::saml2; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); + static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s); + + class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder + { + public: + NameIDAttributeDecoder(const DOMElement* e) + : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) { + const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL; + if (flag && (*flag == chLatin_t || *flag == chDigit_1)) + m_defaultQualifiers = true; + } + ~NameIDAttributeDecoder() {} + + shibsp::Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + void extract( + const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const; + void extract( + const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const; + auto_ptr_char m_formatter; + bool m_defaultQualifiers; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e) + { + return new NameIDAttributeDecoder(e); + } +}; + +shibsp::Attribute* NameIDAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + auto_ptr nameid( + new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER) + ); + vector& dest = nameid->getValues(); + vector::const_iterator v,stop; + + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID"); + + if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { + const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + const NameIDType* n2 = dynamic_cast(*v); + if (n2) + extract(n2, dest, assertingParty, relyingParty); + else { + const NameIdentifier* n1=dynamic_cast(*v); + if (n1) + extract(n1, dest, assertingParty, relyingParty); + else if ((*v)->hasChildren()) { + const list& values = (*v)->getOrderedChildren(); + for (list::const_iterator vv = values.begin(); vv!=values.end(); ++vv) { + if (n2=dynamic_cast(*vv)) + extract(n2, dest, assertingParty, relyingParty); + else if (n1=dynamic_cast(*vv)) + extract(n1, dest, assertingParty, relyingParty); + else + log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier"); + } + } + } + } + + return dest.empty() ? NULL : _decode(nameid.release()); + } + + const NameIDType* saml2name = dynamic_cast(xmlObject); + if (saml2name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml2name->getFormat()); + log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); + } + extract(saml2name, dest, assertingParty, relyingParty); + } + else { + const NameIdentifier* saml1name = dynamic_cast(xmlObject); + if (saml1name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml1name->getFormat()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", + ids.front().c_str(), f.get() ? f.get() : "unspecified" + ); + } + extract(saml1name, dest, assertingParty, relyingParty); + } + else { + log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); + return NULL; + } + } + + return dest.empty() ? NULL : _decode(nameid.release()); +} + +void NameIDAttributeDecoder::extract( + const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const +{ + auto_arrayptr name(toUTF8(n->getName())); + if (name.get() && *name.get()) { + dest.push_back(NameIDAttribute::Value()); + NameIDAttribute::Value& val = dest.back(); + val.m_Name = name.get(); + char* str = toUTF8(n->getFormat()); + if (str) { + val.m_Format = str; + delete[] str; + } + + str = toUTF8(n->getNameQualifier()); + if (str && *str) + val.m_NameQualifier = str; + else if (m_defaultQualifiers && assertingParty) + val.m_NameQualifier = assertingParty; + delete[] str; + + str = toUTF8(n->getSPNameQualifier()); + if (str && *str) + val.m_SPNameQualifier = str; + else if (m_defaultQualifiers && relyingParty) + val.m_SPNameQualifier = relyingParty; + delete[] str; + + str = toUTF8(n->getSPProvidedID()); + if (str) { + val.m_SPProvidedID = str; + delete[] str; + } + } +} + +void NameIDAttributeDecoder::extract( + const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const +{ + auto_arrayptr name(toUTF8(n->getName())); + if (name.get() && *name.get()) { + dest.push_back(NameIDAttribute::Value()); + NameIDAttribute::Value& val = dest.back(); + val.m_Name = name.get(); + char* str = toUTF8(n->getFormat()); + if (str) { + val.m_Format = str; + delete[] str; + } + + str = toUTF8(n->getNameQualifier()); + if (str && *str) + val.m_NameQualifier = str; + else if (m_defaultQualifiers && assertingParty) + val.m_NameQualifier = assertingParty; + delete[] str; + + if (m_defaultQualifiers && relyingParty) + val.m_SPNameQualifier = relyingParty; + } +} diff --git a/shibsp/attribute/StringAttributeDecoder.cpp b/shibsp/attribute/StringAttributeDecoder.cpp index f2a9d6f..c19fc6b 100644 --- a/shibsp/attribute/StringAttributeDecoder.cpp +++ b/shibsp/attribute/StringAttributeDecoder.cpp @@ -1,148 +1,148 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * StringAttributeDecoder.cpp - * - * Decodes SAML into SimpleAttributes - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/SimpleAttribute.h" - -#include -#include - -using namespace shibsp; -using namespace opensaml::saml1; -using namespace opensaml::saml2; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder - { - public: - StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} - ~StringAttributeDecoder() {} - - shibsp::Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e) - { - return new StringAttributeDecoder(e); - } -}; - -shibsp::Attribute* StringAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - char* val; - auto_ptr simple(new SimpleAttribute(ids)); - vector& dest = simple->getValues(); - vector::const_iterator v,stop; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String"); - - if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { - const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - if (!(*v)->hasChildren()) { - val = toUTF8((*v)->getTextContent()); - if (val && *val) - dest.push_back(val); - else - log.warn("skipping empty AttributeValue"); - delete[] val; - } - else { - log.warn("skipping complex AttributeValue"); - } - } - - return dest.empty() ? NULL : _decode(simple.release()); - } - - const NameID* saml2name = dynamic_cast(xmlObject); - if (saml2name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml2name->getFormat()); - log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); - } - val = toUTF8(saml2name->getName()); - } - else { - const NameIdentifier* saml1name = dynamic_cast(xmlObject); - if (saml1name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml1name->getFormat()); - log.debug( - "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", - ids.front().c_str(), f.get() ? f.get() : "unspecified" - ); - } - val = toUTF8(saml1name->getName()); - } - else { - log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); - return NULL; - } - } - - if (val && *val) - dest.push_back(val); - else - log.warn("ignoring empty NameID"); - delete[] val; - return dest.empty() ? NULL : _decode(simple.release()); -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * StringAttributeDecoder.cpp + * + * Decodes SAML into SimpleAttributes + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/SimpleAttribute.h" + +#include +#include + +using namespace shibsp; +using namespace opensaml::saml1; +using namespace opensaml::saml2; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder + { + public: + StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} + ~StringAttributeDecoder() {} + + shibsp::Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e) + { + return new StringAttributeDecoder(e); + } +}; + +shibsp::Attribute* StringAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + char* val; + auto_ptr simple(new SimpleAttribute(ids)); + vector& dest = simple->getValues(); + vector::const_iterator v,stop; + + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String"); + + if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { + const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + if (!(*v)->hasChildren()) { + val = toUTF8((*v)->getTextContent()); + if (val && *val) + dest.push_back(val); + else + log.warn("skipping empty AttributeValue"); + delete[] val; + } + else { + log.warn("skipping complex AttributeValue"); + } + } + + return dest.empty() ? NULL : _decode(simple.release()); + } + + const NameID* saml2name = dynamic_cast(xmlObject); + if (saml2name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml2name->getFormat()); + log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); + } + val = toUTF8(saml2name->getName()); + } + else { + const NameIdentifier* saml1name = dynamic_cast(xmlObject); + if (saml1name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml1name->getFormat()); + log.debug( + "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", + ids.front().c_str(), f.get() ? f.get() : "unspecified" + ); + } + val = toUTF8(saml1name->getName()); + } + else { + log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned"); + return NULL; + } + } + + if (val && *val) + dest.push_back(val); + else + log.warn("ignoring empty NameID"); + delete[] val; + return dest.empty() ? NULL : _decode(simple.release()); +} diff --git a/shibsp/attribute/XMLAttributeDecoder.cpp b/shibsp/attribute/XMLAttributeDecoder.cpp index 2d59528..4c99938 100644 --- a/shibsp/attribute/XMLAttributeDecoder.cpp +++ b/shibsp/attribute/XMLAttributeDecoder.cpp @@ -1,138 +1,138 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * XMLAttributeDecoder.cpp - * - * Decodes arbitrary XML into an XMLAttribute. - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/XMLAttribute.h" - -#include -#include -#include - -using namespace shibsp; -using namespace opensaml; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder - { - public: - XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} - ~XMLAttributeDecoder() {} - - Attribute* decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - DDF convert(DOMElement* e, bool nameit=true) const; - auto_ptr_char m_formatter; - map,string> m_tagMap; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e) - { - return new XMLAttributeDecoder(e); - } -}; - - -Attribute* XMLAttributeDecoder::decode( - const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - if (!xmlObject) - return NULL; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML"); - - auto_ptr attr(new XMLAttribute(ids)); - vector& dest = attr->getValues(); - - // Handle any non-Attribute object directly. - if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { - DOMElement* e = xmlObject->getDOM(); - if (e) { - if (log.isDebugEnabled()) { - log.debug( - "decoding XMLAttribute (%s) from XMLObject (%s)", - ids.front().c_str(), - (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str() - ); - } - dest.push_back(string()); - XMLHelper::serialize(e, dest.back()); - } - else { - log.warn("skipping XMLObject without a backing DOM"); - } - return dest.empty() ? NULL : _decode(attr.release()); - } - - vector::const_iterator v,stop; - - const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug( - "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug( - "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", - ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() - ); - } - } - else { - log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - DOMElement* e = (*v)->getDOM(); - if (e) { - dest.push_back(string()); - XMLHelper::serialize(e, dest.back()); - } - else - log.warn("skipping AttributeValue without a backing DOM"); - } - - return dest.empty() ? NULL : _decode(attr.release()); -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * XMLAttributeDecoder.cpp + * + * Decodes arbitrary XML into an XMLAttribute. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/XMLAttribute.h" + +#include +#include +#include + +using namespace shibsp; +using namespace opensaml; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder + { + public: + XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {} + ~XMLAttributeDecoder() {} + + Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL + ) const; + + private: + DDF convert(DOMElement* e, bool nameit=true) const; + auto_ptr_char m_formatter; + map,string> m_tagMap; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e) + { + return new XMLAttributeDecoder(e); + } +}; + + +Attribute* XMLAttributeDecoder::decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + if (!xmlObject) + return NULL; + + Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML"); + + auto_ptr attr(new XMLAttribute(ids)); + vector& dest = attr->getValues(); + + // Handle any non-Attribute object directly. + if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) { + DOMElement* e = xmlObject->getDOM(); + if (e) { + if (log.isDebugEnabled()) { + log.debug( + "decoding XMLAttribute (%s) from XMLObject (%s)", + ids.front().c_str(), + (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str() + ); + } + dest.push_back(string()); + XMLHelper::serialize(e, dest.back()); + } + else { + log.warn("skipping XMLObject without a backing DOM"); + } + return dest.empty() ? NULL : _decode(attr.release()); + } + + vector::const_iterator v,stop; + + const saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned"); + return NULL; + } + } + + for (; v!=stop; ++v) { + DOMElement* e = (*v)->getDOM(); + if (e) { + dest.push_back(string()); + XMLHelper::serialize(e, dest.back()); + } + else + log.warn("skipping AttributeValue without a backing DOM"); + } + + return dest.empty() ? NULL : _decode(attr.release()); +} diff --git a/shibsp/impl/ChainingAccessControl.cpp b/shibsp/impl/ChainingAccessControl.cpp index 8f6e78c..6feafda 100644 --- a/shibsp/impl/ChainingAccessControl.cpp +++ b/shibsp/impl/ChainingAccessControl.cpp @@ -1,146 +1,146 @@ -/* - * Copyright 2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * ChainingAccessControl.cpp - * - * Access control plugin that combines other plugins. - */ - -#include "internal.h" -#include "exceptions.h" -#include "AccessControl.h" -#include "SessionCache.h" -#include "SPRequest.h" - -#include -#include -#include -#include - -using namespace shibsp; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - - class ChainingAccessControl : public AccessControl - { - public: - ChainingAccessControl(const DOMElement* e); - - ~ChainingAccessControl() { - for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); - } - - Lockable* lock() { - for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::lock)); - return this; - } - void unlock() { - for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::unlock)); - } - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - enum operator_t { OP_AND, OP_OR } m_op; - vector m_ac; - }; - - AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e) - { - return new ChainingAccessControl(e); - } - - static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); - static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r); - static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); - static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); - static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); - - extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e); -} - -void SHIBSP_API shibsp::registerAccessControls() -{ - SPConfig& conf=SPConfig::getConfig(); - conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory); - conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory); - conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory); -} - -AccessControl::AccessControl() -{ -} - -AccessControl::~AccessControl() -{ -} - -ChainingAccessControl::ChainingAccessControl(const DOMElement* e) -{ - const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL; - if (XMLString::equals(op, AND)) - m_op=OP_AND; - else if (XMLString::equals(op, OR)) - m_op=OP_OR; - else - throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration."); - - try { - e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL; - while (e) { - auto_ptr_char type(e->getAttributeNS(NULL, _type)); - if (type.get() && *type.get()) { - Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get()); - m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e)); - } - e = XMLHelper::getNextSiblingElement(e, _AccessControl); - } - } - catch (exception&) { - for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); - throw; - } - if (m_ac.empty()) - throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin."); -} - -AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const -{ - switch (m_op) { - case OP_AND: - { - for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { - if ((*i)->authorized(request, session) != shib_acl_true) - return shib_acl_false; - } - return shib_acl_true; - } - - case OP_OR: - { - for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { - if ((*i)->authorized(request,session) == shib_acl_true) - return shib_acl_true; - } - return shib_acl_false; - } - } - request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access"); - return shib_acl_false; -} +/* + * Copyright 2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * ChainingAccessControl.cpp + * + * Access control plugin that combines other plugins. + */ + +#include "internal.h" +#include "exceptions.h" +#include "AccessControl.h" +#include "SessionCache.h" +#include "SPRequest.h" + +#include +#include +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + class ChainingAccessControl : public AccessControl + { + public: + ChainingAccessControl(const DOMElement* e); + + ~ChainingAccessControl() { + for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); + } + + Lockable* lock() { + for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::lock)); + return this; + } + void unlock() { + for_each(m_ac.begin(), m_ac.end(), mem_fun(&Lockable::unlock)); + } + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + enum operator_t { OP_AND, OP_OR } m_op; + vector m_ac; + }; + + AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e) + { + return new ChainingAccessControl(e); + } + + static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); + static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r); + static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); + static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); + static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); + + extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e); +} + +void SHIBSP_API shibsp::registerAccessControls() +{ + SPConfig& conf=SPConfig::getConfig(); + conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory); + conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory); + conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory); +} + +AccessControl::AccessControl() +{ +} + +AccessControl::~AccessControl() +{ +} + +ChainingAccessControl::ChainingAccessControl(const DOMElement* e) +{ + const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL; + if (XMLString::equals(op, AND)) + m_op=OP_AND; + else if (XMLString::equals(op, OR)) + m_op=OP_OR; + else + throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration."); + + try { + e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL; + while (e) { + auto_ptr_char type(e->getAttributeNS(NULL, _type)); + if (type.get() && *type.get()) { + Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get()); + m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e)); + } + e = XMLHelper::getNextSiblingElement(e, _AccessControl); + } + } + catch (exception&) { + for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup()); + throw; + } + if (m_ac.empty()) + throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin."); +} + +AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const +{ + switch (m_op) { + case OP_AND: + { + for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { + if ((*i)->authorized(request, session) != shib_acl_true) + return shib_acl_false; + } + return shib_acl_true; + } + + case OP_OR: + { + for (vector::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) { + if ((*i)->authorized(request,session) == shib_acl_true) + return shib_acl_true; + } + return shib_acl_false; + } + } + request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access"); + return shib_acl_false; +} diff --git a/shibsp/impl/XMLAccessControl.cpp b/shibsp/impl/XMLAccessControl.cpp index 9c2e4ca..7e08b73 100644 --- a/shibsp/impl/XMLAccessControl.cpp +++ b/shibsp/impl/XMLAccessControl.cpp @@ -1,445 +1,445 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * XMLAccessControl.cpp - * - * XML-based access control syntax - */ - -#include "internal.h" -#include "exceptions.h" -#include "AccessControl.h" -#include "SessionCache.h" -#include "SPRequest.h" -#include "attribute/Attribute.h" - -#include -#include -#include -#include -#include -#include - -#ifndef HAVE_STRCASECMP -# define strcasecmp _stricmp -#endif - -using namespace shibsp; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - - class Rule : public AccessControl - { - public: - Rule(const DOMElement* e); - ~Rule() {} - - Lockable* lock() {return this;} - void unlock() {} - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - string m_alias; - vector m_vals; - }; - - class RuleRegex : public AccessControl - { - public: - RuleRegex(const DOMElement* e); - ~RuleRegex() { - delete m_re; - } - - Lockable* lock() {return this;} - void unlock() {} - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - string m_alias; - auto_arrayptr m_exp; - RegularExpression* m_re; - }; - - class Operator : public AccessControl - { - public: - Operator(const DOMElement* e); - ~Operator(); - - Lockable* lock() {return this;} - void unlock() {} - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - private: - enum operator_t { OP_NOT, OP_AND, OP_OR } m_op; - vector m_operands; - }; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 ) -#endif - - class XMLAccessControl : public AccessControl, public ReloadableXMLFile - { - public: - XMLAccessControl(const DOMElement* e) - : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) { - load(); // guarantees an exception or the policy is loaded - } - - ~XMLAccessControl() { - delete m_rootAuthz; - } - - aclresult_t authorized(const SPRequest& request, const Session* session) const; - - protected: - pair load(); - - private: - AccessControl* m_rootAuthz; - }; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - - AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e) - { - return new XMLAccessControl(e); - } - - static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); - static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e); - static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i); - static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t); - static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e); - static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T); - static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); - static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); - static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e); - static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x); -} - -Rule::Rule(const DOMElement* e) -{ - auto_ptr_char req(e->getAttributeNS(NULL,require)); - if (!req.get() || !*req.get()) - throw ConfigurationException("Access control rule missing require attribute"); - m_alias=req.get(); - - auto_arrayptr vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)); - if (!vals.get()) - return; - - const XMLCh* flag = e->getAttributeNS(NULL,_list); - if (flag && (*flag == chLatin_f || *flag == chDigit_0)) { - if (*vals.get()) - m_vals.push_back(vals.get()); - return; - } - -#ifdef HAVE_STRTOK_R - char* pos=NULL; - const char* token=strtok_r(const_cast(vals.get())," ",&pos); -#else - const char* token=strtok(const_cast(vals.get())," "); -#endif - while (token) { - m_vals.push_back(token); -#ifdef HAVE_STRTOK_R - token=strtok_r(NULL," ",&pos); -#else - token=strtok(NULL," "); -#endif - } -} - -AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const -{ - // We can make this more complex later using pluggable comparison functions, - // but for now, just a straight port to the new Attribute API. - - // Map alias in rule to the attribute. - if (!session) { - request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); - return shib_acl_false; - } - - if (m_alias == "valid-user") { - if (session) { - request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); - return shib_acl_true; - } - return shib_acl_false; - } - if (m_alias == "user") { - for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { - if (*i == request.getRemoteUser()) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted"); - return shib_acl_true; - } - } - return shib_acl_false; - } - else if (m_alias == "authnContextClassRef") { - const char* ref = session->getAuthnContextClassRef(); - for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { - if (!strcmp(i->c_str(),ref)) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted"); - return shib_acl_true; - } - } - return shib_acl_false; - } - else if (m_alias == "authnContextDeclRef") { - const char* ref = session->getAuthnContextDeclRef(); - for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { - if (!strcmp(i->c_str(),ref)) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted"); - return shib_acl_true; - } - } - return shib_acl_false; - } - - // Find the attribute(s) matching the require rule. - pair::const_iterator, multimap::const_iterator> attrs = - session->getIndexedAttributes().equal_range(m_alias); - if (attrs.first == attrs.second) { - request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); - return shib_acl_false; - } - - for (; attrs.first != attrs.second; ++attrs.first) { - bool caseSensitive = attrs.first->second->isCaseSensitive(); - - // Now we have to intersect the attribute's values against the rule's list. - const vector& vals = attrs.first->second->getSerializedValues(); - for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { - for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { - if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted"); - return shib_acl_true; - } - } - } - } - - return shib_acl_false; -} - -RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)) -{ - auto_ptr_char req(e->getAttributeNS(NULL,require)); - if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get()) - throw ConfigurationException("Access control rule missing require attribute or element content."); - m_alias=req.get(); - - const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase); - bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1)); - try { - m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get())); - } -} - -AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const -{ - // Map alias in rule to the attribute. - if (!session) { - request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); - return shib_acl_false; - } - - if (m_alias == "valid-user") { - if (session) { - request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); - return shib_acl_true; - } - return shib_acl_false; - } - - try { - if (m_alias == "user") { - if (m_re->matches(request.getRemoteUser().c_str())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - return shib_acl_false; - } - else if (m_alias == "authnContextClassRef") { - if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - return shib_acl_false; - } - else if (m_alias == "authnContextDeclRef") { - if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - return shib_acl_false; - } - - // Find the attribute(s) matching the require rule. - pair::const_iterator, multimap::const_iterator> attrs = - session->getIndexedAttributes().equal_range(m_alias); - if (attrs.first == attrs.second) { - request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); - return shib_acl_false; - } - - for (; attrs.first != attrs.second; ++attrs.first) { - // Now we have to intersect the attribute's values against the regular expression. - const vector& vals = attrs.first->second->getSerializedValues(); - for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { - if (m_re->matches(j->c_str())) { - request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted"); - return shib_acl_true; - } - } - } - } - catch (XMLException& ex) { - auto_ptr_char tmp(ex.getMessage()); - request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get()); - } - - return shib_acl_false; -} - -Operator::Operator(const DOMElement* e) -{ - if (XMLString::equals(e->getLocalName(),NOT)) - m_op=OP_NOT; - else if (XMLString::equals(e->getLocalName(),AND)) - m_op=OP_AND; - else if (XMLString::equals(e->getLocalName(),OR)) - m_op=OP_OR; - else - throw ConfigurationException("Unrecognized operator in access control rule"); - - try { - e=XMLHelper::getFirstChildElement(e); - if (XMLString::equals(e->getLocalName(),_Rule)) - m_operands.push_back(new Rule(e)); - else if (XMLString::equals(e->getLocalName(),_RuleRegex)) - m_operands.push_back(new RuleRegex(e)); - else - m_operands.push_back(new Operator(e)); - - if (m_op==OP_NOT) - return; - - e=XMLHelper::getNextSiblingElement(e); - while (e) { - if (XMLString::equals(e->getLocalName(),_Rule)) - m_operands.push_back(new Rule(e)); - else if (XMLString::equals(e->getLocalName(),_RuleRegex)) - m_operands.push_back(new RuleRegex(e)); - else - m_operands.push_back(new Operator(e)); - e=XMLHelper::getNextSiblingElement(e); - } - } - catch (exception&) { - for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); - throw; - } -} - -Operator::~Operator() -{ - for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); -} - -AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const -{ - switch (m_op) { - case OP_NOT: - switch (m_operands.front()->authorized(request,session)) { - case shib_acl_true: - return shib_acl_false; - case shib_acl_false: - return shib_acl_true; - default: - return shib_acl_indeterminate; - } - - case OP_AND: - { - for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { - if ((*i)->authorized(request,session) != shib_acl_true) - return shib_acl_false; - } - return shib_acl_true; - } - - case OP_OR: - { - for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { - if ((*i)->authorized(request,session) == shib_acl_true) - return shib_acl_true; - } - return shib_acl_false; - } - } - request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access"); - return shib_acl_false; -} - -pair XMLAccessControl::load() -{ - // Load from source using base class. - pair raw = ReloadableXMLFile::load(); - - // If we own it, wrap it. - XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); - - // Check for AccessControl wrapper and drop a level. - if (XMLString::equals(raw.second->getLocalName(),_AccessControl)) - raw.second = XMLHelper::getFirstChildElement(raw.second); - - AccessControl* authz; - if (XMLString::equals(raw.second->getLocalName(),_Rule)) - authz=new Rule(raw.second); - else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex)) - authz=new RuleRegex(raw.second); - else - authz=new Operator(raw.second); - - delete m_rootAuthz; - m_rootAuthz = authz; - return make_pair(false,(DOMElement*)NULL); -} - -AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const -{ - return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * XMLAccessControl.cpp + * + * XML-based access control syntax + */ + +#include "internal.h" +#include "exceptions.h" +#include "AccessControl.h" +#include "SessionCache.h" +#include "SPRequest.h" +#include "attribute/Attribute.h" + +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_STRCASECMP +# define strcasecmp _stricmp +#endif + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + class Rule : public AccessControl + { + public: + Rule(const DOMElement* e); + ~Rule() {} + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + string m_alias; + vector m_vals; + }; + + class RuleRegex : public AccessControl + { + public: + RuleRegex(const DOMElement* e); + ~RuleRegex() { + delete m_re; + } + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + string m_alias; + auto_arrayptr m_exp; + RegularExpression* m_re; + }; + + class Operator : public AccessControl + { + public: + Operator(const DOMElement* e); + ~Operator(); + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + enum operator_t { OP_NOT, OP_AND, OP_OR } m_op; + vector m_operands; + }; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + class XMLAccessControl : public AccessControl, public ReloadableXMLFile + { + public: + XMLAccessControl(const DOMElement* e) + : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) { + load(); // guarantees an exception or the policy is loaded + } + + ~XMLAccessControl() { + delete m_rootAuthz; + } + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + protected: + pair load(); + + private: + AccessControl* m_rootAuthz; + }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + + AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e) + { + return new XMLAccessControl(e); + } + + static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l); + static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e); + static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i); + static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t); + static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e); + static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T); + static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); + static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); + static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e); + static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x); +} + +Rule::Rule(const DOMElement* e) +{ + auto_ptr_char req(e->getAttributeNS(NULL,require)); + if (!req.get() || !*req.get()) + throw ConfigurationException("Access control rule missing require attribute"); + m_alias=req.get(); + + auto_arrayptr vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)); + if (!vals.get()) + return; + + const XMLCh* flag = e->getAttributeNS(NULL,_list); + if (flag && (*flag == chLatin_f || *flag == chDigit_0)) { + if (*vals.get()) + m_vals.push_back(vals.get()); + return; + } + +#ifdef HAVE_STRTOK_R + char* pos=NULL; + const char* token=strtok_r(const_cast(vals.get())," ",&pos); +#else + const char* token=strtok(const_cast(vals.get())," "); +#endif + while (token) { + m_vals.push_back(token); +#ifdef HAVE_STRTOK_R + token=strtok_r(NULL," ",&pos); +#else + token=strtok(NULL," "); +#endif + } +} + +AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const +{ + // We can make this more complex later using pluggable comparison functions, + // but for now, just a straight port to the new Attribute API. + + // Map alias in rule to the attribute. + if (!session) { + request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); + return shib_acl_false; + } + + if (m_alias == "valid-user") { + if (session) { + request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); + return shib_acl_true; + } + return shib_acl_false; + } + if (m_alias == "user") { + for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { + if (*i == request.getRemoteUser()) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted"); + return shib_acl_true; + } + } + return shib_acl_false; + } + else if (m_alias == "authnContextClassRef") { + const char* ref = session->getAuthnContextClassRef(); + for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { + if (!strcmp(i->c_str(),ref)) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted"); + return shib_acl_true; + } + } + return shib_acl_false; + } + else if (m_alias == "authnContextDeclRef") { + const char* ref = session->getAuthnContextDeclRef(); + for (vector::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) { + if (!strcmp(i->c_str(),ref)) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted"); + return shib_acl_true; + } + } + return shib_acl_false; + } + + // Find the attribute(s) matching the require rule. + pair::const_iterator, multimap::const_iterator> attrs = + session->getIndexedAttributes().equal_range(m_alias); + if (attrs.first == attrs.second) { + request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); + return shib_acl_false; + } + + for (; attrs.first != attrs.second; ++attrs.first) { + bool caseSensitive = attrs.first->second->isCaseSensitive(); + + // Now we have to intersect the attribute's values against the rule's list. + const vector& vals = attrs.first->second->getSerializedValues(); + for (vector::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) { + for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { + if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted"); + return shib_acl_true; + } + } + } + } + + return shib_acl_false; +} + +RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL)) +{ + auto_ptr_char req(e->getAttributeNS(NULL,require)); + if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get()) + throw ConfigurationException("Access control rule missing require attribute or element content."); + m_alias=req.get(); + + const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase); + bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1)); + try { + m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); + } + catch (XMLException& ex) { + auto_ptr_char tmp(ex.getMessage()); + throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get())); + } +} + +AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const +{ + // Map alias in rule to the attribute. + if (!session) { + request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?"); + return shib_acl_false; + } + + if (m_alias == "valid-user") { + if (session) { + request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session"); + return shib_acl_true; + } + return shib_acl_false; + } + + try { + if (m_alias == "user") { + if (m_re->matches(request.getRemoteUser().c_str())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + return shib_acl_false; + } + else if (m_alias == "authnContextClassRef") { + if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + return shib_acl_false; + } + else if (m_alias == "authnContextDeclRef") { + if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + return shib_acl_false; + } + + // Find the attribute(s) matching the require rule. + pair::const_iterator, multimap::const_iterator> attrs = + session->getIndexedAttributes().equal_range(m_alias); + if (attrs.first == attrs.second) { + request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session"); + return shib_acl_false; + } + + for (; attrs.first != attrs.second; ++attrs.first) { + // Now we have to intersect the attribute's values against the regular expression. + const vector& vals = attrs.first->second->getSerializedValues(); + for (vector::const_iterator j=vals.begin(); j!=vals.end(); ++j) { + if (m_re->matches(j->c_str())) { + request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted"); + return shib_acl_true; + } + } + } + } + catch (XMLException& ex) { + auto_ptr_char tmp(ex.getMessage()); + request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get()); + } + + return shib_acl_false; +} + +Operator::Operator(const DOMElement* e) +{ + if (XMLString::equals(e->getLocalName(),NOT)) + m_op=OP_NOT; + else if (XMLString::equals(e->getLocalName(),AND)) + m_op=OP_AND; + else if (XMLString::equals(e->getLocalName(),OR)) + m_op=OP_OR; + else + throw ConfigurationException("Unrecognized operator in access control rule"); + + try { + e=XMLHelper::getFirstChildElement(e); + if (XMLString::equals(e->getLocalName(),_Rule)) + m_operands.push_back(new Rule(e)); + else if (XMLString::equals(e->getLocalName(),_RuleRegex)) + m_operands.push_back(new RuleRegex(e)); + else + m_operands.push_back(new Operator(e)); + + if (m_op==OP_NOT) + return; + + e=XMLHelper::getNextSiblingElement(e); + while (e) { + if (XMLString::equals(e->getLocalName(),_Rule)) + m_operands.push_back(new Rule(e)); + else if (XMLString::equals(e->getLocalName(),_RuleRegex)) + m_operands.push_back(new RuleRegex(e)); + else + m_operands.push_back(new Operator(e)); + e=XMLHelper::getNextSiblingElement(e); + } + } + catch (exception&) { + for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); + throw; + } +} + +Operator::~Operator() +{ + for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup()); +} + +AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const +{ + switch (m_op) { + case OP_NOT: + switch (m_operands.front()->authorized(request,session)) { + case shib_acl_true: + return shib_acl_false; + case shib_acl_false: + return shib_acl_true; + default: + return shib_acl_indeterminate; + } + + case OP_AND: + { + for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { + if ((*i)->authorized(request,session) != shib_acl_true) + return shib_acl_false; + } + return shib_acl_true; + } + + case OP_OR: + { + for (vector::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) { + if ((*i)->authorized(request,session) == shib_acl_true) + return shib_acl_true; + } + return shib_acl_false; + } + } + request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access"); + return shib_acl_false; +} + +pair XMLAccessControl::load() +{ + // Load from source using base class. + pair raw = ReloadableXMLFile::load(); + + // If we own it, wrap it. + XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); + + // Check for AccessControl wrapper and drop a level. + if (XMLString::equals(raw.second->getLocalName(),_AccessControl)) + raw.second = XMLHelper::getFirstChildElement(raw.second); + + AccessControl* authz; + if (XMLString::equals(raw.second->getLocalName(),_Rule)) + authz=new Rule(raw.second); + else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex)) + authz=new RuleRegex(raw.second); + else + authz=new Operator(raw.second); + + delete m_rootAuthz; + m_rootAuthz = authz; + return make_pair(false,(DOMElement*)NULL); +} + +AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const +{ + return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false; +} diff --git a/shibsp/paths.h.in b/shibsp/paths.h.in index f35df0b..abd4f71 100644 --- a/shibsp/paths.h.in +++ b/shibsp/paths.h.in @@ -1,53 +1,53 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file shibsp/paths.h - * - * Default configuration paths. - */ - -#ifndef __shibsp_paths_h__ -#define __shibsp_paths_h__ - -/** Default schema catalogs. */ -#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml" - -/** Default name of SP configuration file. */ -#define SHIBSP_CONFIG "shibboleth2.xml" - -/** Default name of SP console tool logging file. */ -#define SHIBSP_LOGGING "console.logger" - -/** Default prefix for installation (used to resolve relative paths). */ -#define SHIBSP_PREFIX "@-PREFIX-@" - -/** Library directory for installation (used to resolve relative paths). */ -#define SHIBSP_LIBDIR "@-LIBDIR-@" - -/** Log directory for installation (used to resolve relative paths). */ -#define SHIBSP_LOGDIR "@-LOGDIR-@" - -/** Configuration directory for installation (used to resolve relative paths). */ -#define SHIBSP_CFGDIR "@-SYSCONFDIR-@" - -/** Runtime state directory for installation (used to resolve relative paths). */ -#define SHIBSP_RUNDIR "@-RUNDIR-@" - -/** XML directory for installation (used to resolve relative paths). */ -#define SHIBSP_XMLDIR "@-XMLDIR-@" - -#endif /* __shibsp_paths_h__ */ +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file shibsp/paths.h + * + * Default configuration paths. + */ + +#ifndef __shibsp_paths_h__ +#define __shibsp_paths_h__ + +/** Default schema catalogs. */ +#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml" + +/** Default name of SP configuration file. */ +#define SHIBSP_CONFIG "shibboleth2.xml" + +/** Default name of SP console tool logging file. */ +#define SHIBSP_LOGGING "console.logger" + +/** Default prefix for installation (used to resolve relative paths). */ +#define SHIBSP_PREFIX "@-PREFIX-@" + +/** Library directory for installation (used to resolve relative paths). */ +#define SHIBSP_LIBDIR "@-LIBDIR-@" + +/** Log directory for installation (used to resolve relative paths). */ +#define SHIBSP_LOGDIR "@-LOGDIR-@" + +/** Configuration directory for installation (used to resolve relative paths). */ +#define SHIBSP_CFGDIR "@-SYSCONFDIR-@" + +/** Runtime state directory for installation (used to resolve relative paths). */ +#define SHIBSP_RUNDIR "@-RUNDIR-@" + +/** XML directory for installation (used to resolve relative paths). */ +#define SHIBSP_XMLDIR "@-XMLDIR-@" + +#endif /* __shibsp_paths_h__ */ diff --git a/shibsp/resource.h b/shibsp/resource.h index 8df1c2f..79fe549 100644 --- a/shibsp/resource.h +++ b/shibsp/resource.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by shibsp.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by shibsp.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/shibsp/util/SPConstants.cpp b/shibsp/util/SPConstants.cpp index 38f0a0a..6614bad 100644 --- a/shibsp/util/SPConstants.cpp +++ b/shibsp/util/SPConstants.cpp @@ -1,116 +1,116 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * SPConstants.cpp - * - * SP XML namespace constants - */ - -#include "internal.h" -#include "util/SPConstants.h" -#include - -using namespace shibspconstants; - -const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0 -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chNull -}; - -const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0 -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon, - chDigit_1, chPeriod, chDigit_0, chNull -}; - -const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d); - -const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon, - chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, - chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash, - chLatin_m, chLatin_a, chLatin_p, chNull -}; - -const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon, - chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, - chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull -}; - -const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, - chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull -}; - -const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chColon, - chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, - chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_u, chLatin_r, chLatin_i, chNull -}; - -const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chColon, - chLatin_n, chLatin_a, chLatin_m, chLatin_e, - chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull -}; - -const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest -{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, - chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, - chDigit_1, chPeriod, chDigit_0, chColon, - chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon, - chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n, - chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull -}; - -const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit"; - -const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout"; - -const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config"; +/* + * Copyright 2001-2007 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * SPConstants.cpp + * + * SP XML namespace constants + */ + +#include "internal.h" +#include "util/SPConstants.h" +#include + +using namespace shibspconstants; + +const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0 +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chNull +}; + +const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0 +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon, + chDigit_1, chPeriod, chDigit_0, chNull +}; + +const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d); + +const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon, + chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash, + chLatin_m, chLatin_a, chLatin_p, chNull +}; + +const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon, + chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, + chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, + chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull +}; + +const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chColon, + chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, + chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_u, chLatin_r, chLatin_i, chNull +}; + +const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chColon, + chLatin_n, chLatin_a, chLatin_m, chLatin_e, + chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull +}; + +const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_1, chPeriod, chDigit_0, chColon, + chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon, + chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n, + chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull +}; + +const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit"; + +const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout"; + +const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config"; diff --git a/util/mdquery.cpp b/util/mdquery.cpp index 053e994..9b928a8 100644 --- a/util/mdquery.cpp +++ b/util/mdquery.cpp @@ -1,162 +1,162 @@ -/* - * Copyright 2001-2009 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * mdquery.cpp - * - * SAML Metadata Query tool layered on SP configuration - */ - -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#ifdef WIN32 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -# define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace shibsp; -using namespace opensaml::saml2md; -using namespace opensaml; -using namespace xmltooling::logging; -using namespace xmltooling; -using namespace std; - -using xercesc::XMLString; - -void usage() -{ - cerr << "usage: mdquery -e [-a -nostrict]" << endl; - cerr << " mdquery -e -r -p [-a -ns -nostrict]" << endl; -} - -int main(int argc,char* argv[]) -{ - char* entityID = NULL; - char* appID = "default"; - bool strict = true; - char* prot = NULL; - const XMLCh* protocol = NULL; - char* rname = NULL; - char* rns = NULL; - - for (int i=1; ilock(); - - Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery"); - - const Application* app = sp->getApplication(appID); - if (!app) { - log.error("unknown application ID (%s)", appID); - sp->unlock(); - conf.term(); - return -3; - } - - app->getMetadataProvider()->lock(); - MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict); - if (rname) { - const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS; - auto_ptr_XMLCh n(rname); - QName q(ns, n.get()); - mc.role = &q; - mc.protocol = protocol; - const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second; - if (role) - XMLHelper::serialize(role->marshall(), cout, true); - else - log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID); - } - else { - const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first; - if (entity) - XMLHelper::serialize(entity->marshall(), cout, true); - else - log.error("no metadata found for (%s)", entityID); - } - - app->getMetadataProvider()->unlock(); - - sp->unlock(); - conf.term(); - return 0; -} +/* + * Copyright 2001-2009 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * mdquery.cpp + * + * SAML Metadata Query tool layered on SP configuration + */ + +#if defined (_MSC_VER) || defined(__BORLANDC__) +# include "config_win32.h" +#else +# include "config.h" +#endif + +#ifdef WIN32 +# define _CRT_NONSTDC_NO_DEPRECATE 1 +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace opensaml::saml2md; +using namespace opensaml; +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace std; + +using xercesc::XMLString; + +void usage() +{ + cerr << "usage: mdquery -e [-a -nostrict]" << endl; + cerr << " mdquery -e -r -p [-a -ns -nostrict]" << endl; +} + +int main(int argc,char* argv[]) +{ + char* entityID = NULL; + char* appID = "default"; + bool strict = true; + char* prot = NULL; + const XMLCh* protocol = NULL; + char* rname = NULL; + char* rns = NULL; + + for (int i=1; ilock(); + + Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery"); + + const Application* app = sp->getApplication(appID); + if (!app) { + log.error("unknown application ID (%s)", appID); + sp->unlock(); + conf.term(); + return -3; + } + + app->getMetadataProvider()->lock(); + MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict); + if (rname) { + const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS; + auto_ptr_XMLCh n(rname); + QName q(ns, n.get()); + mc.role = &q; + mc.protocol = protocol; + const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second; + if (role) + XMLHelper::serialize(role->marshall(), cout, true); + else + log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID); + } + else { + const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first; + if (entity) + XMLHelper::serialize(entity->marshall(), cout, true); + else + log.error("no metadata found for (%s)", entityID); + } + + app->getMetadataProvider()->unlock(); + + sp->unlock(); + conf.term(); + return 0; +} -- 2.1.4